跳至主要内容

sandbox:// 交接卡

Agent 在 sandbox 裡開了一個瀏覽器工作階段、或產出了一份檔案時,需要一個方式把使用者 交接過去。做法是讓附件卡片的 defaultAction 指向 sandbox:// 這個自訂 scheme。

SDK 會在走到「開新分頁」的預設行為之前攔截它,解析成一個具型別的 intent,再交給對應的 處理器。原始的 sandbox:// URI 永遠不會被丟進 window.open()

sandbox:// 交接卡

當附件卡片的 defaultAction 指向 sandbox:// 這個自訂 scheme 時,SDK 會在走到「開新分頁」的預設行為之前先攔截它,解析成一個具型別的 intent,再交給對應的處理器。一般的 https:// 連結不受影響,照常開連結。

<Chatbot
  config={{ botProviderEndpoint: '...' }}
  customChannelId="my-channel"
  // 攔截 sandbox://<name>/open-browser
  onSandboxOpenBrowser={(sandboxName) => { /* … */ }}
  // 攔截 sandbox://<name>/open-file?absolute_path=…
  onSandboxOpenFile={(sandboxName, absolutePath) => { /* … */ }}
/>

已派送的 intent

尚未點擊任何 sandbox:// 卡片

點左側前兩張卡片 → 解析出的 intent 會記在下方;第三張是一般連結,不會被攔截。

聊天機器人載入中…

URI 格式

sandbox://<sandboxName>/<action>?<query>

目前支援兩個 action:

URI解析結果
sandbox://sbx-a/open-browser{ kind: 'open-browser', sandboxName: 'sbx-a' }
sandbox://sbx-a/open-file?absolute_path=%2Fhome%2Fuser%2Freport.md{ kind: 'open-file', sandboxName: 'sbx-a', absolutePath: '/home/user/report.md' }

absolute_path 必須做 URL 編碼(絕對路徑裡有很多 /)。

接手處理

兩個 action 都可以由整合方覆寫:

<Chatbot
config={{ botProviderEndpoint: "..." }}
customChannelId="my-channel"
// 有給就以你的為準;沒給則走 SDK 預設(取一次性 URL 後開新分頁)
onSandboxOpenBrowser={(sandboxName) => { /* … */ }}
// open-file 的目的地通常是 File Explorer
onSandboxOpenFile={(sandboxName, absolutePath) => {
controller.requestFile(sandboxName, absolutePath);
}}
// 預設處理器開分頁的目標,預設 '_blank'
sandboxBrowserOpenTarget="_blank"
// 想真的接管 open-file 就一定要加這行,理由見下方
fileExplorer="off"
/>
兩個 handler 的語意不一樣

onSandboxOpenBrowser 是真的二選一:有給就以你的為準,沒給才走 SDK 預設。

onSandboxOpenFile 不是。 它是「加上去」而不是「取代掉」——你的 handler 會被呼叫,但內建的 File Explorer 側欄同時也照樣會被拉開,因為那段邏輯只看 fileExplorer prop,不看你有沒有給 callback。而 fileExplorer 預設就是 'builtin'

結果是你自己的 controller 和 Chatbot 內部的 controller 會同時收到同一個 requestFile。要真的 接管,必須另外把 fileExplorer 設成 "off"

自己解析

resolveSandboxUri 也可以單獨使用——例如你自己渲染卡片的時候:

import { resolveSandboxUri } from "@asgard-js/core";

const intent = resolveSandboxUri(uri);

if (intent === null) {
// 不是 sandbox://、action 不認得、或缺 absolute_path
// → 當成一般卡片處理,絕對不要 window.open() 原始 URI
}

回傳型別:

type SandboxUriIntent =
| { kind: "open-browser"; sandboxName: string }
| { kind: "open-file"; sandboxName: string; absolutePath: string };
備註

解析用的是手寫 regex 而不是 new URL()。絕對路徑帶有大量 /,而 WHATWG URL parser 對 非特殊 scheme 的 host 大小寫處理並不可靠;query 的部分仍交給 URLSearchParams 解碼。

一般連結不受影響

https:// 之類的 defaultAction 完全照舊走正常開連結行為——攔截只發生在 sandbox://

也看看