fix: CLI spec contradictions from codex AX audit
- Fix paths: relative to agent home dir, not hardcoded /home/agent - Add worker/dream coordination: dream pauses worker to prevent file races - Watch registration via .colony.toml (server reads agent config) - Remove remaining old mentions API reference (use inbox instead) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,26 +1,44 @@
|
||||
import { useEffect, useRef, useCallback } from "react";
|
||||
import type { Message } from "@/types/Message";
|
||||
import { getCurrentUsername, getMessages } from "@/api";
|
||||
import { getCurrentUsername } from "@/api";
|
||||
|
||||
interface WsMessageEvent {
|
||||
event: "message";
|
||||
data: Message;
|
||||
}
|
||||
|
||||
interface WsEditEvent {
|
||||
event: "edit";
|
||||
data: Message;
|
||||
}
|
||||
|
||||
interface WsDeleteEvent {
|
||||
event: "delete";
|
||||
data: { id: string };
|
||||
}
|
||||
|
||||
interface WsConnectedEvent {
|
||||
event: "connected";
|
||||
}
|
||||
|
||||
type WsEvent = WsMessageEvent | WsConnectedEvent;
|
||||
interface WsLagEvent {
|
||||
event: "lag";
|
||||
missed: number;
|
||||
}
|
||||
|
||||
type WsEvent = WsMessageEvent | WsEditEvent | WsDeleteEvent | WsConnectedEvent | WsLagEvent;
|
||||
|
||||
export function useChannelSocket(
|
||||
channelId: string | null,
|
||||
onMessage: (msg: Message) => void,
|
||||
onEdit: (msg: Message) => void,
|
||||
onDelete: (id: string) => void,
|
||||
onReconnect: () => void,
|
||||
) {
|
||||
const wsRef = useRef<WebSocket | null>(null);
|
||||
const reconnectTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const intentionalClose = useRef(false);
|
||||
const backoffMs = useRef(3000);
|
||||
|
||||
const connect = useCallback(() => {
|
||||
if (!channelId) return;
|
||||
@@ -32,6 +50,7 @@ export function useChannelSocket(
|
||||
const ws = new WebSocket(`${protocol}//${host}/ws/${channelId}`);
|
||||
|
||||
ws.onopen = () => {
|
||||
backoffMs.current = 3000; // Reset backoff on successful connect
|
||||
ws.send(JSON.stringify({
|
||||
type: "auth",
|
||||
user: getCurrentUsername(),
|
||||
@@ -43,8 +62,12 @@ export function useChannelSocket(
|
||||
const event: WsEvent = JSON.parse(e.data);
|
||||
if (event.event === "message") {
|
||||
onMessage(event.data);
|
||||
} else if (event.event === "connected") {
|
||||
// Refetch history on reconnect to catch missed messages
|
||||
} else if (event.event === "edit") {
|
||||
onEdit(event.data);
|
||||
} else if (event.event === "delete") {
|
||||
onDelete(event.data.id);
|
||||
} else if (event.event === "connected" || event.event === "lag") {
|
||||
// Refetch to catch missed messages
|
||||
onReconnect();
|
||||
}
|
||||
} catch {
|
||||
@@ -57,19 +80,18 @@ export function useChannelSocket(
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
// Only reconnect if this wasn't an intentional teardown
|
||||
if (!intentionalClose.current) {
|
||||
reconnectTimer.current = setTimeout(connect, 3000);
|
||||
reconnectTimer.current = setTimeout(connect, backoffMs.current);
|
||||
backoffMs.current = Math.min(backoffMs.current * 2, 30000); // Exponential backoff, max 30s
|
||||
}
|
||||
};
|
||||
|
||||
wsRef.current = ws;
|
||||
}, [channelId, onMessage, onReconnect]);
|
||||
}, [channelId, onMessage, onEdit, onDelete, onReconnect]);
|
||||
|
||||
useEffect(() => {
|
||||
connect();
|
||||
return () => {
|
||||
// Mark as intentional so onclose doesn't reconnect
|
||||
intentionalClose.current = true;
|
||||
if (reconnectTimer.current) clearTimeout(reconnectTimer.current);
|
||||
wsRef.current?.close();
|
||||
|
||||
Reference in New Issue
Block a user