Aller au contenu
BeeuniBeeuni
Français
Esc
↑↓naviguer↵ouvrir⌘Japerçu
Sur cette page

Référence du SDK

L’ensemble de l’API @beeuni/sdk — méthodes du client, modules, tours et distribution.

Cette page présente l’ensemble de l’API @beeuni/sdk : toutes les méthodes du client, les modules indépendants de tout framework, les utilitaires de tours et la distribution du paquet. Consultez SDK pour commencer et Sessions pour approfondir le cycle de vie des sessions.

Le client

createBeeuni(config) renvoie un client unique. Chaque méthode est un appel typé à l’API de la plateforme. Les handles project(id) et session(pid, sid) associent les identifiants pour vous éviter de les répéter.

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

Comptes — beeuni.accounts

méthode fonction
list() · get(accountId) comptes auxquels vous appartenez · un compte
create({ name }) · updateName(accountId, name) créer · renommer un compte
branding.get(accountId) · branding.update(accountId, { app_name }) · branding.uploadAsset(accountId, kind, file) · branding.removeAsset(accountId, kind) · branding.reset(accountId) identité visuelle de l’organisation (Enterprise) : logo / icône / favicon et nom de produit personnalisés ; kind vaut logo · icon · favicon, ou logo_dark · icon_dark · favicon_dark pour la variante du thème sombre
members(accountId) · invite(accountId, input) lister les membres · en inviter un
updateMemberRole(accountId, userId, role) · removeMember(accountId, userId) attribuer le rôle dans le compte · retirer un membre
invites(accountId) invitations en attente
cancelInvite(accountId, inviteId) · resendInvite(accountId, inviteId) annuler · renvoyer une invitation en attente
leave(accountId) quitter le compte

accounts.tokens génère des clés API limitées au compte (beeuni_pat_...). Consultez Authentification du SDK pour le modèle complet des jetons.

méthode fonction
tokens.list(accountId?, options?) lister les clés API — celles de tout le compte, ou uniquement les vôtres avec { mine: true }
tokens.create(input) en générer une — { accountId?, name, expiresAt?, projectId? }
tokens.revoke(tokenId, accountId?) en révoquer une

accounts.audit est le journal de reconstitution pour les entreprises. Il combine les requêtes API authentifiées avec les événements sémantiques de session, de connecteur, d’approbation et d’ordinateur.

méthode fonction
audit.log(accountId, filters?) lister les événements par projet, session, acteur, source, résultat, requête, corrélation, ressource, action ou date
audit.export(accountId, filters?) exporter le même flux d’événements filtré au format CSV ou JSONL
audit.webhooks.list/create/update/remove(...) gérer les webhooks SIEM signés pour le flux centralisé

Chaque événement inclut project_id, session_id, actor_type, source, outcome, request_id, trace_id et correlation_id lorsque l’action les fournit. L’API ne stocke ni corps de requête, ni prompts, ni secrets, ni identifiants d’authentification, ni arguments bruts de connecteur dans l’événement centralisé. Les événements de connecteur peuvent inclure un aperçu limité des arguments qui masque les champs ressemblant à des identifiants d’authentification et les données opaques.

Attributions d’accès

Beeuni utilise un seul type d’enregistrement d’octroi : une attribution. Elle associe un principal (user, group, service_account ou pending) à un rôle, dans un périmètre (account, ou un project), éventuellement limité à un objet (agent, skill, secret, app ou trigger) et éventuellement accompagné d’un expires_at. Les accès de groupe, les accès par ressource et les associations à des rôles personnalisés sont tous des attributions. Consultez Comptes et accès pour le modèle.

L’interface REST canonique est la suivante :

Méthode + chemin Fonction
GET /v1/accounts/{accountId}/iam/assignments lister les attributions, filtrées par principal, périmètre, objet ou rôle
POST /v1/accounts/{accountId}/iam/assignments créer une attribution
DELETE /v1/accounts/{accountId}/iam/assignments/{assignmentId} révoquer une attribution
GET /v1/accounts/{accountId}/iam/permissions le catalogue des permissions, sous forme de données
GET /v1/accounts/{accountId}/iam/roles · …/roles/{roleId}/permissions rôles · permissions d’un rôle

Le SDK les expose via listAssignments, createAssignment, revokeAssignment et listPermissions. Une ligne du catalogue contient action, scope_type, resource_type, delegable, description, area, level et implies — consultez-la plutôt que de coder en dur les chaînes d’action.

L’attribution d’un rôle personnalisé nécessite le droit rbac du compte ; sans celui-ci, la route répond 402 avec code: "entitlement_required".

Invitations au compte — beeuni.accountInvites

Accessible avec le seul jeton d’invitation — la personne invitée peut ne pas encore être membre.

méthode fonction
listMine() toutes les invitations en attente et non expirées adressées à votre e-mail, avec l’espace de travail et les projets auxquels elles donnent accès
describe(inviteId) · accept(inviteId) · decline(inviteId) prévisualiser · accepter · refuser une invitation

Projets — beeuni.projects

méthode fonction
list() · listForAccount(accountId) vos projets · projets d’un compte
get(id) · detail(id) résumé · détails complets
create(input) · createRepo(input) à partir d’un repo_url existant · nouveau dépôt GitHub vide
provision(input) nouveau projet sur un nouveau dépôt géré par Beeuni, initialisé avec un modèle de démarrage — { name, account_id?, seed_starter?, starter_template?, marketplace_items?, source_item_id?, idempotency_key? }
update(id, input) · archive(id) mettre à jour les paramètres · archiver
llmCatalog(id) · modelPicker(id) catalogue de modèles complet · compact pour un sélecteur
sandboxTemplates(id) · sandboxHealth(id) modèles de build du sandbox · état du build
sessions(id) · createSession(id, input?) lister les sessions visibles · créer une session

provision crée un nouveau projet ; il ne démarre pas le sandbox d’un projet existant. Démarrez plutôt une session — voir Sessions.

Envoyez idempotency_key lorsqu’une nouvelle tentative est possible — un rechargement, un deuxième onglet, un délai d’attente dépassé suivi d’une nouvelle tentative. provision génère un tout nouveau dépôt géré à chaque appel ; sans clé, ces appels créent donc tous de véritables projets en double. Réutilisez une même clé pour chaque tentative d’une seule création logique : les appels répétés renvoient le projet créé par la première tentative (201, mêmes project_id et push_token: null). La clé identifie la tentative, pas la charge utile — la réutiliser avec un autre name renvoie le premier projet et ignore la nouvelle valeur ; générez donc une nouvelle clé pour chaque création distincte. Créer un deuxième projet avec le même nom et sans clé reste possible.

Un appel répété qui arrive alors que le premier appel est encore en cours de provisionnement reçoit 409 avec code: 'provision_in_flight' plutôt qu’un project_id que cet appel pourrait encore annuler. Réessayez avec la même clé.

project(id).sessions.list({ scope: 'project' }) est un inventaire du cycle de vie destiné à un appelant disposant des permissions de gestionnaire de projet. Il ajoute les sessions accessibles indisponibles, préchauffées et supprimées de façon réversible, avec des métadonnées de propriété et d’état d’exécution. Les deux périmètres de liste excluent toute session que l’appelant ne peut pas ouvrir.

sessions.list et sessions.listPage acceptent également les filtres de hiérarchie et d’attribution. Sans eux, la liste reste plate et inchangée.

option fonction
parent: 'root' Sessions de premier niveau uniquement. Chaque ligne contient child_count.
parent: '<sessionId>' Les sessions enfants de cette session, les plus récentes d’abord.
startedBy: 'me' | 'others' | 'automated' Filtrer par initiator, relativement à l’appelant.
q Recherche insensible à la casse sur le titre, le libellé de démarrage, le slug du déclencheur et le préfixe de l’identifiant de session, parmi toutes les sessions que l’appelant peut ouvrir. Avec parent: 'root', une racine correspondant via un enfant possède search_match: 'child'.

