





















@@ -41,6 +41,16 @@ export interface SessionLike {
41414242export interface EventBridgeOptions {
4343onAssistantDelta?: (payload: OnAssistantDeltaPayload) => void | Promise<void>;
44+onAgentEvent?: (event: {
45+stream: "item" | "plan";
46+data: Record<string, unknown>;
47+}) => void | Promise<void>;
48+onNativeSubagentEvent?: (
49+event: Extract<
50+SessionEvent,
51+{ type: "subagent.started" | "subagent.completed" | "subagent.failed" }
52+>,
53+) => void;
4454onCompactionComplete?: (payload: {
4555messagesRemoved?: number;
4656success: boolean;
@@ -72,6 +82,7 @@ export interface EventBridgeController {
7282awaitSessionIdle(): Promise<void>;
7383settleCompactionWait(): void;
7484awaitDeltaChain(): Promise<void>;
85+awaitAgentEventChain(): Promise<void>;
7586hasObservedCompaction(): boolean;
7687hasObservedSessionIdle(): boolean;
7788isCompacting(): boolean;
@@ -103,6 +114,7 @@ export function attachEventBridge(
103114let observedCompaction = false;
104115let deltaQueue = Promise.resolve();
105116let deltaChain = Promise.resolve();
117+let agentEventChain = Promise.resolve();
106118let compactionChain = Promise.resolve();
107119let compactionIdle = Promise.resolve();
108120let resolveCompactionIdle: (() => void) | undefined;
@@ -191,6 +203,51 @@ export function attachEventBridge(
191203}
192204});
193205206+registerListener(session, unsubscribeFns, "session.plan_changed", (event) => {
207+enqueueAgentEvent({
208+stream: "plan",
209+data: {
210+phase: "update",
211+title: "Plan updated",
212+source: "copilot-sdk",
213+operation: event.data.operation,
214+ ...(event.agentId ? { agentId: event.agentId } : {}),
215+},
216+});
217+});
218+219+registerListener(session, unsubscribeFns, "exit_plan_mode.requested", (event) => {
220+const steps = splitPlanText(event.data.planContent);
221+enqueueAgentEvent({
222+stream: "plan",
223+data: {
224+phase: "update",
225+title: "Plan updated",
226+source: "copilot-sdk",
227+ ...(event.data.summary ? { explanation: event.data.summary } : {}),
228+ ...(steps.length > 0 ? { steps } : {}),
229+ ...(event.data.actions.length > 0 ? { actions: event.data.actions } : {}),
230+ ...(event.data.requestId ? { requestId: event.data.requestId } : {}),
231+ ...(event.data.recommendedAction
232+ ? { recommendedAction: event.data.recommendedAction }
233+ : {}),
234+ ...(event.agentId ? { agentId: event.agentId } : {}),
235+},
236+});
237+});
238+239+registerListener(session, unsubscribeFns, "subagent.started", (event) => {
240+forwardNativeSubagentEvent(event);
241+});
242+243+registerListener(session, unsubscribeFns, "subagent.completed", (event) => {
244+forwardNativeSubagentEvent(event);
245+});
246+247+registerListener(session, unsubscribeFns, "subagent.failed", (event) => {
248+forwardNativeSubagentEvent(event);
249+});
250+194251registerListener(session, unsubscribeFns, "session.compaction_start", (event) => {
195252if (!isRootCompactionEvent(event)) {
196253return;
@@ -276,6 +333,9 @@ export function attachEventBridge(
276333awaitDeltaChain() {
277334return deltaChain;
278335},
336+awaitAgentEventChain() {
337+return agentEventChain;
338+},
279339hasObservedCompaction() {
280340return observedCompaction;
281341},
@@ -334,6 +394,31 @@ export function attachEventBridge(
334394compactionChain = queued.catch(() => undefined);
335395}
336396397+function enqueueAgentEvent(event: {
398+stream: "item" | "plan";
399+data: Record<string, unknown>;
400+}): void {
401+const callback = options.onAgentEvent;
402+if (!callback) {
403+return;
404+}
405+const invoke = () => callback(event);
406+agentEventChain = agentEventChain.then(invoke, invoke).catch(() => undefined);
407+}
408+409+function forwardNativeSubagentEvent(
410+event: Extract<
411+SessionEvent,
412+{ type: "subagent.started" | "subagent.completed" | "subagent.failed" }
413+>,
414+): void {
415+try {
416+options.onNativeSubagentEvent?.(event);
417+} catch {
418+// Native task mirroring must not corrupt the Copilot turn.
419+}
420+}
421+337422async function awaitStableCompaction(): Promise<void> {
338423const idle = activeCompactionCount > 0 ? compactionIdle : undefined;
339424if (idle) {
@@ -456,6 +541,13 @@ function joinReasoning(order: string[], reasoningById: Map<string, string>): str
456541return order.map((reasoningId) => reasoningById.get(reasoningId) ?? "").join("");
457542}
458543544+function splitPlanText(text: string | undefined): string[] {
545+return (text ?? "")
546+.split(/\r?\n/)
547+.map((line) => line.trim().replace(/^[-*]\s+/, ""))
548+.filter((line) => line.length > 0);
549+}
550+459551function readString(value: unknown): string | undefined {
460552return typeof value === "string" && value.length > 0 ? value : undefined;
461553}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。