| 9 | }>; |
| 10 | |
| 11 | export function useAgentLogs( |
| 12 | options: UseAgentLogsOptions, |
| 13 | ): readonly WorkspaceAgentLog[] { |
| 14 | const { agentId, enabled = true } = options; |
| 15 | const [logs, setLogs] = useState<readonly WorkspaceAgentLog[]>([]); |
| 16 | |
| 17 | // Clean up the logs when the agent is not enabled, using a mid-render |
| 18 | // sync to remove any risk of screen flickering. Clearing the logs helps |
| 19 | // ensure that if the hook flips back to being enabled, we can receive a |
| 20 | // fresh set of logs from the beginning with zero risk of duplicates. |
| 21 | const [prevEnabled, setPrevEnabled] = useState(enabled); |
| 22 | if (!enabled && prevEnabled) { |
| 23 | setLogs([]); |
| 24 | setPrevEnabled(false); |
| 25 | } |
| 26 | if (enabled && !prevEnabled) { |
| 27 | setPrevEnabled(true); |
| 28 | } |
| 29 | |
| 30 | useEffect(() => { |
| 31 | if (!enabled) { |
| 32 | return; |
| 33 | } |
| 34 | |
| 35 | // Always fetch the logs from the beginning. We may want to optimize |
| 36 | // this in the future, but it would add some complexity in the code |
| 37 | // that might not be worth it. |
| 38 | const socket = watchWorkspaceAgentLogs(agentId, { after: 0 }); |
| 39 | socket.addEventListener("message", (e) => { |
| 40 | if (e.parseError) { |
| 41 | console.warn("Error parsing agent log: ", e.parseError); |
| 42 | return; |
| 43 | } |
| 44 | |
| 45 | if (e.parsedMessage.length === 0) { |
| 46 | return; |
| 47 | } |
| 48 | |
| 49 | setLogs((logs) => { |
| 50 | const newLogs = [...logs, ...e.parsedMessage]; |
| 51 | newLogs.sort((l1, l2) => { |
| 52 | const d1 = new Date(l1.created_at).getTime(); |
| 53 | const d2 = new Date(l2.created_at).getTime(); |
| 54 | return d1 - d2; |
| 55 | }); |
| 56 | return newLogs; |
| 57 | }); |
| 58 | }); |
| 59 | |
| 60 | socket.addEventListener("error", (error) => { |
| 61 | console.error("Error in agent log socket: ", error); |
| 62 | toast.error(`Unable to watch "${agentId}" agent logs.`, { |
| 63 | description: "Please try refreshing the browser.", |
| 64 | }); |
| 65 | socket.close(); |
| 66 | }); |
| 67 | |
| 68 | return () => { |