فهرست منبع

fix(app): terminal issues

Adam 6 ماه پیش
والد
کامیت
8c484a05b8
1فایلهای تغییر یافته به همراه19 افزوده شده و 85 حذف شده
  1. 19 85
      packages/opencode/src/pty/index.ts

+ 19 - 85
packages/opencode/src/pty/index.ts

@@ -23,60 +23,6 @@ export namespace Pty {
     close: (code?: number, reason?: string) => void
   }
 
-  type Subscriber = {
-    id: number
-    token: unknown
-  }
-
-  const sockets = new WeakMap<object, number>()
-  const owners = new WeakMap<object, string>()
-  let socketCounter = 0
-
-  const tagSocket = (ws: Socket) => {
-    if (!ws || typeof ws !== "object") return
-    const next = (socketCounter = (socketCounter + 1) % Number.MAX_SAFE_INTEGER)
-    sockets.set(ws, next)
-    return next
-  }
-
-  const token = (ws: Socket) => {
-    const data = ws.data
-    if (data === undefined) return
-    if (data === null) return
-    if (typeof data !== "object") return data
-
-    const id = (data as { connId?: unknown }).connId
-    if (typeof id === "number" || typeof id === "string") return id
-
-    const href = (data as { href?: unknown }).href
-    if (typeof href === "string") return href
-
-    const url = (data as { url?: unknown }).url
-    if (typeof url === "string") return url
-    if (url && typeof url === "object") {
-      const href = (url as { href?: unknown }).href
-      if (typeof href === "string") return href
-      return url
-    }
-
-    const events = (data as { events?: unknown }).events
-    if (typeof events === "number" || typeof events === "string") return events
-    if (events && typeof events === "object") {
-      const id = (events as { connId?: unknown }).connId
-      if (typeof id === "number" || typeof id === "string") return id
-
-      const id2 = (events as { connection?: unknown }).connection
-      if (typeof id2 === "number" || typeof id2 === "string") return id2
-
-      const id3 = (events as { id?: unknown }).id
-      if (typeof id3 === "number" || typeof id3 === "string") return id3
-
-      return events
-    }
-
-    return data
-  }
-
   // WebSocket control frame: 0x00 + UTF-8 JSON.
   const meta = (cursor: number) => {
     const json = JSON.stringify({ cursor })
@@ -141,7 +87,7 @@ export namespace Pty {
     buffer: string
     bufferCursor: number
     cursor: number
-    subscribers: Map<Socket, Subscriber>
+    subscribers: Map<unknown, Socket>
   }
 
   const state = Instance.state(
@@ -151,9 +97,9 @@ export namespace Pty {
         try {
           session.process.kill()
         } catch {}
-        for (const ws of session.subscribers.keys()) {
+        for (const [key, ws] of session.subscribers.entries()) {
           try {
-            ws.close()
+            if (ws.data === key) ws.close()
           } catch {
             // ignore
           }
@@ -224,26 +170,21 @@ export namespace Pty {
     ptyProcess.onData((chunk) => {
       session.cursor += chunk.length
 
-      for (const [ws, sub] of session.subscribers) {
+      for (const [key, ws] of session.subscribers.entries()) {
         if (ws.readyState !== 1) {
-          session.subscribers.delete(ws)
-          continue
-        }
-
-        if (typeof ws === "object" && sockets.get(ws) !== sub.id) {
-          session.subscribers.delete(ws)
+          session.subscribers.delete(key)
           continue
         }
 
-        if (token(ws) !== sub.token) {
-          session.subscribers.delete(ws)
+        if (ws.data !== key) {
+          session.subscribers.delete(key)
           continue
         }
 
         try {
           ws.send(chunk)
         } catch {
-          session.subscribers.delete(ws)
+          session.subscribers.delete(key)
         }
       }
 
@@ -256,9 +197,9 @@ export namespace Pty {
     ptyProcess.onExit(({ exitCode }) => {
       log.info("session exited", { id, exitCode })
       session.info.status = "exited"
-      for (const ws of session.subscribers.keys()) {
+      for (const [key, ws] of session.subscribers.entries()) {
         try {
-          ws.close()
+          if (ws.data === key) ws.close()
         } catch {
           // ignore
         }
@@ -291,9 +232,9 @@ export namespace Pty {
     try {
       session.process.kill()
     } catch {}
-    for (const ws of session.subscribers.keys()) {
+    for (const [key, ws] of session.subscribers.entries()) {
       try {
-        ws.close()
+        if (ws.data === key) ws.close()
       } catch {
         // ignore
       }
@@ -325,23 +266,16 @@ export namespace Pty {
     }
     log.info("client connected to session", { id })
 
-    const socketId = tagSocket(ws)
-    if (socketId === undefined) {
-      ws.close()
-      return
-    }
-
-    const previous = owners.get(ws)
-    if (previous && previous !== id) {
-      state().get(previous)?.subscribers.delete(ws)
-    }
+    // Use ws.data as the unique key for this connection lifecycle.
+    // If ws.data is undefined, fallback to ws object.
+    const connectionKey = ws.data && typeof ws.data === "object" ? ws.data : ws
 
-    owners.set(ws, id)
-    session.subscribers.set(ws, { id: socketId, token: token(ws) })
+    // Optionally cleanup if the key somehow exists
+    session.subscribers.delete(connectionKey)
+    session.subscribers.set(connectionKey, ws)
 
     const cleanup = () => {
-      session.subscribers.delete(ws)
-      if (owners.get(ws) === id) owners.delete(ws)
+      session.subscribers.delete(connectionKey)
     }
 
     const start = session.bufferCursor