# Referência do SDK

Toda a superfície da API do @beeuni/sdk — métodos do cliente, módulos, turns e distribuição.

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

Esta página apresenta toda a superfície da API `@beeuni/sdk`: cada método do cliente, os módulos independentes de framework, os auxiliares de turns e como o pacote é distribuído. Use [SDK](/docs/pt/sdk) para começar e [Sessions](/docs/pt/sdk/sessions) para conhecer em detalhes o ciclo de vida das sessões.

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

## O cliente

`createBeeuni(config)` retorna um cliente. Cada método é uma chamada tipada à API da plataforma. Os handles `project(id)` e `session(pid, sid)` vinculam IDs para que você nunca precise repeti-los.

```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>

### Contas — `beeuni.accounts`

| método | descrição |
| --- | --- |
| `list()` · `get(accountId)` | contas às quais você pertence · uma conta |
| `create({ name })` · `updateName(accountId, name)` | criar · renomear uma conta |
| `branding.get(accountId)` · `branding.update(accountId, { app_name })` · `branding.uploadAsset(accountId, kind, file)` · `branding.removeAsset(accountId, kind)` · `branding.reset(accountId)` | identidade visual da organização (Enterprise): usar logo / ícone / favicon próprios e nome do produto; `kind` é `logo` · `icon` · `favicon`, ou `logo_dark` · `icon_dark` · `favicon_dark` para a variante de esquema escuro |
| `members(accountId)` · `invite(accountId, input)` | listar membros · convidar um membro |
| `updateMemberRole(accountId, userId, role)` · `removeMember(accountId, userId)` | atribuir a função na conta · remover um membro |
| `invites(accountId)` | convites pendentes |
| `cancelInvite(accountId, inviteId)` · `resendInvite(accountId, inviteId)` | cancelar · reenviar um convite pendente |
| `leave(accountId)` | sair da conta |

`accounts.tokens` cria chaves de API vinculadas à conta (`beeuni_pat_...`). Consulte [SDK auth](/docs/pt/accounts#tokens) para conhecer o modelo completo de tokens.

| método | descrição |
| --- | --- |
| `tokens.list(accountId?, options?)` | listar chaves de API — de toda a conta ou apenas as suas com `{ mine: true }` |
| `tokens.create(input)` | criar uma — `{ accountId?, name, expiresAt?, projectId? }` |
| `tokens.revoke(tokenId, accountId?)` | revogar uma |

`accounts.audit` é o registro de reconstrução empresarial. Ele combina solicitações de API autenticadas com eventos semânticos de sessão, conector, aprovação e computador.

| método | descrição |
| --- | --- |
| `audit.log(accountId, filters?)` | listar eventos por projeto, sessão, ator, origem, resultado, solicitação, correlação, recurso, ação ou horário |
| `audit.export(accountId, filters?)` | exportar o mesmo fluxo de eventos filtrado como CSV ou JSONL |
| `audit.webhooks.list/create/update/remove(...)` | gerenciar webhooks SIEM assinados para o fluxo centralizado |

Cada evento inclui `project_id`, `session_id`, `actor_type`, `source`, `outcome`, `request_id`, `trace_id` e `correlation_id` quando a ação os fornece. A API não armazena corpos de solicitações, prompts, segredos, credenciais ou argumentos brutos de conectores no evento centralizado. Os eventos de conectores podem incluir uma prévia limitada dos argumentos que remove campos semelhantes a credenciais e dados opacos.

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

### Atribuições de acesso

O Beeuni tem um único registro de concessão: uma **atribuição**. Ela vincula um principal (`user`, `group`, `service_account` ou `pending`) a uma função, em um escopo (`account` ou um `project`), opcionalmente restringido a um objeto (`agent`, `skill`, `secret`, `app` ou `trigger`) e opcionalmente contendo um `expires_at`. O acesso de grupos, o acesso por recurso e os vínculos de funções personalizadas são todos atribuições. Consulte [Accounts & access](/docs/pt/accounts#one-access-model) para conhecer o modelo.

A superfície REST canônica é:

| Método + caminho | Ação |
| --- | --- |
| `GET /v1/accounts/{accountId}/iam/assignments` | listar atribuições, filtradas por principal, escopo, objeto ou função |
| `POST /v1/accounts/{accountId}/iam/assignments` | criar uma atribuição |
| `DELETE /v1/accounts/{accountId}/iam/assignments/{assignmentId}` | revogar uma atribuição |
| `GET /v1/accounts/{accountId}/iam/permissions` | catálogo de permissões, como dados |
| `GET /v1/accounts/{accountId}/iam/roles` · `…/roles/{roleId}/permissions` | funções · permissões de uma função |

O SDK as expõe como `listAssignments`, `createAssignment`, `revokeAssignment` e `listPermissions`. Uma linha do catálogo contém `action`, `scope_type`, `resource_type`, `delegable`, `description`, `area`, `level` e `implies` — leia esses dados em vez de codificar strings de ação manualmente.

A atribuição de uma função personalizada exige a permissão `rbac` da conta; sem ela, a rota responde `402` com `code: "entitlement_required"`.

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

### Convites de conta — `beeuni.accountInvites`

Acessados apenas pelo token do convite — o convidado ainda pode não ser membro.

| método | descrição |
| --- | --- |
| `listMine()` | todos os convites pendentes e não expirados direcionados ao seu e-mail, com o workspace e todos os projetos que eles concedem |
| `describe(inviteId)` · `accept(inviteId)` · `decline(inviteId)` | visualizar · aceitar · recusar um convite |

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

### Projetos — `beeuni.projects`

| método | descrição |
| --- | --- |
| `list()` · `listForAccount(accountId)` | seus projetos · projetos em uma conta |
| `get(id)` · `detail(id)` | resumo · detalhes completos |
| `create(input)` · `createRepo(input)` | a partir de um `repo_url` existente · novo repositório GitHub vazio |
| `provision(input)` | novo projeto em um novo repositório gerenciado pelo Beeuni, inicializado com um template inicial — `{ name, account_id?, seed_starter?, starter_template?, marketplace_items?, source_item_id?, idempotency_key? }` |
| `update(id, input)` · `archive(id)` | atualizar configurações · arquivar |
| `llmCatalog(id)` · `modelPicker(id)` | catálogo completo · compacto de modelos para um seletor |
| `sandboxTemplates(id)` · `sandboxHealth(id)` | templates de build do sandbox · integridade do build |
| `sessions(id)` · `createSession(id, input?)` | listar sessões visíveis · criar uma sessão |

`provision` cria um novo projeto; não inicia o sandbox de um projeto existente. Em vez disso, inicie uma sessão — consulte [Sessions](/docs/pt/sdk/sessions).

Envie `idempotency_key` quando for possível tentar novamente — uma recarga, uma segunda aba ou um timeout após uma nova tentativa. `provision` cria um novo repositório gerenciado a cada chamada; portanto, sem uma chave, todas essas chamadas criam projetos duplicados reais. Reutilize uma chave em todas as tentativas de uma única criação lógica, e as repetições retornarão o projeto criado pela primeira tentativa (201, mesmo `project_id`, `push_token: null`). A chave identifica a tentativa, não o payload — reutilizá-la com um `name` diferente retorna o primeiro projeto e ignora o novo valor; portanto, crie uma chave nova para cada criação distinta. Criar um segundo projeto com o mesmo **nome** e sem chave continua funcionando.

Uma repetição que chega enquanto a primeira chamada ainda está provisionando recebe `409` com `code: 'provision_in_flight'`, em vez de um `project_id`; essa chamada ainda pode sofrer rollback. Tente novamente com a mesma chave.

`project(id).sessions.list({ scope: 'project' })` é um inventário do ciclo de vida para um chamador com permissões de gerenciamento de projetos. Ele adiciona sessões acessíveis indisponíveis, aquecidas e excluídas logicamente, com metadados de propriedade e estado de execução. Ambos os escopos de listagem omitem todas as sessões que o chamador não pode abrir.

`sessions.list` e `sessions.listPage` também aceitam os filtros de hierarquia e atribuição. Sem eles, a lista permanece simples e inalterada.

| opção | descrição |
| --- | --- |
| `parent: 'root'` | Somente sessões de nível superior. Cada linha contém `child_count`. |
| `parent: '<sessionId>'` | Filhos dessa sessão, do mais recente para o mais antigo. |
| `startedBy: 'me' \| 'others' \| 'automated'` | Filtrar por `initiator`, em relação ao chamador. |
| `q` | Pesquisa que não diferencia maiúsculas de minúsculas em título, rótulo inicial, slug do gatilho e prefixo do ID da sessão, em todas as sessões que o chamador pode abrir. Com `parent: 'root'`, uma raiz que correspondeu por meio de um filho tem `search_match: 'child'`. |

Cada linha de sessão contém `parent_session_id` e `initiator` (`{ type: 'member' | 'trigger' | 'channel' | 'api' | 'system', id, label }`). `initiator` informa quem iniciou toda a execução; um filho copia o valor do pai. `sessionParentId(session)` lê `parent_session_id` e, depois, o legado `metadata.spawned_by_session`. Um cursor só é válido para o conjunto de filtros que o emitiu.

### GitHub — `beeuni.github`

Instalação do GitHub App e vinculação de repositórios no escopo da conta, não do projeto.

| método | função |
| --- | --- |
| `getInstallation(accountId)` · `listInstallations(accountId)` | instalação desta conta · instalações acessíveis ao usuário |
| `saveInstallation(input)` · `deleteInstallation(accountId, installationId?)` | registrar · desvincular uma instalação |
| `listLinkableInstallations(input)` | instalações que o usuário autorizado do GitHub pode vincular; cada entrada contém `linked_to_other_accounts`, uma contagem de outras contas Beeuni que a possuem — nunca seus nomes |
| `listRepositories(accountId, installationId?)` · `listRepositoryBranches(...)` | repositórios que a instalação pode ver · branches e a branch padrão do GitHub |
| `linkRepository(input)` | Importar um repositório como projeto usando uma instalação autorizada do GitHub. |
| `replaceProjectRepository({ project_id, repo_url, expected_repo_url, github_token })` | substituir o repositório GitHub de um projeto existente. Use `github_token` com acesso de leitura/gravação em Contents, ou `installation_id` mais `github_user_token` temporário para verificar o acesso de administrador da organização e conceder acesso somente a este repositório pelo GitHub App. `copy_shared_secrets_from_project_id` mais `copy_shared_secret_identifiers` copia os segredos compartilhados de runtime selecionados na mesma transação. Um `expected_repo_url` desatualizado retorna 409. O repositório antigo permanece no GitHub. Novas sessões usam o repositório substituto; sessões existentes mantêm seu checkout. |

Esta lista contém apenas conexões reais de contas. "Beeuni managed" não é uma
delas — é o backend da instância abaixo.

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

### Backend git da instância — `beeuni.gitBackend`

Um único proprietário e uma credencial para toda a implantação, usados para repositórios
gerenciados pelo Beeuni. Nunca é uma conexão de conta e nunca aparece em
`beeuni.github.listInstallations`.

| método | função |
| --- | --- |
| `get()` | `{ configured, kind: 'app' \| 'pat' \| null, owner }` — legível por qualquer usuário autenticado; expõe apenas o login do proprietário que cada `repo_url` gerenciado já contém |

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

### Faturamento — `beeuni.billing`

Consulta créditos, assinatura, plano e histórico de transações. Use o pagamento e a gestão de cobrança do Beeuni para pagamentos e compras de créditos.

| método | função |
| --- | --- |
| `accountState(accountId?)` · `accountStateMinimal(accountId?)` | estado de faturamento completo · mínimo |
| `transactions(params?)` · `transactionsSummary(params?)` | histórico · totais resumidos |
| `creditBreakdown(accountId?)` · `usageHistory(params?)` | saldo de créditos por origem · uso ao longo do tempo |
| `sessionCosts.list(options?)` · `sessionCosts.get(sessionId, options?)` | registros paginados de custos de sessões · um registro detalhado de uma sessão |
| `tierConfigurations()` | níveis de plano disponíveis |
| `checkout.createSession(input)` · `checkout.confirmSession(sessionId, accountId?)` | **Obsoletos.** Rejeitam com `ENDPOINT_RETIRED`. Removidos na próxima versão principal. |
| `subscription.createPortalSession(...)` · `subscription.cancel(...)` · `subscription.reactivate(...)` | abrir o portal do cliente · cancelar · reativar |
| `subscription.cancelScheduledChange(...)` · `prorationPreview(...)` | cancelar · visualizar uma alteração de plano |
| `subscription.scheduleDowngrade(...)` | **Obsoleto.** Rejeita com `ENDPOINT_RETIRED`. Altere o plano no portal do cliente. Removido na próxima versão principal. |
| `credits.purchase(input)` · `credits.autoTopupSettings(...)` · `credits.configureAutoTopup(...)` | compra avulsa · consultar · configurar recarga automática |

`sessionCosts.list()` aceita `accountId`, `projectId`, `limit` e `offset`.
Cada linha combina o custo finalizado de LLM e o custo faturado de computação do sandbox.
`sessionCosts.get()` adiciona o uso de modelos e o registro discriminado de LLM/computação.
A lista inclui um total de conciliação para custos sem sessão.

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

### Compartilhamentos de sandbox — `beeuni.sandboxShares`

Links públicos de compartilhamento para uma porta exposta do sandbox. Com escopo de sandbox, não
de projeto.

| método | função |
| --- | --- |
| `list(sandboxId)` | links de compartilhamento ativos |
| `create(input)` | criar um — `{ sandboxId, port, ttl?, label? }` |
| `revoke(sandboxId, token)` | revogar um |

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

### Catálogo do marketplace — `beeuni.marketplace`

Navegação no catálogo público, somente leitura — diferente de `project(id).marketplace`,
que instala um item em um projeto.

| método | função |
| --- | --- |
| `items(options?)` · `item(id)` · `itemFile(id, path)` | navegar · um item · um arquivo dentro de um item |
| `marketplaces()` · `featured()` | todos os marketplaces · marketplaces em destaque |
| `sources.list()` · `sources.add(input)` · `sources.remove(id)` | listar · adicionar · remover uma origem |

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

### Notificações — `beeuni.notifications`

As notificações de quem faz a chamada, em todas as contas e projetos. Cada pessoa conectada
tem uma caixa de entrada, um registro de preferências e inscrições Web Push para
seus navegadores. Todos os métodos precisam da credencial de uma pessoa: uma conta de serviço
recebe `403`.

> **Notifications é uma flag de recurso**
>
> O Beeuni grava linhas na caixa de entrada, envia Web Push e e-mails apenas para projetos com a
> flag `notification_center` ativada. Ela vem desativada por padrão. `list()` omite linhas
> de projetos com a flag desativada. `session(pid, sid).watch()` e `.setWatch()`
> respondem `403` com `{ error, code: "feature_disabled", feature: "notification_center" }`
> enquanto ela está desativada; use `isFeatureDisabledError(error)` para decidir o fluxo com base nela.
> Preferências, inscrições Web Push e tokens de dispositivo são por pessoa e funcionam
> em ambos os casos. Com a flag desativada, o celular de quem criou a sessão ainda recebe uma notificação push
> quando um turno termina, falha, faz uma pergunta ou solicita permissão. Veja
> [Flags de recursos](/docs/pt/feature-flags) e [Notificações](/docs/pt/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 } } });
```

