events.ts
2292 bytes
1import type {
2 Event,
3 EventMessageUpdated,
4 EventMessagePartUpdated,
5 Part,
6} from "@opencode-ai/sdk";
7import * as log from "./log.js";
8
9// Server sends `permission.asked` with this shape, which diverges from the SDK's
10// v1 Permission type. Keep a local interface until the SDK aligns.
11export interface PermissionEvent {
12 id: string;
13 sessionID: string;
14 permission: string;
15 patterns: string[];
16 metadata: Record<string, unknown>;
17 always?: string[];
18 tool?: { messageID: string; callID: string };
19}
20
21export type PartHandler = (parts: Part[]) => void;
22export type PermissionHandler = (perm: PermissionEvent) => void;
23
24interface SessionHandler {
25 onPart: PartHandler;
26 onPermission: PermissionHandler;
27 parts: Map<string, Part>;
28 assistantMessageIDs: Set<string>;
29}
30
31const handlers = new Map<string, SessionHandler>();
32
33export function registerSession(
34 sessionId: string,
35 onPart: PartHandler,
36 onPermission: PermissionHandler,
37): void {
38 handlers.set(sessionId, {
39 onPart,
40 onPermission,
41 parts: new Map(),
42 assistantMessageIDs: new Set(),
43 });
44}
45
46export function unregisterSession(sessionId: string): void {
47 handlers.delete(sessionId);
48}
49
50export function handleEvent(event: Event): void {
51 const type = event.type as string;
52
53 if (type === "message.updated") {
54 const info = (event as EventMessageUpdated).properties.info;
55 if (info.role !== "assistant") return;
56 const handler = handlers.get(info.sessionID);
57 if (!handler) return;
58 handler.assistantMessageIDs.add(info.id);
59 return;
60 }
61
62 if (type === "message.part.updated") {
63 const part = (event as EventMessagePartUpdated).properties.part;
64 const handler = handlers.get(part.sessionID);
65 if (!handler) return;
66 if (!handler.assistantMessageIDs.has(part.messageID)) return;
67 handler.parts.set(part.id, part);
68 handler.onPart(Array.from(handler.parts.values()));
69 return;
70 }
71
72 if (type === "permission.asked" || type === "permission.updated") {
73 const perm = event.properties as unknown as PermissionEvent;
74 log.info(
75 `[events] ${type} session=${perm.sessionID} perm=${perm.id} permission=${perm.permission}`,
76 );
77 const handler = handlers.get(perm.sessionID);
78 if (!handler) return;
79 handler.onPermission(perm);
80 return;
81 }
82}