Chaque ligne de session possède parent_session_id et initiator ({ type: 'member' | 'trigger' | 'channel' | 'api' | 'system', id, label }). initiator indique qui a démarré l’ensemble de l’exécution ; un enfant reprend la valeur de son parent. sessionParentId(session) lit parent_session_id, puis l’ancien metadata.spawned_by_session. Un curseur n’est valide que pour l’ensemble de filtres qui l’a émis.

GitHub — beeuni.github

Installation de l’application GitHub et association de dépôts au niveau du compte, et non du projet.

méthode fonction
getInstallation(accountId) · listInstallations(accountId) installation de ce compte · installations accessibles à l’utilisateur
saveInstallation(input) · deleteInstallation(accountId, installationId?) enregistrer · dissocier une installation
listLinkableInstallations(input) installations que l’utilisateur GitHub autorisé peut associer ; chaque entrée contient linked_to_other_accounts, le nombre d’autres comptes Beeuni qui la détiennent — jamais leurs noms
listRepositories(accountId, installationId?) · listRepositoryBranches(...) dépôts visibles par l’installation · branches et branche par défaut de GitHub
linkRepository(input) Importer un dépôt en tant que projet à l’aide d’une installation GitHub autorisée.
replaceProjectRepository({ project_id, repo_url, expected_repo_url, github_token }) remplacer le dépôt GitHub d’un projet existant. Utilisez soit github_token avec un accès Contents en lecture/écriture, soit installation_id avec un github_user_token temporaire pour vérifier l’accès administrateur à l’organisation et autoriser uniquement ce dépôt via la GitHub App. copy_shared_secrets_from_project_id avec copy_shared_secret_identifiers copie les secrets d’exécution partagés sélectionnés dans la même transaction. Un expected_repo_url obsolète renvoie 409. L’ancien dépôt reste sur GitHub. Les nouvelles sessions utilisent le dépôt de remplacement ; les sessions existantes conservent leur copie de travail.

Cette liste ne contient que de véritables connexions de compte. « Beeuni managed » n’en fait pas partie — il s’agit du backend de l’instance ci-dessous.

Backend git de l’instance — beeuni.gitBackend

Un propriétaire unique pour tout le déploiement, accompagné d’un identifiant d’authentification, utilisé pour les dépôts gérés par Beeuni. Ce n’est jamais une connexion de compte et il n’apparaît jamais dans beeuni.github.listInstallations.

méthode fonction
get() { configured, kind: 'app' | 'pat' | null, owner } — lisible par tout utilisateur authentifié ; expose uniquement le nom de connexion du propriétaire déjà présent dans chaque repo_url géré

Facturation — beeuni.billing

Consulte les crédits, l’abonnement, l’offre et l’historique des transactions. Utilisez le paiement et la gestion de facturation Beeuni pour les paiements et les achats de crédits.

méthode fonction
accountState(accountId?) · accountStateMinimal(accountId?) état de facturation complet · minimal
transactions(params?) · transactionsSummary(params?) historique · totaux récapitulatifs
creditBreakdown(accountId?) · usageHistory(params?) solde de crédits par source · utilisation au fil du temps
sessionCosts.list(options?) · sessionCosts.get(sessionId, options?) relevés paginés des coûts des sessions · registre détaillé d’une session
tierConfigurations() niveaux de forfait disponibles
checkout.createSession(input) · checkout.confirmSession(sessionId, accountId?) Obsolètes. Rejettent avec ENDPOINT_RETIRED. Supprimés dans la prochaine version majeure.
subscription.createPortalSession(...) · subscription.cancel(...) · subscription.reactivate(...) ouvrir le portail client · résilier · réactiver
subscription.cancelScheduledChange(...) · prorationPreview(...) résilier · prévisualiser un changement de forfait
subscription.scheduleDowngrade(...) Obsolète. Rejette avec ENDPOINT_RETIRED. Changez de forfait dans le portail client. Supprimé dans la prochaine version majeure.
credits.purchase(input) · credits.autoTopupSettings(...) · credits.configureAutoTopup(...) achat ponctuel · lire · configurer la recharge automatique

sessionCosts.list() accepte accountId, projectId, limit et offset. Chaque ligne combine le coût LLM finalisé et le coût de calcul facturé du sandbox. sessionCosts.get() ajoute l’utilisation des modèles et le registre distinguant LLM et calcul. La liste inclut un total de rapprochement pour les coûts sans session.

Partages de sandbox — beeuni.sandboxShares

Liens de partage publics pour un port exposé du sandbox. Leur portée est le sandbox, pas le projet.

méthode fonction
list(sandboxId) liens de partage actifs
create(input) en créer un — { sandboxId, port, ttl?, label? }
revoke(sandboxId, token) en révoquer un

Catalogue de la marketplace — beeuni.marketplace

Consultation du catalogue public, en lecture seule — distincte de project(id).marketplace, qui installe un élément dans un projet.

méthode fonction
items(options?) · item(id) · itemFile(id, path) parcourir · un élément · un fichier dans un élément
marketplaces() · featured() toutes les marketplaces · marketplaces mises en avant
sources.list() · sources.add(input) · sources.remove(id) lister · ajouter · supprimer une source

Notifications — beeuni.notifications

Les notifications de l’appelant, pour tous les comptes et projets. Chaque personne connectée dispose d’une boîte de réception, d’un enregistrement de préférences et d’abonnements Web Push pour ses navigateurs. Chaque méthode nécessite l’identifiant d’authentification d’une personne : un compte de service reçoit 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 } } });
méthode fonction
list({ limit?, before? }, { signal? }) la page la plus récente : { notifications, unread_count, next_before }. limit va de 1 à 50 (20 par défaut). Passez next_before comme before pour la page suivante. Les entrées que l’appelant ne peut plus voir sont omises. Un échec n’appelle pas le gestionnaire d’erreurs de l’hôte.
markRead({ ids }) · markRead({ all: true }) · markRead({ sessionId }) marquer comme lues 1 à 100 entrées, toutes les entrées ou toutes les entrées d’une session. Ne modifie que les entrées de l’appelant. Renvoie { updated, unread_count }.
preferences() · updatePreferences({ kinds }) lire · modifier le choix des notifications push et des e-mails par type. Renvoie { kinds, email_available }. Un patch ne modifie que les types et les canaux qu’il nomme.
webPushPublicKey() { public_key } : le applicationServerKey pour pushManager.subscribe
registerWebPushSubscription({ endpoint, keys }) envoyer les notifications push à ce navigateur. Nécessite une connexion dans le navigateur : un jeton personnel reçoit 403. Un point de terminaison sur un service push inconnu reçoit 400.
unregisterWebPushSubscription(endpoint, { signal? }) arrêter les notifications push vers ce navigateur. Renvoie { deleted }.
registerDeviceToken(input) · unregisterDeviceToken(token, { signal? }) enregistrer · supprimer le jeton push Expo d’une application native

Types (InboxNotificationKind, répertoriés dans INBOX_NOTIFICATION_KINDS) :

type envoyé lorsque push e-mail (par défaut)
turn_done un tour que vous avez lancé ou que vous suivez est terminé activé désactivé
turn_error ce tour s’est terminé par une erreur activé activé, dans un récapitulatif
question l’agent pose une question activé activé, dans un récapitulatif
permission l’agent demande une autorisation activé désactivé
shared quelqu’un a partagé une session avec vous activé activé, dans un récapitulatif
automation_failed une automatisation que vous suivez a commencé à échouer activé activé, immédiatement
automation_recovered cette automatisation fonctionne à nouveau activé désactivé

DEFAULT_NOTIFICATION_PREFERENCES contient ces valeurs par défaut. L’entrée de la boîte de réception est toujours créée ; les préférences ne déterminent que les notifications push et les e-mails. Un e-mail récapitulatif liste les entrées encore non lues 15 minutes après leur arrivée, avec au maximum un récapitulatif par heure. Masquez la colonne e-mail lorsque email_available vaut false.

