コンテンツにスキップ
移動 開く esc閉じる

Host API

connectHost のメソッド、上限、エラーコードを正確に知りたいときにこのページを使ってください。フォルダ構成、マニフェスト、インストールについては 拡張機能を作る から始めてください。

import { connectHost, HostRequestError } from "@openchamber/sdk";
const host = connectHost();

connectHostwindow がないと HOST_UNAVAILABLE を throw します。OpenChamber の外では、すべての呼び出しが HOST_UNAVAILABLE で reject されるクライアントを返します。ページを破棄するときは dispose() を呼んでください。進行中の呼び出しは同じコードで reject されます。

OpenChamber から届くもの

onReady は最初のスナップショットで発火し、OpenChamber がそれを更新するたびに再び発火します。

一度だけ実行されるマウント用コールバックではありません。UI のマウントと購読登録は一度だけ行い、以降は入力欄や下書きを置き換えずにテーマとコンテキストを更新します。UI kit のガード付き例を参照してください。onConnection などは現在値を即座に通知し、新しいスナップショットで同じ値を再通知する場合があります。次のリクエストを始める前に必要なフィールドを比較し、古いリクエストの応答は無視してください。

フィールド内容
theme.modelight または dark
theme.tokensアプリの色(サーフェス、テキスト、操作状態、primary、success/warning/error/info)、fontmonoradius。UI をマウントする前に applyHostReady に渡してください。
localeアプリの言語タグ
directory現在のプロジェクトディレクトリ、または null
session{ id, title, busy } または null。タイトルがなければセッション ID になります。busy はライブの状態です。セッションが持っていれば modelagent(OpenCode のエージェント)も含まれます。
surfaceレールは panel、添付ウィンドウは dialog、全画面は page
itemこの画面が何のために開かれたか、または null。ユーザーがクリックした添付済みの項目(attach に渡したのと同じフィールド、data を含む)、または宣言したアクションから来たメッセージ(kind: "message")かセッション(kind: "session")。アクション を参照。
connectionあなたの連携の { connected, account }
settingsintegration.settings で宣言した入力欄の値

アクセストークンはここにも request の結果にも決して現れません。

onDirectoryonSessiononSessionLifecycleonConnectiononSettingsonItem は、遅れて購読しても最新の値を再送し、その後は変化のたびに発火し続けます。

theme.tokens には primaryTextsuccessTextwarningTexterrorTextinfoText が含まれます。これらは必須フィールドで、ホストが計算した文字色を持ちます。ニュートラルな背景や UI キットの淡い色付きコントロール用で、濃い単色の塗りつぶし用ではありません。applyHostReady はスナップショットごとにこれらを適用します。CSS 変数については UI キットを参照してください。

メソッド

呼び出し動作
toast({ kind, message })アプリにトーストを表示します。kindinfosuccesserror のいずれかです。
openUrl(url)ユーザーのブラウザで URL を開く
openSurface(surfaceId)アプリをその画面に切り替える
writeClipboard(text)テキストをコピーします。1 から 32000 文字。
compose({ text, mode? })送信せずにチャット欄にテキストを入れます。modeappend(デフォルト)または replace。トリム後 1 から 16000 文字。
attach({ ... })チャット欄にチップを付けます。GitHub や Linear の項目が置かれるのと同じ場所です。チップは同時に 1 つだけ。
startSession({ ... })その項目を添付したセッションを作ります。{ sessionId, sent } を返します。sessions 権限が必要です。
prompt({ text, send? })現在のセッションに書き込む、または送信します。{ sent } を返します。送信には prompt 権限が必要です。
sessionLink({ ... })セッションを作らずに、現在のセッションに項目を添付する
close()添付ウィンドウを閉じます。レール上では何もしません。
oauthStart()プロバイダーの認可ページを開く。host: { provider: "linear" } 連携なら Linear のページ
oauthDisconnect()保存されたトークン、または Linear 接続を忘れる
request({ method, path, query?, body? })ユーザーのトークンを付けて連携の apiOrigin を呼ぶ
serviceRequest({ method, path, query?, body? })拡張機能のローカルサービスを呼ぶ(GUEST_SERVICES.md を参照)
serviceStatus()stoppedstartingreadyfailed のいずれか
readFile(path)テキストファイルを読む。{ content } を返す。
writeFile(path, content)テキストファイルをアトミックに書き、親フォルダも作成する。{ written: true } を返す。
listDir(path)フォルダを一覧する。{ entries: [{ name, kind }] } を返し、kindfiledirectoryother のいずれか。
stat(path){ kind, size, mtime }kindfiledirectoryothermissing のいずれか。
generate({ prompt, system?, maxOutputTokens? })ユーザーの Small Model による一回限りのテキスト。{ text } を返す。model 権限が必要。
onResolve(handler)スラッシュコマンドのハンドラーを登録する。{ command, args } を受け取り、添付する項目または null を返す。
setBadge(count)レールのアイコンに数字(0 から 999)を表示する。null で消す

