跳至主要内容

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,這時閃一下動畫只是雜訊,所以門檻內完成的啟動全程靜音。

手動驅動 phase
  • 冷啟動:按 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 下拉選單吃的就是這份清單。

也看看