# SDKリファレンス

@beeuni/sdk APIの全体 — クライアントメソッド、モジュール、ターン、配布。

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

このページでは、`@beeuni/sdk` の全 API を紹介します。すべてのクライアントメソッド、
フレームワークに依存しないモジュール、ターンのヘルパー、パッケージの配布形式を扱います。
使い始めるには [SDK](/docs/ja/sdk) を、セッションのライフサイクルの詳細については
[セッション](/docs/ja/sdk/sessions) を参照してください。

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

## クライアント

`createBeeuni(config)` は 1 つのクライアントを返します。各メソッドは、プラットフォーム API への型付き呼び出しです。
`project(id)` と `session(pid, sid)` のハンドルは ID をバインドするため、
繰り返し指定する必要はありません。

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

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

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

### アカウント — `beeuni.accounts`

| メソッド | 内容 |
| --- | --- |
| `list()` · `get(accountId)` | 所属するアカウント · 1 つのアカウント |
| `create({ name })` · `updateName(accountId, name)` | アカウントの作成 · 名前の変更 |
| `branding.get(accountId)` · `branding.update(accountId, { app_name })` · `branding.uploadAsset(accountId, kind, file)` · `branding.removeAsset(accountId, kind)` · `branding.reset(accountId)` | 組織のブランディング（Enterprise）：独自のロゴ / アイコン / favicon と製品名。`kind` は `logo` · `icon` · `favicon`、ダーク配色用は `logo_dark` · `icon_dark` · `favicon_dark` |
| `members(accountId)` · `invite(accountId, input)` | メンバーの一覧 · 招待 |
| `updateMemberRole(accountId, userId, role)` · `removeMember(accountId, userId)` | アカウントロールの割り当て · メンバーの削除 |
| `invites(accountId)` | 保留中の招待 |
| `cancelInvite(accountId, inviteId)` · `resendInvite(accountId, inviteId)` | 保留中の招待のキャンセル · 再送 |
| `leave(accountId)` | アカウントから退出 |