Le url de chaque entrée ouvre son sujet. Son paramètre de requête ?notification=<id> permet à la page de marquer l’entrée comme lue.

Le handle de session porte le suivi de l’appelant pour une session :

méthode fonction
session(pid, sid).watch() { watching } : l’appelant reçoit-il des notifications pour cette session
session(pid, sid).setWatch(watching) false désactive les notifications de la session pour l’appelant, true rétablit son suivi. Envoyer un prompt à une session active son suivi, mais ne réactive jamais les notifications désactivées.
session(pid, sid).presence({ tab_id, active, alerts? }, { keepalive? }) le bail de présence de cet onglet. alerts: true indique que l’onglet affiche ses propres notifications : lorsque notification_center est activé, le serveur n’envoie pas de notifications au téléphone ni via Web Push uniquement pendant qu’un onglet affichant des alertes est utilisé. Lorsqu’il est désactivé, alerts est ignoré et tout onglet présent bloque les notifications push au téléphone. keepalive permet à la requête de survivre à la fermeture d’une page. Par défaut : activé pour un signalement d’absence, désactivé pour un signalement de présence. useSession n’envoie keepalive qu’avec presencePageExit.

Le handle de projet — beeuni.project(id)

Lie l’identifiant du projet ; toutes les sous-ressources en dépendent.

const p = beeuni.project(projectId);
await p.detail();
await p.update({ name });
await p.llmCatalog();
méthode description
get · detail · update · archive lire · détails complets · mettre à jour · archiver
llmCatalog · modelPicker · sandboxHealth lectures du modèle et des builds du sandbox
onboardingComplete marquer l’intégration du projet comme terminée
validateManifest(raw) valider un manifeste beeuni.yaml (ou l’ancien beeuni.toml) côté serveur
gitToken() générer un nouveau jeton git push à portée limitée (409 pour un dépôt que vous fournissez)
setAgentScope(agentName, scope) définir les secrets et connecteurs autorisés d’un agent dans le manifeste — la seconde liaison, pas un rôle

p.tokens — clés API limitées au projet

Générées automatiquement à la création d’une session sous la forme BEEUNI_TOKEN ; peuvent aussi être générées manuellement.

méthode description
list() clés API du projet
create(input?) en générer une nouvelle
revoke(tokenId) en révoquer une

Un lien qu’une personne ouvre pour saisir un secret ou connecter une application, sans accès complet au projet.

méthode description
requestSecret(input) · requestConnector(input) lien pour recueillir un secret · connecter une application

p.apps — Apps (versions, machines, volumes)

Nécessite la fonctionnalité de projet apps. Guide : SDK → Apps.

méthode description
list() · get(appId) · create(input) · update(appId, input) · remove(appId) inventaire et cycle de vie ; create accepte uses, update accepte aussi labels
deployments.* · artifacts.* · access.* · rollback · start · stop déploiements, artefacts, politique d’accès, trafic et environnement d’exécution
machines.list/start/stop/restart/destroy · scale(appId, count) · exec(appId, input) machines par groupe de processus ; exec nécessite project.app.admin
volumes.list/create/update/destroy/snapshots/snapshot/restore/fork volumes persistants, instantanés quotidiens, restauration, duplication
token(appId) un jeton de connexion de 15 minutes ; 409 app_capability_unsupported sans member_tokens

p.secrets — secrets du projet

méthode description
list() · upsert(input) lister les métadonnées · créer ou mettre à jour une valeur accessible uniquement en écriture et une politique de transmission
setStrategy(identifier, strategy, options?) modifier l’exposition et sa liste d’hôtes
broker(identifier, request) exécuter une requête HTTPS autorisée par la session et soumise à une politique
remove(identifier) supprimer un secret
setPersonal(name, value) · removePersonal(name) définir · supprimer une substitution par utilisateur
setGitCredential(input) définir un identifiant d’authentification git

runtime avec le consommateur sandbox correspond à l’exposition environment — celle par défaut, et la seule politique qui place une valeur en clair dans la session. egress avec le consommateur network correspond à l’exposition egress-enforced : la session détient une référence et Beeuni substitue la valeur réelle en dehors du sandbox, pour les seuls hôtes HTTPS énumérés dans la politique. L’exposition egress-enforced est expérimentale ; elle nécessite le flag de fonctionnalité secrets_egress (Settings → Feature flags). Lorsque ce flag est désactivé, setStrategy(identifier, 'egress', …) et upsert(...) avec une politique de sortie renvoient 403 feature_disabled. Aucun consommateur broker n’a la moindre présence dans la session. Voir Secrets. La méthode broker(...) nécessite un jeton limité à la session et une référence de session active.

p.access — attributions, invitations et demandes du projet

Chaque méthode ici lit ou écrit une attribution limitée à ce projet. Les rôles du projet sont manager et member.

méthode description
list() · invite(email, role) identités disposant d’un accès · inviter un utilisateur
update(userId, role) · revoke(userId) attribuer un rôle de projet · révoquer l’attribution
pendingInvites() · requests() invitations en cours · demandes d’accès en attente
resendInvite(inviteId) · revokeInvite(inviteId) · approveRequest(id) · rejectRequest(id) renvoyer/révoquer une invitation · approuver/rejeter une demande
groupGrants() · attachGroupGrant(...) · updateGroupGrant(...) · detachGroupGrant(...) les mêmes attributions, avec une identité group

p.access.resourceGrants est la vue des attributions d’objet : elle limite une identité à un seul objet du projet plutôt qu’à l’ensemble du projet. Beeuni applique actuellement les attributions d’objet aux agents et aux compétences. Un agent est fermé par défaut — un membre n’y accède que lorsqu’une attribution le désigne, lui ou l’un de ses groupes. Une attribution d’objet ne porte aucune permission propre et restreint un responsable de projet autant qu’un membre.

méthode description
resourceGrants.list() attributions d’objet dans ce projet
resourceGrants.create(input) attribuer un objet à un utilisateur ou à un groupe
resourceGrants.remove(grantId) révoquer une attribution d’objet

p.connector(slug) — un connecteur

méthode description
run(action, args, options?) la sortie de l’action ; lève ConnectorCallError ou ConnectorApprovalPendingError — voir Erreurs
call(action, args, options?) le résultat brut de l’appel ; 202 se résout avec ok: false
describe() · describe(action) le connecteur avec les schémas d’entrée et de sortie · une action
accounts() les comptes sous lesquels cet appelant peut l’exécuter, celui par défaut en premier
paginate(action, args, { next, maxPages? }) itérateur asynchrone sur la sortie de chaque page ; lève ConnectorPageLimitError avec nextArgs lorsqu’il existe plus de maxPages pages (100 par défaut) — voir Pages
uploadAttachment(content, input) p.connectors.uploadAttachment avec connector défini sur ce slug

options : account, approvalContext, timeoutMs (90 000 par défaut), signal. Avec le fichier de beeuni connectors types, les arguments et la sortie sont typés.

p.connectors — connecteurs d’outils

