Sandbox 冷啟動 HUD
當 agent 需要一個 sandbox 才能繼續時,後端會在串流上送出 sandbox.launch /
sandbox.ready 事件。core 把它們收斂成 sandboxPhase,SDK 則在 chat view 右下角浮出一個
獨立的「Sandbox 啟動中」HUD,ready 之後播一段收尾拍再淡出。
這是自動的——整合方不需要接任何線。
Sandbox 冷啟動 HUD
當 agent 需要一個 sandbox 才能繼續時,後端會送出 sandbox.launch / sandbox.ready 事件;core 把它們收斂成 sandboxPhase,而 SDK 會在 chat view 右下角浮出一個獨立的「Sandbox 啟動中」HUD。重點是那道 1 秒門檻:熱啟動常常 100–300ms 就 ready,這時閃一下動畫只是雜訊,所以門檻內完成的啟動全程靜音。
- 冷啟動:按 launching,等超過 1 秒再按 ready → stage 會走 launching → ready → leaving → hidden。
- 熱啟動:按 launching 後「立刻」按 ready → stage 全程停在 hidden,什麼都不閃。
import { useSandboxLaunch } from '@asgard-js/react';
import type { SandboxPhase } from '@asgard-js/core';
// phase 來自 channel.sandboxPhase$(或 getSandboxPhase())
const { stage, visible } = useSandboxLaunch(phase, {
thresholdMs: 1000, // 低於此時間完成的啟動不顯示
readyBeatMs: 900, // ready 後停留多久再淡出
exitMs: 600, // 淡出時間
});
// stage: 'hidden' | 'launching' | 'ready' | 'leaving'內建 HUD 會自動出現,不需要接線;這個 hook 是給要自己畫啟動提示的整合方用的。HUD 與 footer 上緣的連線指示器(RunningIndicator)互相獨立——前者只管「sandbox 是不是卡在冷啟動」,後者管整個 run 的連線。
useSandboxLaunch 狀態
那道 1 秒門檻
熱啟動常常 100–300ms 就 ready。這種時候閃一下動畫只是雜訊,所以 phase 必須持續
launching 超過門檻(預設 1000ms)才會顯示 HUD;門檻內完成的啟動全程靜音。
反過來,ready 抵達時 HUD 不會瞬間消失:它會停留一段 ready 拍(預設 900ms)讓使用者看到 「好了」,再淡出。若 ready 在門檻前就到(HUD 從未顯示),整段就保持安靜。
phase: idle ──► launching ─────────────────► ready ──► idle
│◄── 1000ms ──►│
stage: hidden hidden launching ready ──► leaving ──► hidden
(動畫) (收尾拍)(淡出)
sandboxPhase
type SandboxPhase = "idle" | "launching" | "ready";
從 Channel 取得,可以訂閱也可以快照:
channel.sandboxPhase$.subscribe((phase) => { /* … */ });
const phase = channel.getSandboxPhase();
自己畫啟動提示
要換掉內建 HUD 的話,useSandboxLaunch 把 phase 轉成顯示用的 stage:
import { useSandboxLaunch } from "@asgard-js/react";
const { stage, visible } = useSandboxLaunch(phase, {
thresholdMs: 1000, // 低於此時間完成的啟動不顯示
readyBeatMs: 900, // ready 後停留多久再開始淡出
exitMs: 600, // 淡出時間,需與你的 CSS 一致
});
// stage: 'hidden' | 'launching' | 'ready' | 'leaving'
// visible: stage !== 'hidden' 的便利旗標
所有計時器都會在 unmount 或 phase 變動時清掉。
與連線指示器互相獨立
footer 上緣的連線進度線(RunningIndicator)綁的是整個 run 的連線;HUD 只管
「sandbox 是不是卡在冷啟動」。兩者可以同時出現,互不干擾。
已啟動的 sandbox 清單
launchedSandboxes$ 帶出每個 sandbox 的識別與能力:
interface LaunchedSandbox {
sandboxName: string; // 權威識別碼;所有 fs / browser API 都用它定位
sandboxBlueprintName: string; // 建立它的藍圖名稱,通常比 sandboxName 好讀
workingDirectory: string; // File Explorer 的樹根
editorServerEnabled: boolean;
browserEnabled: boolean; // 是否啟用瀏覽器(決定交接卡能不能用)
}
sandboxPhase 不同源sandboxPhase 是直接從 SSE 事件收斂的;launchedSandboxes$ 不是。這份清單的唯一權威來源是
GET /channel/metadata,SSE 事件從不直接寫進去。asgard.sandbox.launch 只是一個提示——它把
名字記進待確認清單並觸發一次 metadata 重抓,由回來的結果決定誰還活著。
所以不要拿 sandbox.launch 事件自己推斷「現在有哪些 sandbox」,那會和後端的權威狀態分岔。
File Explorer 的 sandbox 下拉選單吃的就是這份清單。
也看看
- sandbox:// 交接卡 — 把使用者交接到 sandbox 的瀏覽器或檔案
- File Explorer — 瀏覽與編輯 sandbox 裡的檔案