跳到內容

Session 狀態與 Events

PedelecSession 維護 browser-side status,並提供 status、error 與 end lifecycle callbacks。

type PedelecSessionStatus =
| "idle"
| "running"
| "waiting_tool_result"
| "ended"
| "error";
Status 意義 可呼叫 sendText()
idle 沒有 active turn,可接收下一個 prompt 可以
running Preparation 或 user turn active 不可以
waiting_tool_result Agent 已要求 frontend tool,正在等待 不可以
ended Session 已結束;只要 Core 與記錄的 workspace 仍可恢復,同一個 attached handle 可明確呼叫 resume() resume() 成功前不可以
error Runtime 回報 session error 不可以;依產品策略建立或 resume session

PedelecSession object 的 local initial status 是 idleresumeSession() 回傳的 handle 會在 promise resolve 前先和 Core 同步,因此初始也可能是 runningwaiting_tool_resulterrorended

Pedelec.resumeSession(sessionId) 只會重新 attach 到既有 thread,因此 ended thread 仍保持 endedPedelecSession.resume() 才是同一個 handle 的明確 ended → idle transition;它保留 handle handlers 與 session state,provider runtime work 仍會等到下一個正常 operation 才 lazy 執行。

沒有 tool 的 turn:

idle → running → idle

包含 frontend tool:

idle
→ running
→ waiting_tool_result
→ running
→ idle

Active state 也可能直接 error 或 ended:

running → error
running → ended
waiting_tool_result → error
waiting_tool_result → ended

不要假設每個理論 intermediate status 都一定會在 UI 出現。Event 可能被 normalize、de-duplicate,或非常接近地到達。idle 是可觀察的 thread state,單獨不代表特定的 prepare()sendText() promise 已完成。

const offStatus = session.onStatus((status, ctx) => {
console.log(ctx.previousStatus, "", status);
console.log(ctx.type, ctx.source);
});

只有 value 改變時 callback 才執行。Registration 不會立即 emit initial status。

renderStatus(session.getStatus());
const offStatus = session.onStatus(renderStatus);

為了 UI 即時反應,SDK 可在 Core response 前先 emit:

  • sendText()prepare() local set running
  • tool event 處理時 set waiting_tool_result
  • end() request 成功後 local mark ended。
  • session.resume() 不會 optimistic set idle;這個狀態由 authoritative Core snapshot 與 operation-less status_changed event 設定。

Context 可辨識來源:

ctx.source // "sdk" | "core"
ctx.type // "sdk_status_changed" | "status_changed"

Core event 使用 source: "core";SDK 內部主動變更使用 source: "sdk"

Status handler 會去重。SDK 已設為 running,Core 後續也回報 running 時,不會再 callback 一次。

const offError = session.onError((error, ctx) => {
console.error(error.code, error.message, error.details);
console.debug(ctx.type, ctx.source, ctx.sessionId);
});
type ErrorEventContext = PedelecEventContext & {
type: "error" | "sdk_error";
};

onError() 適合 session-wide observation、logging 與 UI;發起 action 的 promise 仍要 catch。

Error callback 不一定代表 status 變成 error。例如 tool result submission 失敗會 emit SDK SUBMIT_TOOL_RESULT_FAILED,最終 session state 仍由 Runtime 決定。Core operation error 是 diagnostic;語意上的 rejection 由相符的 operation completion 提供。

const offEnded = session.onEnded((ctx) => {
console.log("ended by", ctx.source);
});
type EndedEventContext = PedelecEventContext & {
type: "ended" | "sdk_ended";
};

onEnded() 會在每次 transition 進入 ended 時執行一次,無論原因是 runtime event 或成功的 local end()。Handle 已經是 ended 時,重複的 ended notification 不會再次執行 callback。相同 handle 成功透過 resume()ended 回到 idle 後,之後再次 transition 回 ended 會視為新的 lifecycle transition,再執行一次 callback。

Session end 時,pending sendText()prepare() 會 reject SESSION_ENDED

type PedelecEventContext = {
sessionId: string;
provider: string;
effortLevel?: "default" | "low" | "high";
sessionCreatedAt: number;
eventReceivedAt?: number;
eventEmittedAt: number;
turnId?: string;
turnStartedAt?: number;
turnKind?: "user" | "prepare";
source: "core" | "sdk";
};

不是每個 event 都有所有欄位:

  • Core chat/tool callback 有 received time 與 active turn metadata。
  • Local status change 可能發生在 Core event 前,沒有 eventReceivedAt
  • Active turn 之外的 end/error 可能沒有 turn fields。
  • 新的 resumed handle 若應用程式沒自行保存,可能有空 provider metadata。

Tool handler 還會收到:

ctx.type; // "tool_call"
ctx.toolRequestId; // Core tool request identifier
ctx.tool; // tool name
ctx.turnId;

toolRequestId 可用於 diagnostics 與 application bookkeeping,不需要手動 submit result;SDK 會自動送出 handler return value。

Core event 可包含 per-session sequence number。Client 會忽略 sequence 不比上一個更新的 event,且 operation-scoped event 只有在 operation ID 對應目前 active operation 時才會採用。Application 自己 handler 內的 async work 仍要能處理 rapid transition 與 late completion。

Subscription 重建時,SDK 會先收到 authoritative lifecycle snapshot,再接收 live event。Resume 或 recovery handle 會依 snapshot 採用 Core status 與 active operation;若 Core 回報 pending frontend tool,請在 resumeSession() 後註冊 handler,SDK 會先保留 recovered request,等相符 handler 可用後才 submit。同一個 handle 的 session.resume() 也會在 promise resolve 前 reconciliation reactivation 後的 snapshot,因此 await 後 getStatus() 一定是 idle

session.onStatus((status) => {
setSendEnabled(status === "idle");
setBusy(status === "running" || status === "waiting_tool_result");
setToolWaiting(status === "waiting_tool_result");
setSessionClosed(status === "ended");
});

Interactive tool 正在等待使用者時,不要把 waiting_tool_result 只顯示成 frozen。應呈現對應 modal 或操作提示。

下一頁:Session Lifecycle 與 Resume