Riferimento SDK
L'intera superficie API di @beeuni/sdk — metodi client, moduli, turni e distribuzione.
Questa pagina descrive l’intera superficie API di @beeuni/sdk: tutti i metodi del client, i
moduli indipendenti dai framework, gli helper per i turni e le modalità di distribuzione del pacchetto. Usa
SDK per iniziare e Sessioni per approfondire il
ciclo di vita delle sessioni.
Il client
createBeeuni(config) restituisce un client. Ogni metodo è una chiamata tipizzata
all’API della piattaforma. Gli handle project(id) e session(pid, sid) associano gli ID
così non devi mai ripeterli.
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
Account — beeuni.accounts
| metodo | funzione |
|---|---|
list() · get(accountId) |
account di cui fai parte · un account |
create({ name }) · updateName(accountId, name) |
crea · rinomina un account |
branding.get(accountId) · branding.update(accountId, { app_name }) · branding.uploadAsset(accountId, kind, file) · branding.removeAsset(accountId, kind) · branding.reset(accountId) |
branding dell’organizzazione (Enterprise): logo / icona / favicon e nome del prodotto personalizzati; kind è logo · icon · favicon, oppure logo_dark · icon_dark · favicon_dark per la variante con tema scuro |
members(accountId) · invite(accountId, input) |
elenca i membri · invitane uno |
updateMemberRole(accountId, userId, role) · removeMember(accountId, userId) |
assegna il ruolo nell’account · rimuovi un membro |
invites(accountId) |
inviti in sospeso |
cancelInvite(accountId, inviteId) · resendInvite(accountId, inviteId) |
annulla · reinvia un invito in sospeso |
leave(accountId) |
lascia l’account |
accounts.tokens genera chiavi API con ambito account (beeuni_pat_...). Vedi
Autenticazione SDK per il modello completo dei token.
| metodo | funzione |
|---|---|
tokens.list(accountId?, options?) |
elenca le chiavi API — quelle dell’intero account, o solo le tue con { mine: true } |
tokens.create(input) |
generane una — { accountId?, name, expiresAt?, projectId? } |
tokens.revoke(tokenId, accountId?) |
revocane una |
accounts.audit è il registro di ricostruzione aziendale. Combina le richieste
API autenticate con gli eventi semantici di sessioni, connettori, approvazioni e computer.
| metodo | funzione |
|---|---|
audit.log(accountId, filters?) |
elenca gli eventi per progetto, sessione, attore, origine, esito, richiesta, correlazione, risorsa, azione o tempo |
audit.export(accountId, filters?) |
esporta lo stesso flusso di eventi filtrato come CSV o JSONL |
audit.webhooks.list/create/update/remove(...) |
gestisci i webhook SIEM firmati per il flusso centralizzato |
Ogni evento include project_id, session_id, actor_type, source, outcome,
request_id, trace_id e correlation_id quando l’azione li fornisce.
L’API non memorizza corpi delle richieste, prompt, segreti, credenziali o argomenti
non elaborati dei connettori nell’evento centralizzato. Gli eventi dei connettori possono includere
un’anteprima limitata degli argomenti che oscura i campi riconducibili a credenziali e i dati opachi.
Assegnazioni di accesso
Beeuni ha un unico tipo di record di concessione: un’assegnazione. Associa un principal (user,
group, service_account o pending) a un ruolo, in un ambito (account
o un project), eventualmente limitato a un oggetto (agent, skill, secret,
app o trigger) ed eventualmente contenente un expires_at. L’accesso di gruppo,
l’accesso per risorsa e le associazioni a ruoli personalizzati sono tutte assegnazioni. Vedi
Account e accesso per il modello.
La superficie REST canonica è:
| Metodo + percorso | Funzione |
|---|---|
GET /v1/accounts/{accountId}/iam/assignments |
elenca le assegnazioni, filtrate per principal, ambito, oggetto o ruolo |
POST /v1/accounts/{accountId}/iam/assignments |
crea un’assegnazione |
DELETE /v1/accounts/{accountId}/iam/assignments/{assignmentId} |
revoca un’assegnazione |
GET /v1/accounts/{accountId}/iam/permissions |
il catalogo delle autorizzazioni, come dati |
GET /v1/accounts/{accountId}/iam/roles · …/roles/{roleId}/permissions |
ruoli · autorizzazioni di un ruolo |
L’SDK le espone come listAssignments, createAssignment,
revokeAssignment e listPermissions. Una riga del catalogo contiene action,
scope_type, resource_type, delegable, description, area, level e
implies — leggila invece di codificare le stringhe delle azioni direttamente nel codice.
L’assegnazione di un ruolo personalizzato richiede l’abilitazione rbac dell’account; in sua assenza, la route risponde
402 con code: "entitlement_required".
Inviti all’account — beeuni.accountInvites
Accessibili con il solo token di invito — la persona invitata potrebbe non essere ancora un membro.
| metodo | funzione |
|---|---|
listMine() |
tutti gli inviti in sospeso e non scaduti indirizzati alla tua email, con il workspace e gli eventuali progetti a cui danno accesso |
describe(inviteId) · accept(inviteId) · decline(inviteId) |
visualizza l’anteprima · accetta · rifiuta un invito |
Progetti — beeuni.projects
| metodo | funzione |
|---|---|
list() · listForAccount(accountId) |
i tuoi progetti · progetti in un account |
get(id) · detail(id) |
riepilogo · dettagli completi |
create(input) · createRepo(input) |
da un repo_url esistente · nuovo repository GitHub vuoto |
provision(input) |
nuovo progetto su un nuovo repository gestito da Beeuni, inizializzato con un template di partenza — { name, account_id?, seed_starter?, starter_template?, marketplace_items?, source_item_id?, idempotency_key? } |
update(id, input) · archive(id) |
aggiorna le impostazioni · archivia |
llmCatalog(id) · modelPicker(id) |
catalogo dei modelli completo · compatto per un selettore |
sandboxTemplates(id) · sandboxHealth(id) |
template di build della sandbox · stato della build |
sessions(id) · createSession(id, input?) |
elenca le sessioni visibili · crea una sessione |
provision crea un nuovo progetto; non avvia la sandbox di un progetto
esistente. Avvia invece una sessione — vedi Sessioni.
Invia idempotency_key quando è possibile un nuovo tentativo — un ricaricamento, una seconda scheda, un
timeout dopo il quale hai riprovato. provision genera un repository gestito completamente nuovo a ogni chiamata, quindi
senza una chiave tutti questi casi creano progetti duplicati reali. Riutilizza una chiave per ogni
tentativo di un’unica creazione logica e le ripetizioni restituiscono il progetto creato dal primo
tentativo (201, stessi project_id, push_token: null). La chiave identifica il
tentativo, non il payload — riutilizzarla con un name diverso restituisce il primo
progetto e ignora il nuovo valore, quindi genera una nuova chiave per ogni creazione distinta.
Creare un secondo progetto con lo stesso nome e senza chiave funziona comunque.
Una ripetizione che arriva mentre la prima chiamata sta ancora effettuando il provisioning riceve 409 con
code: 'provision_in_flight' anziché un project_id che quella chiamata potrebbe ancora
annullare. Riprova con la stessa chiave.
project(id).sessions.list({ scope: 'project' }) è un inventario del ciclo di vita per un
chiamante con autorizzazioni di gestione del progetto. Aggiunge le sessioni accessibili non disponibili, warm e con eliminazione logica, con
metadati sulla proprietà e sullo stato di esecuzione. Entrambi gli ambiti di elenco escludono tutte le sessioni che il
chiamante non può aprire.
sessions.list e sessions.listPage accettano anche i filtri di gerarchia e attribuzione.
Senza di essi, l’elenco rimane piatto e invariato.
| opzione | funzione |
|---|---|
parent: 'root' |
Solo sessioni di primo livello. Ogni riga contiene child_count. |
parent: '<sessionId>' |
Le sessioni figlie di quella sessione, dalla più recente. |
startedBy: 'me' | 'others' | 'automated' |
Filtra per initiator, rispetto al chiamante. |
q |
Ricerca senza distinzione tra maiuscole e minuscole su titolo, etichetta di avvio, slug del trigger e prefisso dell’ID di sessione, in tutte le sessioni che il chiamante può aprire. Con parent: 'root', una sessione radice che corrisponde tramite una figlia ha search_match: 'child'. |
Ogni riga di sessione ha parent_session_id e initiator
({ type: 'member' | 'trigger' | 'channel' | 'api' | 'system', id, label }).
initiator indica chi ha avviato l’intera esecuzione; una sessione figlia copia quello della sessione padre.
sessionParentId(session) legge parent_session_id, poi il precedente
metadata.spawned_by_session. Un cursore è valido solo per l’insieme di filtri che
lo ha generato.
GitHub — beeuni.github
Installazione della GitHub App e collegamento dei repository con ambito account, non con ambito progetto.
| metodo | funzione |
|---|---|
getInstallation(accountId) · listInstallations(accountId) |
installazione di questo account · installazioni accessibili all’utente |
saveInstallation(input) · deleteInstallation(accountId, installationId?) |
registra · scollega un’installazione |
listLinkableInstallations(input) |
installazioni che l’utente GitHub autorizzato può collegare; ogni voce contiene linked_to_other_accounts, il numero di altri account Beeuni che la possiedono — mai i loro nomi |
listRepositories(accountId, installationId?) · listRepositoryBranches(...) |
repository visibili all’installazione · branch e branch predefinito di GitHub |
linkRepository(input) |
Importa un repository come progetto usando un’installazione GitHub autorizzata. |
replaceProjectRepository({ project_id, repo_url, expected_repo_url, github_token }) |
sostituisce il repository GitHub di un progetto esistente. Usa github_token con accesso Contents in lettura/scrittura, oppure installation_id più github_user_token temporaneo per verificare l’accesso come amministratore dell’organizzazione e concedere l’accesso solo a questo repository tramite la GitHub App. copy_shared_secrets_from_project_id più copy_shared_secret_identifiers copia i segreti runtime condivisi selezionati nella stessa transazione. Un expected_repo_url obsoleto restituisce 409. Il vecchio repository rimane su GitHub. Le nuove sessioni usano il repository sostitutivo; quelle esistenti mantengono il proprio checkout. |
Questo elenco contiene solo connessioni reali degli account. “Beeuni managed” non è una di queste — è il backend dell’istanza descritto di seguito.
Backend git dell’istanza — beeuni.gitBackend
Un unico proprietario con credenziale per l’intero deployment, usato per i repository
gestiti da Beeuni. Non è mai una connessione di account e non compare mai in
beeuni.github.listInstallations.
| metodo | funzione |
|---|---|
get() |
{ configured, kind: 'app' | 'pat' | null, owner } — leggibile da qualsiasi utente autenticato; espone solo il login del proprietario già presente in ogni repo_url gestito |
Fatturazione — beeuni.billing
Legge crediti, abbonamento, piano e cronologia delle transazioni. Usa il pagamento e la gestione della fatturazione Beeuni per i pagamenti e gli acquisti di crediti.
| metodo | funzione |
|---|---|
accountState(accountId?) · accountStateMinimal(accountId?) |
stato di fatturazione completo · minimo |
transactions(params?) · transactionsSummary(params?) |
cronologia · totali riepilogativi |
creditBreakdown(accountId?) · usageHistory(params?) |
saldo crediti per fonte · utilizzo nel tempo |
sessionCosts.list(options?) · sessionCosts.get(sessionId, options?) |
record paginati dei costi delle sessioni · registro dettagliato di una sessione |
tierConfigurations() |
livelli di piano disponibili |
checkout.createSession(input) · checkout.confirmSession(sessionId, accountId?) |
Deprecati. Rifiutano con ENDPOINT_RETIRED. Rimossi nella prossima versione principale. |
subscription.createPortalSession(...) · subscription.cancel(...) · subscription.reactivate(...) |
apre il portale clienti · annulla · riattiva |
subscription.cancelScheduledChange(...) · prorationPreview(...) |
annulla · mostra un’anteprima del cambio di piano |
subscription.scheduleDowngrade(...) |
Deprecato. Rifiuta con ENDPOINT_RETIRED. Cambia il piano nel portale clienti. Rimosso nella prossima versione principale. |
credits.purchase(input) · credits.autoTopupSettings(...) · credits.configureAutoTopup(...) |
acquisto una tantum · legge · configura la ricarica automatica |
sessionCosts.list() accetta accountId, projectId, limit e offset.
Ogni riga combina il costo LLM definitivo e il costo di calcolo della sandbox fatturato.
sessionCosts.get() aggiunge l’utilizzo dei modelli e il registro con distinzione tra LLM e calcolo.
L’elenco include un totale di riconciliazione per i costi senza sessione.
Condivisioni della sandbox — beeuni.sandboxShares
Link di condivisione pubblici per una porta esposta della sandbox. Limitati alla sandbox, non al progetto.
| metodo | funzione |
|---|---|
list(sandboxId) |
link di condivisione attivi |
create(input) |
ne crea uno — { sandboxId, port, ttl?, label? } |
revoke(sandboxId, token) |
ne revoca uno |
Catalogo del marketplace — beeuni.marketplace
Consultazione del catalogo pubblico, in sola lettura — distinta da project(id).marketplace,
che installa un elemento in un progetto.
| metodo | funzione |
|---|---|
items(options?) · item(id) · itemFile(id, path) |
consulta · un elemento · un file all’interno di un elemento |
marketplaces() · featured() |
tutti i marketplace · quelli in evidenza |
sources.list() · sources.add(input) · sources.remove(id) |
elenca · aggiunge · rimuove una fonte |
Notifiche — beeuni.notifications
Le notifiche del chiamante, per tutti gli account e i progetti. Ogni persona che ha effettuato
l’accesso ha una casella di posta, un record di preferenze e sottoscrizioni Web Push per
i propri browser. Ogni metodo richiede la credenziale di una persona: un account di servizio
riceve 403.
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 } } });
| metodo | funzione |
|---|---|
list({ limit?, before? }, { signal? }) |
la pagina più recente: { notifications, unread_count, next_before }. limit va da 1 a 50 (valore predefinito 20). Passa next_before come before per la pagina successiva. Le righe non più visibili al chiamante vengono escluse. Un errore non richiama il gestore degli errori dell’host. |
markRead({ ids }) · markRead({ all: true }) · markRead({ sessionId }) |
segna come lette da 1 a 100 righe, tutte le righe o tutte le righe di una sessione. Modifica solo le righe del chiamante. Restituisce { updated, unread_count }. |
preferences() · updatePreferences({ kinds }) |
legge · modifica la scelta di push ed email per tipo. Restituisce { kinds, email_available }. Una patch modifica solo i tipi e i canali che specifica. |
webPushPublicKey() |
{ public_key }: il applicationServerKey per pushManager.subscribe |
registerWebPushSubscription({ endpoint, keys }) |
invia notifiche push a questo browser. Richiede l’accesso da browser: un token personale riceve 403. Un endpoint su un servizio push sconosciuto riceve 400. |
unregisterWebPushSubscription(endpoint, { signal? }) |
interrompe le notifiche push a questo browser. Restituisce { deleted }. |
registerDeviceToken(input) · unregisterDeviceToken(token, { signal? }) |
registra · rimuove il token push Expo di un’app nativa |
Tipi (InboxNotificationKind, elencati in INBOX_NOTIFICATION_KINDS):
| tipo | inviata quando | push | email (predefinito) |
|---|---|---|---|
turn_done |
un turno che hai avviato con un prompt o che segui è terminato | attivo | disattivata |
turn_error |
quel turno è terminato con un errore | attivo | attiva, in un riepilogo |
question |
l’agente pone una domanda | attivo | attiva, in un riepilogo |
permission |
l’agente chiede un’autorizzazione | attivo | disattivata |
shared |
qualcuno ha condiviso una sessione con te | attivo | attiva, in un riepilogo |
automation_failed |
un’automazione che segui ha iniziato a fallire | attivo | attiva, immediata |
automation_recovered |
quell’automazione funziona di nuovo | attivo | disattivata |
DEFAULT_NOTIFICATION_PREFERENCES contiene questi valori predefiniti. La riga nella casella di posta viene
sempre scritta; le preferenze determinano solo push ed email. Un’email di riepilogo
elenca le righe ancora non lette 15 minuti dopo il loro arrivo, con al massimo un riepilogo
all’ora. Nascondi la colonna email quando email_available è false.
Il url di ogni riga ne apre l’oggetto. Il suo parametro di query ?notification=<id> consente alla
pagina di segnare la riga come letta.
L’handle della sessione contiene lo stato con cui il chiamante segue una sessione:
| metodo | funzione |
|---|---|
session(pid, sid).watch() |
{ watching }: indica se il chiamante riceve notifiche su questa sessione |
session(pid, sid).setWatch(watching) |
false silenzia la sessione per il chiamante, true torna a seguirla. Inviare un prompt a una sessione fa sì che venga seguita, ma non annulla mai il silenziamento. |
session(pid, sid).presence({ tab_id, active, alerts? }, { keepalive? }) |
lease di presenza di questa scheda. alerts: true indica che la scheda mostra le proprie notifiche: con notification_center attivo, il server omette le notifiche al telefono e Web Push solo mentre è in uso una scheda che mostra avvisi. Se è disattivato, alerts viene ignorato e qualsiasi scheda presente blocca le notifiche push al telefono. keepalive consente alla richiesta di proseguire dopo la chiusura di una pagina. Valore predefinito: attivo per una segnalazione di assenza, disattivato per una di presenza. useSession invia keepalive solo con presencePageExit. |
L’handle del progetto — beeuni.project(id)
Associa l’ID del progetto; tutte le sottorisorse dipendono da esso.
const p = beeuni.project(projectId);
await p.detail();
await p.update({ name });
await p.llmCatalog();
| metodo | funzione |
|---|---|
get · detail · update · archive |
lettura · dettagli completi · aggiornamento · archiviazione |
llmCatalog · modelPicker · sandboxHealth |
lettura di modelli e build della sandbox |
onboardingComplete |
contrassegna l’onboarding del progetto come completato |
validateManifest(raw) |
convalida lato server un manifest beeuni.yaml (o il precedente beeuni.toml) |
gitToken() |
genera un nuovo token git push con ambito limitato (409 per un repository proprio) |
setAgentScope(agentName, scope) |
imposta nel manifest i segreti e i connettori consentiti a un agente — la seconda associazione, non un ruolo |
p.tokens — chiavi API con ambito di progetto
Generate automaticamente alla creazione della sessione come BEEUNI_TOKEN; possono anche essere generate manualmente.
| metodo | funzione |
|---|---|
list() |
chiavi API del progetto |
create(input?) |
genera una nuova chiave |
revoke(tokenId) |
revoca una chiave |
p.setupLinks — link di configurazione generati dall’agente
Un link che una persona apre per inserire un segreto o collegare un’app, senza accesso completo al progetto.
| metodo | funzione |
|---|---|
requestSecret(input) · requestConnector(input) |
link per raccogliere un segreto · collegare un’app |
p.apps — Apps (release, macchine, volumi)
Richiede la funzionalità di progetto apps. Guida: SDK → Apps.
| metodo | funzione |
|---|---|
list() · get(appId) · create(input) · update(appId, input) · remove(appId) |
inventario e ciclo di vita; create accetta uses, update accetta anche labels |
deployments.* · artifacts.* · access.* · rollback · start · stop |
distribuzioni, artefatti, policy di accesso, traffico e runtime |
machines.list/start/stop/restart/destroy · scale(appId, count) · exec(appId, input) |
macchine per gruppo di processi; exec richiede project.app.admin |
volumes.list/create/update/destroy/snapshots/snapshot/restore/fork |
volumi persistenti, snapshot giornalieri, ripristino, fork |
token(appId) |
un token di accesso valido per 15 minuti; 409 app_capability_unsupported senza member_tokens |
p.secrets — segreti del progetto
| metodo | funzione |
|---|---|
list() · upsert(input) |
elenca i metadati · crea o aggiorna un valore di sola scrittura e la policy di distribuzione |
setStrategy(identifier, strategy, options?) |
modifica l’esposizione e il relativo elenco di host |
broker(identifier, request) |
esegue una richiesta HTTPS autorizzata dalla sessione e vincolata alla policy |
remove(identifier) |
elimina un segreto |
setPersonal(name, value) · removePersonal(name) |
imposta · rimuove una sostituzione per utente |
setGitCredential(input) |
imposta una credenziale di autenticazione git |
runtime con consumer sandbox è l’esposizione environment — quella predefinita,
e l’unica policy che inserisce un valore in chiaro nella sessione. egress con
consumer network è l’esposizione egress-enforced: la sessione contiene un handle
e Beeuni sostituisce il valore reale fuori dalla sandbox, per gli esatti host HTTPS
elencati dalla policy. L’esposizione egress-enforced è sperimentale; richiede il
flag di funzionalità secrets_egress (Settings → Feature flags). Con il flag disattivato,
setStrategy(identifier, 'egress', …) e upsert(...) con una policy egress
restituiscono 403 feature_disabled. Nessun consumer broker è presente
nella sessione. Vedi
Segreti. Il metodo broker(...) richiede un
token con ambito di sessione e un handle di sessione attivo.
p.access — assegnazioni, inviti e richieste del progetto
Ogni metodo qui legge o scrive un’assegnazione con ambito limitato a questo progetto. I ruoli
del progetto sono manager e member.
| metodo | funzione |
|---|---|
list() · invite(email, role) |
soggetti con accesso · invita un utente |
update(userId, role) · revoke(userId) |
assegna un ruolo nel progetto · revoca l’assegnazione |
pendingInvites() · requests() |
inviti in sospeso · richieste di accesso in attesa |
resendInvite(inviteId) · revokeInvite(inviteId) · approveRequest(id) · rejectRequest(id) |
reinvia/revoca un invito · approva/rifiuta una richiesta |
groupGrants() · attachGroupGrant(...) · updateGroupGrant(...) · detachGroupGrant(...) |
le stesse assegnazioni, con un soggetto group |
p.access.resourceGrants è la vista assegnazione di oggetti: limita un
soggetto a un solo oggetto nel progetto anziché all’intero progetto. Beeuni
applica attualmente le assegnazioni di oggetti ad agenti e skill. Un agente è chiuso per
impostazione predefinita — un membro vi accede solo quando un’assegnazione indica lui o uno dei suoi
gruppi. Un’assegnazione di oggetti non conferisce autorizzazioni proprie e limita un
responsabile di progetto tanto quanto un membro.
| metodo | funzione |
|---|---|
resourceGrants.list() |
assegnazioni di oggetti in questo progetto |
resourceGrants.create(input) |
assegna un oggetto a un utente o a un gruppo |
resourceGrants.remove(grantId) |
revoca un’assegnazione di oggetti |
p.connector(slug) — un connettore
| metodo | funzione |
|---|---|
run(action, args, options?) |
l’output dell’azione; genera ConnectorCallError o ConnectorApprovalPendingError — vedi Errori |
call(action, args, options?) |
il risultato grezzo della chiamata; 202 si risolve con ok: false |
describe() · describe(action) |
il connettore con schemi di input e output · un’azione |
accounts() |
gli account con cui il chiamante può eseguirlo, quello predefinito per primo |
paginate(action, args, { next, maxPages? }) |
iteratore asincrono sull’output di ogni pagina; genera ConnectorPageLimitError con nextArgs quando esistono più di maxPages pagine (valore predefinito 100) — vedi Pagine |
uploadAttachment(content, input) |
p.connectors.uploadAttachment con connector impostato su questo slug |
options: account, approvalContext, timeoutMs (valore predefinito 90 000), signal. Con il file di beeuni connectors types, gli argomenti e l’output sono tipizzati.
p.connectors — connettori di strumenti
| metodo | funzione |
|---|---|
catalog() · tools() |
catalogo Connector invocabile · strumenti <connector>.<action> appiattiti |
search(query, options?) · describe(tool) |
trova · ispeziona uno strumento invocabile |
call(tool, args?, options?) |
chiama uno strumento <connector>.<action> tramite il gateway lato server. options.account indica l’account con cui eseguirlo — vedi sotto. |
accounts(slug) |
gli account con cui il chiamante può chiamare slug, quello predefinito per primo — ciò con cui options.account verifica la corrispondenza |
uploadAttachment(content, input) |
prepara i byte per input.connector; restituisce ref ({ $beeuni_attachment }) da inserire negli argomenti di una chiamata successiva — vedi Allegare file |
list() · config(connectorId) |
connettori configurati · configurazione di un connettore |
create(input) |
aggiunge un connettore |
auth.discover(input) |
mostra un’anteprima dell’autenticazione da una specifica OpenAPI, una raccolta Postman o un endpoint |
remove(connectorId) · sync() |
elimina un connettore · risincronizza i connettori |
setName(connectorId, name) · setSensitive(connectorId, sensitive) |
rinomina · contrassegna come sensibile (ulteriore controllo di approvazione) |
setAuthorizationStrategy(slug, strategy) |
@deprecated. Chiama ancora la route; la route non esegue operazioni, risponde {ok:true, deprecated:true} e non modifica nulla. owner_type su ogni connessione costituisce ora l’intera regola di accesso. |
setCredentialMode(connectorId, mode) · setCredential(connectorId, input) |
cambia origine · imposta il valore della credenziale |
policies.get(connectorId) · policies.set(connectorId, policies) |
legge · sostituisce le relative policy degli strumenti |
connections.list() · connections.reconcile(input) |
elenca · crea/aggiorna gli account collegati |
connections.updateCredential(connectionId, input) |
ruota una credenziale di connessione |
connections.revoke(connectionId) · connections.activate(connectionId) |
nega · ripristina una connessione |
connections.setDefault(connectionId) |
la imposta come predefinita per l’ambito del suo proprietario |
connections.rename(connectionId, label) |
modifica solo l’etichetta; l’account resta autorizzato. Ogni connessione contiene connected_as, l’identità con cui è stata autorizzata. |
p.connectors.discover esplora il catalogo dei connettori diretti. È sperimentale e disattivato per impostazione predefinita — abilitalo per ciascun progetto in Settings → Feature flags → “Connectors API Discover”. Easy Connect resta il marketplace predefinito dei connettori.
| metodo | funzione |
|---|---|
discover.list(query?, cursor?) · discover.detail(id) |
cerca voci OpenAPI/MCP/GraphQL/CLI · dettagli di una voce |
p.connectors.pipedream è il percorso di compatibilità OAuth gestito precedente; listApps
restituisce solo le app OAuth. Usa Easy Connect per le nuove integrazioni gestite. Collega direttamente le app con chiave API.
| metodo | cosa |
|---|---|
pipedream.listApps(params?) · pipedream.connect(input) · pipedream.finalize(input) |
esplora il catalogo delle app · avvia un flusso di collegamento · finalizzalo |
Un connettore definisce lo strumento, l’app del provider e i criteri. connections
memorizza i suoi account collegati: un connettore può contenerne diversi affiancati.
Una sessione può fissarne uno per ogni chiamata con
connector_bindings: { alias: { connection_id } }, oppure una singola chiamata può specificarne
uno con call(tool, args, { account }). Le credenziali restano crittografate e
vengono risolte per richiesta.
connections è l’unica facciata di autorizzazione attiva. I nomi ritirati
authorizations e profiles non fanno parte della superficie dell’SDK attuale.
Account e controllo al momento della chiamata
Ogni connessione ha un owner_type: project (condiviso — raggiungibile da chiunque
abbia accesso al connettore, persona o account di servizio) oppure member (privato —
raggiungibile solo dal relativo proprietario e solo in una sessione privata; mai da un
account di servizio). Un account condiviso può essere limitato a gruppi e persone:
connections.list() restituisce le autorizzazioni in shared_with e
connectionSharedWithEveryone(connection) indica se tutti gli utenti del
progetto possono usarlo. Un account limitato segue le regole private per le
persone indicate e usable: false contrassegna quello che il chiamante vede solo per
amministrarlo. Concedi o revoca l’accesso con createAssignment / revokeAssignment
(object: { type: 'connection', id }) — vedi
Chi può usare un account condiviso.
p.connectors.accounts(slug) elenca ogni account raggiungibile da questo chiamante,
con quello predefinito per primo:
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`
);
Una chiamata che non specifica alcun account risolve prima l’account privato predefinito
del chiamante, poi l’account condiviso predefinito del progetto. Un account specificato
che non viene risolto è negato con connector_not_connected — non viene mai
sostituito automaticamente — e il rifiuto elenca requested_account e
available_accounts. Ogni chiamata riuscita indica con quale account è stata eseguita:
result.account = { connection_id, label, owner_type }.
Non esiste più un controllo del connettore al momento della creazione della sessione. In precedenza una
sessione veniva rifiutata con 409 CONNECTOR_CONNECTION_REQUIRED quando un connettore richiesto non aveva
una connessione utilizzabile; quel rifiuto è stato rimosso (require_connectors è inattivo — vedi
p.sessions). Il controllo è stato spostato sulla
chiamata: un connector_not_connected negato include connect_url, un link
di autorizzazione ospitato, ogni volta che è possibile generarlo per il chiamante — l’intero
rimedio richiede un solo clic ed è esposto dal pulsante di collegamento della trascrizione.
p.policies — criteri del progetto
| metodo | cosa |
|---|---|
list() · set(policies) |
i criteri del progetto · sostituisci l’insieme |
p.triggers — automazioni cron, webhook, monitor ed eventi
Un trigger avvia un’azione dell’agente in base a una pianificazione, a un webhook in ingresso, a un comando monitorato o a un evento dell’app su un connettore. Vedi Trigger per la strategia della sessione e la modellazione del payload.
| metodo | cosa |
|---|---|
list() |
tutti i trigger |
eventTypes({ connector }) |
gli eventi dell’app che un connettore può attivare ({ provider, app, event_types }); 404 per un connettore sconosciuto, 409 event_source_unavailable quando il relativo provider non ha alcuna sorgente di eventi |
create(input) |
creane uno |
update(triggerId, input) |
modifica un trigger |
remove(triggerId) |
elimina un trigger |
fire(triggerId) |
eseguilo ora |
setActivation(paused) |
metti in pausa o riprendi ogni trigger del progetto |
create(input) accetta { 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 sono obbligatori.
cron/run_at sono mutuamente esclusivi (type: 'cron'); secret_env (il
segreto HMAC del webhook) si applica a type: 'webhook'.
Un trigger event richiede connector (uno slug del connettore) e event (un ID del tipo
da eventTypes). event_account è opzionale: l’etichetta di un account condiviso di
quel connettore; null o l’omissione usa l’account condiviso predefinito del connettore.
event_source è opzionale: l’ID dell’adattatore della sorgente di eventi, ad esempio composio. null o l’omissione usa il
provider del connettore. L’ID del tipo appartiene a quell’adattatore. event_config segue la struttura definita da config_schema del tipo.
eventTypes e eventApps riportano l’adattatore come source; provider è un alias deprecato.
Ogni trigger elencato contiene event: { connector, account, connected_as, type, config, source, provider, app, status: 'active' | 'needs_connection' | 'error' | 'pending', error, last_event_at } | null. I modelli di prompt leggono l’evento come
{{ event.data.<field> }} più event.id, event.type, event.app,
event.connector e event.occurred_at.
session_access controlla chi può aprire le sessioni create dal trigger. È
{ mode: 'private' | 'members' | 'project', memberIds: string[], groupIds: string[] } and defaults to private. Questo criterio è uno stato di runtime locale all’account.
Non entra nel manifest portabile beeuni.yaml. L’aggiornamento del solo
session_access non crea alcun commit Git. Una sessione fissata mantiene le proprie
impostazioni di condivisione. Un responsabile del progetto può sempre aprire le sessioni create dai trigger,
comprese quelle che usano private o l’accesso a membri selezionati.
session_access è un’impostazione di visibilità per risorsa che si aggiunge al modello dei ruoli,
non un ruolo. Decide chi può aprire le sessioni di un trigger. Non concede alcuna
autorizzazione negata dal verdetto del ruolo. Vedi
Account e accesso.
p.marketplace / p.registry — elementi installati
Installa i file di un elemento del catalogo nel branch predefinito del progetto.
registry.* è un alias identico di marketplace.*.
| metodo | cosa |
|---|---|
marketplace.list() · marketplace.install(id) |
elementi installati · installa un elemento del catalogo |
marketplace.updates() · marketplace.update(name) · marketplace.updateAll() |
aggiornamenti disponibili · aggiorna uno · aggiorna tutti |
marketplace.remove(name) |
disinstalla un elemento |
p.files — file del repository (lettura)
Accesso in sola lettura all’albero git del progetto. Per leggere e scrivere file all’interno di una sessione in esecuzione, usa le operazioni sui file della sessione — vedi File nella sezione Moduli.
| metodo | cosa |
|---|---|
listDirectory({ ref?, path? }) |
un livello di cartella: { entries: [{ path, type, size? }], truncated }. Usalo per creare un albero; ogni cartella è completa fino a 5.000 elementi. |
list(options?) · read(path, ref?) |
ogni file sotto un percorso, ricorsivamente, fino a 1.000 (la risposta contiene X-Beeuni-Truncated: 1 quando viene troncata) · il contenuto di un file a un riferimento git |
search(query, { content?, ref?, limit? }) |
cerca i nomi dei file nell’intero repository o i contenuti con content: true |
archive(options?) · history(path) |
scarica un tarball · la cronologia git di un file |
p.git — cronologia
| metodo | cosa |
|---|---|
commits() |
il log dei commit |
commit(sha) · commitDiff(sha) |
un commit · il relativo diff |
branches() · versionDiff(from, to) |
branch · diff tra due riferimenti |
p.changeRequests — ciclo di vita e merge
Una richiesta di modifica (CR) è il modo in cui il lavoro di una sessione viene unito al branch predefinito.
| metodo | cosa |
|---|---|
list() · get(crId) |
CR aperte · una CR |
diff(crId) · mergePreview(crId) |
il relativo diff · visualizza in anteprima il risultato del merge |
open(input) · merge(crId, input?) |
apri · unisci una CR |
close(crId, input?) · reopen(crId, input?) |
chiudi senza eseguire il merge · riapri una CR chiusa |
requestChanges(crId, input) |
registra il feedback, facoltativamente inviato alla sessione di origine |
p.sessions — e l’handle della sessione
| metodo | funzione |
|---|---|
list() |
le sessioni del progetto |
create(input?) |
creare una sessione |
session(sid) |
l’handle della sessione (come beeuni.session(id, sid)) |
L’handle della sessione è il cuore del runtime — vedi Sessioni.
create(input) accetta connector_bindings con lo slug della connessione del connettore come chiave.
Ogni valore identifica un connection_id. Accetta anche secrets per
limitare i segreti provenienti dal backend. require_connectors è deprecato e
inattivo: il campo è ancora accettato (un vecchio client non viene mai rifiutato perché
lo invia), ma nulla lo legge — una sessione non viene mai rifiutata al momento della creazione
per un connettore senza un account utilizzabile. Vedi Account e controllo al momento della
chiamata.
p.approvals — la casella delle approvazioni dei connettori
Azioni soggette al controllo dei connettori in attesa di una decisione — supporta la
UX di approvazione delle autorizzazioni (APPROVE / ASK / BLOCK).
| metodo | funzione |
|---|---|
list(options?) · sessionsNeedingInput(options?) |
approvazioni in sospeso · sessioni bloccate in attesa di una decisione |
resolve(executionId, decision, scope?) |
approvare o negare una richiesta — decision: 'approve' | 'deny', scope: 'once' | 'session' | 'session_all' |
p.gateway — osservabilità degli LLM
Log delle richieste, aggregazioni di costi/latenza, budget e chiavi API del gateway per il traffico verso i modelli di questo progetto.
| metodo | funzione |
|---|---|
logs(opts?) · log(logId) |
voci del log delle richieste · una voce del log |
overview(days?) · series(days?) · breakdown(days?) · sessions(days?) · errors(days?) |
aggregazioni, costo per sessione ed errori in un intervallo |
budgets() · setBudget(input) · deleteBudget(budgetId) |
leggere · creare/modificare · rimuovere un budget |
keys() · createKey(name) · revokeKey(keyId) |
elencare · generare · revocare una chiave API del gateway |
playground(prompt, models) |
eseguire un prompt su un massimo di 6 modelli |
routing.get() · routing.set(policy) · routing.reset() |
leggere · sostituire · ereditare la politica di instradamento |
routing.preview(input) |
risolvere una route senza invocare un modello |
Una politica di instradamento contiene un modello predefinito, un modello per la visione e una catena
ordinata di fallback; ogni modello viene tentato al massimo una volta; fallbackOn è
transient o any-error.
Il gateway passa al modello di fallback successivo solo quando il modello corrente ha fallito prima di restituire qualsiasi output:
transient: un errore di rete, un timeout, qualsiasi5xxoppure402,403,429.any-error: ogni errore, incluso un400.
Un errore dopo l’inizio dell’output resta associato a quel modello. Una richiesta con la propria chiave del provider (BYOK) non passa mai a un modello fatturato da Beeuni. Ogni modello di fallback riceve i propri valori predefiniti di generazione.
p.channels — Slack / email / voce
Interfacce dei connettori che consentono a un agente di agire come app Slack, come indirizzo email o di partecipare a una chiamata vocale in tempo reale.
| metodo | funzione |
|---|---|
slack.installation() · slack.mode() · slack.manifest() |
installazione corrente · modalità · manifest dell’app |
slack.connect(input) · slack.disconnect() |
connettere · disconnettere |
slack.getFile(url) · slack.uploadFile(input) |
scaricare · caricare un file tramite il proxy del server |
email.installation(connectorSlug?) · email.mode() |
installazione corrente · modalità |
email.connect(input) · email.disconnect(...) · email.updatePolicy(input) |
connettere · disconnettere · aggiornare la politica di invio/risposta |
voice.setBotName(name) |
rinominare il bot durante una chiamata in corso |
p.modelDefaults — preferenze del modello predefinito
Valori predefiniti dei modelli a livello di account, agente e progetto, risolti dal gateway.
| metodo | funzione |
|---|---|
get() · set(input) · clear(params) |
leggere · impostare un valore predefinito · cancellare una sovrascrittura |
p.setDefaultAgent — agente predefinito del progetto
p.setDefaultAgent(agentName) verifica che l’agente sia dichiarato e abilitato,
poi lo imposta come default_agent nel beeuni.yaml del progetto. Le nuove sessioni
preferiscono questo agente, a meno che un utente non ne scelga un altro.
p.updateFeatureFlag — flag di funzionalità
p.updateFeatureFlag(feature, enabled) attiva o disattiva un flag di funzionalità per il
progetto. Passa enabled: null per cancellare la sovrascrittura e tornare al
valore predefinito della piattaforma. Chiama il PATCH /v1/projects/:id/features canonico.
feature è uno dei FEATURE_FLAG_KEYS (esportati da @beeuni/sdk, con tipo
FeatureFlagKey). Il chiamante deve avere l’autorizzazione project.settings.write del progetto;
altrimenti la route risponde con 403.
Ogni route controllata da un flag rifiuta le richieste allo stesso modo quando il flag è disattivato: HTTP 403
con { error, code: "feature_disabled", feature }. Usa isFeatureDisabledError(error)
per gestire il caso e featureDisabledKey(error) per leggere la chiave del flag — non
basarti mai sul testo del messaggio.
p.updateExperimentalFeature(feature, enabled) è l’alias deprecato. Continua
a chiamare l’alias deprecato della route PATCH /v1/projects/:id/experimental
così i consumer vincolati a una versione precedente dell’API distribuita continuano a funzionare. Usa
p.updateFeatureFlag nel nuovo codice.
p.sandbox — template e build degli snapshot
Configurazione delle build delle sandbox oltre a sandboxHealth/sandboxTemplates sull’handle
del progetto: template Dockerfile/immagine/warm pool e relative build degli snapshot.
| metodo | funzione |
|---|---|
list() · snapshots() |
sandbox di questo progetto · snapshot compilati |
rebuildSnapshot(slug?) · fixWithAgent() |
ricompilare uno snapshot · chiedere a un agente di correggere una build non funzionante |
createTemplate(input) · updateTemplate(...) · removeTemplate(...) · buildTemplate(...) |
aggiungere · modificare · eliminare · compilare un template |
setProvider(provider) |
richiedere un cambio di provider. null (oppure il valore predefinito della piattaforma / il provider già attivo) si applica immediatamente; il passaggio a un altro provider abilitato avvia una transizione persistente di preparazione→verifica→attivazione — il provider corrente continua a servire le richieste mentre l’immagine pronta all’uso di destinazione viene compilata e verificata, poi attivata. Il valore restituito è un’unione discriminata: kind:'project' (immediata) oppure kind:'preparation' (interrogare periodicamente getProjectSandboxProviderTransition() fino a activated/failed) |
Hook di amministrazione della piattaforma (@beeuni/sdk/react)
Questi hook servono la console di amministrazione. L’API risponde solo agli amministratori
della piattaforma. Ogni mutazione invalida le query ['admin', 'accounts'].
| Hook | Funzione |
|---|---|
useAdminRole(userId, options?) |
leggere il ruolo del chiamante da GET /user-roles → { isAdmin, role }. userId funge da chiave della cache. L’assenza di userId disabilita la query. Recupera nuovamente i dati al montaggio e al focus, così un ruolo revocato cessa di concedere accesso entro una navigazione. |
useAdminGrantCredits() |
mutazione { accountId, amount, description, isExpiring }: aggiungere credito al portafoglio. POST /admin/api/accounts/:id/credits. Sposta denaro: confermare prima nell’UI. |
useAdminDebitCredits() |
mutazione { accountId, amount, description }: rimuovere credito dal portafoglio. POST /admin/api/accounts/:id/credits/debit. Sposta denaro: confermare prima nell’UI. |
useAdminSetTier() |
mutazione { accountId, tier }: impostare il livello del piano. |
useAdminGrantTrial() |
mutazione { accountId, tierKey, seats, durationDays, creditGrant?, note? }: concedere o sostituire un periodo di prova. L’account si comporta come tierKey fino al termine del periodo. creditGrant aggiunge anche credito al portafoglio. |
useAdminRevokeTrial() |
mutazione { accountId }: terminare subito un periodo di prova attivo. Risponde con 400 quando non ce n’è uno attivo. |
Via di uscita
beeuni.runtime() restituisce il client REST runtime tipizzato per la sandbox
attiva.
Su un client creato da createScopedBeeuni (@beeuni/sdk/server), genera un’eccezione
— il runtime “attivo” globale del processo è la sandbox di un’altra richiesta in un
server multi-tenant, una fuga di dati tra tenant. Usa invece
beeuni.session(pid, sid).runtime con ambito di sessione (chiama prima ensureReady()), che
risolve la sandbox della sessione stessa.
Moduli
I moduli indipendenti dal framework alla base della facciata del client e degli hook React. Usali quando ti serve una singola operazione senza la facciata, un helper puro o un livello di isolamento solo per Node. Ogni modulo indica un livello di stabilità, così sai su cosa basarti.
| Livello | Significato |
|---|---|
| Canonico | Importa dalla radice @beeuni/sdk. Usalo per tutto il nuovo codice. |
| Supportato | Un sottopercorso dedicato (@beeuni/sdk/react, @beeuni/sdk/server). Pienamente supportato, non deprecato. |
| Alias deprecato | Un vecchio sottopercorso ancora funzionante. Riesporta codice già esportato dalla radice. Importa invece dalla radice. |
| Interno | Fuori da semver. Non importarlo nel codice host. |
Il punto di ingresso radice è canonico. Ogni nome indipendente dai framework elencato sotto è importabile
direttamente da @beeuni/sdk:
import { files, getSessionHealth, getClient, authenticatedFetch, backendApi } from '@beeuni/sdk';
Moduli canonici
| Modulo | Cosa fa |
|---|---|
| File | Operazioni sui file del workspace: elenco, lettura, ricerca, scrittura |
| Runtime di sessione | Verifica dello stato e generatori di URL di anteprima/proxy |
| Client runtime | Il client REST runtime tipizzato e l’intero insieme dei suoi tipi |
| Autenticazione | authenticatedFetch e funzioni di accesso ai token |
| REST dei progetti | Le funzioni REST di base incapsulate dalla facciata |
| Client API | backendApi, il client HTTP tipizzato di basso livello |
| Turni | Raggruppamento dei messaggi in turni, calcolo dei costi e degli stati — vedi Turni |
| Trascrizioni | formatTranscript, un’esportazione Markdown lato client |
| Elenchi del compositore | Gli elenchi di agenti e modelli del compositore di sessione: quali proporre, quali vengono eseguiti |
File
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}`);
},
});
I caricamenti superiori a 64 KiB attraversano il confine della sandbox in blocchi verificati. La callback di avanzamento viene eseguita dopo che ogni blocco raggiunge il filesystem della sessione.
uploadNativeFile({ uri, name, type? }, targetPath, baseUrl) carica un file del
dispositivo da React Native in un’unica richiesta. Il runtime trasmette i byte in streaming da
uri, quindi non entrano mai nell’heap JS. Usa la stessa autenticazione, scadenza e
ripetizione 401 di files.upload. Non suddivide in blocchi.
fetchProjectArchive, fetchCostExportCsv e le chiamate alla versione della sandbox inviano
tramite lo stesso trasporto. Un errore genera un’eccezione ApiError con status.
files.write(path, blob) sostituisce il file in path e fallisce se path è una
cartella. files.create(path) crea un file vuoto e non sovrascrive mai: quando un
file o una cartella esiste già in path, genera FileExistsError
(status 409, code 'FILE_EXISTS').
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 opera sulla sandbox attiva a livello globale. Se il tuo host esegue più di una
sessione alla volta, chiama invece s.files sull’handle della sessione. Opera sempre
sulla sandbox di quella sessione. Vedi Sessioni.
Funzioni ausiliarie del runtime di sessione
import { getSessionHealth, isRuntimeReady } from '@beeuni/sdk';
const result = await getSessionHealth();
if (result.ok && isRuntimeReady(result.health)) {
// the sandbox daemon is ready
}
getSessionHealth non genera mai eccezioni per uno stato non 2xx. Restituisce
{ status, ok, health, body } e ti lascia decidere cosa significa uno stato. Lo
stesso modulo esporta le funzioni ausiliarie per gli URL che riscrivono l’output localhost di un agente
in un URL proxy raggiungibile: detectLocalhostUrls, rewriteLocalhostUrl,
proxyLocalhostUrl, parseLocalhostUrl e buildWebProxyUrl.
Client runtime
import { getClient } from '@beeuni/sdk';
const client = getClient();
const { data } = await client.session.list({ limit: 100 });
getClient() restituisce il client di compatibilità runtime tipizzato per la sandbox attiva,
con l’autenticazione già inserita. Preferisci beeuni.session(pid, sid).runtime, lo
stesso client limitato a una sessione, al globale getClient() quando il tuo
host esegue più di una sessione.
Funzioni ausiliarie di autenticazione
import { authenticatedFetch, getAuthToken } from '@beeuni/sdk';
const res = await authenticatedFetch(`${runtimeUrl}/beeuni/health`);
const token = await getAuthToken();
Il token proviene dalla funzione getToken che hai passato a createBeeuni.
La maggior parte del codice dell’app non ha bisogno di questo modulo: i livelli dei file, delle sessioni e della facciata
eseguono già l’autenticazione per te.
Client API
import { backendApi } from '@beeuni/sdk';
const data = await backendApi.get('/some/endpoint');
await backendApi.post('/some/endpoint', { name: 'x' });
backendApi è il client HTTP tipizzato su cui si basa ogni funzione REST. Usalo
solo per un endpoint che non ha ancora un wrapper tipizzato.
Elenchi di agenti e modelli del compositore
Crea i selettori di agenti e modelli di un compositore di sessione con le stesse regole usate dall’app web Beeuni. Ogni funzione è pura: recupera gli input con il client, poi passali alla funzione.
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 restituisce explicit: undefined quando il compositore usa
l’impostazione predefinita. model è la chiave da visualizzare e inviare. Il
id di ogni modello appiattito è il riferimento memorizzato da una selezione; modelRefToKey(ref, gatewayEnabled) riconverte un
riferimento memorizzato (un elemento fissato alla sessione, un’associazione di canale, il model di un trigger) in una
chiave.
Sottopercorsi supportati
| Sottopercorso | Cosa fa |
|---|---|
@beeuni/sdk/react |
Hook React — vedi Hook React |
@beeuni/sdk/server |
Configurazione limitata alla richiesta per backend multi-tenant |
@beeuni/sdk/wire-message-id |
Solo l’orologio degli ID dei messaggi del protocollo runtime (un modulo, nessuna importazione). La radice esporta gli stessi nomi |
ID dei messaggi del protocollo
Il messageId di un prompt è la sua posizione nella trascrizione. runtime ordina
i messaggi per msg_ + un orologio a 48 bit (Date.now() * 0x1000, i 48 bit meno significativi) +
14 caratteri base62, e l’orologio riparte da zero ogni 2^36 ms (circa 2,2 anni).
Non codificarlo mai a mano.
import { mintWireMessageId } from '@beeuni/sdk';
// `after`: the ids already in this session's transcript.
const messageId = mintWireMessageId({ after: transcriptIds });
La generazione viene retrodatata di due minuti, poi portata un tick oltre l’ID più recente
in after che sia al massimo un’ora avanti. Un chiamante che conserva la posizione più recente
come orologio anziché come ID usa mintWireMessageIdAbove({ nowMs, newestKnownTime }), which returns { id, time }. newestWireIdClock(ids)
per trovare quell’orologio. Ogni confronto avviene sull’anello, quindi gli ID ai due lati di un
ritorno a zero mantengono il loro ordine effettivo.
L’orologio a 48 bit riparte da zero ogni ~2,2 anni, quindi non confrontare mai due orologi con >
o <=: un ID generato subito dopo un ritorno a zero è numericamente inferiore a uno generato
subito prima. Usa wireIdClockDelta(clock, reference), la distanza con segno
sull’anello (positiva quando clock è avanti), e maxWireIdClock(clocks) per
il più recente tra diversi valori:
import { maxWireIdClock, wireIdClockDelta } from '@beeuni/sdk/wire-message-id';
const floor = maxWireIdClock([transcriptNewest, deliveredNewest]);
const stale = floor !== null && wireIdClockDelta(clientClock, floor) <= 0n;
Isolamento lato server
createBeeuni memorizza la propria configurazione, inclusa la funzione del token, in una
variabile globale del processo. Va bene per una scheda del browser, una CLI o un
server single-tenant. Non è sicuro per un server Node che gestisce richieste
simultanee per utenti diversi, perché l’ultima chiamata a createBeeuni prevale per
ogni richiesta in corso. @beeuni/sdk/server risolve il problema con l’isolamento per
richiesta:
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 isolano la configurazione per richiesta con
AsyncLocalStorage di Node. Non importare mai @beeuni/sdk/server da un bundle per il
browser: include staticamente node:async_hooks.
Il runtime() di primo livello di un client con ambito limitato genera un’eccezione (risolverebbe la
sandbox di un altro tenant). Accedi al runtime di una sessione specifica tramite
beeuni.session(pid, sid).runtime dopo await s.ensureReady().
Alias deprecati
Circa venti vecchi sottopercorsi funzionano ancora: /files, /turns, /session, /auth,
/projects-client, /api-client, /config, /event-stream,
/opencode-client, /platform-client e altri. Ognuno riesporta codice già esportato dal
punto di ingresso radice @beeuni/sdk. Restano funzionanti affinché nessun elemento esistente
import breaks, but new code should import from the root.
Moduli interni
@beeuni/sdk/internal/* contiene gli store zustand che il runtime di apps/web usa
internamente: stato di sincronizzazione della sessione, monitoraggio del runtime attivo e gestione delle
riconnessioni. Questo sottopercorso è esplicitamente fuori da semver. Non importarlo nel
codice host; gli Hook React espongono già lo stato di cui
hai bisogno.
Turni
Funzioni semplici che raggruppano i messaggi di sessione in turni e classificano ogni
parte di messaggio. Usale per creare un renderer di chat personalizzato anziché quello di
riferimento in apps/web. Niente React, niente DOM: ogni esportazione è una semplice
funzione o un tipo, richiamabile in sicurezza da qualsiasi host.
import { classifyPart, classifyTurn, toolInfo, toolViewModel } from '@beeuni/sdk';
Importa ogni funzione dal punto di ingresso radice @beeuni/sdk. Il
sottopercorso @beeuni/sdk/turns funziona ancora, ma è un alias deprecato. Il nuovo
codice deve usare il punto di ingresso radice — vedi Distribuzione.
Classificare una parte
classifyPart(part) normalizza uno dei 12 tipi di parte del formato di
trascrizione Beeuni (beeuni.transcript.v1, BEEUNI_TRANSCRIPT_SCHEMA) in un
ClassifiedPart — un’unione indicizzata da kind. Ogni variante risolve già i
campi necessari a un renderer: stato dello strumento, output JSON analizzato,
rilevamento delle immagini.
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;
}
}
kind |
forma |
|---|---|
text |
{ id, text, synthetic } — ignora le parti synthetic; indicano il prompt sintetico della modalità shell |
reasoning |
{ id, text } |
tool |
{ id, tool: ToolView } |
file |
{ id, filename?, mime, url, isImage, isPdf } |
subtask |
{ id, description, agent, prompt, model? } |
patch |
{ id, hash, files, fileCount } |
snapshot |
{ id, snapshot } |
agent |
{ id, name } |
retry |
{ id, attempt, message, createdAt } |
compaction |
{ id, auto, overflow, tailStartId? } |
step |
{ id, phase: 'start' | 'finish', snapshot?, reason?, cost?, tokens? } |
unknown |
{ raw } — un tipo di parte che questa versione dell’SDK non conosce |
Una parte wire non riconosciuta viene degradata a unknown in fase di runtime invece di
lanciare un’eccezione. Questo consente a un client meno recente di comunicare con un server più recente.
Una parte di strumento viene classificata in ToolView:
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
}
toToolView(part) ne crea una direttamente da una parte di strumento. Leggi questi campi
invece del personale state.metadata dell’harness: la stessa scheda restituisce quindi un
edit di runtime (filePath, filediff) e un edit di pi (path, edits,
un patch unificato).
Alcuni strumenti (web_search, image_search, chiamate ai connector) segnalano
state.status: 'completed' anche quando il loro corpo JSON contiene
success: false. classifyPart lo rileva e imposta ToolView.status su
'error' anche in questo caso.
classifyTurn(message) classifica ogni parte di un messaggio dell’assistente e
restituisce un ClassifiedTurn con tre campi:
parts— ogni parte, classificataerror— damessage.info.error, se presenteisEmpty— true quando il turno non contiene errori né parti con contenuto visibile
Metadati degli strumenti
toolKind(name) è l’unica tassonomia degli strumenti: associa il nome dello strumento di qualsiasi harness
(write di pi, oc-apply_patch di runtime, pty_spawn di un plugin) a un
ToolKind — read, edit, write, bash, web_search, task,
question, … oppure other. Le famiglie di narrazione, i view model, le categorie toolInfo
e il gruppo degli strumenti di contesto derivano tutti da essa. inputPath(input)
legge il percorso di uno strumento file da filePath, file_path o path.
toolKind('oc-apply_patch'); // 'apply_patch'
toolKind('pty_spawn'); // 'pty'
inputPath({ path: 'app.py' }); // 'app.py'
Altre due lookup descrivono entrambe uno strumento. Non confonderle.
toolInfo(name)— senza icona, restituisce{ label, category }.classifyPartla usa internamente.ToolCategoryè'shell' | 'files' | 'search' | 'edit' | 'web' | 'task' | 'other'.getToolInfo(name, input)— consapevole dell’icona, restituisce{ icon, title, subtitle }per l’interfaccia di riferimento delle schede degli strumenti. Il sottotitolo deriva dall’input dello strumento, ad esempio un percorso file o una query di ricerca.
toolInfo('bash'); // { label: 'Shell', category: 'shell' }
getToolInfo('write', { filePath: '/workspace/main.go' });
// { icon: 'file-pen', title: 'Write', subtitle: 'main.go /workspace' }
Entrambe le funzioni verificano i prefissi dei nomi degli strumenti, quindi le famiglie di strumenti plugin di Beeuni
(agent_*, session_*, task_*, trigger_*, project_*, pty_*) vengono risolte
senza aggiornare il registro. Un nome di strumento sconosciuto non genera mai un’eccezione: ricade su
humanizeToolName(name) con categoria 'other'.
View model degli strumenti
toolViewModel(classifiedTool) associa una parte di strumento classificata a una forma costruita
per una famiglia di strumenti. L’interfaccia può quindi visualizzarla in modo specifico anziché come
un generico blob JSON.
const vm = toolViewModel(classifiedTool);
if (vm.kind === 'shell') {
render(vm.command, vm.stdout, vm.exitCode);
}
kind |
forma | strumenti |
|---|---|---|
web-search |
{ query, results?, answer?, error? } |
web_search, image_search |
shell |
{ command, stdout?, exitCode? } |
bash |
file-read |
{ path, preview? } |
read |
file-write |
{ path, preview? } |
write |
file-edit |
{ path, diff?: DiffLine[] } |
edit, morph_edit |
search |
{ pattern, matches?: SearchMatch[] } |
grep, glob |
task |
{ description, agent? } |
task |
todo |
{ items: TodoItem[] } |
todowrite |
question |
{ questions: QuestionItem[], answers? } |
question, ask |
generic |
{ label, inputPretty?, outputPretty? } |
tutto il resto, sempre sicuro da visualizzare |
DiffLine è { type: 'added' | 'removed' | 'unchanged', text }. I campi stringa sono limitati, così un singolo output di strumento molto grande non interrompe il rendering: 4000
caratteri per il JSON formattato, 256 KB prima dell’esecuzione di un diff.
Raggruppare i messaggi in turni
Un turno associa un messaggio dell’utente ai messaggi dell’assistente che vi hanno risposto. È l’unità che un’interfaccia chat visualizza come un unico scambio.
import { groupMessagesIntoTurns, collectTurnParts, type TurnLike } from '@beeuni/sdk';
const turns: TurnLike[] = groupMessagesIntoTurns(messages);
for (const turn of turns) {
const parts = collectTurnParts(turn);
}
groupMessagesIntoTurns collega ogni messaggio dell’assistente al relativo messaggio dell’utente.
Se manca un collegamento al genitore, usa l’ordine dei messaggi. Collega inoltre un messaggio dell’assistente orfano — uno senza genitore che precede ogni messaggio dell’utente — al primo turno, non all’ultimo.
Helper correlati:
findLastTextPart(parts)— il testo della risposta finale del turnoturnHasSteps(parts)— true se esiste una partetool,compaction,snapshotopatchisShellMode(turn)/getShellModePart(turn)— un turno costituito da un prompt sintetico che esegue una chiamatabash
Type guard
Riduci il tipo di una parte tramite type:
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
Sono disponibili anche: isReasoningPart, isFilePart, isAgentPart,
isCompactionPart, isSnapshotPart, isPatchPart, isStepPart
(step-start e step-finish).
Stato ed errori
import { getWorkingState, getTurnStatus, formatDuration } from '@beeuni/sdk';
const status = getTurnStatus(parts, childMessages); // "Running commands..."
formatDuration(4300); // "4s" — durations under 1s return ''
getTurnStatus analizza le parti di un turno alla ricerca dell’ultima riga di stato. Quando l’ultima
parte è una delega task in esecuzione, passa childMessages affinché lo stato mostri
l’attività effettiva del sottoagente anziché una riga generica “Delegating…”.
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
Totali di costi e token
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"
Entrambe le funzioni leggono i totali di costi e token dalle parti step-finish. Quando una
parte segnala zero, stimano il costo dai conteggi dei token usando un
ModelPricingLookup.
I messaggi degli abbonamenti ChatGPT/Codex contribuiscono $0.00, inclusi i messaggi storici
con costi runtime diversi da zero. L’utilizzo di token e contesto resta visibile.
Le sessioni miste conservano gli addebiti per i messaggi API a pagamento. I modelli API OpenAI restano fatturabili, inclusi i modelli API i cui nomi contengono codex.
Sessioni figlie e richieste in sospeso
L’albero delle conversazioni di una sessione di progetto (la radice e le conversazioni degli
sottoagenti che ha creato) proviene dal suo elenco runtime_sessions. Questi helper lo leggono,
preferendo i nomi attuali a quelli precedenti a W4:
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
Una chiamata allo strumento task delega a una sessione figlia. Questi helper collegano un
turno padre ai messaggi propri di quella sessione figlia.
import { getChildSessionId, getChildSessionToolParts } from '@beeuni/sdk';
const childId = getChildSessionId(taskToolPart);
const steps = getChildSessionToolParts(childMessages);
Abbina una richiesta di autorizzazione o domanda in sospeso alla relativa chiamata dello strumento e individua quali parti dello strumento nascondere mentre è attiva:
import { getPermissionForTool, getHiddenToolParts, isToolPartHidden } from '@beeuni/sdk';
const permission = getPermissionForTool(permissions, callID);
const hidden = getHiddenToolParts(activePermission, activeQuestion);
Formattazione ed elenchi
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"
Gli helper degli elenchi di sessioni operano sugli stessi dati di sessione:
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);
Stato del nuovo tentativo: getRetryInfo(sessionStatus) restituisce { attempt, message, next, details? } when status.type === 'retry', with message limitato a 60
caratteri. details conserva, quando presente, un envelope strutturato del gateway LLM:
il provider finale, il codice del gateway, l’ID della richiesta, il suggerimento, lo stato upstream e gli
errori candidati ordinati. Ogni errore candidato contiene attempt,
provider, routeModel, resolvedModel, stage, status opzionale, code,
e message. I nuovi tentativi in testo semplice legacy restituiscono details: undefined.
getRetryMessage(sessionStatus) restituisce il messaggio completo senza envelope. Quando
runtime conserva solo quel messaggio, il composito del gateway include comunque l’ID della richiesta e il
provider, il modello risolto, lo stato HTTP, il codice e il messaggio limitato di ciascun candidato.
Tipi strutturali
Le funzioni di raggruppamento e stato accettano tipi strutturali minimi —
PartLike, MessageInfoLike, TurnLike, ToolStateLike,
SessionStatusLike — invece dei tipi concreti delle trascrizioni.
Le forme del tuo messaggio e delle tue parti passano senza modifiche, purché corrispondano
ai campi richiesti. classifyPart e classifyTurn fanno eccezione.
Sono tipizzati rispetto all’unione Beeuni Part (beeuni.transcript.v1), quindi il loro
controllo di esaustività rileva un nuovo tipo di parte in fase di compilazione.
Distribuzione
npm install @beeuni/sdk
Il pacchetto viene distribuito come ESM compilato con dichiarazioni di tipo TypeScript complete.
react e @tanstack/react-query sono dipendenze peer facoltative. Se
usi @beeuni/sdk/react, installale entrambe.
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
Punti di ingresso e stabilità
Il punto di ingresso principale, @beeuni/sdk, è quello canonico. Esporta l’intera
superficie indipendente dai framework ed è eseguibile nei browser, in Node 18+,
Bun e negli ambienti edge.
| Punto di ingresso | Livello | Contratto |
|---|---|---|
@beeuni/sdk |
Canonico | Indipendente dai framework. Non importa mai React o node:*. |
@beeuni/sdk/react |
Supportato | Hook React. L’unico punto di ingresso che importa React. |
@beeuni/sdk/server |
Supportato | Isolamento della configurazione per richiesta per i server Node e Bun, tramite node:async_hooks. Non includerlo mai in un bundle per browser. |
Sottopercorsi legacy (/projects-client, /turns, /files e altri) |
Deprecati | Funzionano ancora. Ognuno riesporta dal punto di ingresso principale. Importa invece dal punto di ingresso principale. |
@beeuni/sdk/internal/* |
Interno | Usato solo dall’app web Beeuni. Non è un’API supportata. |
Bundle CDN
Il pacchetto include anche due bundle per browser, compilati da tsup: un bundle ESM
(dist/beeuni.esm.min.js) e un globale IIFE (dist/beeuni.global.js) che
definisce window.Beeuni.
<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>
window.Beeuni espone lo stesso punto di ingresso principale dell’import npm:
Beeuni.createBeeuni, Beeuni.classifyTurn, Beeuni.ApiError.
Vedi anche
- SDK — installazione e prima sessione.
- Sessioni — ciclo di vita, streaming e gestione degli errori.
- Hook React — il livello reattivo basato su questi moduli.
Accesso al repository dell’agente
La configurazione dell’agente accetta repository_access?: boolean (predefinito true).
Imposta false per eseguire nuove sessioni senza il repository del progetto o l’accesso all’API del repository.
Le autorizzazioni Git, per i segreti, per i connettori e per gli strumenti restano separate. Le sessioni esistenti conservano i criteri salvati.
AgentConfigBlock.workspace è deprecato. L’SDK mappa branch/runtime legacy al campo booleano.
Una scrittura legacy di read richiede una scelta esplicita di repository_access; non abilita l’accesso in sola lettura al repository.
Accesso a provider e modelli
Leggi beeuni.projects.modelAccess(projectId). Modifica un singolo target con beeuni.projects.setModelAccess(projectId, { target: 'provider' | 'model', id, enabled }).
Usa l’ID provider beeuni per i modelli gestiti da Beeuni, oppure l’ID di un provider del catalogo per BYOK, Codex e i provider personalizzati. Usa l’ID wire completo del gateway per un modello. La disabilitazione di un provider si applica ai modelli futuri e conserva le preferenze dei singoli modelli e le credenziali salvate.
Il modello predefinito corrente e il relativo provider richiedono una sostituzione prima della disabilitazione (409 cannot_disable_default). Le richieste dirette al gateway verso target disabilitati non vanno a buon fine con model_disabled o provider_disabled. Le richieste upstream già in corso terminano normalmente. Il flag enforced della risposta è false quando il progetto usa runtime nativo invece del gateway.
I consumer React usano useModelAccess(projectId) da @beeuni/sdk/react. La sua mutazione setEnabled(change) aggiorna il catalogo di gestione e il selettore delle sessioni.