3 つとも同じ項目フィールドを受け取ります。

await host.attach({
providerId: "acme-hello",
id: "TICKET-1",
title: "Login is broken",
url: "https://example.com/TICKET-1",
});
await host.attach({
providerId: "acme-hello",
id: "!12",
title: "Fix login",
url: "https://example.com/merge_requests/12",
kind: "pull",
author: "ada",
branches: { head: "feature", base: "main" },
text: "Optional notes for the model",
});
await host.startSession({
providerId: "acme-hello",
id: "!12",
title: "Fix login",
url: "https://example.com/merge_requests/12",
kind: "pull",
worktree: true,
text: "Optional first message",
});

providerId はパネル ID です。いずれにせよ OpenChamber があなたの ID で上書きします。id は項目に対するあなた自身の識別子です。kindissue(デフォルト)または pull です。text はモデルに渡す任意のコンテキストで、トリム後 1 から 16000 文字です。data は任意の JSON で、内容は自由です(ステータス、コメントなど)。シリアライズ後 16000 文字までです。OpenChamber はこれをチップと一緒に保存し、ユーザーがチップをクリックしたときに ctx.item でそのまま返します。モデルには決して渡りません。

startSessionprojectId を指定して、表示中のプロジェクトを切り替えずに作成できます。worktree 省略時は対象ディレクトリ、true は名前を生成する新規 worktree、{ kind: "existing", directory } は既存、{ kind: "new", name?, baseBranch? } は名前と基点を指定する新規 worktree です。名前はブランチにも使います。navigation は既定で "preserve""open" なら新しいチャットを開きます。最初のメッセージのモデル、エージェント、バリアントは開始時に確定します。

結果は sessionIddirectorysentlinked と任意の worktree を含みます。sentsentno-modelskippedfailed です。linked: false は項目の保存失敗です。準備やセッション作成の失敗後に worktree が残った場合は sessionId: nullfailure: "bootstrap-failed" | "session-create-failed" を返します。再試行前に確認してください。待機は最大180秒で、タイムアウトは取り消しの証拠ではありません。

sessionLink は今開いているセッションに項目を添付します。プロジェクトやセッションがない場合は NO_SESSION エラーになります。

送信前にクライアント側で適用される上限:

フィールド最大文字数
id128
title200
url2000
text16000
data(シリアライズ後)16000
author80
各ブランチ名200

prompt とセッションのライフサイクル

await host.prompt({ text: "Fix the login" });
await host.prompt({ text: "Fix the login", send: true });
host.onSessionLifecycle((event) => {
document.body.dataset.phase = event.phase;
});

send なしの prompt はチャット欄のテキストを置き換えます。send: true を付けると、ユーザーが選択しているモデルとエージェントでメッセージを送ります。拡張機能がそれらを選ぶことはありません。開いているセッションがなければ NO_SESSION です。セッションがビジー中の送信は SESSION_BUSY になります。ビジー中でも欄への書き込みはできます。結果は { sent } で、値は startSession と同じです。

onSessionLifecycle はセッションが何をしているかを伝えます。phase は、モデルが作業中なら started、アイドルになったら completed、予期しない状態なら failure です。遅れて登録したリスナーにも現在の phase がすぐ届きます。

プロジェクト、ライブ状態、保存

listProjects()listWorktrees(projectId)listSessions(projectId) は既存の sessions 権限で共有ストアを読みます。呼び出しごとに Git を調べず、会話内容も公開しません。プロジェクトの ID・名前・ディレクトリ、worktree のブランチ・利用状態、セッションの日時・親・worktree・この拡張機能の添付項目を取得できます。既知のアーカイブ済みセッションも含みます。

await onProjects(listener)await onWorktrees(projectId, listener)await onSessions(projectId, listener) は購読解除関数を返します。登録時の権限エラーを処理してください。初期スナップショットの後に変更が届きます。1フレーム最大32件で、dispose()、閉じる操作、一時停止、削除、サーバー切り替えで解除されます。stateloadingreadyerror で、セッションにはディレクトリ別の coverage もあります。失敗時はデータを保持し、完全な空一覧を保証するのは ready だけです。

activityunknownidlerunningretryingwaiting-permissionwaiting-question です。outcome は観測済みの completedfailed、または null で、最大2,000セッション分をメモリだけに保持します。エラー後の idle は次の実行まで失敗を保持します。タスクの完了を意味しません。openSession(sessionId) でチャットを明示的に開けます。

