Relay · Client integration
SDK 與 Widget
Relay 提供 TypeScript core SDK、React binding 與 UI、Vue composable、script-tag widget,以及 browser streaming renderer。應選擇符合產品需要的最薄一層。Authentication、channel membership 與 business authorization 仍由 host 負責。
Distribution status
@tonetify/relay@0.1.0-beta.1 已透過 npm 的 beta tag 公開發布。Package 包含 ESM、CommonJS、type declaration、streaming style 與 IIFE widget bundle,採用 MIT 授權,且不包含 source map。
明確安裝測試版本:
npm install @tonetify/relay@0.1.0-beta.1 Production automation 應固定使用完整的 beta version。Package 已公開,但 Relay 尚未提供 server-to-SDK compatibility matrix 或 upgrade policy。
Relay + Govern
SDK 傳遞 turn,Govern 約束 reply
組合路徑
-
Host
從 Govern 取得有 scope 的 Relay session。
-
Relay SDK
加入 channel,傳送 user message。
-
Govern
處理
message.created,並選擇 effect。 -
Relay
提交並送出最後的 reply。
Core SDK
Host 必須提供 JWT、tenant ID、channel ID 與 WebSocket URL。只有 reaction inspection、notification mute 等 REST convenience helper 需要 apiUrl。userId 可讓這些 helper 計算 viewer-specific state。
import { ChatClient } from "@tonetify/relay";
const client = new ChatClient({
url: "wss://relay.example.com/socket",
apiUrl: "https://relay.example.com",
token,
userId
});
client.connect();
const channel = client.channel(channelId, tenantId);
channel.on("msg:new", (message) => {
console.log(message.seq, message.body);
});
await channel.join();
await channel.send("Hello from Relay", {
nonce: crypto.randomUUID()
}); 只能在 browser 呼叫 connect(),server-side rendering 期間呼叫會直接 throw。應在 React effect、Vue client scope,或相等的 browser lifecycle 內 mount,並在 integration dispose 時呼叫 disconnect()。
穩定核心與預覽介面
契約測試版的穩定核心包括:
- join、leave、可安全重試的 send 與 cursor update;
- 穩定的
presence_state、presence_diff、msg:new、catch_up:truncated與unread_count事件; - 連線狀態與生命週期事件;
- notification mute helper。
ChatChannel 也提供 edit、retract、pin、unpin、thread、reaction 與 typing 能力。這些目前屬於預覽介面。方法可以使用,但相關 WebSocket event name、payload 與恢復行為在契約測試期間仍可能改變。
如果 caller 沒有提供 nonce,channel.send() 會自動產生一個。Send result 不確定而需要 retry 時,host 必須保留原 nonce。再次呼叫 send() 卻沒有傳回原 nonce,代表新的 logical send。
React integration
需要 minimal conversation UI 時,可以使用 RelayWidget:
import { RelayWidget } from "@tonetify/relay/react";
export function SupportChat({ token }: { token: string }) {
return (
<RelayWidget
url="wss://relay.example.com/socket"
apiUrl="https://relay.example.com"
token={token}
userId="current-user-id"
tenantId="tenant-uuid"
channelId="channel-uuid"
channelName="Support"
/>
);
} Product-owned UI 可以組合 ChatProvider、useChannel、useMessages 與 usePresence,或直接使用 core SDK。React layer 會在 mount 時 connect、join 指定 channel、套用 optimistic send,並在 unmount 時 disconnect。
Script-tag widget
Build 會產生 dist/tonetify-relay-widget.global.js。Host 需要託管這份確切 artifact,再明確 mount:
<div id="chat-root"></div>
<script src="/assets/tonetify-relay-widget.global.js"></script>
<script>
window.TonetifyRelay.init({
url: "wss://relay.example.com/socket",
token: "host-signed-jwt",
tenantId: "tenant-uuid",
channelId: "channel-uuid",
target: "#chat-root",
mode: "shadow",
theme: { primaryColor: "#3158d3" }
});
</script> mode 可以是 shadow 或 iframe。Iframe mode 使用 same-document srcdoc,只是 styling boundary,不是 cross-origin security boundary。Widget 會顯示 minimal live timeline、presence status、connection error 與 message composer。它不是完整的 support desk 或 moderation UI。
再次呼叫 TonetifyRelay.init() 時,會先 destroy 前一個 singleton widget,再 mount 新 instance。
Vue 與 streaming
@tonetify/relay/vue 提供 useChat、useChannel、useMessages 與 usePresence。這些 composable 已實作並有測試,但仍是 preview integration surface。在公開 compatibility policy 建立前,它們仍可能變更。
@tonetify/relay/streaming 提供 browser-only renderer,可逐步顯示 text 或 Markdown,也包含有上限的 CJK tokenization。它只影響 presentation。Relay 仍只儲存一份 final message body,沒有 server streaming-message contract。
Recovery boundary
Phoenix 會 reconnect socket 並 rejoin channel,但 default React、Vue 與 script widget store 都只存在 memory。Page reload 後會失去 last known seq。High-level binding 目前也不會 persist 或完整 drain truncated catch-up window。
需要可靠的 history recovery 時,應 persist 最新 confirmed seq、呼叫 channel.join(lastSeq)、監聽 catch_up:truncated,再透過 REST history contract 取得後續 page。不能把目前 SDK 描述成具備 offline storage 或 exactly-once client rendering。
SDK 目前沒有 attachment upload、search、channel administration、user export 或 tenant operation helper。這些 surface 請使用已公開的 HTTP API。
Artifact verification
Distribute build 前執行:
cd sdk
npm run build
npm test
npm run typecheck
npm run pack:check 這些 command 能證明 repository 內的 package 可以 build、typecheck、test 與 pack。公開的 0.1.0-beta.1 artifact 也已從 npm 讀回驗證。這不代表已建立 browser compatibility target、跨版本 server compatibility、semantic-version support 或 managed upgrade service。