méthode description
catalog() · tools() catalogue Connector appelable · outils <connector>.<action> aplatis
search(query, options?) · describe(tool) rechercher · inspecter un outil appelable
call(tool, args?, options?) appeler un outil <connector>.<action> via la passerelle côté serveur. options.account indique le compte sous lequel l’exécuter — voir ci-dessous.
accounts(slug) les comptes sous lesquels cet appelant peut appeler slug, celui par défaut en premier — les comptes auxquels options.account est comparé
uploadAttachment(content, input) préparer des octets pour input.connector ; renvoie ref ({ $beeuni_attachment }) à placer dans les arguments d’un appel ultérieur — voir Joindre des fichiers
list() · config(connectorId) connecteurs configurés · configuration d’un connecteur
create(input) ajouter un connecteur
auth.discover(input) prévisualiser l’authentification à partir d’une spécification OpenAPI, d’une collection Postman ou d’un point de terminaison
remove(connectorId) · sync() supprimer un connecteur · resynchroniser les connecteurs
setName(connectorId, name) · setSensitive(connectorId, sensitive) renommer · le marquer comme sensible (approbation supplémentaire requise)
setAuthorizationStrategy(slug, strategy) @deprecated. Appelle toujours la route ; celle-ci est sans effet, répond {ok:true, deprecated:true} et ne change rien. owner_type sur chaque connexion constitue désormais l’intégralité de la règle d’accès.
setCredentialMode(connectorId, mode) · setCredential(connectorId, input) changer de source · définir la valeur de l’identifiant d’authentification
policies.get(connectorId) · policies.set(connectorId, policies) lire · remplacer ses politiques d’outils
connections.list() · connections.reconcile(input) lister · créer/mettre à jour les comptes connectés
connections.updateCredential(connectionId, input) renouveler un identifiant d’authentification de connexion
connections.revoke(connectionId) · connections.activate(connectionId) bloquer · rétablir une connexion
connections.setDefault(connectionId) en faire la connexion par défaut pour le périmètre de son propriétaire
connections.rename(connectionId, label) modifier uniquement le libellé ; le compte reste autorisé. Chaque connexion porte connected_as, l’identité sous laquelle elle a été autorisée.

p.connectors.discover permet de parcourir le catalogue des connecteurs directs. Cette fonctionnalité est expérimentale et désactivée par défaut — activez-la pour chaque projet sous Settings → Feature flags → “Connectors API Discover”. Easy Connect reste la place de marché de connecteurs par défaut.

méthode description
discover.list(query?, cursor?) · discover.detail(id) rechercher des entrées OpenAPI/MCP/GraphQL/CLI · détails d’une entrée

p.connectors.pipedream est la voie de compatibilité de l’ancien OAuth géré ; listApps ne renvoie que les applications OAuth. Utilisez Easy Connect pour les nouvelles intégrations gérées. Connectez directement les applications à clé API.

méthode fonction
pipedream.listApps(params?) · pipedream.connect(input) · pipedream.finalize(input) parcourir le catalogue d’applications · lancer un parcours de connexion · le finaliser

Un connecteur définit l’outil, l’application du fournisseur et les politiques. connections stocke ses comptes connectés — un connecteur peut en contenir plusieurs côte à côte. Une session peut en fixer un pour chaque appel avec connector_bindings: { alias: { connection_id } }, ou un appel individuel peut en désigner un avec call(tool, args, { account }). Les identifiants restent chiffrés et sont résolus à chaque requête.

connections est la seule façade d’autorisation active. Les anciens noms authorizations et profiles ne font pas partie de l’interface actuelle du SDK.

Comptes et contrôle au moment de l’appel

Chaque connexion possède un owner_type : project (partagé — accessible à toute personne à qui le connecteur est accordé, humain ou compte de service) ou member (privé — accessible uniquement à son propriétaire, et seulement dans une session privée ; jamais à un compte de service). L’accès à un compte partagé peut être restreint à des groupes et à des personnes : connections.list() renvoie ses autorisations dans shared_with, et connectionSharedWithEveryone(connection) indique si tous les membres du projet peuvent l’utiliser. Un compte à accès restreint suit les règles des comptes privés pour les personnes désignées, et usable: false signale un compte que l’appelant ne voit que pour le gérer. Accordez ou révoquez l’accès avec createAssignment / revokeAssignment (object: { type: 'connection', id }) — voir Choisir qui peut utiliser un compte partagé. p.connectors.accounts(slug) répertorie tous les comptes accessibles à cet appelant, avec celui par défaut en premier :

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

Un appel qui ne désigne aucun compte utilise d’abord le compte privé par défaut de l’appelant, puis le compte partagé par défaut du projet. Un compte désigné qui ne peut pas être résolu est refusé avec connector_not_connected — jamais remplacé silencieusement — et le refus indique requested_account et available_accounts. Chaque appel réussi indique le compte sous lequel il a été exécuté : result.account = { connection_id, label, owner_type }.

Il n’y a plus de contrôle des connecteurs lors de la création d’une session. Une session était auparavant refusée avec 409 CONNECTOR_CONNECTION_REQUIRED lorsqu’un connecteur requis n’avait aucune connexion utilisable ; ce refus a été supprimé (require_connectors est inactif — voir p.sessions). Le contrôle s’effectue désormais au moment de l’appel : un connector_not_connected refusé contient connect_url, un lien d’autorisation hébergé, dès qu’il est possible d’en générer un pour l’appelant — la résolution se fait en un clic, via le bouton de connexion de la transcription.

p.policies — politiques du projet

méthode fonction
list() · set(policies) les politiques du projet · remplacer l’ensemble

p.triggers — automatisations cron, webhook, de surveillance et d’événements

Un déclencheur lance une action d’agent selon une planification, un webhook entrant, une commande surveillée ou un événement d’application sur un connecteur. Voir Déclencheurs pour la stratégie de session et les modèles de charge utile.

méthode fonction
list() tous les déclencheurs
eventTypes({ connector }) les événements d’application sur lesquels un connecteur peut se déclencher ({ provider, app, event_types }) ; 404 pour un connecteur inconnu, 409 event_source_unavailable lorsque son fournisseur n’a aucune source d’événements
create(input) en créer un
update(triggerId, input) modifier un déclencheur
remove(triggerId) supprimer un déclencheur
fire(triggerId) l’exécuter maintenant
setActivation(paused) suspendre ou reprendre tous les déclencheurs du projet