| método | função |
| --- | --- |
| `list({ limit?, before? }, { signal? })` | a página mais recente: `{ notifications, unread_count, next_before }`. `limit` vai de 1 a 50 (padrão 20). Passe `next_before` como `before` para a próxima página. Linhas que quem faz a chamada não pode mais ver são omitidas. Uma falha não chama o manipulador de erros do host. |
| `markRead({ ids })` · `markRead({ all: true })` · `markRead({ sessionId })` | marcar como lidas de 1 a 100 linhas, todas as linhas ou todas as linhas de uma sessão. Altera apenas as linhas de quem faz a chamada. Retorna `{ updated, unread_count }`. |
| `preferences()` · `updatePreferences({ kinds })` | consultar · alterar a opção de push e e-mail por tipo. Retorna `{ kinds, email_available }`. Um patch altera apenas os tipos e canais que especifica. |
| `webPushPublicKey()` | `{ public_key }`: o `applicationServerKey` para `pushManager.subscribe` |
| `registerWebPushSubscription({ endpoint, keys })` | enviar push para este navegador. Exige login no navegador: um token pessoal recebe `403`. Um endpoint em um serviço push desconhecido recebe `400`. |
| `unregisterWebPushSubscription(endpoint, { signal? })` | parar o push para este navegador. Retorna `{ deleted }`. |
| `registerDeviceToken(input)` · `unregisterDeviceToken(token, { signal? })` | registrar · remover o token push Expo de um aplicativo nativo |