host.storage.get(key)set(key, value)delete(key)keys() は追加権限なしで独自 JSON を接続先サーバーに保存します。未保存は undefined、保存した null は null です。キーは1〜128文字、値は UTF-8 で64 KiB、全体は2 MiB・2,000キーまでです。プロジェクト別データにはキーにプロジェクト ID を含めます。書き込みは直列化されアトミックで、失敗時は既存データを保持します。アンインストールで削除されます。

request

const user = await host.request({ method: "GET", path: "/api/v2/user" });

path/ で始まり、スキームやホストを含みません。OpenChamber がマニフェストの apiOrigin と結合し、Authorization ヘッダーを付けます。トークン連携は貼り付けられたトークンをそのまま送るか、マニフェストで token.scheme: "bearer" を設定していれば Bearer <token> として、"basic" を設定していれば Basic base64(username:token) として送ります。OAuth と Linear の連携は常に Bearer を送ります。結果は { status, body } です。body はテキストなので、JSON は自分でパースしてください。

Linear 連携では GET /api/linear/issues/get も呼べます。これには OpenChamber が自身の Linear ルートから応答します。

20 秒以内に応答がなければ HOST_TIMEOUT です。

try {
await host.request({ method: "GET", path: "/api/v2/user" });
} catch (error) {
if (error instanceof HostRequestError && error.code === "DISCONNECTED") {
await host.oauthStart();
}
}

serviceRequest

マニフェストで contributes.service を宣言すると、OpenChamber がそのプロセスを起動し、ページは同じ種類の呼び出しでそれと話します。ページ自身がソケットを開くことはありません。

const status = await host.serviceStatus();
const result = await host.serviceRequest({ method: "GET", path: "/containers" });

pathrequest と同じ規則に従います。ローカルサービスを宣言すると、インストール時にユーザーが承認する権限に service が加わります。承認されるまで、すべての serviceRequestNO_SERVICE です。完全な契約はパッケージ内のファイル GUEST_SERVICES.md にあります。

ファイル

相対パスは開いているプロジェクトの中を指し、files 権限が必要です。/ または ~/ で始まるパスは、宣言済みの contributes.filesystem パターンに一致する必要があり、filesystem 権限が必要です。規則は 拡張機能を作る を参照してください。

const { content } = await host.readFile("package.json");
await host.writeFile("notes/today.md", "# Today\n");
const { entries } = await host.listDir("src");
const info = await host.stat("~/.config/opencode/opencode.json");

上限: パスは 1024 文字まで、内容は 2,000,000 文字まで、一覧は 2000 件まで。内容の上限を超えると FILE_TOO_LARGE です。

generate

const { text } = await host.generate({ prompt: notes, system: "Summarize in one sentence." });

prompt はトリム後 1 から 64,000 文字、system は 8,000 文字まで、maxOutputTokens は 1 から 4,000 です。何もセッションには入らず、履歴も残りません。拡張機能がモデルを選ぶことはありません。呼び出しは最大 90 秒待ちます。使える Small Model がない場合は NO_MODEL、モデルがエラーを返した場合は MODEL_FAILED です。テキストを生成する を参照してください。

エラーコード

失敗した呼び出しは HostRequestError を throw します。code は次のいずれかで、message に詳細が入ります。

コード発生条件
HOST_UNAVAILABLEwindow がない、OpenChamber の中ではない、または dispose() が実行された
HOST_TIMEOUT20 秒間応答がない
HOST_REJECTEDOpenChamber が拒否した、またはこの SDK が知らないコードで応答した
DISCONNECTED連携用のトークンや Linear 接続がない
BAD_PATHpath の形式が不正、または許可されたオリジンの外に出ようとした
NO_INTEGRATIONマニフェストに integration がない
NO_SESSION開いているセッションがない状態での prompt または sessionLink
SESSION_BUSYセッションがビジー中の prompt({ send: true })
DISABLEDユーザーが 設定 → 拡張機能 で拡張機能を一時停止した
NO_SERVICEローカルサービスが未宣言、未承認、または未起動
NOT_GRANTEDこの呼び出しに必要な権限をユーザーが承認していない
SERVICE_FAILEDローカルサービスがクラッシュした、または ready にならなかった
NO_DIRECTORY開いているプロジェクトがない状態で相対ファイルパスを使った
NOT_FOUND存在しないファイルに対する readFile
FILE_TOO_LARGE読み込みまたは書き込み時にファイル内容が上限を超えた
DENIEDオペレーティングシステムがファイル操作を拒否した
NO_MODEL利用できる Small Model がない状態での generate
MODEL_FAILEDSmall Model がエラーを返した

関連