`accounts.tokens` はアカウントスコープの API キー（`beeuni_pat_...`）を発行します。
トークンモデルの詳細は [SDK 認証](/docs/ja/accounts#tokens) を参照してください。

| メソッド | 内容 |
| --- | --- |
| `tokens.list(accountId?, options?)` | API キーの一覧 — アカウント全体、または `{ mine: true }` で自分のキーのみ |
| `tokens.create(input)` | 1 つ発行 — `{ accountId?, name, expiresAt?, projectId? }` |
| `tokens.revoke(tokenId, accountId?)` | 1 つ失効 |

`accounts.audit` はエンタープライズ向けの再構成ログです。認証済みの API リクエストと、
セッション、コネクター、承認、コンピューターに関する意味情報を持つイベントを統合します。

| メソッド | 内容 |
| --- | --- |
| `audit.log(accountId, filters?)` | プロジェクト、セッション、実行主体、ソース、結果、リクエスト、相関、リソース、アクション、時刻でイベントを一覧表示 |
| `audit.export(accountId, filters?)` | 同じフィルター済みイベントストリームを CSV または JSONL でエクスポート |
| `audit.webhooks.list/create/update/remove(...)` | 集約ストリーム用の署名付き SIEM Webhook を管理 |

各イベントには、アクションが提供する場合、`project_id`、`session_id`、`actor_type`、`source`、`outcome`、
`request_id`、`trace_id`、`correlation_id` が含まれます。
API は、リクエスト本文、プロンプト、シークレット、認証情報、未加工のコネクター引数を
集約イベントに保存しません。コネクターイベントには、認証情報らしきフィールドと不透明なデータを伏せた、
範囲を限定した引数プレビューを含めることができます。

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

### アクセスの割り当て

Beeuni の権限付与レコードは **assignment（割り当て）** の 1 種類です。1 つのプリンシパル（`user`、
`group`、`service_account`、`pending`）を、1 つのスコープ（`account`
または 1 つの `project`）で 1 つのロールにバインドします。任意で 1 つのオブジェクト（`agent`、`skill`、`secret`、
`app`、`trigger`）に限定したり、`expires_at` を付加したりできます。グループアクセス、
リソースごとのアクセス、カスタムロールのバインドはすべて割り当てです。モデルについては
[アカウントとアクセス](/docs/ja/accounts#one-access-model) を参照してください。

標準の REST API は次のとおりです。

| メソッド + パス | 動作 |
| --- | --- |
| `GET /v1/accounts/{accountId}/iam/assignments` | プリンシパル、スコープ、オブジェクト、ロールで絞り込んだ割り当ての一覧 |
| `POST /v1/accounts/{accountId}/iam/assignments` | 1 つの割り当てを作成 |
| `DELETE /v1/accounts/{accountId}/iam/assignments/{assignmentId}` | 1 つの割り当てを取り消し |
| `GET /v1/accounts/{accountId}/iam/permissions` | 権限カタログをデータとして取得 |
| `GET /v1/accounts/{accountId}/iam/roles` · `…/roles/{roleId}/permissions` | ロール · 1 つのロールの権限 |

SDK では、これらを `listAssignments`、`createAssignment`、
`revokeAssignment`、`listPermissions` として公開しています。カタログの各行には `action`、
`scope_type`、`resource_type`、`delegable`、`description`、`area`、`level`、
`implies` が含まれます。アクション文字列をハードコードせず、これを読み取ってください。

カスタムロールの割り当てには、アカウントの `rbac` 利用資格が必要です。これがない場合、ルートは
`code: "entitlement_required"` を伴う `402` を返します。

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

### アカウントへの招待 — `beeuni.accountInvites`

招待トークンだけでアクセスできます。招待された人は、まだメンバーでない場合があります。

| メソッド | 内容 |
| --- | --- |
| `listMine()` | 自分のメールアドレス宛ての、有効期限内の保留中のすべての招待。アクセスが付与されるワークスペースとプロジェクトを含む |
| `describe(inviteId)` · `accept(inviteId)` · `decline(inviteId)` | 招待のプレビュー · 承諾 · 辞退 |

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

### プロジェクト — `beeuni.projects`

| メソッド | 内容 |
| --- | --- |
| `list()` · `listForAccount(accountId)` | 自分のプロジェクト · アカウント内のプロジェクト |
| `get(id)` · `detail(id)` | 概要 · 詳細全体 |
| `create(input)` · `createRepo(input)` | 既存の `repo_url` から · 新しい空の GitHub リポジトリ |
| `provision(input)` | スターターテンプレートを初期配置した、Beeuni 管理の新しいリポジトリ上の新規プロジェクト — `{ name, account_id?, seed_starter?, starter_template?, marketplace_items?, source_item_id?, idempotency_key? }` |
| `update(id, input)` · `archive(id)` | 設定の更新 · アーカイブ |
| `llmCatalog(id)` · `modelPicker(id)` | セレクター用の完全版 · コンパクト版モデルカタログ |
| `sandboxTemplates(id)` · `sandboxHealth(id)` | サンドボックスのビルドテンプレート · ビルドの健全性 |
| `sessions(id)` · `createSession(id, input?)` | 表示可能なセッションの一覧 · セッションの作成 |

`provision` は新しいプロジェクトを作成します。既存プロジェクトの
サンドボックスは起動しません。代わりにセッションを開始してください。[セッション](/docs/ja/sdk/sessions) を参照してください。

再読み込み、別のタブ、タイムアウト後の再試行など、再試行が起こり得る場合は
`idempotency_key` を送信してください。`provision` は呼び出しごとに新しい管理対象リポジトリを作成するため、
キーがなければ、それぞれが実際に重複プロジェクトを作成します。論理的に 1 回の作成に対するすべての
試行で同じキーを使うと、繰り返しの呼び出しは最初の試行で作成したプロジェクトを返します
（201、同じ `project_id`、`push_token: null`）。キーが識別するのは
試行であり、ペイロードではありません。異なる `name` で同じキーを再利用すると、最初の
プロジェクトを返し、新しい値を無視します。そのため、別の作成ごとに新しいキーを発行してください。
キーなしで同じ**名前**の 2 つ目のプロジェクトを作成することもできます。

最初の呼び出しがまだプロビジョニング中に繰り返しの呼び出しが届くと、その呼び出しがまだロールバックする可能性のある
`project_id` ではなく、`code: 'provision_in_flight'` を伴う `409` が返されます。
同じキーで再試行してください。

`project(id).sessions.list({ scope: 'project' })` は、プロジェクト管理者権限を持つ
呼び出し元向けのライフサイクル一覧です。アクセス可能な、利用不可、ウォーム状態、ソフト削除済みのセッションを、
所有者とランタイム状態のメタデータ付きで追加します。どちらの一覧スコープも、
呼び出し元が開けないセッションはすべて除外します。

`sessions.list` と `sessions.listPage` は、階層と帰属の
フィルターも受け付けます。指定しなければ、一覧はフラットなまま変わりません。

| オプション | 内容 |
| --- | --- |
| `parent: 'root'` | 最上位のセッションのみ。各行に `child_count` が含まれます。 |
| `parent: '<sessionId>'` | そのセッションの子セッションを新しい順に表示。 |
| `startedBy: 'me' \| 'others' \| 'automated'` | 呼び出し元を基準に `initiator` で絞り込み。 |
| `q` | 呼び出し元が開けるすべてのセッションを対象に、タイトル、スターターラベル、トリガースラッグ、セッション ID のプレフィックスを大文字・小文字を区別せず検索。`parent: 'root'` を指定すると、子を通じて一致したルートには `search_match: 'child'` が含まれます。 |

各セッション行には `parent_session_id` と `initiator`
（`{ type: 'member' | 'trigger' | 'channel' | 'api' | 'system', id, label }`）があります。
`initiator` は実行全体を開始した人を示し、子は親の値をコピーします。
`sessionParentId(session)` は `parent_session_id`、次に従来の
`metadata.spawned_by_session` を読み取ります。カーソルは、それを発行したフィルターの組み合わせでのみ
有効です。

### GitHub — `beeuni.github`

GitHub App のインストールとリポジトリのリンクは、プロジェクトスコープではなくアカウントスコープです。

| メソッド | 内容 |
| --- | --- |
| `getInstallation(accountId)` · `listInstallations(accountId)` | このアカウントのインストール · ユーザーがアクセスできるインストール |
| `saveInstallation(input)` · `deleteInstallation(accountId, installationId?)` | インストールを記録 · リンク解除 |
| `listLinkableInstallations(input)` | 認可済みのGitHubユーザーがリンクできるインストール。各エントリの`linked_to_other_accounts`は、それを保持する他のBeeuniアカウントの数であり、名前は一切含まれません |
| `listRepositories(accountId, installationId?)` · `listRepositoryBranches(...)` | インストールから参照できるリポジトリ · ブランチとGitHubのデフォルト |
| `linkRepository(input)` | 認可済みのGitHubインストールを使って、リポジトリをプロジェクトとしてインポートします。 |
| `replaceProjectRepository({ project_id, repo_url, expected_repo_url, github_token })` | 既存プロジェクトのGitHubリポジトリを置き換えます。Contentsの読み書き権限を持つ`github_token`、または`installation_id`と一時的な`github_user_token`を使って組織の管理者権限を確認し、GitHub App経由でこのリポジトリだけにアクセスを許可します。`copy_shared_secrets_from_project_id`と`copy_shared_secret_identifiers`を併用すると、選択した共有ランタイムシークレットを同じトランザクション内でコピーします。古い`expected_repo_url`は409を返します。元のリポジトリはGitHubに残ります。新しいセッションは置き換え後のリポジトリを使い、既存のセッションはチェックアウトを保持します。 |

このリストには実際のアカウント接続だけが含まれます。「Beeuni managed」は
含まれません。これは以下のインスタンスバックエンドです。

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

### インスタンスのgitバックエンド — `beeuni.gitBackend`

デプロイ全体で1つの所有者と認証情報を使用し、Beeuni管理の
リポジトリに使います。アカウント接続になることはなく、
`beeuni.github.listInstallations`にも表示されません。

| メソッド | 内容 |
| --- | --- |
| `get()` | `{ configured, kind: 'app' \| 'pat' \| null, owner }` — 認証済みユーザーなら誰でも読み取り可能。すべての管理対象`repo_url`にすでに含まれている所有者のログイン名だけを公開します |

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

### 請求 — `beeuni.billing`

クレジット、サブスクリプション、プラン、取引履歴を取得します。支払いやクレジット購入には Beeuni の決済と請求管理を使用します。

| メソッド | 内容 |
| --- | --- |
| `accountState(accountId?)` · `accountStateMinimal(accountId?)` | 完全な請求状態 · 最小限の請求状態 |
| `transactions(params?)` · `transactionsSummary(params?)` | 履歴 · 合計の要約 |
| `creditBreakdown(accountId?)` · `usageHistory(params?)` | ソース別クレジット残高 · 時系列の使用量 |
| `sessionCosts.list(options?)` · `sessionCosts.get(sessionId, options?)` | ページ分割されたセッション費用の記録 · 1セッションの詳細台帳 |
| `tierConfigurations()` | 利用可能なプラン階層 |
| `checkout.createSession(input)` · `checkout.confirmSession(sessionId, accountId?)` | **非推奨。** `ENDPOINT_RETIRED`で拒否します。次のメジャーバージョンで削除されます。 |
| `subscription.createPortalSession(...)` · `subscription.cancel(...)` · `subscription.reactivate(...)` | カスタマーポータルを開く · 解約 · 再有効化 |
| `subscription.cancelScheduledChange(...)` · `prorationPreview(...)` | 解約 · プラン変更をプレビュー |
| `subscription.scheduleDowngrade(...)` | **非推奨。** `ENDPOINT_RETIRED`で拒否します。プランはカスタマーポータルで変更してください。次のメジャーバージョンで削除されます。 |
| `credits.purchase(input)` · `credits.autoTopupSettings(...)` · `credits.configureAutoTopup(...)` | 単発購入 · 読み取り · 自動チャージの設定 |

`sessionCosts.list()`は`accountId`、`projectId`、`limit`、`offset`を受け付けます。
各行は、確定したLLM費用と請求済みのサンドボックス計算費用をまとめたものです。
`sessionCosts.get()`はモデル使用量と、LLM/計算を区別した台帳を追加します。
リストには、セッションに紐づかない費用の照合用合計も含まれます。

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

### サンドボックス共有 — `beeuni.sandboxShares`

公開されたサンドボックスポート1つに対する公開共有リンク。
プロジェクト単位ではなく、サンドボックス単位です。

| メソッド | 内容 |
| --- | --- |
| `list(sandboxId)` | 有効な共有リンク |
| `create(input)` | 1つ作成 — `{ sandboxId, port, ttl?, label? }` |
| `revoke(sandboxId, token)` | 1つ失効 |

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

### マーケットプレイスカタログ — `beeuni.marketplace`

公開カタログの閲覧専用。プロジェクトにアイテムをインストールする
`project(id).marketplace`とは異なります。

| メソッド | 内容 |
| --- | --- |
| `items(options?)` · `item(id)` · `itemFile(id, path)` | 閲覧 · 1つのアイテム · アイテム内のファイル |
| `marketplaces()` · `featured()` | すべてのマーケットプレイス · おすすめのマーケットプレイス |
| `sources.list()` · `sources.add(input)` · `sources.remove(id)` | ソースを一覧表示 · 追加 · 削除 |

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

### 通知 — `beeuni.notifications`

すべてのアカウントとプロジェクトにわたる呼び出し元の通知。サインインした
各ユーザーは、受信トレイ1つ、設定レコード1つ、ブラウザー用のWeb Pushサブスクリプションを持ちます。
すべてのメソッドに個人の認証情報が必要です。サービスアカウントには
`403`が返されます。

> **通知は機能フラグです**
>
> Beeuniが受信トレイの行を書き込み、Web Pushとメールを送信するのは、
> `notification_center`フラグがオンのプロジェクトだけです。デフォルトではオフです。`list()`は、
> フラグがオフのプロジェクトの行を除外します。`session(pid, sid).watch()`と`.setWatch()`は、
> オフの間、`403`に`{ error, code: "feature_disabled", feature: "notification_center" }`で応答します。
> `isFeatureDisabledError(error)`を使って条件分岐してください。
> 設定、Web Pushサブスクリプション、デバイストークンは個人単位で、
> フラグの状態にかかわらず機能します。フラグがオフでも、ターンが終了、失敗、質問、
> または権限を要求したとき、セッション作成者のスマートフォンにはプッシュ通知が届きます。
> [機能フラグ](/docs/ja/feature-flags)と[通知](/docs/ja/work/notifications)を参照してください。

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

| メソッド | 内容 |
| --- | --- |
| `list({ limit?, before? }, { signal? })` | 最新のページ：`{ notifications, unread_count, next_before }`。`limit`は1～50（デフォルト20）です。次のページには`next_before`を`before`として渡します。呼び出し元が参照できなくなった行は除外されます。失敗してもホストのエラーハンドラーは呼び出されません。 |
| `markRead({ ids })` · `markRead({ all: true })` · `markRead({ sessionId })` | 1～100行、すべての行、または1つのセッションのすべての行を既読にします。呼び出し元の行だけを変更します。`{ updated, unread_count }`を返します。 |
| `preferences()` · `updatePreferences({ kinds })` | 種類ごとのプッシュとメールの選択を読み取り · 変更。`{ kinds, email_available }`を返します。パッチは指定された種類とチャネルだけを変更します。 |
| `webPushPublicKey()` | `{ public_key }`：`pushManager.subscribe`用の`applicationServerKey` |
| `registerWebPushSubscription({ endpoint, keys })` | このブラウザーにプッシュ通知を配信します。ブラウザーでのサインインが必要です。個人トークンには`403`が返されます。未知のプッシュサービスのエンドポイントには`400`が返されます。 |
| `unregisterWebPushSubscription(endpoint, { signal? })` | このブラウザーへのプッシュ通知を停止します。`{ deleted }`を返します。 |
| `registerDeviceToken(input)` · `unregisterDeviceToken(token, { signal? })` | ネイティブアプリのExpoプッシュトークンを登録 · 削除 |

種類（`InboxNotificationKind`、`INBOX_NOTIFICATION_KINDS`に記載）：

| 種類 | 送信タイミング | プッシュ | メール（デフォルト） |
| --- | --- | --- | --- |
| `turn_done` | 自分がプロンプトを送った、またはウォッチしているターンが終了したとき | オン | オフ |
| `turn_error` | そのターンがエラーで終了したとき | オン | オン、ダイジェストで送信 |
| `question` | エージェントが質問したとき | オン | オン、ダイジェストで送信 |
| `permission` | エージェントが権限を要求したとき | オン | オフ |
| `shared` | 誰かが自分にセッションを共有したとき | オン | オン、ダイジェストで送信 |
| `automation_failed` | ウォッチしている自動化が失敗し始めたとき | オン | オン、即時送信 |
| `automation_recovered` | その自動化が再び正常に動作したとき | オン | オフ |

`DEFAULT_NOTIFICATION_PREFERENCES`がこれらのデフォルト値を保持します。受信トレイの行は
常に書き込まれ、設定が決めるのはプッシュとメールだけです。ダイジェストメールには、
到着から15分後も未読の行が記載され、送信は1時間に最大1通です。
`email_available`が`false`の場合はメール列を非表示にしてください。

各行の`url`はその対象を開きます。`?notification=<id>`クエリにより、
ページはその行を既読にできます。

セッションハンドルは、1つのセッションに対する呼び出し元のウォッチ状態を保持します。

| メソッド | 内容 |
| --- | --- |
| `session(pid, sid).watch()` | `{ watching }`：呼び出し元がこのセッションの通知を受け取るかどうか |
| `session(pid, sid).setWatch(watching)` | `false`は呼び出し元に対してセッションをミュートし、`true`は再びウォッチします。セッションにプロンプトを送るとウォッチしますが、ミュートを解除することはありません。 |
| `session(pid, sid).presence({ tab_id, active, alerts? }, { keepalive? })` | このタブのプレゼンスリース。`alerts: true`はタブが独自の通知を表示することを示します。`notification_center`がオンの場合、通知を表示するタブが使用中の間だけ、サーバーはスマートフォンとWeb Pushへの通知を省略します。オフの場合、`alerts`は無視され、存在するタブがあればスマートフォンへのプッシュ通知が抑制されます。`keepalive`により、ページを閉じた後もリクエストを継続できます。デフォルト：不在の報告ではオン、在席の報告ではオフ。`useSession`は`presencePageExit`の場合にのみ`keepalive`を送信します。 |

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

### プロジェクトハンドル — `beeuni.project(id)`

プロジェクトIDをバインドします。すべてのサブリソースはこれに紐づきます。

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

| メソッド | 内容 |
| --- | --- |
| `get` · `detail` · `update` · `archive` | 読み取り · 全詳細 · 更新 · アーカイブ |
| `llmCatalog` · `modelPicker` · `sandboxHealth` | モデルとサンドボックスビルドの読み取り |
| `onboardingComplete` | プロジェクトのオンボーディングを完了としてマーク |
| `validateManifest(raw)` | `beeuni.yaml`（または旧形式の`beeuni.toml`）マニフェストをサーバー側で検証 |
| `gitToken()` | スコープ付きの新しいgit pushトークンを発行（持ち込みリポジトリの場合は`409`） |
| `setAgentScope(agentName, scope)` | マニフェストでエージェントに許可するシークレットとコネクタを設定 — ロールではなく、2つ目のバインディング |

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

#### `p.tokens` — プロジェクトスコープのAPIキー

セッション作成時に`BEEUNI_TOKEN`として自動発行されます。手動でも発行できます。

| メソッド | 内容 |
| --- | --- |
| `list()` | プロジェクトのAPIキー |
| `create(input?)` | 新しいキーを発行 |
| `revoke(tokenId)` | キーを失効 |

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

#### `p.setupLinks` — エージェントが発行するセットアップリンク

プロジェクト全体へのアクセス権なしで、ユーザーが開いてシークレットを入力したり、アプリを接続したりできるリンクです。

| メソッド | 内容 |
| --- | --- |
| `requestSecret(input)` · `requestConnector(input)` | シークレットを収集するリンク · アプリを接続 |

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

#### `p.apps` — Apps（リリース、マシン、ボリューム）

プロジェクト機能`apps`で有効になります。ガイド：[SDK → Apps](/docs/ja/sdk/apps)。

| メソッド | 内容 |
| --- | --- |
| `list()` · `get(appId)` · `create(input)` · `update(appId, input)` · `remove(appId)` | インベントリとライフサイクル。`create`は`uses`を受け取り、`update`は`labels`も受け取ります |
| `deployments.*` · `artifacts.*` · `access.*` · `rollback` · `start` · `stop` | デプロイ、アーティファクト、アクセスポリシー、トラフィック、ランタイム |
| `machines.list/start/stop/restart/destroy` · `scale(appId, count)` · `exec(appId, input)` | プロセスグループごとのマシン。`exec`には`project.app.admin`が必要 |
| `volumes.list/create/update/destroy/snapshots/snapshot/restore/fork` | 永続ボリューム、日次スナップショット、復元、フォーク |
| `token(appId)` | 有効期間15分のサインイントークン。`member_tokens`なしの`409 app_capability_unsupported` |

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

#### `p.secrets` — プロジェクトのシークレット

| メソッド | 内容 |
| --- | --- |
| `list()` · `upsert(input)` | メタデータを一覧表示 · 書き込み専用の値と配信ポリシーを作成または更新 |
| `setStrategy(identifier, strategy, options?)` | 公開方式とそのホストリストを変更 |
| `broker(identifier, request)` | セッションで認可され、ポリシーに制約されたHTTPSリクエストを実行 |
| `remove(identifier)` | シークレットを削除 |
| `setPersonal(name, value)` · `removePersonal(name)` | ユーザーごとのオーバーライドを設定 · 削除 |
| `setGitCredential(input)` | git認証情報を設定 |

コンシューマー`sandbox`を指定した`runtime`は、**環境変数**による公開です。これがデフォルトで、セッションに平文の値を配置する唯一のポリシーです。コンシューマー`network`を指定した`egress`は、**エグレス強制**による公開です。セッションはハンドルを保持し、Beeuniがサンドボックスの外で、ポリシーに列挙されたHTTPSホストに限り実際の値を代入します。エグレス強制による公開は実験的機能で、`secrets_egress`機能フラグ（Settings → Feature flags）が必要です。フラグがオフの場合、エグレスポリシーを指定した`setStrategy(identifier, 'egress', …)`と`upsert(...)`は`403` `feature_disabled`を返します。すべての`broker`コンシューマーは、セッション内には一切存在しません。[シークレット](/docs/ja/project/secrets)を参照してください。`broker(...)`メソッドには、セッションスコープのトークンとアクティブなセッションハンドルが必要です。

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

#### `p.access` — プロジェクトの割り当て、招待、リクエスト

ここにあるすべてのメソッドは、このプロジェクトにスコープを限定した割り当てを読み書きします。プロジェクトのロールは`manager`と`member`です。

| メソッド | 内容 |
| --- | --- |
| `list()` · `invite(email, role)` | アクセス権を持つプリンシパル · ユーザーを招待 |
| `update(userId, role)` · `revoke(userId)` | プロジェクトロールを割り当て · 割り当てを取り消し |
| `pendingInvites()` · `requests()` | 未完了の招待 · 保留中のアクセスリクエスト |
| `resendInvite(inviteId)` · `revokeInvite(inviteId)` · `approveRequest(id)` · `rejectRequest(id)` | 招待を再送/取り消し · リクエストを承認/拒否 |
| `groupGrants()` · `attachGroupGrant(...)` · `updateGroupGrant(...)` · `detachGroupGrant(...)` | `group`プリンシパルに対する同じ割り当て |

`p.access.resourceGrants`は**オブジェクト割り当て**ビューです。プリンシパルの対象を、プロジェクト全体ではなく、プロジェクト内の1つのオブジェクトに限定します。Beeuniは現在、エージェントとスキルにオブジェクト割り当てを適用しています。エージェントはデフォルトでアクセス不可です。メンバーは、自分自身または所属グループのいずれかが割り当てに指定されている場合にのみアクセスできます。オブジェクト割り当て自体には権限はなく、プロジェクトマネージャーにもメンバーと同じ制限が適用されます。

| メソッド | 内容 |
| --- | --- |
| `resourceGrants.list()` | このプロジェクトのオブジェクト割り当て |
| `resourceGrants.create(input)` | 1つのオブジェクトをユーザーまたはグループに割り当て |
| `resourceGrants.remove(grantId)` | 1つのオブジェクト割り当てを取り消し |

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

#### `p.connector(slug)` — 単一のコネクタ

| メソッド | 内容 |
| --- | --- |
| `run(action, args, options?)` | アクションの出力。`ConnectorCallError`または`ConnectorApprovalPendingError`をスロー — [エラー](/docs/ja/sdk/reference#pconnectorslug--one-connector)を参照 |
| `call(action, args, options?)` | 生の呼び出し結果。`202`は`ok: false`で解決 |
| `describe()` · `describe(action)` | 入出力スキーマ付きのコネクタ · 単一のアクション |
| `accounts()` | この呼び出し元が実行に使用できるアカウント。デフォルトが先頭 |
| `paginate(action, args, { next, maxPages? })` | 各ページの出力を返す非同期イテレーター。ページ数が`maxPages`（デフォルト100）を超えると、`nextArgs`を伴う`ConnectorPageLimitError`をスロー — [ページ](/docs/ja/sdk/reference#pconnectorslug--one-connector)を参照 |
| `uploadAttachment(content, input)` | `connector`をこのスラッグに設定した`p.connectors.uploadAttachment` |

`options`：`account`、`approvalContext`、`timeoutMs`（デフォルト90 000）、`signal`。`beeuni connectors types`のファイルを使うと、引数と出力に型が付きます。

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

#### `p.connectors` — ツールコネクタ

| メソッド | 内容 |
| --- | --- |
| `catalog()` · `tools()` | 呼び出し可能なConnectorカタログ · フラット化された`<connector>.<action>`ツール |
| `search(query, options?)` · `describe(tool)` | 呼び出し可能な単一のツールを検索 · 詳細を確認 |
| `call(tool, args?, options?)` | サーバー側ゲートウェイ経由で単一の`<connector>.<action>`ツールを呼び出し。`options.account`は実行に使用するアカウントを指定 — 下記を参照。 |
| `accounts(slug)` | この呼び出し元が`slug`の呼び出しに使用できるアカウント。デフォルトが先頭 — `options.account`の照合対象 |
| `uploadAttachment(content, input)` | `input.connector`用のバイトデータをステージング。後続の呼び出しの引数に配置する`ref`（`{ $beeuni_attachment }`）を返す — [ファイルの添付](/docs/ja/connect/connectors#attach-files)を参照 |
| `list()` · `config(connectorId)` | 設定済みのコネクタ · 単一コネクタの設定 |
| `create(input)` | コネクタを追加 |
| `auth.discover(input)` | OpenAPI仕様、Postmanコレクション、またはエンドポイントから認証をプレビュー |
| `remove(connectorId)` · `sync()` | コネクタを削除 · コネクタを再同期 |
| `setName(connectorId, name)` · `setSensitive(connectorId, sensitive)` | 名前を変更 · 機密としてマーク（追加の承認ゲート） |
| `setAuthorizationStrategy(slug, strategy)` | @deprecated。引き続きルートを呼び出しますが、このルートは`{ok:true, deprecated:true}`を返すだけで何も変更しないno-opです。現在は各接続の`owner_type`がアクセスルールのすべてです。 |
| `setCredentialMode(connectorId, mode)` · `setCredential(connectorId, input)` | ソースを切り替え · 認証情報の値を設定 |
| `policies.get(connectorId)` · `policies.set(connectorId, policies)` | ツールポリシーを読み取り · 置き換え |
| `connections.list()` · `connections.reconcile(input)` | 接続済みアカウントを一覧表示 · 作成/更新 |
| `connections.updateCredential(connectionId, input)` | 接続の認証情報をローテーション |
| `connections.revoke(connectionId)` · `connections.activate(connectionId)` | 接続を拒否 · 復元 |
| `connections.setDefault(connectionId)` | 所有者スコープのデフォルトに設定 |
| `connections.rename(connectionId, label)` | ラベルのみを変更。アカウントの認可は維持されます。各接続には、認可時のIDである`connected_as`が保持されます。 |

`p.connectors.discover`は直接接続コネクタのカタログを閲覧します。これは**実験的機能**で、デフォルトではオフです。プロジェクトごとに[Settings → Feature flags](/docs/ja/feature-flags) → "Connectors API Discover"で有効にしてください。Easy Connectが引き続きデフォルトのコネクタマーケットプレイスです。

| メソッド | 内容 |
| --- | --- |
| `discover.list(query?, cursor?)` · `discover.detail(id)` | OpenAPI/MCP/GraphQL/CLIエントリを検索 · 単一エントリの詳細 |

`p.connectors.pipedream` は旧マネージド OAuth 接続の互換経路です。`listApps` は
OAuth アプリのみを返します。新しいマネージド連携には Easy Connect を使用してください。API キーを使うアプリは直接接続してください。

| メソッド | 内容 |
| --- | --- |
| `pipedream.listApps(params?)` · `pipedream.connect(input)` · `pipedream.finalize(input)` | アプリカタログを閲覧 · 接続フローを開始 · 接続を完了 |

コネクターはツール、プロバイダーアプリ、ポリシーを定義します。`connections` は
接続済みの**アカウント**を保存します。1 つのコネクターに複数のアカウントを併存させられます。
セッションでは `connector_bindings: { alias: { connection_id } }` で全呼び出しに使うアカウントを固定でき、
個別の呼び出しでは `call(tool, args, { account })` でアカウントを指定できます。
認証情報は暗号化されたまま保持され、リクエストごとに解決されます。

`connections` が唯一の有効な認可ファサードです。廃止された
`authorizations` と `profiles` は、現在の SDK インターフェースには含まれません。

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

#### アカウントと呼び出し時のアクセス判定

各接続には `owner_type` があります。`project`（共有 — コネクターの利用権限を
付与された人間またはサービスアカウントがアクセス可能）か、`member`（非公開 —
所有者本人が非公開セッション内でのみアクセス可能。サービスアカウントは
アクセス不可）のいずれかです。共有アカウントの利用範囲はグループや個人に限定できます。
`connections.list()` は付与された権限を `shared_with` に返し、
`connectionSharedWithEveryone(connection)` はプロジェクトの全員が利用できるかを返します。
利用範囲を限定したアカウントは、指定された人に対して非公開アカウントのルールに従います。
`usable: false` は、呼び出し元が管理目的でのみ表示できるアカウントを示します。
`createAssignment` / `revokeAssignment`（`object: { type: 'connection', id }`）で権限を付与または取り消せます。
[共有アカウントを利用できる人を選ぶ](/docs/ja/connect/connectors#choose-who-can-use-a-shared-account)を参照してください。
`p.connectors.accounts(slug)` は、呼び出し元がアクセスできるすべてのアカウントを、
デフォルトを先頭にして一覧表示します。

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

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

アカウントを指定しない呼び出しは、まず呼び出し元自身のデフォルトの非公開アカウント、
次にプロジェクトのデフォルトの共有アカウントに解決されます。指定したアカウントを
解決できない場合、`connector_not_connected` で**拒否**されます。別のアカウントに黙って
置き換えられることはありません。拒否には `requested_account` と
`available_accounts` が記載されます。成功した呼び出しはすべて、実行に使ったアカウントを返します。
`result.account = { connection_id, label, owner_type }`。

セッション作成時のコネクターのアクセス判定はなくなりました。以前は、必須のコネクターに
利用可能な接続がないと、セッションが `409 CONNECTOR_CONNECTION_REQUIRED` で拒否されていましたが、
この拒否は廃止されました（`require_connectors` は機能しません。
[`p.sessions`](#psessions--and-the-session-handle)を参照）。アクセス判定は呼び出し時に移りました。
拒否された `connector_not_connected` には、呼び出し元向けに発行できる場合、ホストされた
認可リンク `connect_url` が含まれます。トランスクリプトの接続ボタンから
ワンクリックですべて解決できます。

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

#### `p.policies` — プロジェクトのポリシー

| メソッド | 内容 |
| --- | --- |
| `list()` · `set(policies)` | プロジェクトのポリシー · ポリシー一式を置き換え |

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

#### `p.triggers` — cron、webhook、監視、イベントの自動化

トリガーは、スケジュール、受信 webhook、監視対象のコマンド、またはコネクター上のアプリイベントに応じてエージェントのアクションを開始します。
セッション戦略とペイロードのテンプレート化については、
[トリガー](/docs/ja/connect/triggers)を参照してください。

| メソッド | 内容 |
| --- | --- |
| `list()` | すべてのトリガー |
| `eventTypes({ connector })` | コネクターがトリガーにできるアプリイベント（`{ provider, app, event_types }`）。不明なコネクターには 404、プロバイダーにイベントソースがない場合は 409 `event_source_unavailable` |
| `create(input)` | 作成 |
| `update(triggerId, input)` | トリガーを編集 |
| `remove(triggerId)` | トリガーを削除 |
| `fire(triggerId)` | 今すぐ実行 |
| `setActivation(paused)` | プロジェクトの全トリガーを一時停止または再開 |

`create(input)` は `{ name, type: 'cron' | 'webhook' | 'monitor' | 'event', prompt_template,
slug?, agent?, model?, enabled?, session_mode?, session_id?, cron?, run_at?,
timezone?, secret_env?, connector?, event?, event_source?, event_account?, event_config?, session_access? }`. `name` and `prompt_template` を受け取り、これらは必須です。
`cron`/`run_at` は同時に指定できません（`type: 'cron'`）。`secret_env`（webhook の
HMAC シークレット）は `type: 'webhook'` に適用されます。

`event` トリガーには `connector`（コネクターのスラッグ）と `event`（`eventTypes` の
タイプ ID）が必要です。`event_account` は任意で、そのコネクターの共有アカウントの
ラベルです。`null` または省略時は、コネクターのデフォルトの共有アカウントを使います。
`event_source` は任意で、`composio` などのイベントソースアダプター ID です。`null` または省略時は
コネクターのプロバイダーを使います。タイプ ID はそのアダプターに属します。`event_config` の構造は、そのタイプの `config_schema` によって決まります。
`eventTypes` と `eventApps` は、アダプターを `source` として返します。`provider` は非推奨のエイリアスです。
一覧の各トリガーには `event: { connector, account, connected_as, type, config, source, provider, app,
status: 'active' | 'needs_connection' | 'error' | 'pending', error,
last_event_at } | null` が含まれます。プロンプトテンプレートでは、イベントを
`{{ event.data.<field> }}` と `event.id`、`event.type`、`event.app`、
`event.connector`、`event.occurred_at` として読み取れます。

`session_access` は、トリガーが作成するセッションを誰が開けるかを制御します。
形式は `{ mode: 'private' | 'members' | 'project', memberIds: string[], groupIds:
string[] }` and defaults to `private` です。このポリシーはアカウントローカルの実行時
状態です。ポータブルな `beeuni.yaml` マニフェストには含まれません。`session_access` のみを
更新しても Git コミットは作成されません。固定されたセッションは独自の共有
設定を維持します。プロジェクト管理者は、`private` または選択したメンバーのみのアクセスを
使うセッションも含め、トリガーが作成したセッションを常に開けます。

`session_access` はロールモデルに加わるリソース単位の可視性設定であり、
ロールではありません。特定のトリガーのセッションを誰が開けるかを決めます。
ロール判定で拒否された権限を付与することはありません。
[アカウントとアクセス](/docs/ja/accounts#per-feature-access-settings)を参照してください。

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

#### `p.marketplace` / `p.registry` — インストール済みアイテム

カタログアイテムのファイルをプロジェクトのデフォルトブランチにインストールします。
`registry.*` は `marketplace.*` と同一のエイリアスです。

| メソッド | 内容 |
| --- | --- |
| `marketplace.list()` · `marketplace.install(id)` | インストール済みアイテム · カタログアイテムをインストール |
| `marketplace.updates()` · `marketplace.update(name)` · `marketplace.updateAll()` | 利用可能な更新 · 1 件を更新 · すべて更新 |
| `marketplace.remove(name)` | アイテムをアンインストール |

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

#### `p.files` — リポジトリのファイル（読み取り）

プロジェクトの git ツリーへの読み取り専用アクセスです。実行中のセッション内で
ファイルを読み書きするには、セッションのファイル操作を使ってください。
下記のモジュール内の[ファイル](#files)を参照してください。

| メソッド | 内容 |
| --- | --- |
| `listDirectory({ ref?, path? })` | フォルダーの 1 階層：`{ entries: [{ path, type, size? }], truncated }`。ツリーの構築に使えます。各フォルダーは 5,000 エントリまで完全に取得されます。 |
| `list(options?)` · `read(path, ref?)` | パス配下の全ファイルを再帰的に取得し、1,000 件で打ち切り（打ち切り時はレスポンスに `X-Beeuni-Truncated: 1` を含む） · git ref におけるファイルの内容 |
| `search(query, { content?, ref?, limit? })` | リポジトリ全体のファイル名、または `content: true` で内容を検索 |
| `archive(options?)` · `history(path)` | tarball をダウンロード · ファイルの git 履歴 |

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

#### `p.git` — 履歴

| メソッド | 内容 |
| --- | --- |
| `commits()` | コミットログ |
| `commit(sha)` · `commitDiff(sha)` | 1 件のコミット · その差分 |
| `branches()` · `versionDiff(from, to)` | ブランチ · 2 つの ref 間の差分 |

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

#### `p.changeRequests` — ライフサイクルとマージ

変更リクエスト（CR）は、セッションの作業をデフォルトブランチにマージするための仕組みです。

| メソッド | 内容 |
| --- | --- |
| `list()` · `get(crId)` | オープン中の CR · 1 件の CR |
| `diff(crId)` · `mergePreview(crId)` | その差分 · マージ結果をプレビュー |
| `open(input)` · `merge(crId, input?)` | CR を作成 · マージ |
| `close(crId, input?)` · `reopen(crId, input?)` | マージせずに閉じる · 閉じた CR を再度開く |
| `requestChanges(crId, input)` | フィードバックを記録し、必要に応じて元のセッションに返す |

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

#### `p.sessions` — およびセッションハンドル

| メソッド | 内容 |
| --- | --- |
| `list()` | プロジェクトのセッション |
| `create(input?)` | セッションを作成 |
| `session(sid)` | セッションハンドル（`beeuni.session(id, sid)` と同じ） |

セッションハンドルはランタイムの中核です。[セッション](/docs/ja/sdk/sessions)を参照してください。

`create(input)` は、コネクター接続のスラッグをキーとする `connector_bindings` を受け取ります。
各値は `connection_id` を指定します。また、バックエンド由来のシークレットを絞り込むための `secrets` も受け取ります。`require_connectors` は非推奨で、効果はありません。このフィールドは引き続き受け付けられます（古いクライアントが送信しても拒否されません）が、読み取られることはありません。使用可能なアカウントがないコネクターを理由に、セッションが作成時に拒否されることはありません。[アカウントと呼び出し時のゲート](#accounts-and-the-call-time-gate)を参照してください。

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

#### `p.approvals` — コネクター承認受信箱

判断待ちの、コネクターによって制御されるアクションです。権限承認 UX（`APPROVE` / `ASK` / `BLOCK`）を支えます。

| メソッド | 内容 |
| --- | --- |
| `list(options?)` · `sessionsNeedingInput(options?)` | 承認待ち · 判断待ちでブロックされたセッション |
| `resolve(executionId, decision, scope?)` | 1 件を承認または拒否 — `decision: 'approve' \| 'deny'`、`scope: 'once' \| 'session' \| 'session_all'` |

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

#### `p.gateway` — LLM の可観測性

このプロジェクトのモデルトラフィックに関するリクエストログ、コスト/レイテンシの集計、予算、ゲートウェイ API キー。

| メソッド | 内容 |
| --- | --- |
| `logs(opts?)` · `log(logId)` | リクエストログのエントリ · 1 件のログエントリ |
| `overview(days?)` · `series(days?)` · `breakdown(days?)` · `sessions(days?)` · `errors(days?)` | 指定期間の集計、セッションごとのコスト、エラー |
| `budgets()` · `setBudget(input)` · `deleteBudget(budgetId)` | 予算の読み取り · 作成/編集 · 削除 |
| `keys()` · `createKey(name)` · `revokeKey(keyId)` | ゲートウェイ API キーの一覧取得 · 発行 · 失効 |
| `playground(prompt, models)` | 1 つのプロンプトを最大 6 モデルで実行 |
| `routing.get()` · `routing.set(policy)` · `routing.reset()` | ルーティングポリシーの読み取り · 置き換え · 継承 |
| `routing.preview(input)` | モデルを呼び出さずにルートを解決 |

ルーティングポリシーには、デフォルトモデル、画像対応モデル、順序付きのフォールバックチェーンが含まれ、各モデルの試行は最大 1 回です。`fallbackOn` は `transient` または `any-error` です。

ゲートウェイが次のフォールバックモデルに移るのは、現在のモデルが出力を返す前に失敗した場合だけです。

- `transient`: ネットワークエラー、タイムアウト、任意の `5xx`、または `402`、`403`、`429`。
- `any-error`: `400` を含むすべての失敗。

出力開始後の失敗では、そのモデルのままになります。独自のプロバイダーキー（BYOK）を使ったリクエストが、Beeuni によって課金されるモデルにフォールバックすることはありません。各フォールバックモデルには、それぞれ固有の生成デフォルト設定が適用されます。

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

#### `p.channels` — Slack / メール / 音声

エージェントが Slack アプリやメールアドレスとして動作したり、リアルタイム音声通話に参加したりできるコネクターインターフェース。

| メソッド | 内容 |
| --- | --- |
| `slack.installation()` · `slack.mode()` · `slack.manifest()` | 現在のインストール · モード · アプリマニフェスト |
| `slack.connect(input)` · `slack.disconnect()` | 接続 · 切断 |
| `slack.getFile(url)` · `slack.uploadFile(input)` | サーバープロキシ経由でファイルをダウンロード · アップロード |
| `email.installation(connectorSlug?)` · `email.mode()` | 現在のインストール · モード |
| `email.connect(input)` · `email.disconnect(...)` · `email.updatePolicy(input)` | 接続 · 切断 · 送信/返信ポリシーの更新 |
| `voice.setBotName(name)` | 進行中の通話でボットの名前を変更 |

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

#### `p.modelDefaults` — デフォルトモデルの設定

ゲートウェイによって解決される、アカウント、エージェント、プロジェクト単位のモデルのデフォルト設定。

| メソッド | 内容 |
| --- | --- |
| `get()` · `set(input)` · `clear(params)` | 読み取り · デフォルトの設定 · 上書き設定の解除 |

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

#### `p.setDefaultAgent` — プロジェクトのデフォルトエージェント

`p.setDefaultAgent(agentName)` は、エージェントが宣言済みで有効になっていることを確認し、プロジェクトの `beeuni.yaml` 内で `default_agent` として設定します。新しいセッションでは、ユーザーが別のエージェントを選ばない限り、このエージェントが優先されます。

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

#### `p.updateFeatureFlag` — 機能フラグ

`p.updateFeatureFlag(feature, enabled)` は、プロジェクトの 1 つの機能フラグをオンまたはオフにします。`enabled: null` を渡すと上書き設定を解除し、プラットフォームのデフォルトに戻ります。正規の `PATCH /v1/projects/:id/features` を呼び出します。

`feature` は `FEATURE_FLAG_KEYS` のいずれかです（`@beeuni/sdk` からエクスポートされ、型は `FeatureFlagKey`）。呼び出し元にはプロジェクトの `project.settings.write` 権限が必要です。それ以外の場合、ルートは `403` を返します。

フラグで制御されるすべてのルートは、フラグがオフの間、同じ方法で拒否します。HTTP `403` と `{ error, code: "feature_disabled", feature }` を返します。`isFeatureDisabledError(error)` で分岐し、`featureDisabledKey(error)` でフラグキーを読み取ってください。メッセージのテキストで照合しないでください。

`p.updateExperimentalFeature(feature, enabled)` は**非推奨**のエイリアスです。
古いデプロイ済み API に固定された利用側が引き続き動作するよう、非推奨のルートエイリアス `PATCH /v1/projects/:id/experimental` を呼び出し続けます。新しいコードでは `p.updateFeatureFlag` を使用してください。

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

#### `p.sandbox` — テンプレートとスナップショットビルド

プロジェクトハンドルの `sandboxHealth`/`sandboxTemplates` に加わるサンドボックスのビルド設定です。Dockerfile/イメージ/ウォームプールのテンプレートと、それらのスナップショットビルドを扱います。

| メソッド | 内容 |
| --- | --- |
| `list()` · `snapshots()` | このプロジェクトのサンドボックス · ビルド済みスナップショット |
| `rebuildSnapshot(slug?)` · `fixWithAgent()` | スナップショットを再ビルド · 失敗したビルドの修正をエージェントに依頼 |
| `createTemplate(input)` · `updateTemplate(...)` · `removeTemplate(...)` · `buildTemplate(...)` | テンプレートの追加 · 編集 · 削除 · ビルド |
| `setProvider(provider)` | プロバイダーの切り替えをリクエスト。`null`（またはプラットフォームのデフォルト / すでに有効なプロバイダー）は即座に適用されます。別の有効なプロバイダーへの切り替えでは、永続的な準備→検証→有効化の遷移が開始されます。切り替え先のウォームイメージがビルド、検証され、その後有効化されるまで、現在のプロバイダーが処理を継続します。戻り値はタグ付き共用体で、`kind:'project'`（即時）または `kind:'preparation'`（`activated`/`failed` になるまで `getProjectSandboxProviderTransition()` をポーリング）です |

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

### プラットフォーム管理者用フック（`@beeuni/sdk/react`）

これらのフックは管理コンソール向けです。API はプラットフォーム管理者に対してのみ応答します。各ミューテーションは `['admin', 'accounts']` クエリを無効化します。

| フック | 動作 |
| --- | --- |
| `useAdminRole(userId, options?)` | `GET /user-roles` → `{ isAdmin, role }` から呼び出し元のロールを読み取ります。`userId` がキャッシュのキーになります。`userId` がない場合、クエリは無効になります。マウント時とフォーカス時に再取得するため、ロールが取り消されると、1 回の画面遷移以内にアクセス制御への適用が停止します。 |
| `useAdminGrantCredits()` | ミューテーション `{ accountId, amount, description, isExpiring }`: ウォレットのクレジットを追加します。`POST /admin/api/accounts/:id/credits`。資金を移動するため、まず UI で確認してください。 |
| `useAdminDebitCredits()` | ミューテーション `{ accountId, amount, description }`: ウォレットのクレジットを減らします。`POST /admin/api/accounts/:id/credits/debit`。資金を移動するため、まず UI で確認してください。 |
| `useAdminSetTier()` | ミューテーション `{ accountId, tier }`: プランのティアを設定します。 |
| `useAdminGrantTrial()` | ミューテーション `{ accountId, tierKey, seats, durationDays, creditGrant?, note? }`: トライアルを付与または置き換えます。期間が終了するまで、アカウントは `tierKey` として動作します。`creditGrant` はウォレットのクレジットも追加します。 |
| `useAdminRevokeTrial()` | ミューテーション `{ accountId }`: 有効なトライアルを今すぐ終了します。有効なトライアルがない場合は `400` を返します。 |

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

### エスケープハッチ

`beeuni.runtime()` は、アクティブなサンドボックス用の型付き 実行環境 REST クライアントを返します。
`createScopedBeeuni`（`@beeuni/sdk/server`）で作成されたクライアントでは、**例外をスローします**。マルチテナントサーバーでは、プロセス全体の「アクティブ」ランタイムが別のリクエストのサンドボックスとなり、テナント間の漏洩につながるためです。代わりに、セッションスコープの `beeuni.session(pid, sid).runtime` を使用してください（先に `ensureReady()` を呼び出します）。これにより、そのセッション自身のサンドボックスが解決されます。

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

## モジュール

[クライアント](#the-client)ファサードと React フックの基盤となる、フレームワーク非依存のモジュールです。ファサードなしで 1 つの操作を実行したい場合、純粋なヘルパーや Node 専用の分離レイヤーが必要な場合に使用してください。各モジュールには安定性のティアが付いているため、何を基盤として構築できるかがわかります。

| 区分 | 意味 |
| --- | --- |
| 標準 | ルート `@beeuni/sdk` からインポートします。新しいコードではすべてこれを使ってください。 |
| サポート対象 | 専用サブパス（`@beeuni/sdk/react`、`@beeuni/sdk/server`）。正式にサポートされており、非推奨ではありません。 |
| 非推奨のエイリアス | 引き続き動作する古いサブパス。ルートがすでにエクスポートしているコードを再エクスポートします。代わりにルートからインポートしてください。 |
| 内部用 | semver の対象外。ホスト側のコードではインポートしないでください。 |

ルートエントリが標準です。以下のフレームワークに依存しない名前はすべて、`@beeuni/sdk` から直接インポートできます。

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

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

### 標準モジュール

| モジュール | 機能 |
| --- | --- |
| ファイル | ワークスペースのファイル操作：一覧取得、読み取り、検索、書き込み |
| セッションランタイム | ヘルスプローブとプレビュー／プロキシ URL のビルダー |
| 実行環境 クライアント | 型付き 実行環境 REST クライアントとその全型定義 |
| 認証 | `authenticatedFetch` とトークンアクセサー |
| Projects REST | ファサードがラップする生の REST 関数 |
| API クライアント | 低レベルの型付き HTTP クライアント `backendApi` |
| ターン | メッセージのターンへのグループ化、コストとステータスの計算 — [ターン](#turns) を参照 |
| トランスクリプト | クライアント側の Markdown エクスポート `formatTranscript` |
| コンポーザーのリスト | セッションコンポーザーのエージェントとモデルのリスト：提示するものと実行するもの |

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

#### ファイル

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

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

64 KiB を超えるアップロードは、検証済みのチャンクでサンドボックスの境界を通過します。進捗コールバックは、各チャンクがセッションのファイルシステムに到達した後に実行されます。

`uploadNativeFile({ uri, name, type? }, targetPath, baseUrl)` は、React Native からデバイス上のファイルを1回のリクエストでアップロードします。ランタイムは `uri` からバイトをストリーミングするため、JS ヒープに入ることはありません。`files.upload` と同じ認証、期限、`401` のリプレイを使います。チャンク分割はしません。

`fetchProjectArchive`、`fetchCostExportCsv`、およびサンドボックスのバージョン呼び出しは、同じトランスポートを通じて送信されます。失敗すると、`status` を伴う `ApiError` がスローされます。

`files.write(path, blob)` は `path` のファイルを置き換え、`path` がフォルダーの場合は失敗します。`files.create(path)` は空のファイルを作成し、上書きはしません。`path` にファイルまたはフォルダーがすでに存在する場合、`FileExistsError`（`status` `409`、`code` `'FILE_EXISTS'`）をスローします。

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

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

`files` は、グローバルにアクティブなサンドボックスを対象とします。ホストが複数のセッションを同時に実行する場合は、代わりにセッションハンドルで `s.files` を呼び出してください。常にそのセッション自身のサンドボックスを対象とします。[セッション](/docs/ja/sdk/sessions) を参照してください。

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

#### セッションランタイムのヘルパー

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

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

`getSessionHealth` は、2xx 以外のステータスでもスローしません。`{ status, ok, health, body }` を返し、ステータスの意味は呼び出し側で判断できます。同じモジュールは、エージェントの `localhost` 出力を到達可能なプロキシ URL に書き換える URL ヘルパーもエクスポートします：`detectLocalhostUrls`、`rewriteLocalhostUrl`、`proxyLocalhostUrl`、`parseLocalhostUrl`、`buildWebProxyUrl`。

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

#### 実行環境 クライアント

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

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

`getClient()` は、認証が注入済みの、アクティブなサンドボックス用の型付き 実行環境 v2 互換クライアントを返します。ホストが複数のセッションを実行する場合は、グローバルな `getClient()` よりも、同じクライアントを1つのセッションにスコープした `beeuni.session(pid, sid).runtime` を優先してください。

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

#### 認証ヘルパー

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

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

トークンは、`createBeeuni` に渡した `getToken` 関数から取得されます。ほとんどのアプリコードではこのモジュールは不要です。ファイル、セッション、ファサードの各レイヤーがすでに認証を処理します。

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

#### API クライアント

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

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

`backendApi` は、すべての REST 関数の基盤となる型付き HTTP クライアントです。型付きラッパーがまだないエンドポイントにのみ使ってください。

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

#### コンポーザーのエージェントとモデルのリスト

Beeuni ウェブアプリと同じルールで、セッションコンポーザーのエージェント選択とモデル選択を構築します。すべての関数は純粋関数です。クライアントで入力を取得し、それを渡してください。

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

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

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

`resolveComposerModel` は、コンポーザーがデフォルト設定の場合に `explicit: undefined` を返します。`model` は表示および送信するキーです。フラット化された各モデルの `id` は、選択時に保存される参照です。`modelRefToKey(ref, gatewayEnabled)` は、保存された参照（セッションのピン、チャネルのバインディング、トリガーの `model`）をキーに戻します。

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

### サポート対象のサブパス

| サブパス | 機能 |
| --- | --- |
| `@beeuni/sdk/react` | React フック — [React フック](/docs/ja/sdk/react) を参照 |
| `@beeuni/sdk/server` | マルチテナントのバックエンド用のリクエストスコープ設定 |
| `@beeuni/sdk/wire-message-id` | 実行環境 のワイヤーメッセージ ID クロックのみ（1モジュール、インポートなし）。ルートも同じ名前をエクスポートします |

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

#### ワイヤーメッセージ ID

プロンプトの `messageId` は、トランスクリプト内の位置です。実行環境 は、`msg_` + 48ビットのクロック（`Date.now() * 0x1000`、下位48ビット）+ 14文字の base62 文字列でメッセージを並べ替えます。クロックは 2^36 ms（約2.2年）ごとに周回します。手動でエンコードしないでください。

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

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

生成時刻は2分前に設定され、その後、`after` 内で現在より最大1時間先までの最新 ID より1ティック上に引き上げられます。最新の位置を ID ではなくクロックとして保持する呼び出し側は、`mintWireMessageIdAbove({ nowMs,
newestKnownTime })`, which returns `{ id, time }`. `newestWireIdClock(ids)` を使ってそのクロックを取得します。すべての比較はリング上で行われるため、周回の両側にある ID も正しい順序を維持します。

48ビットのクロックは約2.2年ごとに周回するため、2つのクロックを `>` や `<=` で比較しないでください。周回直後に生成された ID は、直前に生成された ID より数値的に小さくなります。リング上の符号付き距離である `wireIdClockDelta(clock, reference)`（`clock` が先にある場合は正）を使い、複数の中から最新のものを選ぶには `maxWireIdClock(clocks)` を使ってください。

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

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

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

#### サーバー側の分離

`createBeeuni` は、トークン関数を含む設定をプロセス全体で共有する1つの変数に保存します。ブラウザーのタブ、CLI、シングルテナントのサーバーでは問題ありません。異なるユーザーのリクエストを同時に処理する Node サーバーでは安全ではありません。最後の `createBeeuni` 呼び出しが、処理中のすべてのリクエストに適用されるためです。`@beeuni/sdk/server` は、リクエストごとの分離でこれを解決します。

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

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

`createScopedBeeuni` と `runWithBeeuni` は、Node の `AsyncLocalStorage` を使ってリクエストごとに設定を分離します。ブラウザーバンドルから `@beeuni/sdk/server` をインポートしないでください。`node:async_hooks` が静的に取り込まれます。

スコープ付きクライアントのトップレベルの `runtime()` はスローします（別のテナントのサンドボックスを解決してしまうためです）。`await s.ensureReady()` の後に `beeuni.session(pid, sid).runtime` を使って、特定のセッションのランタイムにアクセスしてください。

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

### 非推奨のエイリアス

約20の古いサブパスが引き続き動作します：`/files`、`/turns`、`/session`、`/auth`、`/projects-client`、`/api-client`、`/config`、`/event-stream`、`/opencode-client`、`/platform-client` などです。それぞれ、ルートの `@beeuni/sdk` エントリがすでにエクスポートしているコードを再エクスポートします。既存のものに影響しないよう、引き続き動作します。
```ts
import { classifyPart, classifyTurn, toolInfo, toolViewModel } from '@beeuni/sdk';
```
```ts
import { classifyPart, type ClassifiedPart } from '@beeuni/sdk';

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

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

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

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

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

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

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

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

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

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

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

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