Tipos (`InboxNotificationKind`, listados em `INBOX_NOTIFICATION_KINDS`):

| tipo | enviado quando | push | e-mail (padrão) |
| --- | --- | --- | --- |
| `turn_done` | um turno que você solicitou ou acompanha terminou | ativado | desativado |
| `turn_error` | esse turno terminou com um erro | ativado | ativado, em um resumo |
| `question` | o agente faz uma pergunta | ativado | ativado, em um resumo |
| `permission` | o agente solicita permissão | ativado | desativado |
| `shared` | alguém compartilhou uma sessão com você | ativado | ativado, em um resumo |
| `automation_failed` | uma automação que você acompanha começou a falhar | ativado | ativado, imediatamente |
| `automation_recovered` | essa automação volta a funcionar | ativado | desativado |

`DEFAULT_NOTIFICATION_PREFERENCES` contém esses padrões. A linha da caixa de entrada é
sempre gravada; as preferências determinam apenas push e e-mail. Um e-mail de resumo
lista as linhas ainda não lidas 15 minutos após sua chegada, com no máximo um resumo
por hora. Oculte a coluna de e-mail quando `email_available` for `false`.

O `url` de cada linha abre seu assunto. Seu parâmetro de consulta `?notification=<id>` permite que a
página marque a linha como lida.

O handle da sessão contém o acompanhamento de uma sessão por quem faz a chamada:

| método | função |
| --- | --- |
| `session(pid, sid).watch()` | `{ watching }`: se quem faz a chamada recebe notificações sobre esta sessão |
| `session(pid, sid).setWatch(watching)` | `false` silencia a sessão para quem faz a chamada, `true` volta a acompanhá-la. Enviar um prompt a uma sessão passa a acompanhá-la, mas nunca desfaz o silenciamento. |
| `session(pid, sid).presence({ tab_id, active, alerts? }, { keepalive? })` | concessão de presença desta aba. `alerts: true` indica que a aba mostra suas próprias notificações: com `notification_center` ativado, o servidor omite o push para celular e o Web Push apenas enquanto uma aba que exibe alertas está em uso. Com ele desativado, `alerts` é ignorado e qualquer aba presente impede o push para celular. `keepalive` permite que a solicitação continue após o fechamento de uma página. Padrão: ativado para um relatório de ausência, desativado para um de presença. `useSession` envia `keepalive` apenas com `presencePageExit`. |

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

### O handle do projeto — `beeuni.project(id)`

Vincula o ID do projeto; todos os sub-recursos dependem dele.

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

| método | descrição |
| --- | --- |
| `get` · `detail` · `update` · `archive` | ler · detalhes completos · atualizar · arquivar |
| `llmCatalog` · `modelPicker` · `sandboxHealth` | leituras do modelo e da compilação no sandbox |
| `onboardingComplete` | marcar a integração inicial do projeto como concluída |
| `validateManifest(raw)` | validar no servidor um manifesto `beeuni.yaml` (ou `beeuni.toml` legado) |
| `gitToken()` | gerar um novo token de push do git com escopo (`409` para um repositório próprio) |
| `setAgentScope(agentName, scope)` | definir os segredos e conectores permitidos para um agente no manifesto — a segunda vinculação, não uma função |

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

#### `p.tokens` — chaves de API com escopo de projeto

Geradas automaticamente na criação da sessão como `BEEUNI_TOKEN`; também podem ser geradas manualmente.

| método | descrição |
| --- | --- |
| `list()` | chaves de API do projeto |
| `create(input?)` | gerar uma nova |
| `revoke(tokenId)` | revogar uma |

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

#### `p.setupLinks` — links de configuração gerados pelo agente

Um link que uma pessoa abre para inserir um segredo ou conectar um aplicativo, sem acesso completo ao projeto.