create(input) accepte { 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 sont obligatoires. cron/run_at s’excluent mutuellement (type: 'cron') ; secret_env (le secret HMAC du webhook) s’applique à type: 'webhook'.

Un déclencheur event nécessite connector (un slug de connecteur) et event (un identifiant de type issu de eventTypes). event_account est facultatif : le libellé d’un compte partagé de ce connecteur ; null ou son omission utilise le compte partagé par défaut du connecteur. event_source est facultatif : l’identifiant de l’adaptateur de source d’événements, par exemple composio. null ou son omission utilise le fournisseur du connecteur. L’identifiant de type appartient à cet adaptateur. La structure de event_config est définie par le config_schema de ce type. eventTypes et eventApps indiquent l’adaptateur sous source ; provider est un alias obsolète. Chaque déclencheur répertorié contient event: { connector, account, connected_as, type, config, source, provider, app, status: 'active' | 'needs_connection' | 'error' | 'pending', error, last_event_at } | null. Les modèles de prompt lisent l’événement via {{ event.data.<field> }} ainsi que event.id, event.type, event.app, event.connector et event.occurred_at.

session_access contrôle qui peut ouvrir les sessions créées par le déclencheur. Sa structure est { mode: 'private' | 'members' | 'project', memberIds: string[], groupIds: string[] } and defaults to private. Cette politique est un état d’exécution local au compte. Elle n’entre pas dans le manifeste portable beeuni.yaml. La modification du seul session_access ne crée aucun commit Git. Une session fixée conserve ses propres paramètres de partage. Un gestionnaire de projet peut toujours ouvrir les sessions créées par les déclencheurs, y compris celles qui utilisent private ou un accès réservé aux membres sélectionnés.

session_access est un paramètre de visibilité par ressource qui s’ajoute au modèle de rôles, et non un rôle. Il détermine qui peut ouvrir les sessions d’un déclencheur donné. Il n’accorde aucune permission refusée par la décision du rôle. Voir Comptes et accès.

p.marketplace / p.registry — éléments installés

Installe les fichiers d’un élément du catalogue sur la branche par défaut du projet. registry.* est un alias identique de marketplace.*.

méthode fonction
marketplace.list() · marketplace.install(id) éléments installés · installer un élément du catalogue
marketplace.updates() · marketplace.update(name) · marketplace.updateAll() mises à jour disponibles · en mettre un à jour · tous les mettre à jour
marketplace.remove(name) désinstaller un élément

p.files — fichiers du dépôt (lecture)

Accès en lecture seule à l’arborescence git du projet. Pour lire et écrire des fichiers dans une session en cours d’exécution, utilisez les opérations sur les fichiers de la session — voir Fichiers sous Modules ci-dessous.

méthode fonction
listDirectory({ ref?, path? }) un niveau de dossier : { entries: [{ path, type, size? }], truncated }. Utilisez-le pour construire une arborescence ; chaque dossier est complet jusqu’à 5 000 entrées.
list(options?) · read(path, ref?) tous les fichiers sous un chemin, récursivement, limités à 1 000 (la réponse contient X-Beeuni-Truncated: 1 en cas de troncature) · le contenu d’un fichier à une référence git
search(query, { content?, ref?, limit? }) rechercher des noms de fichiers dans tout le dépôt, ou du contenu avec content: true
archive(options?) · history(path) télécharger une archive tar · l’historique git d’un fichier

p.git — historique

méthode fonction
commits() le journal des commits
commit(sha) · commitDiff(sha) un commit · son diff
branches() · versionDiff(from, to) les branches · le diff entre deux références

p.changeRequests — cycle de vie et fusion

Une demande de modification (CR) permet de fusionner le travail d’une session dans la branche par défaut.

méthode fonction
list() · get(crId) les CR ouvertes · une CR
diff(crId) · mergePreview(crId) son diff · prévisualiser le résultat de la fusion
open(input) · merge(crId, input?) ouvrir · fusionner une CR
close(crId, input?) · reopen(crId, input?) fermer sans fusionner · rouvrir une CR fermée
requestChanges(crId, input) enregistrer des retours, éventuellement transmis à la session d’origine

p.sessions — et le handle de session

méthode fonction
list() les sessions du projet
create(input?) créer une session
session(sid) le handle de session (identique à beeuni.session(id, sid))

Le handle de session est au cœur du runtime — voir Sessions.

create(input) accepte connector_bindings indexé par slug de connexion de connecteur. Chaque valeur désigne un connection_id. Il accepte aussi secrets pour restreindre les secrets provenant du backend. require_connectors est obsolète et sans effet : le champ reste accepté (un ancien client n’est jamais rejeté pour l’avoir envoyé), mais rien ne le lit — une session n’est jamais refusée à sa création pour un connecteur sans compte utilisable. Voir Comptes et contrôle au moment de l’appel.

p.approvals — la boîte de réception des approbations de connecteurs

Actions soumises à un contrôle de connecteur en attente d’une décision — alimente l’interface d’approbation des autorisations (APPROVE / ASK / BLOCK).

méthode fonction
list(options?) · sessionsNeedingInput(options?) approbations en attente · sessions bloquées dans l’attente d’une décision
resolve(executionId, decision, scope?) approuver ou refuser une action — decision: 'approve' | 'deny', scope: 'once' | 'session' | 'session_all'

p.gateway — observabilité des LLM

Journaux de requêtes, agrégats de coût/latence, budgets et clés API de passerelle pour le trafic des modèles de ce projet.

méthode fonction
logs(opts?) · log(logId) entrées du journal de requêtes · une entrée du journal
overview(days?) · series(days?) · breakdown(days?) · sessions(days?) · errors(days?) agrégats, coût par session et erreurs sur une période
budgets() · setBudget(input) · deleteBudget(budgetId) lire · créer/modifier · supprimer un budget
keys() · createKey(name) · revokeKey(keyId) lister · générer · révoquer une clé API de passerelle
playground(prompt, models) exécuter un prompt sur un maximum de 6 modèles
routing.get() · routing.set(policy) · routing.reset() lire · remplacer · hériter de la politique de routage
routing.preview(input) résoudre une route sans invoquer de modèle

Une politique de routage contient un modèle par défaut, un modèle de vision et une chaîne ordonnée de modèles de repli, chaque modèle étant essayé au plus une fois ; fallbackOn vaut transient ou any-error.

La passerelle ne passe au modèle de repli suivant que si le modèle actuel a échoué avant de renvoyer la moindre sortie :

  • transient : une erreur réseau, un délai d’attente dépassé, tout 5xx, ou 402, 403, 429.
  • any-error : tout échec, y compris un 400.

Un échec après le début de la sortie reste associé à ce modèle. Une requête utilisant votre propre clé fournisseur (BYOK) ne bascule jamais vers un modèle facturé par Beeuni. Chaque modèle de repli utilise ses propres paramètres de génération par défaut.

p.channels — Slack / e-mail / voix

Interfaces de connecteurs permettant à un agent d’agir comme une application Slack, une adresse e-mail, ou de rejoindre un appel vocal en temps réel.

méthode fonction
slack.installation() · slack.mode() · slack.manifest() installation actuelle · mode · manifeste de l’application
slack.connect(input) · slack.disconnect() connecter · déconnecter
slack.getFile(url) · slack.uploadFile(input) télécharger · téléverser un fichier via le proxy serveur
email.installation(connectorSlug?) · email.mode() installation actuelle · mode
email.connect(input) · email.disconnect(...) · email.updatePolicy(input) connecter · déconnecter · mettre à jour la politique d’envoi/de réponse
voice.setBotName(name) renommer le bot pendant un appel en cours

p.modelDefaults — préférences de modèle par défaut

Modèles par défaut définis au niveau du compte, de l’agent et du projet, résolus par la passerelle.

méthode fonction
get() · set(input) · clear(params) lire · définir une valeur par défaut · supprimer une surcharge

p.setDefaultAgent — agent par défaut du projet

p.setDefaultAgent(agentName) vérifie que l’agent est déclaré et activé, puis le définit comme default_agent dans le beeuni.yaml du projet. Les nouvelles sessions privilégient cet agent, sauf si un utilisateur en choisit un autre.

p.updateFeatureFlag — indicateurs de fonctionnalités

p.updateFeatureFlag(feature, enabled) active ou désactive un indicateur de fonctionnalité pour le projet. Passez enabled: null pour supprimer la surcharge et revenir à la valeur par défaut de la plateforme. Il appelle le PATCH /v1/projects/:id/features canonique.

feature est l’un des FEATURE_FLAG_KEYS (exportés depuis @beeuni/sdk, typé comme FeatureFlagKey). L’appelant doit disposer de l’autorisation project.settings.write du projet ; sinon, la route répond 403.

Toutes les routes contrôlées par un indicateur rejettent les requêtes de la même manière lorsque celui-ci est désactivé : HTTP 403 avec { error, code: "feature_disabled", feature }. Utilisez isFeatureDisabledError(error) pour adapter le traitement et featureDisabledKey(error) pour lire la clé de l’indicateur — ne vous basez jamais sur le texte du message.

p.updateExperimentalFeature(feature, enabled) est l’alias obsolète. Il continue d’appeler l’alias de route obsolète PATCH /v1/projects/:id/experimental pour que les consommateurs liés à une ancienne API déployée continuent de fonctionner. Utilisez p.updateFeatureFlag dans le nouveau code.

p.sandbox — modèles et builds de snapshots

Configuration de build des sandbox au-delà de sandboxHealth/sandboxTemplates sur le handle du projet : modèles Dockerfile/image/pool préchauffé et leurs builds de snapshots.

méthode fonction
list() · snapshots() sandbox de ce projet · snapshots construits
rebuildSnapshot(slug?) · fixWithAgent() reconstruire un snapshot · demander à un agent de corriger un build défaillant
createTemplate(input) · updateTemplate(...) · removeTemplate(...) · buildTemplate(...) ajouter · modifier · supprimer · construire un modèle
setProvider(provider) demander un changement de fournisseur. null (ou le fournisseur par défaut de la plateforme / le fournisseur déjà actif) s’applique immédiatement ; passer à un autre fournisseur activé lance une transition durable préparation→vérification→activation — le fournisseur actuel continue de servir pendant que l’image préchauffée cible est construite et vérifiée, puis activée. La valeur renvoyée est une union discriminée : kind:'project' (immédiat) ou kind:'preparation' (interroger getProjectSandboxProviderTransition() jusqu’à activated/failed)

Hooks d’administration de la plateforme (@beeuni/sdk/react)

Ces hooks servent la console d’administration. L’API n’y répond que pour un administrateur de la plateforme. Chaque mutation invalide les requêtes ['admin', 'accounts'].

Hook Fonction
useAdminRole(userId, options?) lire le rôle de l’appelant depuis GET /user-roles → { isAdmin, role }. userId sert de clé de cache. L’absence de userId désactive la requête. Recharge au montage et à la prise de focus, afin qu’un rôle révoqué cesse de conditionner l’accès en une navigation.
useAdminGrantCredits() mutation { accountId, amount, description, isExpiring } : ajouter du crédit au portefeuille. POST /admin/api/accounts/:id/credits. Déplace de l’argent : confirmer d’abord dans l’interface.
useAdminDebitCredits() mutation { accountId, amount, description } : retirer du crédit du portefeuille. POST /admin/api/accounts/:id/credits/debit. Déplace de l’argent : confirmer d’abord dans l’interface.
useAdminSetTier() mutation { accountId, tier } : définir le niveau de l’offre.
useAdminGrantTrial() mutation { accountId, tierKey, seats, durationDays, creditGrant?, note? } : accorder ou remplacer un essai. Le compte se comporte comme tierKey jusqu’à la fin de la période. creditGrant ajoute aussi du crédit au portefeuille.
useAdminRevokeTrial() mutation { accountId } : mettre fin immédiatement à un essai actif. Répond 400 si aucun essai n’est actif.

Accès direct

beeuni.runtime() renvoie le client REST runtime typé pour la sandbox active. Sur un client créé par createScopedBeeuni (@beeuni/sdk/server), il lève une exception — le runtime « actif » global au processus est la sandbox d’une autre requête dans un serveur multi-tenant, ce qui entraîne une fuite entre tenants. Utilisez plutôt beeuni.session(pid, sid).runtime, limité à la session (appelez d’abord ensureReady()), qui résout la sandbox propre à cette session.

Modules

Les modules indépendants de tout framework derrière la façade du client et les hooks React. Utilisez-les lorsque vous avez besoin d’une opération sans la façade, d’une fonction utilitaire pure ou d’une couche d’isolation réservée à Node. Chaque module indique un niveau de stabilité pour vous aider à choisir sur quoi vous appuyer.

Niveau Signification
Canonique Importez depuis la racine @beeuni/sdk. À utiliser pour tout nouveau code.
Pris en charge Un sous-chemin dédié (@beeuni/sdk/react, @beeuni/sdk/server). Pleinement pris en charge, non obsolète.
Alias obsolète Un ancien sous-chemin qui fonctionne encore. Il réexporte du code déjà exporté par la racine. Importez plutôt depuis la racine.
Interne Hors semver. Ne l’importez pas dans le code hôte.

Le point d’entrée racine est canonique. Chaque nom indépendant de tout framework ci-dessous peut être importé directement depuis @beeuni/sdk :

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

Modules canoniques

Module Fonction
Fichiers Opérations sur les fichiers de l’espace de travail : lister, lire, rechercher, écrire
Runtime de session Sonde d’état et générateurs d’URL d’aperçu/proxy
Client runtime Le client REST runtime typé et l’ensemble de ses types
Authentification authenticatedFetch et accesseurs de jetons
REST des projets Les fonctions REST brutes encapsulées par la façade
Client API backendApi, le client HTTP typé de bas niveau
Tours Regroupement des messages en tours, calcul des coûts et des statuts — voir Tours
Transcriptions formatTranscript, un export Markdown côté client
Listes de l’éditeur Les listes d’agents et de modèles de l’éditeur de session : lesquels proposer, lesquels exécuter

Fichiers

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

Les téléversements de plus de 64 Kio franchissent la frontière du sandbox par blocs vérifiés. Le callback de progression s’exécute après l’arrivée de chaque bloc dans le système de fichiers de la session.

uploadNativeFile({ uri, name, type? }, targetPath, baseUrl) téléverse un fichier de l’appareil depuis React Native en une seule requête. Le runtime diffuse les octets depuis uri, de sorte qu’ils n’entrent jamais dans le tas JS. Il utilise la même authentification, la même échéance et la même réexécution 401 que files.upload. Il ne découpe pas le fichier en blocs.

fetchProjectArchive, fetchCostExportCsv et les appels de version du sandbox passent par le même transport. Un échec lève une exception ApiError avec status.

files.write(path, blob) remplace le fichier à path et échoue si path est un dossier. files.create(path) crée un fichier vide sans jamais écraser : lorsqu’un fichier ou dossier existe déjà à path, il lève 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 cible le sandbox actif globalement. Si votre hôte exécute plusieurs sessions à la fois, appelez plutôt s.files sur le handle de session. Il cible toujours le sandbox propre à cette session. Voir Sessions.

Utilitaires du runtime de session

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

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

getSessionHealth ne lève jamais d’exception pour un statut non-2xx. Il renvoie { status, ok, health, body } et vous laisse décider de la signification du statut. Le même module exporte les utilitaires d’URL qui réécrivent la sortie localhost d’un agent en une URL proxy accessible : detectLocalhostUrls, rewriteLocalhostUrl, proxyLocalhostUrl, parseLocalhostUrl et buildWebProxyUrl.

Client runtime

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

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

getClient() renvoie le client de compatibilité runtime typé pour le sandbox actif, avec l’authentification déjà injectée. Préférez beeuni.session(pid, sid).runtime, le même client limité à une session, au client global getClient() lorsque votre hôte exécute plusieurs sessions.

Utilitaires d’authentification

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

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

Le jeton provient de la fonction getToken que vous avez passée à createBeeuni. La plupart du code applicatif n’a pas besoin de ce module : les couches de fichiers, de session et de façade assurent déjà l’authentification pour vous.

Client API

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

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

backendApi est le client HTTP typé sur lequel repose chaque fonction REST. Utilisez-le uniquement pour un endpoint qui n’a pas encore de wrapper typé.

Listes d’agents et de modèles de l’éditeur

Construisez les sélecteurs d’agent et de modèle d’un éditeur de session avec les mêmes règles que l’application web Beeuni. Chaque fonction est pure : récupérez les entrées avec le client, puis passez-les à la fonction.

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 renvoie explicit: undefined lorsque l’éditeur utilise sa valeur par défaut. model est la clé à afficher et à envoyer. Le id de chaque modèle aplati est la référence stockée par une sélection ; modelRefToKey(ref, gatewayEnabled) reconvertit une référence stockée (un épinglage de session, une liaison de canal, le model d’un déclencheur) en clé.

Sous-chemins pris en charge

Sous-chemin Fonction
@beeuni/sdk/react Hooks React — voir Hooks React
@beeuni/sdk/server Configuration limitée à une requête pour les backends multilocataires
@beeuni/sdk/wire-message-id L’horloge des identifiants de messages du protocole runtime seule (un module, aucun import). La racine exporte les mêmes noms

Identifiants de messages du protocole

Le messageId d’un prompt est sa position dans la transcription. runtime ordonne les messages selon msg_ + une horloge de 48 bits (Date.now() * 0x1000, les 48 bits de poids faible) + 14 caractères base62, et l’horloge revient à zéro toutes les 2^36 ms (environ 2,2 ans). Ne l’encodez jamais manuellement.

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

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

La création est antidatée de deux minutes, puis avancée d’un tick au-delà de l’identifiant le plus récent dans after qui n’est pas en avance de plus d’une heure. Un appelant qui conserve la position la plus récente sous forme d’horloge plutôt que d’identifiants utilise mintWireMessageIdAbove({ nowMs, newestKnownTime }), which returns { id, time }. newestWireIdClock(ids) pour trouver cette horloge. Chaque comparaison s’effectue sur l’anneau, de sorte que les identifiants de part et d’autre d’un retour à zéro conservent leur ordre réel.

L’horloge de 48 bits revient à zéro tous les ~2,2 ans ; ne comparez donc jamais deux horloges avec > ou <= : un identifiant créé juste après un retour à zéro est numériquement inférieur à un identifiant créé juste avant. Utilisez wireIdClockDelta(clock, reference), la distance signée sur l’anneau (positive lorsque clock est en avance), et maxWireIdClock(clocks) pour le plus récent parmi plusieurs :

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

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

Isolation côté serveur

createBeeuni stocke sa configuration, y compris la fonction de jeton, dans une variable unique à l’échelle du processus. Cela convient à un onglet de navigateur, à une CLI ou à un serveur monolocataire. Ce n’est pas sûr pour un serveur Node qui traite des requêtes simultanées pour différents utilisateurs, car le dernier appel à createBeeuni prévaut pour toutes les requêtes en cours. @beeuni/sdk/server corrige cela grâce à une isolation par requête :

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

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

createScopedBeeuni et runWithBeeuni isolent la configuration par requête avec AsyncLocalStorage de Node. N’importez jamais @beeuni/sdk/server dans un bundle pour navigateur : il importe statiquement node:async_hooks.

Le runtime() de premier niveau d’un client à portée limitée lève une exception (il résoudrait le sandbox d’un autre locataire). Accédez au runtime d’une session précise via beeuni.session(pid, sid).runtime après await s.ensureReady().

Alias obsolètes

Une vingtaine d’anciens sous-chemins fonctionnent encore : /files, /turns, /session, /auth, /projects-client, /api-client, /config, /event-stream, /opencode-client, /platform-client, entre autres. Chacun réexporte du code que le point d’entrée racine @beeuni/sdk exporte déjà. Ils continuent de fonctionner afin qu’aucun élément existant import breaks, but new code should import from the root.

Modules internes

@beeuni/sdk/internal/* contient les stores zustand utilisés en interne par le runtime propre à apps/web — état de synchronisation des sessions, suivi du runtime actif et gestion des reconnexions. Ce sous-chemin est explicitement hors semver. Ne l’importez pas dans le code hôte ; les hooks React exposent déjà l’état dont vous avez besoin.

Tours

Des fonctions simples qui regroupent les messages de session en tours et classent chaque partie de message. Utilisez-les pour construire un moteur de rendu de chat personnalisé plutôt que celui de référence dans apps/web. Ni React ni DOM : chaque export est une simple fonction ou un type, utilisable sans risque depuis n’importe quel hôte.

import { classifyPart, classifyTurn, toolInfo, toolViewModel } from '@beeuni/sdk';

Importez chaque fonction depuis le point d’entrée racine @beeuni/sdk. Le sous-chemin @beeuni/sdk/turns fonctionne encore, mais c’est un alias obsolète. Le nouveau code doit utiliser le point d’entrée racine — voir Distribution.

Classer une partie

classifyPart(part) normalise l’un des 12 types de parties du format de transcription Beeuni (beeuni.transcript.v1, BEEUNI_TRANSCRIPT_SCHEMA) en un ClassifiedPart — une union discriminée par kind. Chaque variante résout déjà les champs nécessaires au rendu : état de l’outil, sortie JSON analysée, détection d’images.

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 structure
text { id, text, synthetic } — ignorer les parties synthetic ; elles marquent le prompt synthétique du mode 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 type de partie inconnu de cette version du SDK

Une partie reçue non reconnue devient unknown à l’exécution au lieu de lever une exception. Cela permet à un ancien client de communiquer avec un serveur plus récent.

Une partie d’outil est classée dans 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) en construit un directement à partir d’une partie d’outil. Lisez ces champs plutôt que le state.metadata propre à un harness : la même carte affiche alors un edit runtime (filePath, filediff) et un edit pi (path, edits, un patch unifié).

Certains outils (web_search, image_search, appels de connecteurs) signalent state.status: 'completed' même lorsque leur corps JSON contient success: false. classifyPart le détecte et définit aussi ToolView.status sur 'error' dans ce cas.

classifyTurn(message) classe chaque partie d’un message de l’assistant et renvoie un ClassifiedTurn avec trois champs :

  • parts — chaque partie, classée
  • error — issu de message.info.error, le cas échéant
  • isEmpty — vrai lorsque le tour ne comporte aucune erreur ni aucune partie au contenu visible

Métadonnées des outils

toolKind(name) est la taxonomie unique des outils : elle associe le nom d’outil de n’importe quel harness (write de pi, oc-apply_patch d’runtime, pty_spawn d’un plugin) à un ToolKind — read, edit, write, bash, web_search, task, question, … ou other. Les familles de narration, les modèles de vue, les catégories toolInfo et le groupe d’outils de contexte en dérivent tous. inputPath(input) lit le chemin d’un outil de fichier depuis filePath, file_path ou path.

toolKind('oc-apply_patch'); // 'apply_patch'
toolKind('pty_spawn');      // 'pty'
inputPath({ path: 'app.py' }); // 'app.py'

Deux autres fonctions de recherche décrivent toutes deux un outil. Ne les confondez pas.

  • toolInfo(name) — sans icône, renvoie { label, category }. classifyPart l’utilise en interne. ToolCategory est 'shell' | 'files' | 'search' | 'edit' | 'web' | 'task' | 'other'.
  • getToolInfo(name, input) — avec prise en charge des icônes, renvoie { icon, title, subtitle } pour l’interface de référence des cartes d’outils. Le sous-titre provient de l’entrée de l’outil, par exemple un chemin de fichier ou une requête de recherche.
toolInfo('bash'); // { label: 'Shell', category: 'shell' }
getToolInfo('write', { filePath: '/workspace/main.go' });
// { icon: 'file-pen', title: 'Write', subtitle: 'main.go /workspace' }

Les deux fonctions reconnaissent les préfixes des noms d’outils ; les familles d’outils des plugins Beeuni (agent_*, session_*, task_*, trigger_*, project_*, pty_*) sont donc résolues sans mise à jour du registre. Un nom d’outil inconnu ne lève jamais d’exception — il se rabat sur humanizeToolName(name) avec la catégorie 'other'.

Modèles de vue des outils

toolViewModel(classifiedTool) associe une partie d’outil classée à une structure conçue pour une famille d’outils. Une interface peut alors lui appliquer un rendu spécifique plutôt que de l’afficher comme un bloc JSON générique.

const vm = toolViewModel(classifiedTool);
if (vm.kind === 'shell') {
  render(vm.command, vm.stdout, vm.exitCode);
}
kind structure outils
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? } tout le reste, toujours affichable sans risque

DiffLine est { type: 'added' | 'removed' | 'unchanged', text }. Les champs de type chaîne sont plafonnés pour qu’une sortie d’outil volumineuse ne perturbe jamais le rendu : 4000 caractères pour le JSON mis en forme, 256 Ko avant l’exécution d’un diff.

Regrouper les messages en tours

Un tour associe un message utilisateur aux messages de l’assistant qui y ont répondu. C’est l’unité qu’une interface de chat affiche comme un échange.

import { groupMessagesIntoTurns, collectTurnParts, type TurnLike } from '@beeuni/sdk';

const turns: TurnLike[] = groupMessagesIntoTurns(messages);
for (const turn of turns) {
  const parts = collectTurnParts(turn);
}

groupMessagesIntoTurns relie chaque message de l’assistant à son message utilisateur parent. Il se rabat sur l’ordre des messages lorsqu’un lien parent manque. Il rattache aussi un message de l’assistant orphelin — sans parent et précédant tous les messages utilisateur — au premier tour, et non au dernier.

Fonctions utilitaires associées :

  • findLastTextPart(parts) — le texte de la réponse finale du tour
  • turnHasSteps(parts) — vrai si une partie tool, compaction, snapshot ou patch existe
  • isShellMode(turn) / getShellModePart(turn) — un tour constitué d’un prompt synthétique déclenchant un appel bash

Gardes de type

Affinez le type d’une partie par 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

Également disponibles : isReasoningPart, isFilePart, isAgentPart, isCompactionPart, isSnapshotPart, isPatchPart, isStepPart (step-start et step-finish).

État et erreurs

import { getWorkingState, getTurnStatus, formatDuration } from '@beeuni/sdk';

const status = getTurnStatus(parts, childMessages); // "Running commands..."
formatDuration(4300); // "4s" — durations under 1s return ''

getTurnStatus parcourt les parties d’un tour pour trouver la dernière ligne d’état. Lorsque la dernière partie est une délégation task en cours, passez childMessages pour que l’état affiche l’activité réelle du sous-agent plutôt qu’une ligne générique « Délégation en cours… ».

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

Totaux des coûts et des tokens

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"

Les deux fonctions lisent les totaux des coûts et des tokens depuis les parties step-finish. Lorsqu’une partie indique zéro, elles estiment le coût à partir du nombre de tokens à l’aide d’un ModelPricingLookup.

Les messages liés à un abonnement ChatGPT/Codex contribuent à hauteur de $0.00, y compris les messages historiques dont les coûts d’exécution sont non nuls. L’utilisation des tokens et du contexte reste visible. Les sessions mixtes conservent les frais des messages d’API payants. Les modèles de l’API OpenAI restent facturables, y compris ceux dont le nom contient codex.

Sessions enfants et demandes en attente

L’arbre de conversation d’une session de projet (la racine et les conversations des sous-agents qu’elle a créées) provient de sa liste runtime_sessions. Ces fonctions utilitaires le lisent, en privilégiant les noms actuels plutôt que ceux d’avant 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

Un appel d’outil task délègue à une session enfant. Ces fonctions utilitaires relient un tour parent aux messages propres à cet enfant.

import { getChildSessionId, getChildSessionToolParts } from '@beeuni/sdk';

const childId = getChildSessionId(taskToolPart);
const steps = getChildSessionToolParts(childMessages);

Associez une demande d’autorisation ou une question en attente à son appel d’outil et déterminez quelles parties d’outil masquer tant qu’une demande est active :

import { getPermissionForTool, getHiddenToolParts, isToolPartHidden } from '@beeuni/sdk';

const permission = getPermissionForTool(permissions, callID);
const hidden = getHiddenToolParts(activePermission, activeQuestion);

Mise en forme et listes

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"

Les fonctions utilitaires de liste de sessions opèrent sur les mêmes données de session :

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

État de nouvelle tentative : getRetryInfo(sessionStatus) renvoie { attempt, message, next, details? } when status.type === 'retry', with message limité à 60 caractères. details préserve une enveloppe structurée de passerelle LLM lorsqu’elle est présente : le fournisseur final, le code de passerelle, l’identifiant de requête, la suggestion, l’état en amont et les échecs des candidats dans l’ordre. Chaque échec de candidat contient attempt, provider, routeModel, resolvedModel, stage, éventuellement status, code et message. Les anciennes nouvelles tentatives en texte brut renvoient details: undefined. getRetryMessage(sessionStatus) renvoie le message complet extrait de son enveloppe. Lorsque runtime ne conserve que ce message, le composite de passerelle inclut toujours l’identifiant de requête ainsi que le fournisseur, le modèle résolu, le statut HTTP, le code et le message de longueur limitée de chaque candidat.

Types structurels

Les fonctions de regroupement et de statut acceptent des types structurels minimaux — PartLike, MessageInfoLike, TurnLike, ToolStateLike, SessionStatusLike — plutôt que les types concrets de transcription. Vos propres structures de messages et de parties sont transmises sans modification tant qu’elles correspondent aux champs requis. classifyPart et classifyTurn font exception. Leur typage repose sur l’union Beeuni Part (beeuni.transcript.v1), de sorte que leur vérification d’exhaustivité détecte tout nouveau type de partie lors de la compilation.

Distribution

npm install @beeuni/sdk

Le package est distribué en ESM compilé avec des déclarations de types TypeScript complètes. react et @tanstack/react-query sont des dépendances homologues facultatives. Si vous utilisez @beeuni/sdk/react, installez les deux.

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

Points d’entrée et stabilité

Le point d’entrée racine, @beeuni/sdk, est canonique. Il exporte toute l’interface indépendante des frameworks et fonctionne dans les navigateurs, Node 18+, Bun et les environnements d’exécution edge.

Point d’entrée Niveau Contrat
@beeuni/sdk Canonique Indépendant des frameworks. N’importe jamais React ni node:*.
@beeuni/sdk/react Pris en charge Hooks React. Le seul point d’entrée qui importe React.
@beeuni/sdk/server Pris en charge Isolation de la configuration par requête pour les serveurs Node et Bun, via node:async_hooks. Ne jamais l’inclure dans un bundle destiné au navigateur.
Anciens sous-chemins (/projects-client, /turns, /files, et d’autres) Obsolètes Fonctionnent toujours. Chacun réexporte depuis la racine. Importez plutôt depuis la racine.
@beeuni/sdk/internal/* Interne Utilisé uniquement par l’application web Beeuni. Ce n’est pas une API prise en charge.

Bundles CDN

Le package fournit également deux bundles pour navigateur, générés par tsup : un bundle ESM (dist/beeuni.esm.min.js) et un bundle global IIFE (dist/beeuni.global.js) qui définit 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 expose le même point d’entrée racine que l’import npm : Beeuni.createBeeuni, Beeuni.classifyTurn, Beeuni.ApiError.

Voir aussi

  • SDK — installation et première session.
  • Sessions — cycle de vie, streaming et gestion des erreurs.
  • Hooks React — la couche réactive construite sur ces modules.

Accès de l’agent au dépôt

La configuration de l’agent accepte repository_access?: boolean (par défaut true). Définissez false pour exécuter de nouvelles sessions sans accès au dépôt du projet ni à l’API du dépôt. Les autorisations Git, de secrets, de connecteurs et d’outils restent distinctes. Les sessions existantes conservent leur politique enregistrée. AgentConfigBlock.workspace est obsolète. Le SDK convertit les anciennes valeurs branch/runtime vers le champ booléen. Une écriture avec l’ancienne valeur read nécessite un choix explicite repository_access ; elle n’active pas l’accès au dépôt en lecture seule.

Accès aux fournisseurs et aux modèles

Consultez beeuni.projects.modelAccess(projectId). Modifiez une cible avec beeuni.projects.setModelAccess(projectId, { target: 'provider' | 'model', id, enabled }).

Utilisez l’identifiant de fournisseur beeuni pour Beeuni Managed Models, ou un identifiant de fournisseur du catalogue pour BYOK, Codex et les fournisseurs personnalisés. Utilisez l’identifiant complet du modèle dans le protocole de la passerelle. La désactivation d’un fournisseur s’applique aux futurs modèles et préserve les préférences individuelles des modèles ainsi que les identifiants enregistrés.

Le modèle par défaut actuel et son fournisseur nécessitent un remplacement avant leur désactivation (409 cannot_disable_default). Les requêtes directes à la passerelle visant des cibles désactivées échouent avec model_disabled ou provider_disabled. Les requêtes en amont déjà en cours se terminent normalement. L’indicateur enforced de la réponse est faux lorsque le projet utilise runtime natif plutôt que la passerelle.

Les utilisateurs de React utilisent useModelAccess(projectId) depuis @beeuni/sdk/react. Sa mutation setEnabled(change) actualise le catalogue de gestion et le sélecteur de session.

Cette page vous a-t-elle été utile ?