| método | descrição |
| --- | --- |
| `requestSecret(input)` · `requestConnector(input)` | link para coletar um segredo · conectar um aplicativo |

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

#### `p.apps` — Aplicativos (releases, máquinas, volumes)

Por trás do recurso de projeto `apps`. Guia: [SDK → Aplicativos](/docs/pt/sdk/apps).

| método | descrição |
| --- | --- |
| `list()` · `get(appId)` · `create(input)` · `update(appId, input)` · `remove(appId)` | inventário e ciclo de vida; `create` aceita `uses`, `update` também aceita `labels` |
| `deployments.*` · `artifacts.*` · `access.*` · `rollback` · `start` · `stop` | implantações, artefatos, a política de acesso, tráfego e runtime |
| `machines.list/start/stop/restart/destroy` · `scale(appId, count)` · `exec(appId, input)` | máquinas por grupo de processos; `exec` precisa de `project.app.admin` |
| `volumes.list/create/update/destroy/snapshots/snapshot/restore/fork` | volumes persistentes, snapshots diários, restauração, bifurcação |
| `token(appId)` | um token de login válido por 15 minutos; `409 app_capability_unsupported` sem `member_tokens` |

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

#### `p.secrets` — segredos do projeto

| método | descrição |
| --- | --- |
| `list()` · `upsert(input)` | listar metadados · criar ou atualizar um valor somente para escrita e a política de entrega |
| `setStrategy(identifier, strategy, options?)` | alterar a exposição e sua lista de hosts |
| `broker(identifier, request)` | executar uma solicitação HTTPS autorizada pela sessão e vinculada à política |
| `remove(identifier)` | excluir um segredo |
| `setPersonal(name, value)` · `removePersonal(name)` | definir · remover uma substituição por usuário |
| `setGitCredential(input)` | definir uma credencial de autenticação do git |

`runtime` com o consumidor `sandbox` é uma exposição de **ambiente** — o padrão e a única política que coloca um valor em texto simples na sessão. `egress` com o consumidor `network` é uma exposição **imposta na saída**: a sessão mantém um identificador e o Beeuni substitui o valor real fora do sandbox, para os hosts HTTPS exatos listados pela política. A exposição imposta na saída é experimental; ela precisa do sinalizador de recurso `secrets_egress` (Configurações → Sinalizadores de recursos). Com o sinalizador desativado, `setStrategy(identifier, 'egress', …)` e `upsert(...)` com uma política de saída retornam `403` `feature_disabled`. Todo consumidor `broker` não tem presença alguma na sessão. Consulte [Segredos](/docs/pt/project/secrets). O método `broker(...)` exige um token com escopo de sessão e um identificador de sessão ativo.

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

#### `p.access` — atribuições, convites e solicitações do projeto

Cada método aqui lê ou grava uma atribuição com escopo para este projeto. As funções do projeto são `manager` e `member`.

| método | descrição |
| --- | --- |
| `list()` · `invite(email, role)` | identidades com acesso · convidar um usuário |
| `update(userId, role)` · `revoke(userId)` | atribuir uma função de projeto · revogar a atribuição |
| `pendingInvites()` · `requests()` | convites pendentes · solicitações de acesso pendentes |
| `resendInvite(inviteId)` · `revokeInvite(inviteId)` · `approveRequest(id)` · `rejectRequest(id)` | reenviar/revogar um convite · aprovar/rejeitar uma solicitação |
| `groupGrants()` · `attachGroupGrant(...)` · `updateGroupGrant(...)` · `detachGroupGrant(...)` | as mesmas atribuições, com uma identidade `group` |

`p.access.resourceGrants` é a visualização de **atribuição de objeto**: ela restringe uma identidade a um objeto no projeto, em vez de ao projeto inteiro. Atualmente, o Beeuni impõe atribuições de objeto a agentes e habilidades. Um agente é fechado por padrão — um membro só chega até ele quando uma atribuição o nomeia ou nomeia um de seus grupos. Uma atribuição de objeto não tem permissões próprias e restringe um gerente de projeto tanto quanto um membro.

| método | descrição |
| --- | --- |
| `resourceGrants.list()` | atribuições de objeto neste projeto |
| `resourceGrants.create(input)` | atribuir um objeto a um usuário ou grupo |
| `resourceGrants.remove(grantId)` | revogar uma atribuição de objeto |

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

#### `p.connector(slug)` — um conector

| método | descrição |
| --- | --- |
| `run(action, args, options?)` | a saída da ação; gera `ConnectorCallError` ou `ConnectorApprovalPendingError` — consulte [Erros](/docs/pt/sdk/reference#pconnectorslug--one-connector) |
| `call(action, args, options?)` | o resultado bruto da chamada; `202` resolve com `ok: false` |
| `describe()` · `describe(action)` | o conector com esquemas de entrada e saída · uma ação |
| `accounts()` | as contas que este chamador pode usar para executá-lo, a primeira por padrão |
| `paginate(action, args, { next, maxPages? })` | iterador assíncrono sobre a saída de cada página; gera `ConnectorPageLimitError` com `nextArgs` quando existem mais de `maxPages` páginas (100 por padrão) — consulte [Páginas](/docs/pt/sdk/reference#pconnectorslug--one-connector) |
| `uploadAttachment(content, input)` | `p.connectors.uploadAttachment` com `connector` definido como este slug |

`options`: `account`, `approvalContext`, `timeoutMs` (90.000 por padrão), `signal`. Com o arquivo de `beeuni connectors types`, os argumentos e a saída são tipados.

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

#### `p.connectors` — conectores de ferramentas

| método | descrição |
| --- | --- |
| `catalog()` · `tools()` | catálogo de Connectors chamáveis · ferramentas `<connector>.<action>` niveladas |
| `search(query, options?)` · `describe(tool)` | localizar · inspecionar uma ferramenta chamável |
| `call(tool, args?, options?)` | chamar uma ferramenta `<connector>.<action>` pelo gateway no servidor. `options.account` indica qual conta usar — veja abaixo. |
| `accounts(slug)` | as contas que este chamador pode usar para chamar `slug`, a primeira por padrão — aquilo com que `options.account` faz correspondência |
| `uploadAttachment(content, input)` | preparar bytes para `input.connector`; retorna `ref` (`{ $beeuni_attachment }`) para inserir nos argumentos de uma chamada posterior — consulte [Anexar arquivos](/docs/pt/connect/connectors#attach-files) |
| `list()` · `config(connectorId)` | conectores configurados · configuração de um conector |
| `create(input)` | adicionar um conector |
| `auth.discover(input)` | visualizar a autenticação de uma especificação OpenAPI, coleção do Postman ou endpoint |
| `remove(connectorId)` · `sync()` | excluir um conector · ressincronizar conectores |
| `setName(connectorId, name)` · `setSensitive(connectorId, sensitive)` | renomear · marcá-lo como sensível (exige aprovação adicional) |
| `setAuthorizationStrategy(slug, strategy)` | @deprecated. Ainda chama a rota; a rota não faz nada e responde `{ok:true, deprecated:true}`. `owner_type` em cada conexão é agora toda a regra de acesso. |
| `setCredentialMode(connectorId, mode)` · `setCredential(connectorId, input)` | trocar a origem · definir o valor da credencial |
| `policies.get(connectorId)` · `policies.set(connectorId, policies)` | ler · substituir as políticas de ferramentas |
| `connections.list()` · `connections.reconcile(input)` | listar · criar/atualizar contas conectadas |
| `connections.updateCredential(connectionId, input)` | alternar a credencial de uma conexão |
| `connections.revoke(connectionId)` · `connections.activate(connectionId)` | negar · restaurar uma conexão |
| `connections.setDefault(connectionId)` | torná-la padrão para o escopo de proprietário |
| `connections.rename(connectionId, label)` | alterar apenas o rótulo; a conta continua autorizada. Cada conexão contém `connected_as`, a identidade com a qual foi autorizada. |

`p.connectors.discover` navega pelo catálogo de conectores diretos. É **experimental** e fica desativado por padrão — ative-o por projeto em [Configurações → Sinalizadores de recursos](/docs/pt/feature-flags) → "Connectors API Discover". O Easy Connect continua sendo o marketplace de conectores padrão.

| método | descrição |
| --- | --- |
| `discover.list(query?, cursor?)` · `discover.detail(id)` | pesquisar entradas OpenAPI/MCP/GraphQL/CLI · detalhes de uma entrada |

`p.connectors.pipedream` é o caminho de compatibilidade do OAuth gerenciado anterior; `listApps`
retorna apenas apps OAuth. Use Easy Connect para novas integrações gerenciadas. Conecte apps com chave de API diretamente.

| método | função |
| --- | --- |
| `pipedream.listApps(params?)` · `pipedream.connect(input)` · `pipedream.finalize(input)` | navegar pelo catálogo de apps · iniciar um fluxo de conexão · finalizá-lo |

Um conector define a ferramenta, o app do provedor e as políticas. `connections`
armazena suas **contas** conectadas — um conector pode manter várias lado a lado.
Uma sessão pode fixar uma para todas as chamadas com
`connector_bindings: { alias: { connection_id } }`, ou uma chamada individual pode indicar
uma com `call(tool, args, { account })`. As credenciais permanecem criptografadas e
são resolvidas a cada solicitação.

`connections` é a única fachada de autorização ativa. Os nomes descontinuados
`authorizations` e `profiles` não fazem parte da interface atual do SDK.

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

#### Contas e a verificação no momento da chamada

Cada conexão tem um `owner_type`: `project` (compartilhada — acessível por qualquer pessoa
à qual o conector tenha sido concedido, seja uma pessoa ou uma conta de serviço) ou `member` (privada —
acessível apenas pelo próprio proprietário, e somente em uma sessão privada; nunca por uma
conta de serviço). Uma conta compartilhada pode ser restrita a grupos e pessoas:
`connections.list()` retorna suas concessões em `shared_with`, e
`connectionSharedWithEveryone(connection)` informa se todos no
projeto podem usá-la. Uma conta restrita segue as regras de contas privadas para as
pessoas que especifica, e `usable: false` marca uma conta que o chamador vê apenas para gerenciá-la.
Conceda ou revogue com `createAssignment` / `revokeAssignment`
(`object: { type: 'connection', id }`) — veja
[Escolha quem pode usar uma conta compartilhada](/docs/pt/connect/connectors#choose-who-can-use-a-shared-account).
`p.connectors.accounts(slug)` lista todas as contas que este chamador pode acessar,
com a padrão primeiro:

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

Uma chamada que não indica uma conta é resolvida primeiro para a conta privada padrão
do próprio chamador e, depois, para a conta compartilhada padrão do projeto. Uma conta indicada
que não é resolvida é **negada** com `connector_not_connected` — nunca
substituída silenciosamente — e a negação lista `requested_account` e
`available_accounts`. Toda chamada bem-sucedida informa com qual conta foi executada:
`result.account = { connection_id, label, owner_type }`.

Não há mais uma verificação de conector no momento da criação da sessão. Antes, uma sessão era
recusada com `409 CONNECTOR_CONNECTION_REQUIRED` quando um conector obrigatório não tinha uma
conexão utilizável; essa recusa foi removida (`require_connectors` é inerte — veja
[`p.sessions`](#psessions--and-the-session-handle)). A verificação passou para a
chamada: um `connector_not_connected` negado inclui `connect_url`, um link de
autorização hospedado, sempre que for possível gerar um para o chamador — toda a
solução exige um clique, disponibilizado pelo botão de conexão da transcrição.

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

#### `p.policies` — políticas do projeto

| método | função |
| --- | --- |
| `list()` · `set(policies)` | políticas do projeto · substituir o conjunto |

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

#### `p.triggers` — automações de cron, webhook, monitoramento e eventos

Um gatilho inicia uma ação do agente em um agendamento, um webhook recebido, um comando monitorado ou um evento de app em um conector. Veja
[Gatilhos](/docs/pt/connect/triggers) para a estratégia de sessão e a criação de templates de
payload.

| método | função |
| --- | --- |
| `list()` | todos os gatilhos |
| `eventTypes({ connector })` | eventos de app que podem acionar um conector (`{ provider, app, event_types }`); 404 para um conector desconhecido, 409 `event_source_unavailable` quando seu provedor não tem uma fonte de eventos |
| `create(input)` | criar um |
| `update(triggerId, input)` | editar um gatilho |
| `remove(triggerId)` | excluir um gatilho |
| `fire(triggerId)` | executá-lo agora |
| `setActivation(paused)` | pausar ou retomar todos os gatilhos do projeto |

`create(input)` recebe `{ 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` são obrigatórios.
`cron`/`run_at` são mutuamente exclusivos (`type: 'cron'`); `secret_env` (o
segredo HMAC do webhook) se aplica a `type: 'webhook'`.

Um gatilho `event` precisa de `connector` (um slug de conector) e `event` (um ID de tipo
de `eventTypes`). `event_account` é opcional: o rótulo de uma conta compartilhada
desse conector; `null` ou sua omissão usa a conta compartilhada padrão do conector.
`event_source` é opcional: o ID do adaptador de fonte de eventos, como `composio`. `null` ou sua omissão usa o
provedor do conector. O ID de tipo pertence a esse adaptador. `event_config` tem a estrutura definida pelo `config_schema` desse tipo.
`eventTypes` e `eventApps` informam o adaptador como `source`; `provider` é um alias obsoleto.
Cada gatilho listado inclui `event: { connector, account, connected_as, type, config, source, provider, app,
status: 'active' | 'needs_connection' | 'error' | 'pending', error,
last_event_at } | null`. Os templates de prompt leem o evento como
`{{ event.data.<field> }}` mais `event.id`, `event.type`, `event.app`,
`event.connector` e `event.occurred_at`.

`session_access` controla quem pode abrir as sessões criadas pelo gatilho. É
`{ mode: 'private' | 'members' | 'project', memberIds: string[], groupIds:
string[] }` and defaults to `private`. Essa política é um estado de execução
local da conta. Ela não entra no manifesto portátil `beeuni.yaml`. Atualizar apenas
`session_access` não cria um commit Git. Uma sessão fixada mantém suas próprias configurações de
compartilhamento. Um gerente de projeto sempre pode abrir sessões criadas por gatilhos, incluindo
sessões que usam `private` ou acesso para membros selecionados.

`session_access` é uma configuração de visibilidade por recurso sobre o modelo de papéis,
não um papel. Ela decide quem pode abrir as sessões de um gatilho. Não concede nenhuma
permissão negada pela decisão do papel. Veja
[Contas e acesso](/docs/pt/accounts#per-feature-access-settings).

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

#### `p.marketplace` / `p.registry` — itens instalados

Instala os arquivos de um item do catálogo na branch padrão do projeto.
`registry.*` é um alias idêntico de `marketplace.*`.

| método | função |
| --- | --- |
| `marketplace.list()` · `marketplace.install(id)` | itens instalados · instalar um item do catálogo |
| `marketplace.updates()` · `marketplace.update(name)` · `marketplace.updateAll()` | atualizações disponíveis · atualizar um · atualizar todos |
| `marketplace.remove(name)` | desinstalar um item |

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

#### `p.files` — arquivos do repositório (leitura)

Acesso somente leitura à árvore Git do projeto. Para ler e gravar arquivos em uma
sessão em execução, use as operações de arquivo da sessão — veja
[Arquivos](#files) em Módulos abaixo.

| método | função |
| --- | --- |
| `listDirectory({ ref?, path? })` | um nível de pasta: `{ entries: [{ path, type, size? }], truncated }`. Use para construir uma árvore; cada pasta está completa até 5.000 entradas. |
| `list(options?)` · `read(path, ref?)` | todos os arquivos em um caminho, recursivamente, limitado a 1.000 (a resposta inclui `X-Beeuni-Truncated: 1` quando limitada) · o conteúdo de um arquivo em uma ref Git |
| `search(query, { content?, ref?, limit? })` | pesquisar nomes de arquivos em todo o repositório, ou conteúdo com `content: true` |
| `archive(options?)` · `history(path)` | baixar um tarball · o histórico Git de um arquivo |

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

#### `p.git` — histórico

| método | função |
| --- | --- |
| `commits()` | o log de commits |
| `commit(sha)` · `commitDiff(sha)` | um commit · seu diff |
| `branches()` · `versionDiff(from, to)` | branches · diff entre duas refs |

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

#### `p.changeRequests` — ciclo de vida e merge

Uma solicitação de alteração (CR) é a forma de integrar o trabalho de uma sessão à branch padrão.

| método | função |
| --- | --- |
| `list()` · `get(crId)` | CRs abertas · uma CR |
| `diff(crId)` · `mergePreview(crId)` | seu diff · visualizar o resultado do merge |
| `open(input)` · `merge(crId, input?)` | abrir · fazer merge de uma CR |
| `close(crId, input?)` · `reopen(crId, input?)` | fechar sem fazer merge · reabrir uma fechada |
| `requestChanges(crId, input)` | registrar feedback, opcionalmente enviado de volta à sessão de origem |

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

#### `p.sessions` — e o handle da sessão

| método | descrição |
| --- | --- |
| `list()` | as sessões do projeto |
| `create(input?)` | criar uma sessão |
| `session(sid)` | o identificador da sessão (igual a `beeuni.session(id, sid)`) |

O identificador da sessão é o coração do runtime — consulte
[Sessões](/docs/pt/sdk/sessions).

`create(input)` aceita `connector_bindings` identificados pelo slug da conexão do conector.
Cada valor nomeia um `connection_id`. Ele também aceita `secrets` para
restringir segredos originados no backend. `require_connectors` está obsoleto e
inativo: o campo ainda é aceito (um cliente antigo nunca é rejeitado por
enviá-lo), mas nada o lê — uma sessão nunca é recusada no momento da criação
por um conector sem uma conta utilizável. Consulte [Contas e o bloqueio no momento da chamada](#accounts-and-the-call-time-gate).

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

#### `p.approvals` — caixa de entrada de aprovações de conectores

Ações pendentes protegidas por conectores aguardando uma decisão — dá suporte à
UX de aprovação de permissões (`APPROVE` / `ASK` / `BLOCK`).

| método | descrição |
| --- | --- |
| `list(options?)` · `sessionsNeedingInput(options?)` | aprovações pendentes · sessões bloqueadas aguardando uma decisão |
| `resolve(executionId, decision, scope?)` | aprovar ou negar uma — `decision: 'approve' \| 'deny'`, `scope: 'once' \| 'session' \| 'session_all'` |

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

#### `p.gateway` — observabilidade de LLM

Logs de solicitações, agregações de custo/latência, orçamentos e chaves de API
do gateway para o tráfego de modelos deste projeto.

| método | descrição |
| --- | --- |
| `logs(opts?)` · `log(logId)` | entradas do log de solicitações · uma entrada do log |
| `overview(days?)` · `series(days?)` · `breakdown(days?)` · `sessions(days?)` · `errors(days?)` | agregações, custo por sessão e erros em um intervalo |
| `budgets()` · `setBudget(input)` · `deleteBudget(budgetId)` | ler · criar/editar · remover um orçamento |
| `keys()` · `createKey(name)` · `revokeKey(keyId)` | listar · gerar · revogar uma chave de API do gateway |
| `playground(prompt, models)` | executar um prompt em até 6 modelos |
| `routing.get()` · `routing.set(policy)` · `routing.reset()` | ler · substituir · herdar a política de roteamento |
| `routing.preview(input)` | resolver uma rota sem invocar um modelo |

Uma política de roteamento contém um modelo padrão, um modelo de visão e uma
cadeia ordenada de fallback; cada modelo é tentado no máximo uma vez; `fallbackOn` é
`transient` ou `any-error`.

O gateway passa para o próximo modelo de fallback somente quando o modelo atual
falha antes de retornar qualquer saída:

- `transient`: um erro de rede, um timeout, qualquer `5xx` ou `402`, `403`, `429`.
- `any-error`: toda falha, incluindo um `400`.

Uma falha após o início da saída permanece com esse modelo. Uma solicitação com
sua própria chave de provedor (BYOK) nunca faz fallback para um modelo faturado
pela Beeuni. Cada modelo de fallback recebe seus próprios padrões de geração.

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

#### `p.channels` — Slack / e-mail / voz

Superfícies de conectores que permitem que um agente atue como um app do Slack,
um endereço de e-mail ou participe de uma chamada de voz em tempo real.

| método | descrição |
| --- | --- |
| `slack.installation()` · `slack.mode()` · `slack.manifest()` | instalação atual · modo · manifesto do app |
| `slack.connect(input)` · `slack.disconnect()` | conectar · desconectar |
| `slack.getFile(url)` · `slack.uploadFile(input)` | baixar · enviar um arquivo por meio do proxy do servidor |
| `email.installation(connectorSlug?)` · `email.mode()` | instalação atual · modo |
| `email.connect(input)` · `email.disconnect(...)` · `email.updatePolicy(input)` | conectar · desconectar · atualizar a política de envio/resposta |
| `voice.setBotName(name)` | renomear o bot em uma chamada em andamento |

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

#### `p.modelDefaults` — preferências do modelo padrão

Padrões de modelo no escopo da conta, do agente e do projeto, resolvidos pelo
gateway.

| método | descrição |
| --- | --- |
| `get()` · `set(input)` · `clear(params)` | ler · definir um padrão · limpar uma substituição |

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

#### `p.setDefaultAgent` — agente padrão do projeto

`p.setDefaultAgent(agentName)` verifica se o agente foi declarado e está habilitado,
então o define como `default_agent` no `beeuni.yaml` do projeto. Novas sessões
preferem esse agente, a menos que o usuário escolha outro.

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

#### `p.updateFeatureFlag` — flags de recurso

`p.updateFeatureFlag(feature, enabled)` ativa ou desativa uma flag de recurso para o
projeto. Passe `enabled: null` para limpar a substituição e voltar ao
padrão da plataforma. Ele chama o `PATCH /v1/projects/:id/features` canônico.

`feature` é um de `FEATURE_FLAG_KEYS` (exportado de `@beeuni/sdk`, tipado como
`FeatureFlagKey`). O chamador precisa da permissão `project.settings.write` do projeto;
a rota responde `403` caso contrário.

Toda rota protegida por flag rejeita da mesma forma enquanto a flag estiver desativada: HTTP `403`
com `{ error, code: "feature_disabled", feature }`. Use `isFeatureDisabledError(error)`
para testar essa condição e `featureDisabledKey(error)` para ler a chave da flag — nunca
compare o texto da mensagem.

`p.updateExperimentalFeature(feature, enabled)` é o alias **obsoleto**. Ele
continua chamando o alias de rota obsoleto `PATCH /v1/projects/:id/experimental`
para que consumidores fixados em uma API implantada mais antiga continuem funcionando. Use
`p.updateFeatureFlag` em código novo.

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

#### `p.sandbox` — templates e builds de snapshot

Configuração de build do sandbox além de `sandboxHealth`/`sandboxTemplates` no identificador
do projeto: templates de Dockerfile/imagem/pool aquecido e seus builds de snapshot.

| método | descrição |
| --- | --- |
| `list()` · `snapshots()` | sandboxes deste projeto · snapshots compilados |
| `rebuildSnapshot(slug?)` · `fixWithAgent()` | reconstruir um snapshot · pedir a um agente para corrigir um build com falha |
| `createTemplate(input)` · `updateTemplate(...)` · `removeTemplate(...)` · `buildTemplate(...)` | adicionar · editar · excluir · compilar um template |
| `setProvider(provider)` | solicitar uma troca de provedor. `null` (ou o padrão da plataforma / o provedor já ativo) é aplicado imediatamente; trocar para um provedor habilitado diferente inicia uma transição durável de preparação→verificação→ativação — o provedor atual continua atendendo enquanto a imagem aquecida do destino é compilada e verificada, e então ativada. O retorno é uma união marcada: `kind:'project'` (imediato) ou `kind:'preparation'` (consultar `getProjectSandboxProviderTransition()` até `activated`/`failed`) |

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

### Ganchos de administração da plataforma (`@beeuni/sdk/react`)

Esses ganchos atendem ao console de administração. A API só responde a eles
para um administrador da plataforma. Cada mutação invalida as consultas de
`['admin', 'accounts']`.

| Hook | O que faz |
| --- | --- |
| `useAdminRole(userId, options?)` | ler a função do chamador de `GET /user-roles` → `{ isAdmin, role }`. `userId` identifica o cache. A ausência de `userId` desativa a consulta. Faz nova busca na montagem e ao receber foco, portanto uma função revogada deixa de controlar o acesso em uma navegação. |
| `useAdminGrantCredits()` | mutação `{ accountId, amount, description, isExpiring }`: adicionar crédito à carteira. `POST /admin/api/accounts/:id/credits`. Move dinheiro: confirme primeiro na UI. |
| `useAdminDebitCredits()` | mutação `{ accountId, amount, description }`: remover crédito da carteira. `POST /admin/api/accounts/:id/credits/debit`. Move dinheiro: confirme primeiro na UI. |
| `useAdminSetTier()` | mutação `{ accountId, tier }`: definir o nível do plano. |
| `useAdminGrantTrial()` | mutação `{ accountId, tierKey, seats, durationDays, creditGrant?, note? }`: conceder ou substituir um período de avaliação. A conta se comporta como `tierKey` até o fim da janela. `creditGrant` também adiciona crédito à carteira. |
| `useAdminRevokeTrial()` | mutação `{ accountId }`: encerrar agora um período de avaliação ativo. Responde `400` quando não há nenhum ativo. |

### Escape hatch

`beeuni.runtime()` retorna o cliente REST tipado do runtime para o sandbox
ativo.
Em um cliente criado por `createScopedBeeuni` (`@beeuni/sdk/server`), ele **lança uma exceção**
— o runtime global "ativo" é o sandbox da solicitação de outro locatário em um
servidor multi-inquilino, um vazamento entre locatários. Use o
`beeuni.session(pid, sid).runtime` com escopo de sessão (chame `ensureReady()` primeiro), que
resolve o próprio sandbox dessa sessão.

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

## Módulos

Os módulos sem framework por trás da fachada [do cliente](#the-client) e dos
hooks do React. Use-os quando precisar de uma operação sem a fachada, de um
helper puro ou de uma camada de isolamento exclusiva do Node. Cada módulo tem
um nível de estabilidade para que você saiba sobre o que construir.

| Categoria | Significado |
| --- | --- |
| Canônico | Importe da raiz `@beeuni/sdk`. Use isso em todo código novo. |
| Suportado | Um subcaminho dedicado (`@beeuni/sdk/react`, `@beeuni/sdk/server`). De primeira classe, não obsoleto. |
| Alias obsoleto | Um subcaminho antigo que ainda funciona. Reexporta código que a raiz já exporta. Importe da raiz em vez disso. |
| Interno | Fora do semver. Não importe isso no código do host. |

O ponto de entrada raiz é canônico. Todos os nomes abaixo que não dependem de frameworks podem ser importados
diretamente de `@beeuni/sdk`:

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

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

### Módulos canônicos

| Módulo | O que faz |
| --- | --- |
| Arquivos | Operações de arquivos do workspace: listar, ler, pesquisar, gravar |
| Runtime de sessão | Sondagem de integridade e construtores de URLs de prévia/proxy |
| Cliente runtime | O cliente REST tipado do runtime e todo o seu conjunto de tipos |
| Autenticação | `authenticatedFetch` e acessores de token |
| REST de projetos | As funções REST brutas encapsuladas pela fachada |
| Cliente de API | `backendApi`, o cliente HTTP tipado de baixo nível |
| Turnos | Agrupamento de mensagens em turnos, cálculos de custo e status — veja [Turnos](#turns) |
| Transcrições | `formatTranscript`, uma exportação Markdown no lado do cliente |
| Listas do compositor | As listas de agentes e modelos do compositor de sessão: quais oferecer, quais são executados |

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

#### Arquivos

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

Uploads maiores que 64 KiB atravessam o limite do sandbox em blocos verificados. O
callback de progresso é executado após cada bloco chegar ao sistema de arquivos da sessão.

`uploadNativeFile({ uri, name, type? }, targetPath, baseUrl)` envia um
arquivo do dispositivo a partir do React Native em uma única requisição. O runtime transmite os bytes de
`uri`, portanto eles nunca entram no heap do JS. Ele usa a mesma autenticação, prazo e
reexecução de `401` que `files.upload`. Não divide em blocos.

`fetchProjectArchive`, `fetchCostExportCsv` e as chamadas de versão do sandbox enviam
pelo mesmo transporte. Uma falha lança um `ApiError` com `status`.

`files.write(path, blob)` substitui o arquivo em `path` e falha se `path` for uma
pasta. `files.create(path)` cria um arquivo vazio e nunca sobrescreve: quando um
arquivo ou pasta já existe em `path`, lança `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` tem como alvo o sandbox globalmente ativo. Se o host executa mais de uma
sessão ao mesmo tempo, chame `s.files` no identificador da sessão em vez disso. Ele sempre
tem como alvo o sandbox da própria sessão. Veja [Sessões](/docs/pt/sdk/sessions).

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

#### Funções auxiliares do runtime de sessão

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

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

`getSessionHealth` nunca lança uma exceção para um status fora de 2xx. Retorna
`{ status, ok, health, body }` e deixa você decidir o que um status significa. O
mesmo módulo exporta as funções auxiliares de URL que reescrevem a saída `localhost` de um agente
como uma URL de proxy acessível: `detectLocalhostUrls`, `rewriteLocalhostUrl`,
`proxyLocalhostUrl`, `parseLocalhostUrl` e `buildWebProxyUrl`.

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

#### Cliente runtime

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

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

`getClient()` retorna o cliente de compatibilidade tipado do runtime para o sandbox ativo,
com a autenticação já injetada. Prefira `beeuni.session(pid, sid).runtime`, o
mesmo cliente com escopo de uma sessão, ao `getClient()` global quando o
host executar mais de uma sessão.

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

#### Funções auxiliares de autenticação

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

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

O token vem da função `getToken` que você passou para `createBeeuni`.
A maior parte do código do aplicativo não precisa deste módulo — as camadas de arquivos, sessões e fachada
já autenticam por você.

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

#### Cliente de API

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

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

`backendApi` é o cliente HTTP tipado no qual todas as funções REST se baseiam. Use-o
apenas para um endpoint que ainda não tenha um wrapper tipado.

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

#### Listas de agentes e modelos do compositor

Crie os seletores de agentes e modelos de um compositor de sessão com as mesmas regras
usadas pelo aplicativo web Beeuni. Todas as funções são puras: busque as entradas com o
cliente e depois passe-as para as funções.

```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` retorna `explicit: undefined` quando o compositor está em
seu padrão. `model` é a chave a exibir e enviar. O
`id` de cada modelo achatado é a referência armazenada por uma seleção; `modelRefToKey(ref, gatewayEnabled)` converte uma
referência armazenada (uma fixação de sessão, uma vinculação de canal, o `model` de um gatilho) de volta em uma
chave.

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

### Subcaminhos suportados

| Subcaminho | O que faz |
| --- | --- |
| `@beeuni/sdk/react` | Hooks do React — veja [Hooks do React](/docs/pt/sdk/react) |
| `@beeuni/sdk/server` | Configuração com escopo de requisição para backends multitenant |
| `@beeuni/sdk/wire-message-id` | Apenas o relógio de IDs de mensagens do protocolo runtime (um módulo, sem importações). A raiz exporta os mesmos nomes |

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

#### IDs de mensagens do protocolo

O `messageId` de um prompt é sua posição na transcrição. O runtime ordena
mensagens por `msg_` + um relógio de 48 bits (`Date.now() * 0x1000`, 48 bits inferiores) +
14 caracteres base62, e o relógio volta ao início a cada 2^36 ms (cerca de 2,2 anos).
Nunca o codifique manualmente.

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

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

A geração é datada dois minutos atrás e depois elevada um tick acima do ID mais recente
em `after` que esteja no máximo uma hora à frente. Um chamador que mantém a posição mais recente
como relógio em vez de IDs usa `mintWireMessageIdAbove({ nowMs,
newestKnownTime })`, which returns `{ id, time }`. `newestWireIdClock(ids)`
para encontrar esse relógio. Todas as comparações são feitas no anel, portanto IDs dos dois lados de um
retorno ao início mantêm sua ordem real.

O relógio de 48 bits volta ao início a cada ~2,2 anos, então nunca compare dois relógios com `>`
ou `<=`: um ID gerado logo após um retorno ao início é numericamente menor que um gerado
logo antes. Use `wireIdClockDelta(clock, reference)`, a distância com sinal
no anel (positiva quando `clock` está à frente), e `maxWireIdClock(clocks)` para
o mais recente entre vários:

```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>

#### Isolamento no lado do servidor

`createBeeuni` armazena sua configuração, incluindo a função de token, em uma
variável global do processo. Isso funciona para uma aba do navegador, uma CLI ou um
servidor de tenant único. Não é seguro para um servidor Node que processa requisições
simultâneas de usuários diferentes, porque a última chamada de `createBeeuni` prevalece para
todas as requisições em andamento. `@beeuni/sdk/server` resolve isso com isolamento por
requisição:

```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` e `runWithBeeuni` isolam a configuração por requisição com
`AsyncLocalStorage` do Node. Nunca importe `@beeuni/sdk/server` de um bundle de
navegador — ele inclui estaticamente `node:async_hooks`.

O `runtime()` de nível superior de um cliente com escopo lança uma exceção (ele resolveria o
sandbox de outro tenant). Acesse o runtime de uma sessão específica via
`beeuni.session(pid, sid).runtime` após `await s.ensureReady()`.

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

### Aliases obsoletos

Cerca de vinte subcaminhos antigos ainda funcionam: `/files`, `/turns`, `/session`, `/auth`,
`/projects-client`, `/api-client`, `/config`, `/event-stream`,
`/opencode-client`, `/platform-client` e outros. Cada um reexporta código que o
ponto de entrada raiz `@beeuni/sdk` já exporta. Eles continuam funcionando para que nenhum existente
```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>
```
