@thrillee/aegischat 0.1.12 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +30 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/hooks/useAutoRead.ts +9 -11
- package/src/hooks/useChat.ts +30 -9
package/dist/index.mjs
CHANGED
|
@@ -266,8 +266,12 @@ function useChat(options = {}) {
|
|
|
266
266
|
const [session, setSession] = useState(null);
|
|
267
267
|
const [isConnected, setIsConnected] = useState(false);
|
|
268
268
|
const [isConnecting, setIsConnecting] = useState(false);
|
|
269
|
+
const getStoredActiveChannel = () => {
|
|
270
|
+
if (typeof window === "undefined") return null;
|
|
271
|
+
return sessionStorage.getItem(SESSION_STORAGE_KEY);
|
|
272
|
+
};
|
|
269
273
|
const [activeChannelId, setActiveChannelIdState] = useState(
|
|
270
|
-
|
|
274
|
+
getStoredActiveChannel
|
|
271
275
|
);
|
|
272
276
|
const [channels, setChannels] = useState([]);
|
|
273
277
|
const [messages, setMessages] = useState([]);
|
|
@@ -301,6 +305,7 @@ function useChat(options = {}) {
|
|
|
301
305
|
return sessionStorage.getItem(SESSION_STORAGE_KEY);
|
|
302
306
|
}, []);
|
|
303
307
|
const setActiveChannelId = useCallback((id) => {
|
|
308
|
+
activeChannelIdRef.current = id;
|
|
304
309
|
setActiveChannelIdState(id);
|
|
305
310
|
if (typeof window !== "undefined") {
|
|
306
311
|
if (id) {
|
|
@@ -570,7 +575,9 @@ function useChat(options = {}) {
|
|
|
570
575
|
if (!currentSession) return;
|
|
571
576
|
setIsLoadingChannels(true);
|
|
572
577
|
try {
|
|
573
|
-
const response = await fetchFromComms(
|
|
578
|
+
const response = await fetchFromComms(
|
|
579
|
+
"/channels"
|
|
580
|
+
);
|
|
574
581
|
setChannels(response.channels || []);
|
|
575
582
|
} catch (error) {
|
|
576
583
|
console.error("[AegisChat] Failed to fetch channels:", error);
|
|
@@ -630,6 +637,14 @@ function useChat(options = {}) {
|
|
|
630
637
|
},
|
|
631
638
|
[fetchFromComms]
|
|
632
639
|
);
|
|
640
|
+
const updateChannel = useCallback(
|
|
641
|
+
(channelId, updates) => {
|
|
642
|
+
setChannels(
|
|
643
|
+
(prev) => prev.map((ch) => ch.id === channelId ? { ...ch, ...updates } : ch)
|
|
644
|
+
);
|
|
645
|
+
},
|
|
646
|
+
[]
|
|
647
|
+
);
|
|
633
648
|
const loadMoreMessages = useCallback(async () => {
|
|
634
649
|
if (!activeChannelId || !hasMoreMessages || isLoadingMessages) return;
|
|
635
650
|
setIsLoadingMessages(true);
|
|
@@ -1050,18 +1065,22 @@ function useChat(options = {}) {
|
|
|
1050
1065
|
retryMessage,
|
|
1051
1066
|
deleteFailedMessage,
|
|
1052
1067
|
markAsRead,
|
|
1068
|
+
updateChannel,
|
|
1053
1069
|
setup
|
|
1054
1070
|
};
|
|
1055
1071
|
}
|
|
1056
1072
|
|
|
1057
1073
|
// src/hooks/useAutoRead.ts
|
|
1058
|
-
import { useCallback as useCallback2, useEffect as useEffect2,
|
|
1074
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
1059
1075
|
function useAutoRead(options = {}) {
|
|
1060
|
-
const
|
|
1076
|
+
const isFocusedRef = useRef2(typeof document !== "undefined" && document.hasFocus());
|
|
1061
1077
|
useEffect2(() => {
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1078
|
+
const handleFocus = () => {
|
|
1079
|
+
isFocusedRef.current = true;
|
|
1080
|
+
};
|
|
1081
|
+
const handleBlur = () => {
|
|
1082
|
+
isFocusedRef.current = false;
|
|
1083
|
+
};
|
|
1065
1084
|
window.addEventListener("focus", handleFocus);
|
|
1066
1085
|
window.addEventListener("blur", handleBlur);
|
|
1067
1086
|
return () => {
|
|
@@ -1070,16 +1089,16 @@ function useAutoRead(options = {}) {
|
|
|
1070
1089
|
};
|
|
1071
1090
|
}, []);
|
|
1072
1091
|
const markAsRead = useCallback2(async (channelId) => {
|
|
1073
|
-
if (!
|
|
1092
|
+
if (!isFocusedRef.current) return;
|
|
1074
1093
|
try {
|
|
1075
1094
|
await channelsApi.markAsRead(channelId);
|
|
1076
1095
|
options.onMarkAsRead?.(channelId);
|
|
1077
1096
|
} catch (error) {
|
|
1078
1097
|
console.error("[AegisChat] useAutoRead: Failed to mark as read:", error);
|
|
1079
1098
|
}
|
|
1080
|
-
}, [
|
|
1099
|
+
}, [options.onMarkAsRead]);
|
|
1081
1100
|
const markAllAsRead = useCallback2(async () => {
|
|
1082
|
-
if (!
|
|
1101
|
+
if (!isFocusedRef.current) return;
|
|
1083
1102
|
try {
|
|
1084
1103
|
const response = await channelsApi.list({});
|
|
1085
1104
|
const channels = response.channels || [];
|
|
@@ -1089,18 +1108,18 @@ function useAutoRead(options = {}) {
|
|
|
1089
1108
|
} catch (error) {
|
|
1090
1109
|
console.error("[AegisChat] useAutoRead: Failed to mark all as read:", error);
|
|
1091
1110
|
}
|
|
1092
|
-
}, [
|
|
1093
|
-
return { markAsRead, markAllAsRead, isFocused };
|
|
1111
|
+
}, []);
|
|
1112
|
+
return { markAsRead, markAllAsRead, isFocused: isFocusedRef.current };
|
|
1094
1113
|
}
|
|
1095
1114
|
|
|
1096
1115
|
// src/hooks/useChannels.ts
|
|
1097
|
-
import { useCallback as useCallback3, useEffect as useEffect3, useRef as
|
|
1116
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
|
|
1098
1117
|
function useChannels(options = {}) {
|
|
1099
1118
|
const { type, limit = 20, autoFetch = true, onChannelCreated, onError } = options;
|
|
1100
|
-
const [channels, setChannels] =
|
|
1101
|
-
const [isLoading, setIsLoading] =
|
|
1102
|
-
const [error, setError] =
|
|
1103
|
-
const abortControllerRef =
|
|
1119
|
+
const [channels, setChannels] = useState2([]);
|
|
1120
|
+
const [isLoading, setIsLoading] = useState2(false);
|
|
1121
|
+
const [error, setError] = useState2(null);
|
|
1122
|
+
const abortControllerRef = useRef3(null);
|
|
1104
1123
|
const fetchChannels = useCallback3(async (signal) => {
|
|
1105
1124
|
setIsLoading(true);
|
|
1106
1125
|
setError(null);
|
|
@@ -1161,11 +1180,11 @@ function useChannels(options = {}) {
|
|
|
1161
1180
|
}
|
|
1162
1181
|
|
|
1163
1182
|
// src/hooks/useMessages.ts
|
|
1164
|
-
import { useCallback as useCallback4, useState as
|
|
1183
|
+
import { useCallback as useCallback4, useState as useState3 } from "react";
|
|
1165
1184
|
function useMessages(_options) {
|
|
1166
|
-
const [messages, setMessages] =
|
|
1167
|
-
const [isLoading, setIsLoading] =
|
|
1168
|
-
const [hasMore, setHasMore] =
|
|
1185
|
+
const [messages, setMessages] = useState3([]);
|
|
1186
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
1187
|
+
const [hasMore, setHasMore] = useState3(true);
|
|
1169
1188
|
const sendMessage = useCallback4(async (params) => {
|
|
1170
1189
|
}, []);
|
|
1171
1190
|
const loadMore = useCallback4(async () => {
|
|
@@ -1174,9 +1193,9 @@ function useMessages(_options) {
|
|
|
1174
1193
|
}
|
|
1175
1194
|
|
|
1176
1195
|
// src/hooks/useTypingIndicator.ts
|
|
1177
|
-
import { useCallback as useCallback5, useState as
|
|
1196
|
+
import { useCallback as useCallback5, useState as useState4 } from "react";
|
|
1178
1197
|
function useTypingIndicator(_options) {
|
|
1179
|
-
const [typingUsers, setTypingUsers] =
|
|
1198
|
+
const [typingUsers, setTypingUsers] = useState4([]);
|
|
1180
1199
|
const startTyping = useCallback5(() => {
|
|
1181
1200
|
}, []);
|
|
1182
1201
|
const stopTyping = useCallback5(() => {
|
|
@@ -1185,9 +1204,9 @@ function useTypingIndicator(_options) {
|
|
|
1185
1204
|
}
|
|
1186
1205
|
|
|
1187
1206
|
// src/hooks/useReactions.ts
|
|
1188
|
-
import { useState as
|
|
1207
|
+
import { useState as useState5 } from "react";
|
|
1189
1208
|
function useReactions(_options) {
|
|
1190
|
-
const [reactions, setReactions] =
|
|
1209
|
+
const [reactions, setReactions] = useState5([]);
|
|
1191
1210
|
const addReaction = async (_emoji) => {
|
|
1192
1211
|
};
|
|
1193
1212
|
const removeReaction = async (_emoji) => {
|
|
@@ -1196,9 +1215,9 @@ function useReactions(_options) {
|
|
|
1196
1215
|
}
|
|
1197
1216
|
|
|
1198
1217
|
// src/hooks/useFileUpload.ts
|
|
1199
|
-
import { useState as
|
|
1218
|
+
import { useState as useState6 } from "react";
|
|
1200
1219
|
function useFileUpload(_options) {
|
|
1201
|
-
const [uploadProgress, setUploadProgress] =
|
|
1220
|
+
const [uploadProgress, setUploadProgress] = useState6([]);
|
|
1202
1221
|
const upload = async (_file) => null;
|
|
1203
1222
|
return { uploadProgress, upload };
|
|
1204
1223
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useChat.ts","../src/services/api.ts","../src/hooks/useAutoRead.ts","../src/hooks/useChannels.ts","../src/hooks/useMessages.ts","../src/hooks/useTypingIndicator.ts","../src/hooks/useReactions.ts","../src/hooks/useFileUpload.ts","../src/hooks/useMentions.ts"],"sourcesContent":["// ============================================================================\n// AegisChat React SDK - useChat Hook\n// ============================================================================\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n chatApi,\n channelsApi,\n messagesApi,\n filesApi,\n configureApiClient,\n} from \"../services/api\";\nimport type {\n AegisConfig,\n ChatSession,\n ChannelListItem,\n Message,\n MessagesResponse,\n TypingUser,\n UserSummary,\n FileAttachment,\n UploadProgress,\n MessageSummary,\n} from \"../types\";\n\nconst TYPING_TIMEOUT = 3000;\nconst RECONNECT_INTERVAL = 3000;\nconst MAX_RECONNECT_ATTEMPTS = 5;\nconst MAX_RECONNECT_DELAY = 30000;\nconst PING_INTERVAL = 30000;\nconst SESSION_STORAGE_KEY = \"@aegischat/activeChannel\";\n\nexport interface UseChatOptions {\n config?: AegisConfig;\n role?: \"lawyer\" | \"client\";\n clientId?: string;\n\n initialSession?: ChatSession | null;\n autoConnect?: boolean;\n onMessage?: (message: Message) => void;\n onTyping?: (channelId: string, user: TypingUser) => void;\n onConnectionChange?: (connected: boolean) => void;\n}\n\nexport interface UseChatReturn {\n session: ChatSession | null;\n isConnected: boolean;\n isConnecting: boolean;\n channels: ChannelListItem[];\n messages: Message[];\n activeChannelId: string | null;\n typingUsers: TypingUser[];\n isLoadingChannels: boolean;\n isLoadingMessages: boolean;\n hasMoreMessages: boolean;\n uploadProgress: UploadProgress[];\n connect: () => Promise<void>;\n disconnect: () => void;\n selectChannel: (channelId: string) => void;\n sendMessage: (\n content: string,\n options?: {\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n },\n ) => Promise<void>;\n sendMessageWithFiles: (\n content: string,\n files: File[],\n options?: {\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n },\n ) => Promise<void>;\n uploadFile: (file: File) => Promise<FileAttachment | null>;\n loadMoreMessages: () => Promise<void>;\n startTyping: () => void;\n stopTyping: () => void;\n refreshChannels: () => Promise<void>;\n createDMWithUser: (userId: string) => Promise<string | null>;\n retryMessage: (tempId: string) => Promise<void>;\n deleteFailedMessage: (tempId: string) => void;\n markAsRead: (channelId: string) => Promise<void>;\n setup: (options: UseChatOptions) => void;\n}\n\nexport function useChat(options: Partial<UseChatOptions> = {}): UseChatReturn {\n const {\n config,\n role,\n clientId,\n initialSession,\n autoConnect = true,\n onMessage,\n onTyping,\n onConnectionChange,\n } = options;\n\n const [session, setSession] = useState<ChatSession | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [isConnecting, setIsConnecting] = useState(false);\n const [activeChannelId, setActiveChannelIdState] = useState<string | null>(\n null,\n );\n const [channels, setChannels] = useState<ChannelListItem[]>([]);\n const [messages, setMessages] = useState<Message[]>([]);\n const [typingUsers, setTypingUsers] = useState<Record<string, TypingUser[]>>(\n {},\n );\n const [isLoadingChannels, setIsLoadingChannels] = useState(false);\n const [isLoadingMessages, setIsLoadingMessages] = useState(false);\n const [hasMoreMessages, setHasMoreMessages] = useState(true);\n const [uploadProgress, setUploadProgress] = useState<UploadProgress[]>([]);\n\n const wsRef = useRef<WebSocket | null>(null);\n const reconnectAttempts = useRef(0);\n const reconnectTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pingInterval = useRef<ReturnType<typeof setInterval> | null>(null);\n const typingTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n const isManualDisconnect = useRef(false);\n const oldestMessageId = useRef<string | null>(null);\n const activeChannelIdRef = useRef<string | null>(null);\n const sessionRef = useRef<ChatSession | null>(null);\n const roleRef = useRef<string | undefined>(undefined);\n const clientIdRef = useRef<string | undefined>(undefined);\n const autoConnectRef = useRef(true);\n const onMessageRef = useRef<(message: Message) => void | undefined>(undefined);\n const onTypingRef = useRef<((channelId: string, user: TypingUser) => void) | undefined>(undefined);\n const onConnectionChangeRef = useRef<((connected: boolean) => void) | undefined>(undefined);\n\n useEffect(() => {\n activeChannelIdRef.current = activeChannelId;\n }, [activeChannelId]);\n\n const getActiveChannelId = useCallback((): string | null => {\n if (typeof window === \"undefined\") return null;\n return sessionStorage.getItem(SESSION_STORAGE_KEY);\n }, []);\n\n const setActiveChannelId = useCallback((id: string | null) => {\n setActiveChannelIdState(id);\n if (typeof window !== \"undefined\") {\n if (id) {\n sessionStorage.setItem(SESSION_STORAGE_KEY, id);\n } else {\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n }\n }\n }, []);\n\n const fetchFromComms = useCallback(\n async <T>(path: string, fetchOptions: RequestInit = {}): Promise<T> => {\n const currentSession = sessionRef.current;\n if (!currentSession) {\n throw new Error(\"Chat session not initialized\");\n }\n\n const response = await fetch(`${currentSession.api_url}${path}`, {\n ...fetchOptions,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${currentSession.access_token}`,\n ...fetchOptions.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.message || `HTTP ${response.status}`);\n }\n\n const data = await response.json();\n return data.data || data;\n },\n [],\n );\n\n const clearTimers = useCallback(() => {\n if (reconnectTimeout.current) {\n clearTimeout(reconnectTimeout.current);\n reconnectTimeout.current = null;\n }\n if (pingInterval.current) {\n clearInterval(pingInterval.current);\n pingInterval.current = null;\n }\n }, []);\n\n const handleWebSocketMessage = useCallback(\n (data: { type: string; payload: unknown }) => {\n const currentActiveChannelId = activeChannelIdRef.current;\n console.log(\"[AegisChat] WebSocket message received:\", data.type, data);\n\n switch (data.type) {\n case \"message.new\": {\n const newMessage = data.payload as Message;\n if (newMessage.channel_id === currentActiveChannelId) {\n setMessages((prev) => {\n const existingIndex = prev.findIndex(\n (m) =>\n m.tempId &&\n m.content === newMessage.content &&\n m.status === \"sending\",\n );\n if (existingIndex !== -1) {\n const updated = [...prev];\n updated[existingIndex] = { ...newMessage, status: \"sent\" };\n return updated;\n }\n if (prev.some((m) => m.id === newMessage.id)) return prev;\n return [...prev, { ...newMessage, status: \"delivered\" }];\n });\n onMessageRef.current?.(newMessage);\n }\n setChannels((prev) => {\n const updated = prev.map((ch) =>\n ch.id === newMessage.channel_id\n ? {\n ...ch,\n last_message: {\n id: newMessage.id,\n content: newMessage.content,\n created_at: newMessage.created_at,\n sender: {\n id: newMessage.sender_id,\n display_name: \"Unknown\",\n status: \"online\" as const,\n },\n } as MessageSummary,\n unread_count:\n ch.id === currentActiveChannelId\n ? 0\n : ch.unread_count + 1,\n }\n : ch,\n );\n return updated.sort((a, b) => {\n const timeA = a.last_message?.created_at || \"\";\n const timeB = b.last_message?.created_at || \"\";\n return timeB.localeCompare(timeA);\n });\n });\n break;\n }\n case \"message.updated\": {\n const updatedMessage = data.payload as Message;\n setMessages((prev) =>\n prev.map((m) => (m.id === updatedMessage.id ? updatedMessage : m)),\n );\n break;\n }\n case \"message.deleted\": {\n const { message_id } = data.payload as { message_id: string };\n setMessages((prev) =>\n prev.map((m) =>\n m.id === message_id ? { ...m, deleted: true } : m,\n ),\n );\n break;\n }\n case \"message.delivered\":\n case \"message.read\": {\n const { message_id, channel_id, status } = data.payload as {\n message_id: string;\n channel_id: string;\n status: string;\n };\n if (channel_id === currentActiveChannelId) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === message_id\n ? {\n ...m,\n status: (status as Message[\"status\"]) || \"delivered\",\n }\n : m,\n ),\n );\n }\n break;\n }\n case \"message.delivered.batch\":\n case \"message.read.batch\": {\n const { channel_id } = data.payload as { channel_id: string };\n if (channel_id === currentActiveChannelId) {\n setMessages((prev) =>\n prev.map((m) =>\n m.status === \"sent\" || m.status === \"delivered\"\n ? {\n ...m,\n status:\n data.type === \"message.delivered.batch\"\n ? \"delivered\"\n : \"read\",\n }\n : m,\n ),\n );\n }\n break;\n }\n case \"typing.start\": {\n const { channel_id, user } = data.payload as {\n channel_id: string;\n user: UserSummary;\n };\n const typingUser: TypingUser = {\n id: user.id,\n displayName: user.display_name,\n avatarUrl: user.avatar_url,\n startedAt: Date.now(),\n };\n setTypingUsers((prev) => ({\n ...prev,\n [channel_id]: [\n ...(prev[channel_id] || []).filter((u) => u.id !== user.id),\n typingUser,\n ],\n }));\n onTypingRef.current?.(channel_id, typingUser);\n break;\n }\n case \"typing.stop\": {\n const { channel_id, user_id } = data.payload as {\n channel_id: string;\n user_id: string;\n };\n setTypingUsers((prev) => ({\n ...prev,\n [channel_id]: (prev[channel_id] || []).filter(\n (u) => u.id !== user_id,\n ),\n }));\n break;\n }\n case \"pong\":\n break;\n default:\n console.log(\"[AegisChat] Unhandled message type:\", data.type);\n }\n },\n [],\n );\n\n const connectWebSocket = useCallback(() => {\n const currentSession = sessionRef.current;\n if (!currentSession?.websocket_url || !currentSession?.access_token) {\n console.warn(\n \"[AegisChat] Cannot connect WebSocket - missing session or token\",\n );\n return;\n }\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n console.log(\"[AegisChat] WebSocket already open, skipping connection\");\n return;\n }\n\n setIsConnecting(true);\n isManualDisconnect.current = false;\n\n const wsUrl = `${currentSession.websocket_url}?token=${currentSession.access_token}`;\n console.log(\"[AegisChat] Creating WebSocket connection to:\", wsUrl);\n const ws = new WebSocket(wsUrl);\n\n ws.onopen = () => {\n console.log(\"[AegisChat] WebSocket connected\");\n setIsConnected(true);\n setIsConnecting(false);\n reconnectAttempts.current = 0;\n onConnectionChangeRef.current?.(true);\n\n pingInterval.current = setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: \"ping\" }));\n }\n }, PING_INTERVAL);\n\n if (activeChannelIdRef.current) {\n ws.send(\n JSON.stringify({\n type: \"channel.join\",\n payload: { channel_id: activeChannelIdRef.current },\n }),\n );\n }\n };\n\n ws.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data);\n handleWebSocketMessage(data);\n } catch (error) {\n console.error(\"[AegisChat] Failed to parse WebSocket message:\", error);\n }\n };\n\n ws.onclose = () => {\n console.log(\"[AegisChat] WebSocket disconnected\");\n setIsConnected(false);\n setIsConnecting(false);\n clearTimers();\n onConnectionChangeRef.current?.(false);\n\n if (\n !isManualDisconnect.current &&\n reconnectAttempts.current < MAX_RECONNECT_ATTEMPTS\n ) {\n const delay = Math.min(\n RECONNECT_INTERVAL * Math.pow(2, reconnectAttempts.current),\n MAX_RECONNECT_DELAY,\n );\n console.log(`[AegisChat] Reconnecting in ${delay}ms...`);\n reconnectTimeout.current = setTimeout(() => {\n reconnectAttempts.current++;\n connectWebSocket();\n }, delay);\n }\n };\n\n ws.onerror = (error) => {\n console.error(\"[AegisChat] WebSocket error:\", error);\n };\n\n wsRef.current = ws;\n }, [clearTimers, handleWebSocketMessage]);\n\n const connect = useCallback(async () => {\n console.log(\"[AegisChat] connect() called\");\n const targetSession = sessionRef.current;\n if (!targetSession) {\n console.log(\"[AegisChat] No session available, skipping connect\");\n return;\n }\n if (!autoConnectRef.current) {\n console.log(\"[AegisChat] autoConnect is false, skipping connect\");\n return;\n }\n connectWebSocket();\n }, [connectWebSocket]);\n\n const disconnect = useCallback(() => {\n isManualDisconnect.current = true;\n clearTimers();\n if (wsRef.current) {\n wsRef.current.close();\n wsRef.current = null;\n }\n setIsConnected(false);\n setSession(null);\n setChannels([]);\n setMessages([]);\n }, [clearTimers]);\n\n const refreshChannels = useCallback(async () => {\n const currentSession = sessionRef.current;\n if (!currentSession) return;\n\n setIsLoadingChannels(true);\n try {\n const response = await fetchFromComms<{ channels: ChannelListItem[] }>('/channels');\n setChannels(response.channels || []);\n } catch (error) {\n console.error(\"[AegisChat] Failed to fetch channels:\", error);\n } finally {\n setIsLoadingChannels(false);\n }\n }, []);\n\n const selectChannel = useCallback(\n async (channelId: string) => {\n const currentActiveChannelId = activeChannelIdRef.current;\n setActiveChannelId(channelId);\n setMessages([]);\n setHasMoreMessages(true);\n oldestMessageId.current = null;\n\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n if (currentActiveChannelId) {\n wsRef.current.send(\n JSON.stringify({\n type: \"channel.leave\",\n payload: { channel_id: currentActiveChannelId },\n }),\n );\n }\n wsRef.current.send(\n JSON.stringify({\n type: \"channel.join\",\n payload: { channel_id: channelId },\n }),\n );\n }\n\n setIsLoadingMessages(true);\n try {\n const response = await fetchFromComms<MessagesResponse>(\n `/channels/${channelId}/messages?limit=50`,\n );\n setMessages(response.messages || []);\n setHasMoreMessages(response.has_more);\n if (response.oldest_id) {\n oldestMessageId.current = response.oldest_id;\n }\n\n } catch (error) {\n console.error(\"[AegisChat] Failed to load messages:\", error);\n setMessages([]);\n } finally {\n setIsLoadingMessages(false);\n }\n },\n [setActiveChannelId, fetchFromComms],\n );\n\n const markAsRead = useCallback(\n async (channelId: string) => {\n try {\n await fetchFromComms(`/channels/${channelId}/read`, { method: \"POST\" });\n } catch (error) {\n console.error(\"[AegisChat] Failed to mark as read:\", error);\n }\n },\n [fetchFromComms],\n );\n\n const loadMoreMessages = useCallback(async () => {\n if (!activeChannelId || !hasMoreMessages || isLoadingMessages) return;\n\n setIsLoadingMessages(true);\n try {\n const params = oldestMessageId.current\n ? `?before=${oldestMessageId.current}&limit=50`\n : \"?limit=50\";\n const response = await fetchFromComms<MessagesResponse>(\n `/channels/${activeChannelId}/messages${params}`,\n );\n setMessages((prev) => [...(response.messages || []), ...prev]);\n setHasMoreMessages(response.has_more);\n if (response.oldest_id) {\n oldestMessageId.current = response.oldest_id;\n }\n } catch (error) {\n console.error(\"[AegisChat] Failed to load more messages:\", error);\n } finally {\n setIsLoadingMessages(false);\n }\n }, [activeChannelId, hasMoreMessages, isLoadingMessages, fetchFromComms]);\n\n const sendMessage = useCallback(\n async (\n content: string,\n msgOptions: {\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n } = {},\n ) => {\n const currentActiveChannelId = activeChannelIdRef.current;\n const currentSession = sessionRef.current;\n if (!currentActiveChannelId || !content.trim() || !currentSession) return;\n\n const tempId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const trimmedContent = content.trim();\n\n const optimisticMessage: Message = {\n id: tempId,\n tempId,\n channel_id: currentActiveChannelId,\n sender_id: currentSession.comms_user_id,\n content: trimmedContent,\n type: (msgOptions.type as Message[\"type\"]) || \"text\",\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n status: \"sending\",\n metadata: msgOptions.metadata || {},\n };\n\n setMessages((prev) => [...prev, optimisticMessage]);\n\n const now = new Date().toISOString();\n setChannels((prev) => {\n const updated = prev.map((ch) =>\n ch.id === currentActiveChannelId\n ? {\n ...ch,\n last_message: {\n id: tempId,\n content: trimmedContent,\n created_at: now,\n sender: {\n id: currentSession.comms_user_id,\n display_name: \"You\",\n status: \"online\" as const,\n },\n },\n }\n : ch,\n );\n return updated.sort((a, b) => {\n const timeA = a.last_message?.created_at || \"\";\n const timeB = b.last_message?.created_at || \"\";\n return timeB.localeCompare(timeA);\n });\n });\n\n try {\n await fetchFromComms<Message>(\n `/channels/${currentActiveChannelId}/messages`,\n {\n method: \"POST\",\n body: JSON.stringify({\n content: trimmedContent,\n type: msgOptions.type || \"text\",\n parent_id: msgOptions.parent_id,\n metadata: msgOptions.metadata,\n }),\n },\n );\n } catch (error) {\n console.error(\"[AegisChat] Failed to send message:\", error);\n setMessages((prev) =>\n prev.map((m) =>\n m.tempId === tempId\n ? {\n ...m,\n status: \"failed\",\n errorMessage:\n error instanceof Error ? error.message : \"Failed to send\",\n }\n : m,\n ),\n );\n throw error;\n }\n },\n [fetchFromComms],\n );\n\n const uploadFile = useCallback(\n async (file: File): Promise<FileAttachment | null> => {\n const currentSession = sessionRef.current;\n if (!currentSession) return null;\n\n const fileId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\n setUploadProgress((prev) => [\n ...prev,\n { fileId, fileName: file.name, progress: 0, status: \"pending\" },\n ]);\n\n try {\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === fileId\n ? { ...p, status: \"uploading\", progress: 10 }\n : p,\n ),\n );\n\n const uploadUrlResponse = await fetchFromComms<{\n upload_url: string;\n file_id: string;\n expires_at: string;\n }>(\"/files/upload-url\", {\n method: \"POST\",\n body: JSON.stringify({\n file_name: file.name,\n file_type: file.type || \"application/octet-stream\",\n file_size: file.size,\n }),\n });\n\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === fileId\n ? { ...p, fileId: uploadUrlResponse.file_id, progress: 30 }\n : p,\n ),\n );\n\n const uploadResponse = await fetch(uploadUrlResponse.upload_url, {\n method: \"PUT\",\n body: file,\n headers: { \"Content-Type\": file.type || \"application/octet-stream\" },\n });\n\n if (!uploadResponse.ok)\n throw new Error(`Upload failed: ${uploadResponse.statusText}`);\n\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === uploadUrlResponse.file_id\n ? { ...p, status: \"confirming\", progress: 70 }\n : p,\n ),\n );\n\n const confirmResponse = await fetchFromComms<{ file: FileAttachment }>(\n \"/files\",\n {\n method: \"POST\",\n body: JSON.stringify({ file_id: uploadUrlResponse.file_id }),\n },\n );\n\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === uploadUrlResponse.file_id\n ? { ...p, status: \"complete\", progress: 100 }\n : p,\n ),\n );\n setTimeout(\n () =>\n setUploadProgress((prev) =>\n prev.filter((p) => p.fileId !== uploadUrlResponse.file_id),\n ),\n 2000,\n );\n\n return confirmResponse.file;\n } catch (error) {\n console.error(\"[AegisChat] Failed to upload file:\", error);\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === fileId\n ? {\n ...p,\n status: \"error\",\n error:\n error instanceof Error ? error.message : \"Upload failed\",\n }\n : p,\n ),\n );\n setTimeout(\n () =>\n setUploadProgress((prev) =>\n prev.filter((p) => p.fileId !== fileId),\n ),\n 5000,\n );\n return null;\n }\n },\n [fetchFromComms],\n );\n\n const sendMessageWithFiles = useCallback(\n async (\n content: string,\n files: File[],\n msgOptions: {\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n } = {},\n ) => {\n const currentActiveChannelId = activeChannelIdRef.current;\n const currentSession = sessionRef.current;\n if (\n !currentActiveChannelId ||\n (!content.trim() && files.length === 0) ||\n !currentSession\n )\n return;\n\n const tempId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const trimmedContent = content.trim();\n\n const optimisticMessage: Message = {\n id: tempId,\n tempId,\n channel_id: currentActiveChannelId,\n sender_id: currentSession.comms_user_id,\n content: trimmedContent || `Uploading ${files.length} file(s)...`,\n type: \"file\",\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n status: \"sending\",\n metadata: {\n ...msgOptions.metadata,\n files: files.map((f) => ({\n id: `temp-${f.name}`,\n filename: f.name,\n mime_type: f.type,\n size: f.size,\n url: \"\",\n })),\n },\n };\n\n setMessages((prev) => [...prev, optimisticMessage]);\n\n try {\n const uploadedFiles: FileAttachment[] = [];\n for (const file of files) {\n const attachment = await uploadFile(file);\n if (attachment) uploadedFiles.push(attachment);\n }\n\n const messageType =\n uploadedFiles.length > 0 && !trimmedContent ? \"file\" : \"text\";\n\n await fetchFromComms<Message>(\n `/channels/${currentActiveChannelId}/messages`,\n {\n method: \"POST\",\n body: JSON.stringify({\n content:\n trimmedContent ||\n (uploadedFiles.length > 0\n ? `Shared ${uploadedFiles.length} file(s)`\n : \"\"),\n type: msgOptions.type || messageType,\n parent_id: msgOptions.parent_id,\n metadata: { ...msgOptions.metadata, files: uploadedFiles },\n file_ids: uploadedFiles.map((f) => f.id),\n }),\n },\n );\n } catch (error) {\n console.error(\"[AegisChat] Failed to send message with files:\", error);\n setMessages((prev) =>\n prev.map((m) =>\n m.tempId === tempId\n ? {\n ...m,\n status: \"failed\",\n errorMessage:\n error instanceof Error ? error.message : \"Failed to send\",\n }\n : m,\n ),\n );\n throw error;\n }\n },\n [fetchFromComms, uploadFile],\n );\n\n const stopTyping = useCallback(() => {\n const currentActiveChannelId = activeChannelIdRef.current;\n if (!currentActiveChannelId || !wsRef.current) return;\n wsRef.current.send(\n JSON.stringify({\n type: \"typing.stop\",\n payload: { channel_id: currentActiveChannelId },\n }),\n );\n if (typingTimeout.current) {\n clearTimeout(typingTimeout.current);\n typingTimeout.current = null;\n }\n }, []);\n\n const startTyping = useCallback(() => {\n const currentActiveChannelId = activeChannelIdRef.current;\n if (!currentActiveChannelId || !wsRef.current) return;\n wsRef.current.send(\n JSON.stringify({\n type: \"typing.start\",\n payload: { channel_id: currentActiveChannelId },\n }),\n );\n if (typingTimeout.current) clearTimeout(typingTimeout.current);\n typingTimeout.current = setTimeout(stopTyping, TYPING_TIMEOUT);\n }, [stopTyping]);\n\n const createDMWithUser = useCallback(\n async (userId: string): Promise<string | null> => {\n try {\n const channel = await fetchFromComms<{ id: string }>(\"/channels/dm\", {\n method: \"POST\",\n body: JSON.stringify({ user_id: userId }),\n });\n await refreshChannels();\n return channel.id;\n } catch (error) {\n console.error(\"[AegisChat] Failed to create DM:\", error);\n return null;\n }\n },\n [fetchFromComms, refreshChannels],\n );\n\n const retryMessage = useCallback(\n async (tempId: string) => {\n const failedMessage = messages.find(\n (m) => m.tempId === tempId && m.status === \"failed\",\n );\n const currentActiveChannelId = activeChannelIdRef.current;\n if (!failedMessage || !currentActiveChannelId) return;\n\n setMessages((prev) =>\n prev.map((m) =>\n m.tempId === tempId\n ? { ...m, status: \"sending\", errorMessage: undefined }\n : m,\n ),\n );\n\n try {\n await fetchFromComms<Message>(\n `/channels/${currentActiveChannelId}/messages`,\n {\n method: \"POST\",\n body: JSON.stringify({\n content: failedMessage.content,\n type: failedMessage.type,\n metadata: failedMessage.metadata,\n }),\n },\n );\n } catch (error) {\n console.error(\"[AegisChat] Failed to retry message:\", error);\n setMessages((prev) =>\n prev.map((m) =>\n m.tempId === tempId\n ? {\n ...m,\n status: \"failed\",\n errorMessage:\n error instanceof Error ? error.message : \"Failed to send\",\n }\n : m,\n ),\n );\n }\n },\n [messages, fetchFromComms],\n );\n\n const deleteFailedMessage = useCallback((tempId: string) => {\n setMessages((prev) => prev.filter((m) => m.tempId !== tempId));\n }, []);\n\n const setup = useCallback((options: UseChatOptions) => {\n const {\n config,\n role,\n clientId,\n initialSession,\n autoConnect = true,\n onMessage,\n onTyping,\n onConnectionChange,\n } = options;\n\n roleRef.current = role;\n clientIdRef.current = clientId;\n autoConnectRef.current = autoConnect;\n onMessageRef.current = onMessage;\n onTypingRef.current = onTyping;\n onConnectionChangeRef.current = onConnectionChange;\n\n if (initialSession) {\n sessionRef.current = initialSession;\n\n if (!config) {\n const url = initialSession.api_url;\n const normalizedUrl = url.includes('/api/v1') || url.includes('/v')\n ? url\n : `${url}/api/v1`;\n configureApiClient({\n baseUrl: normalizedUrl,\n getAccessToken: async () => sessionRef.current?.access_token || \"\",\n });\n }\n\n setSession(initialSession);\n }\n }, []);\n\n useEffect(() => {\n if (session && !isConnected && !isConnecting && autoConnectRef.current) {\n connectWebSocket();\n }\n }, [session, isConnected, isConnecting, connectWebSocket]);\n\n useEffect(() => {\n if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {\n wsRef.current.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data);\n handleWebSocketMessage(data);\n } catch (error) {\n console.error(\n \"[AegisChat] Failed to parse WebSocket message:\",\n error,\n );\n }\n };\n }\n }, [handleWebSocketMessage]);\n\n useEffect(() => {\n if (isConnected && channels.length === 0) {\n refreshChannels();\n }\n }, [isConnected, channels.length, refreshChannels]);\n\n useEffect(() => {\n const storedActiveChannel = getActiveChannelId();\n if (storedActiveChannel && !activeChannelId) {\n selectChannel(storedActiveChannel);\n }\n }, [getActiveChannelId, activeChannelId, selectChannel]);\n\n useEffect(() => {\n return () => {\n clearTimers();\n if (typingTimeout.current) clearTimeout(typingTimeout.current);\n if (wsRef.current) {\n isManualDisconnect.current = true;\n wsRef.current.close();\n wsRef.current = null;\n }\n };\n }, [clearTimers]);\n\n return {\n session,\n isConnected,\n isConnecting,\n channels,\n messages,\n activeChannelId,\n typingUsers: activeChannelId ? typingUsers[activeChannelId] || [] : [],\n isLoadingChannels,\n isLoadingMessages,\n hasMoreMessages,\n uploadProgress,\n connect,\n disconnect,\n selectChannel,\n sendMessage,\n sendMessageWithFiles,\n uploadFile,\n loadMoreMessages,\n startTyping,\n stopTyping,\n refreshChannels,\n createDMWithUser,\n retryMessage,\n deleteFailedMessage,\n markAsRead,\n setup,\n };\n}\n\nexport default useChat;\n","// ============================================================================\n// AegisChat React SDK - API Service\n// ============================================================================\n\nimport type {\n ChatSession,\n ChatConnectParams,\n Channel,\n ChannelListItem,\n Message,\n MessagesResponse,\n UserSummary,\n ReactionSummary,\n FileAttachment,\n UploadUrlResponse,\n} from \"../types\";\n\nlet baseUrl = \"\";\nlet getAccessToken: () => Promise<string> | string = () => \"\";\nlet onUnauthorized: (() => void) | undefined;\n\nexport function configureApiClient(config: {\n baseUrl: string;\n getAccessToken: () => Promise<string> | string;\n onUnauthorized?: () => void;\n}): void {\n baseUrl = config.baseUrl;\n getAccessToken = config.getAccessToken;\n onUnauthorized = config.onUnauthorized;\n}\n\nasync function fetchWithAuth<T>(\n path: string,\n options: RequestInit = {},\n): Promise<T> {\n const token = await (typeof getAccessToken === \"function\"\n ? getAccessToken()\n : getAccessToken);\n\n const response = await fetch(`${baseUrl}${path}`, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n ...options.headers,\n },\n });\n\n if (response.status === 401) {\n onUnauthorized?.();\n throw new Error(\"Unauthorized\");\n }\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.message || `HTTP ${response.status}`);\n }\n\n return response.json();\n}\n\nexport const chatApi = {\n /**\n * Connect to chat session\n */\n async connect(\n params: ChatConnectParams,\n signal?: AbortSignal,\n ): Promise<ChatSession> {\n return fetchWithAuth(\"/chat/connect\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal,\n });\n },\n\n /**\n * Refresh access token\n */\n async refreshToken(\n refreshToken: string,\n signal?: AbortSignal,\n ): Promise<{ access_token: string; expires_in: number }> {\n return fetchWithAuth(\"/chat/refresh\", {\n method: \"POST\",\n body: JSON.stringify({ refresh_token: refreshToken }),\n signal,\n });\n },\n};\n\nexport const channelsApi = {\n /**\n * List channels\n */\n async list(\n options: { type?: string; limit?: number } = {},\n signal?: AbortSignal,\n ): Promise<{ channels: ChannelListItem[] }> {\n const params = new URLSearchParams();\n if (options.type) params.append(\"type\", options.type);\n if (options.limit) params.append(\"limit\", String(options.limit));\n const query = params.toString() ? `?${params.toString()}` : \"\";\n return fetchWithAuth(`/channels${query}`, { signal });\n },\n\n /**\n * Get channel by ID\n */\n async get(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<Channel> {\n return fetchWithAuth(`/channels/${channelId}`, { signal });\n },\n\n /**\n * Get or create DM channel\n */\n async getOrCreateDM(\n userId: string,\n signal?: AbortSignal,\n ): Promise<Channel> {\n return fetchWithAuth(\"/channels/dm\", {\n method: \"POST\",\n body: JSON.stringify({ user_id: userId }),\n signal,\n });\n },\n\n /**\n * Create channel\n */\n async create(\n data: {\n name: string;\n type?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n },\n signal?: AbortSignal,\n ): Promise<Channel> {\n return fetchWithAuth(\"/channels\", {\n method: \"POST\",\n body: JSON.stringify(data),\n signal,\n });\n },\n\n /**\n * Mark channel as read\n */\n async markAsRead(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<{ unread_count: number }> {\n return fetchWithAuth(`/channels/${channelId}/read`, {\n method: \"POST\",\n signal,\n });\n },\n\n /**\n * Get channel members\n */\n async getMembers(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<{ members: UserSummary[] }> {\n return fetchWithAuth(`/channels/${channelId}/members`, { signal });\n },\n\n /**\n * Update channel\n */\n async update(\n channelId: string,\n data: {\n name?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n },\n signal?: AbortSignal,\n ): Promise<Channel> {\n return fetchWithAuth(`/channels/${channelId}`, {\n method: \"PATCH\",\n body: JSON.stringify(data),\n signal,\n });\n },\n};\n\nexport const messagesApi = {\n /**\n * List messages in a channel\n */\n async list(\n channelId: string,\n options: { limit?: number; before?: string } = {},\n signal?: AbortSignal,\n ): Promise<MessagesResponse> {\n const params = new URLSearchParams();\n if (options.limit) params.append(\"limit\", String(options.limit));\n if (options.before) params.append(\"before\", options.before);\n const query = params.toString() ? `?${params.toString()}` : \"\";\n return fetchWithAuth(`/channels/${channelId}/messages${query}`, {\n signal,\n });\n },\n\n /**\n * Send a message\n */\n async send(\n channelId: string,\n data: {\n content: string;\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n file_ids?: string[];\n },\n signal?: AbortSignal,\n ): Promise<Message> {\n return fetchWithAuth(`/channels/${channelId}/messages`, {\n method: \"POST\",\n body: JSON.stringify(data),\n signal,\n });\n },\n\n /**\n * Update a message\n */\n async update(\n channelId: string,\n messageId: string,\n data: { content?: string; metadata?: Record<string, unknown> },\n signal?: AbortSignal,\n ): Promise<Message> {\n return fetchWithAuth(`/channels/${channelId}/messages/${messageId}`, {\n method: \"PATCH\",\n body: JSON.stringify(data),\n signal,\n });\n },\n\n /**\n * Delete a message\n */\n async delete(\n channelId: string,\n messageId: string,\n signal?: AbortSignal,\n ): Promise<{ success: boolean }> {\n return fetchWithAuth(`/channels/${channelId}/messages/${messageId}`, {\n method: \"DELETE\",\n signal,\n });\n },\n\n /**\n * Mark messages as delivered\n */\n async markDelivered(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<{ success: boolean }> {\n return fetchWithAuth(`/channels/${channelId}/messages/delivered`, {\n method: \"POST\",\n signal,\n });\n },\n\n /**\n * Mark messages as read\n */\n async markRead(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<{ success: boolean }> {\n return fetchWithAuth(`/channels/${channelId}/messages/read`, {\n method: \"POST\",\n signal,\n });\n },\n};\n\nexport const reactionsApi = {\n /**\n * Add reaction to a message\n */\n async add(\n channelId: string,\n messageId: string,\n emoji: string,\n signal?: AbortSignal,\n ): Promise<{ reactions: ReactionSummary[] }> {\n return fetchWithAuth(\n `/channels/${channelId}/messages/${messageId}/reactions`,\n {\n method: \"POST\",\n body: JSON.stringify({ emoji }),\n signal,\n },\n );\n },\n\n /**\n * Remove reaction from a message\n */\n async remove(\n channelId: string,\n messageId: string,\n emoji: string,\n signal?: AbortSignal,\n ): Promise<{ reactions: ReactionSummary[] }> {\n return fetchWithAuth(\n `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`,\n { method: \"DELETE\", signal },\n );\n },\n};\n\nexport const filesApi = {\n /**\n * Get upload URL\n */\n async getUploadUrl(\n data: { file_name: string; file_type: string; file_size: number },\n signal?: AbortSignal,\n ): Promise<UploadUrlResponse> {\n return fetchWithAuth(\"/files/upload-url\", {\n method: \"POST\",\n body: JSON.stringify(data),\n signal,\n });\n },\n\n /**\n * Confirm file upload\n */\n async confirm(\n fileId: string,\n signal?: AbortSignal,\n ): Promise<{ file: FileAttachment }> {\n return fetchWithAuth(\"/files\", {\n method: \"POST\",\n body: JSON.stringify({ file_id: fileId }),\n signal,\n });\n },\n\n /**\n * Get download URL\n */\n async getDownloadUrl(\n fileId: string,\n signal?: AbortSignal,\n ): Promise<{ url: string; expires_at: string }> {\n return fetchWithAuth(`/files/${fileId}/download`, { signal });\n },\n};\n\nexport const usersApi = {\n /**\n * Search users\n */\n async search(\n query: string,\n signal?: AbortSignal,\n ): Promise<{ users: UserSummary[] }> {\n return fetchWithAuth(`/users/search?q=${encodeURIComponent(query)}`, {\n signal,\n });\n },\n\n /**\n * Get user by ID\n */\n async get(\n userId: string,\n signal?: AbortSignal,\n ): Promise<UserSummary> {\n return fetchWithAuth(`/users/${userId}`, { signal });\n },\n};\n\nexport default {\n chatApi,\n channelsApi,\n messagesApi,\n reactionsApi,\n filesApi,\n usersApi,\n configureApiClient,\n};\n","// ============================================================================\n// AegisChat React SDK - useAutoRead Hook\n// ============================================================================\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { channelsApi } from '../services/api';\n\nconst SESSION_STORAGE_KEY = '@aegischat/activeChannel';\n\nexport interface UseAutoReadOptions {\n onMarkAsRead?: (channelId: string) => void;\n}\n\nexport interface UseAutoReadReturn {\n markAsRead: (channelId: string) => Promise<void>;\n markAllAsRead: () => Promise<void>;\n isFocused: boolean;\n}\n\nexport function useAutoRead(options: UseAutoReadOptions = {}): UseAutoReadReturn {\n const [isFocused, setIsFocused] = useState(false);\n\n useEffect(() => {\n setIsFocused(typeof document !== 'undefined' && document.hasFocus());\n\n const handleFocus = () => setIsFocused(true);\n const handleBlur = () => setIsFocused(false);\n\n window.addEventListener('focus', handleFocus);\n window.addEventListener('blur', handleBlur);\n\n return () => {\n window.removeEventListener('focus', handleFocus);\n window.removeEventListener('blur', handleBlur);\n };\n }, []);\n\n const markAsRead = useCallback(async (channelId: string) => {\n if (!isFocused) return;\n try {\n await channelsApi.markAsRead(channelId);\n options.onMarkAsRead?.(channelId);\n } catch (error) {\n console.error('[AegisChat] useAutoRead: Failed to mark as read:', error);\n }\n }, [isFocused, options.onMarkAsRead]);\n\n const markAllAsRead = useCallback(async () => {\n if (!isFocused) return;\n try {\n const response = await channelsApi.list({});\n const channels = response.channels || [];\n await Promise.all(\n channels.filter((ch) => ch.unread_count > 0).map((ch) => channelsApi.markAsRead(ch.id))\n );\n } catch (error) {\n console.error('[AegisChat] useAutoRead: Failed to mark all as read:', error);\n }\n }, [isFocused]);\n\n return { markAsRead, markAllAsRead, isFocused };\n}\n\nexport default useAutoRead;\n","// ============================================================================\n// AegisChat React SDK - useChannels Hook\n// ============================================================================\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { channelsApi } from '../services/api';\nimport type { ChannelListItem, Channel } from '../types';\n\nexport interface UseChannelsOptions {\n type?: 'direct' | 'public' | 'private';\n limit?: number;\n autoFetch?: boolean;\n onChannelCreated?: (channel: Channel) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseChannelsReturn {\n channels: ChannelListItem[];\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n getOrCreateDM: (userId: string) => Promise<Channel>;\n markAsRead: (channelId: string) => Promise<void>;\n}\n\nexport function useChannels(options: UseChannelsOptions = {}): UseChannelsReturn {\n const { type, limit = 20, autoFetch = true, onChannelCreated, onError } = options;\n\n const [channels, setChannels] = useState<ChannelListItem[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const fetchChannels = useCallback(async (signal?: AbortSignal) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const response = await channelsApi.list({ type, limit }, signal);\n if (signal?.aborted) return;\n setChannels(response.channels);\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') return;\n const error = err instanceof Error ? err : new Error('Failed to fetch channels');\n setError(error);\n onError?.(error);\n } finally {\n if (!signal?.aborted) setIsLoading(false);\n }\n }, [type, limit, onError]);\n\n const refetch = useCallback(async () => {\n if (abortControllerRef.current) abortControllerRef.current.abort();\n const controller = new AbortController();\n abortControllerRef.current = controller;\n await fetchChannels(controller.signal);\n }, [fetchChannels]);\n\n const getOrCreateDM = useCallback(async (userId: string): Promise<Channel> => {\n try {\n const response = await channelsApi.getOrCreateDM(userId);\n if (abortControllerRef.current) abortControllerRef.current.abort();\n const controller = new AbortController();\n abortControllerRef.current = controller;\n fetchChannels(controller.signal);\n onChannelCreated?.(response);\n return response;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to create DM');\n onError?.(error);\n throw error;\n }\n }, [fetchChannels, onChannelCreated, onError]);\n\n const markAsRead = useCallback(async (channelId: string): Promise<void> => {\n try {\n await channelsApi.markAsRead(channelId);\n setChannels((prev) => prev.map((ch) => ch.id === channelId ? { ...ch, unread_count: 0 } : ch));\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to mark as read');\n onError?.(error);\n throw error;\n }\n }, [onError]);\n\n useEffect(() => {\n if (autoFetch) {\n if (abortControllerRef.current) abortControllerRef.current.abort();\n const controller = new AbortController();\n abortControllerRef.current = controller;\n fetchChannels(controller.signal);\n return () => controller.abort();\n }\n }, [autoFetch, fetchChannels]);\n\n return { channels, isLoading, error, refetch, getOrCreateDM, markAsRead };\n}\n\nexport default useChannels;\n","// ============================================================================\n// AegisChat React SDK - useMessages Hook\n// ============================================================================\n\nimport { useCallback, useState } from 'react';\nimport { messagesApi } from '../services/api';\nimport type { Message, MessagesResponse } from '../types';\n\nexport interface UseMessagesOptions {\n channelId: string;\n}\n\nexport interface UseMessagesReturn {\n messages: Message[];\n isLoading: boolean;\n hasMore: boolean;\n sendMessage: (params: { content: string; type?: string; metadata?: Record<string, unknown> }) => Promise<void>;\n loadMore: () => Promise<void>;\n}\n\nexport function useMessages(_options: UseMessagesOptions): UseMessagesReturn {\n const [messages, setMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n\n const sendMessage = useCallback(async (params: { content: string; type?: string; metadata?: Record<string, unknown> }) => {\n // Implementation would go here\n }, []);\n\n const loadMore = useCallback(async () => {\n // Implementation would go here\n }, []);\n\n return { messages, isLoading, hasMore, sendMessage, loadMore };\n}\n\nexport default useMessages;\n","// ============================================================================\n// AegisChat React SDK - useTypingIndicator Hook\n// ============================================================================\n\nimport { useCallback, useState } from 'react';\nimport type { TypingUser } from '../types';\n\nexport interface UseTypingIndicatorOptions {\n channelId: string;\n ws?: WebSocket | null;\n}\n\nexport interface UseTypingIndicatorReturn {\n typingUsers: TypingUser[];\n startTyping: () => void;\n stopTyping: () => void;\n}\n\nexport function useTypingIndicator(_options: UseTypingIndicatorOptions): UseTypingIndicatorReturn {\n const [typingUsers, setTypingUsers] = useState<TypingUser[]>([]);\n\n const startTyping = useCallback(() => {}, []);\n const stopTyping = useCallback(() => {}, []);\n\n return { typingUsers, startTyping, stopTyping };\n}\n\nexport default useTypingIndicator;\n","// ============================================================================\n// AegisChat React SDK - useReactions Hook\n// ============================================================================\n\nimport { useState } from 'react';\nimport type { ReactionSummary } from '../types';\n\nexport interface UseReactionsOptions {\n channelId: string;\n messageId: string;\n}\n\nexport interface UseReactionsReturn {\n reactions: ReactionSummary[];\n addReaction: (emoji: string) => Promise<void>;\n removeReaction: (emoji: string) => Promise<void>;\n}\n\nexport function useReactions(_options: UseReactionsOptions): UseReactionsReturn {\n const [reactions, setReactions] = useState<ReactionSummary[]>([]);\n\n const addReaction = async (_emoji: string) => {};\n const removeReaction = async (_emoji: string) => {};\n\n return { reactions, addReaction, removeReaction };\n}\n\nexport default useReactions;\n","// ============================================================================\n// AegisChat React SDK - useFileUpload Hook\n// ============================================================================\n\nimport { useState } from 'react';\nimport type { FileAttachment, UploadProgress } from '../types';\n\nexport interface UseFileUploadOptions {\n channelId: string;\n}\n\nexport interface UseFileUploadReturn {\n uploadProgress: UploadProgress[];\n upload: (file: File) => Promise<FileAttachment | null>;\n}\n\nexport function useFileUpload(_options: UseFileUploadOptions): UseFileUploadReturn {\n const [uploadProgress, setUploadProgress] = useState<UploadProgress[]>([]);\n\n const upload = async (_file: File): Promise<FileAttachment | null> => null;\n\n return { uploadProgress, upload };\n}\n\nexport default useFileUpload;\n","// ============================================================================\n// AegisChat React SDK - useMentions Hook\n// ============================================================================\n\nexport interface UseMentionsOptions {}\n\nexport interface UseMentionsReturn {\n parseMentions: (content: string) => string[];\n highlightMentions: (content: string) => string;\n isUserMentioned: (content: string, userId: string) => boolean;\n}\n\nexport function useMentions(_options: UseMentionsOptions = {}): UseMentionsReturn {\n const parseMentions = (content: string): string[] => {\n const mentionRegex = /@\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n const mentions: string[] = [];\n let match;\n while ((match = mentionRegex.exec(content)) !== null) {\n mentions.push(match[2]);\n }\n return mentions;\n };\n\n const highlightMentions = (content: string): string => {\n return content.replace(/@\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<span class=\"mention\">@$1</span>');\n };\n\n const isUserMentioned = (content: string, userId: string): boolean => {\n const mentions = parseMentions(content);\n return mentions.includes(userId);\n };\n\n return { parseMentions, highlightMentions, isUserMentioned };\n}\n\nexport default useMentions;\n"],"mappings":"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","names":["options","config","role","clientId","initialSession","autoConnect","onMessage","onTyping","onConnectionChange","useCallback","useEffect","useState","useState","useEffect","useCallback","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","error","useEffect","useCallback","useState","useCallback","useState","useState","useState"]}
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useChat.ts","../src/services/api.ts","../src/hooks/useAutoRead.ts","../src/hooks/useChannels.ts","../src/hooks/useMessages.ts","../src/hooks/useTypingIndicator.ts","../src/hooks/useReactions.ts","../src/hooks/useFileUpload.ts","../src/hooks/useMentions.ts"],"sourcesContent":["// ============================================================================\n// AegisChat React SDK - useChat Hook\n// ============================================================================\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n chatApi,\n channelsApi,\n messagesApi,\n filesApi,\n configureApiClient,\n} from \"../services/api\";\nimport type {\n AegisConfig,\n ChatSession,\n ChannelListItem,\n Message,\n MessagesResponse,\n TypingUser,\n UserSummary,\n FileAttachment,\n UploadProgress,\n MessageSummary,\n} from \"../types\";\n\nconst TYPING_TIMEOUT = 3000;\nconst RECONNECT_INTERVAL = 3000;\nconst MAX_RECONNECT_ATTEMPTS = 5;\nconst MAX_RECONNECT_DELAY = 30000;\nconst PING_INTERVAL = 30000;\nconst SESSION_STORAGE_KEY = \"@aegischat/activeChannel\";\n\nexport interface UseChatOptions {\n config?: AegisConfig;\n role?: \"lawyer\" | \"client\";\n clientId?: string;\n\n initialSession?: ChatSession | null;\n autoConnect?: boolean;\n onMessage?: (message: Message) => void;\n onTyping?: (channelId: string, user: TypingUser) => void;\n onConnectionChange?: (connected: boolean) => void;\n}\n\nexport interface UseChatReturn {\n session: ChatSession | null;\n isConnected: boolean;\n isConnecting: boolean;\n channels: ChannelListItem[];\n messages: Message[];\n activeChannelId: string | null;\n typingUsers: TypingUser[];\n isLoadingChannels: boolean;\n isLoadingMessages: boolean;\n hasMoreMessages: boolean;\n uploadProgress: UploadProgress[];\n connect: () => Promise<void>;\n disconnect: () => void;\n selectChannel: (channelId: string) => void;\n sendMessage: (\n content: string,\n options?: {\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n },\n ) => Promise<void>;\n sendMessageWithFiles: (\n content: string,\n files: File[],\n options?: {\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n },\n ) => Promise<void>;\n uploadFile: (file: File) => Promise<FileAttachment | null>;\n loadMoreMessages: () => Promise<void>;\n startTyping: () => void;\n stopTyping: () => void;\n refreshChannels: () => Promise<void>;\n createDMWithUser: (userId: string) => Promise<string | null>;\n retryMessage: (tempId: string) => Promise<void>;\n deleteFailedMessage: (tempId: string) => void;\n markAsRead: (channelId: string) => Promise<void>;\n setup: (options: UseChatOptions) => void;\n updateChannel: (channelId: string, updates: Partial<ChannelListItem>) => void;\n}\n\nexport function useChat(options: Partial<UseChatOptions> = {}): UseChatReturn {\n const {\n config,\n role,\n clientId,\n initialSession,\n autoConnect = true,\n onMessage,\n onTyping,\n onConnectionChange,\n } = options;\n\n const [session, setSession] = useState<ChatSession | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [isConnecting, setIsConnecting] = useState(false);\n const getStoredActiveChannel = (): string | null => {\n if (typeof window === \"undefined\") return null;\n return sessionStorage.getItem(SESSION_STORAGE_KEY);\n };\n const [activeChannelId, setActiveChannelIdState] = useState<string | null>(\n getStoredActiveChannel,\n );\n const [channels, setChannels] = useState<ChannelListItem[]>([]);\n const [messages, setMessages] = useState<Message[]>([]);\n const [typingUsers, setTypingUsers] = useState<Record<string, TypingUser[]>>(\n {},\n );\n const [isLoadingChannels, setIsLoadingChannels] = useState(false);\n const [isLoadingMessages, setIsLoadingMessages] = useState(false);\n const [hasMoreMessages, setHasMoreMessages] = useState(true);\n const [uploadProgress, setUploadProgress] = useState<UploadProgress[]>([]);\n\n const wsRef = useRef<WebSocket | null>(null);\n const reconnectAttempts = useRef(0);\n const reconnectTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pingInterval = useRef<ReturnType<typeof setInterval> | null>(null);\n const typingTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n const isManualDisconnect = useRef(false);\n const oldestMessageId = useRef<string | null>(null);\n const activeChannelIdRef = useRef<string | null>(null);\n const sessionRef = useRef<ChatSession | null>(null);\n const roleRef = useRef<string | undefined>(undefined);\n const clientIdRef = useRef<string | undefined>(undefined);\n const autoConnectRef = useRef(true);\n const onMessageRef =\n useRef<(message: Message) => void | undefined>(undefined);\n const onTypingRef = useRef<\n ((channelId: string, user: TypingUser) => void) | undefined\n >(undefined);\n const onConnectionChangeRef = useRef<\n ((connected: boolean) => void) | undefined\n >(undefined);\n\n useEffect(() => {\n activeChannelIdRef.current = activeChannelId;\n }, [activeChannelId]);\n\n const getActiveChannelId = useCallback((): string | null => {\n if (typeof window === \"undefined\") return null;\n return sessionStorage.getItem(SESSION_STORAGE_KEY);\n }, []);\n\n const setActiveChannelId = useCallback((id: string | null) => {\n activeChannelIdRef.current = id;\n setActiveChannelIdState(id);\n if (typeof window !== \"undefined\") {\n if (id) {\n sessionStorage.setItem(SESSION_STORAGE_KEY, id);\n } else {\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n }\n }\n }, []);\n\n const fetchFromComms = useCallback(\n async <T>(path: string, fetchOptions: RequestInit = {}): Promise<T> => {\n const currentSession = sessionRef.current;\n if (!currentSession) {\n throw new Error(\"Chat session not initialized\");\n }\n\n const response = await fetch(`${currentSession.api_url}${path}`, {\n ...fetchOptions,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${currentSession.access_token}`,\n ...fetchOptions.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.message || `HTTP ${response.status}`);\n }\n\n const data = await response.json();\n return data.data || data;\n },\n [],\n );\n\n const clearTimers = useCallback(() => {\n if (reconnectTimeout.current) {\n clearTimeout(reconnectTimeout.current);\n reconnectTimeout.current = null;\n }\n if (pingInterval.current) {\n clearInterval(pingInterval.current);\n pingInterval.current = null;\n }\n }, []);\n\n const handleWebSocketMessage = useCallback(\n (data: { type: string; payload: unknown }) => {\n const currentActiveChannelId = activeChannelIdRef.current;\n console.log(\"[AegisChat] WebSocket message received:\", data.type, data);\n\n switch (data.type) {\n case \"message.new\": {\n const newMessage = data.payload as Message;\n if (newMessage.channel_id === currentActiveChannelId) {\n setMessages((prev) => {\n const existingIndex = prev.findIndex(\n (m) =>\n m.tempId &&\n m.content === newMessage.content &&\n m.status === \"sending\",\n );\n if (existingIndex !== -1) {\n const updated = [...prev];\n updated[existingIndex] = { ...newMessage, status: \"sent\" };\n return updated;\n }\n if (prev.some((m) => m.id === newMessage.id)) return prev;\n return [...prev, { ...newMessage, status: \"delivered\" }];\n });\n onMessageRef.current?.(newMessage);\n }\n setChannels((prev) => {\n const updated = prev.map((ch) =>\n ch.id === newMessage.channel_id\n ? {\n ...ch,\n last_message: {\n id: newMessage.id,\n content: newMessage.content,\n created_at: newMessage.created_at,\n sender: {\n id: newMessage.sender_id,\n display_name: \"Unknown\",\n status: \"online\" as const,\n },\n } as MessageSummary,\n unread_count:\n ch.id === currentActiveChannelId\n ? 0\n : ch.unread_count + 1,\n }\n : ch,\n );\n return updated.sort((a, b) => {\n const timeA = a.last_message?.created_at || \"\";\n const timeB = b.last_message?.created_at || \"\";\n return timeB.localeCompare(timeA);\n });\n });\n break;\n }\n case \"message.updated\": {\n const updatedMessage = data.payload as Message;\n setMessages((prev) =>\n prev.map((m) => (m.id === updatedMessage.id ? updatedMessage : m)),\n );\n break;\n }\n case \"message.deleted\": {\n const { message_id } = data.payload as { message_id: string };\n setMessages((prev) =>\n prev.map((m) =>\n m.id === message_id ? { ...m, deleted: true } : m,\n ),\n );\n break;\n }\n case \"message.delivered\":\n case \"message.read\": {\n const { message_id, channel_id, status } = data.payload as {\n message_id: string;\n channel_id: string;\n status: string;\n };\n if (channel_id === currentActiveChannelId) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === message_id\n ? {\n ...m,\n status: (status as Message[\"status\"]) || \"delivered\",\n }\n : m,\n ),\n );\n }\n break;\n }\n case \"message.delivered.batch\":\n case \"message.read.batch\": {\n const { channel_id } = data.payload as { channel_id: string };\n if (channel_id === currentActiveChannelId) {\n setMessages((prev) =>\n prev.map((m) =>\n m.status === \"sent\" || m.status === \"delivered\"\n ? {\n ...m,\n status:\n data.type === \"message.delivered.batch\"\n ? \"delivered\"\n : \"read\",\n }\n : m,\n ),\n );\n }\n break;\n }\n case \"typing.start\": {\n const { channel_id, user } = data.payload as {\n channel_id: string;\n user: UserSummary;\n };\n const typingUser: TypingUser = {\n id: user.id,\n displayName: user.display_name,\n avatarUrl: user.avatar_url,\n startedAt: Date.now(),\n };\n setTypingUsers((prev) => ({\n ...prev,\n [channel_id]: [\n ...(prev[channel_id] || []).filter((u) => u.id !== user.id),\n typingUser,\n ],\n }));\n onTypingRef.current?.(channel_id, typingUser);\n break;\n }\n case \"typing.stop\": {\n const { channel_id, user_id } = data.payload as {\n channel_id: string;\n user_id: string;\n };\n setTypingUsers((prev) => ({\n ...prev,\n [channel_id]: (prev[channel_id] || []).filter(\n (u) => u.id !== user_id,\n ),\n }));\n break;\n }\n case \"pong\":\n break;\n default:\n console.log(\"[AegisChat] Unhandled message type:\", data.type);\n }\n },\n [],\n );\n\n const connectWebSocket = useCallback(() => {\n const currentSession = sessionRef.current;\n if (!currentSession?.websocket_url || !currentSession?.access_token) {\n console.warn(\n \"[AegisChat] Cannot connect WebSocket - missing session or token\",\n );\n return;\n }\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n console.log(\"[AegisChat] WebSocket already open, skipping connection\");\n return;\n }\n\n setIsConnecting(true);\n isManualDisconnect.current = false;\n\n const wsUrl = `${currentSession.websocket_url}?token=${currentSession.access_token}`;\n console.log(\"[AegisChat] Creating WebSocket connection to:\", wsUrl);\n const ws = new WebSocket(wsUrl);\n\n ws.onopen = () => {\n console.log(\"[AegisChat] WebSocket connected\");\n setIsConnected(true);\n setIsConnecting(false);\n reconnectAttempts.current = 0;\n onConnectionChangeRef.current?.(true);\n\n pingInterval.current = setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: \"ping\" }));\n }\n }, PING_INTERVAL);\n\n if (activeChannelIdRef.current) {\n ws.send(\n JSON.stringify({\n type: \"channel.join\",\n payload: { channel_id: activeChannelIdRef.current },\n }),\n );\n }\n };\n\n ws.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data);\n handleWebSocketMessage(data);\n } catch (error) {\n console.error(\"[AegisChat] Failed to parse WebSocket message:\", error);\n }\n };\n\n ws.onclose = () => {\n console.log(\"[AegisChat] WebSocket disconnected\");\n setIsConnected(false);\n setIsConnecting(false);\n clearTimers();\n onConnectionChangeRef.current?.(false);\n\n if (\n !isManualDisconnect.current &&\n reconnectAttempts.current < MAX_RECONNECT_ATTEMPTS\n ) {\n const delay = Math.min(\n RECONNECT_INTERVAL * Math.pow(2, reconnectAttempts.current),\n MAX_RECONNECT_DELAY,\n );\n console.log(`[AegisChat] Reconnecting in ${delay}ms...`);\n reconnectTimeout.current = setTimeout(() => {\n reconnectAttempts.current++;\n connectWebSocket();\n }, delay);\n }\n };\n\n ws.onerror = (error) => {\n console.error(\"[AegisChat] WebSocket error:\", error);\n };\n\n wsRef.current = ws;\n }, [clearTimers, handleWebSocketMessage]);\n\n const connect = useCallback(async () => {\n console.log(\"[AegisChat] connect() called\");\n const targetSession = sessionRef.current;\n if (!targetSession) {\n console.log(\"[AegisChat] No session available, skipping connect\");\n return;\n }\n if (!autoConnectRef.current) {\n console.log(\"[AegisChat] autoConnect is false, skipping connect\");\n return;\n }\n connectWebSocket();\n }, [connectWebSocket]);\n\n const disconnect = useCallback(() => {\n isManualDisconnect.current = true;\n clearTimers();\n if (wsRef.current) {\n wsRef.current.close();\n wsRef.current = null;\n }\n setIsConnected(false);\n setSession(null);\n setChannels([]);\n setMessages([]);\n }, [clearTimers]);\n\n const refreshChannels = useCallback(async () => {\n const currentSession = sessionRef.current;\n if (!currentSession) return;\n\n setIsLoadingChannels(true);\n try {\n const response = await fetchFromComms<{ channels: ChannelListItem[] }>(\n \"/channels\",\n );\n setChannels(response.channels || []);\n } catch (error) {\n console.error(\"[AegisChat] Failed to fetch channels:\", error);\n } finally {\n setIsLoadingChannels(false);\n }\n }, []);\n\n const selectChannel = useCallback(\n async (channelId: string) => {\n const currentActiveChannelId = activeChannelIdRef.current;\n setActiveChannelId(channelId);\n setMessages([]);\n setHasMoreMessages(true);\n oldestMessageId.current = null;\n\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n if (currentActiveChannelId) {\n wsRef.current.send(\n JSON.stringify({\n type: \"channel.leave\",\n payload: { channel_id: currentActiveChannelId },\n }),\n );\n }\n wsRef.current.send(\n JSON.stringify({\n type: \"channel.join\",\n payload: { channel_id: channelId },\n }),\n );\n }\n\n setIsLoadingMessages(true);\n try {\n const response = await fetchFromComms<MessagesResponse>(\n `/channels/${channelId}/messages?limit=50`,\n );\n setMessages(response.messages || []);\n setHasMoreMessages(response.has_more);\n if (response.oldest_id) {\n oldestMessageId.current = response.oldest_id;\n }\n } catch (error) {\n console.error(\"[AegisChat] Failed to load messages:\", error);\n setMessages([]);\n } finally {\n setIsLoadingMessages(false);\n }\n },\n [setActiveChannelId, fetchFromComms],\n );\n\n const markAsRead = useCallback(\n async (channelId: string) => {\n try {\n await fetchFromComms(`/channels/${channelId}/read`, { method: \"POST\" });\n } catch (error) {\n console.error(\"[AegisChat] Failed to mark as read:\", error);\n }\n },\n [fetchFromComms],\n );\n\n const updateChannel = useCallback(\n (channelId: string, updates: Partial<ChannelListItem>) => {\n setChannels((prev) =>\n prev.map((ch) => (ch.id === channelId ? { ...ch, ...updates } : ch)),\n );\n },\n [],\n );\n\n const loadMoreMessages = useCallback(async () => {\n if (!activeChannelId || !hasMoreMessages || isLoadingMessages) return;\n\n setIsLoadingMessages(true);\n try {\n const params = oldestMessageId.current\n ? `?before=${oldestMessageId.current}&limit=50`\n : \"?limit=50\";\n const response = await fetchFromComms<MessagesResponse>(\n `/channels/${activeChannelId}/messages${params}`,\n );\n setMessages((prev) => [...(response.messages || []), ...prev]);\n setHasMoreMessages(response.has_more);\n if (response.oldest_id) {\n oldestMessageId.current = response.oldest_id;\n }\n } catch (error) {\n console.error(\"[AegisChat] Failed to load more messages:\", error);\n } finally {\n setIsLoadingMessages(false);\n }\n }, [activeChannelId, hasMoreMessages, isLoadingMessages, fetchFromComms]);\n\n const sendMessage = useCallback(\n async (\n content: string,\n msgOptions: {\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n } = {},\n ) => {\n const currentActiveChannelId = activeChannelIdRef.current;\n const currentSession = sessionRef.current;\n if (!currentActiveChannelId || !content.trim() || !currentSession) return;\n\n const tempId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const trimmedContent = content.trim();\n\n const optimisticMessage: Message = {\n id: tempId,\n tempId,\n channel_id: currentActiveChannelId,\n sender_id: currentSession.comms_user_id,\n content: trimmedContent,\n type: (msgOptions.type as Message[\"type\"]) || \"text\",\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n status: \"sending\",\n metadata: msgOptions.metadata || {},\n };\n\n setMessages((prev) => [...prev, optimisticMessage]);\n\n const now = new Date().toISOString();\n setChannels((prev) => {\n const updated = prev.map((ch) =>\n ch.id === currentActiveChannelId\n ? {\n ...ch,\n last_message: {\n id: tempId,\n content: trimmedContent,\n created_at: now,\n sender: {\n id: currentSession.comms_user_id,\n display_name: \"You\",\n status: \"online\" as const,\n },\n },\n }\n : ch,\n );\n return updated.sort((a, b) => {\n const timeA = a.last_message?.created_at || \"\";\n const timeB = b.last_message?.created_at || \"\";\n return timeB.localeCompare(timeA);\n });\n });\n\n try {\n await fetchFromComms<Message>(\n `/channels/${currentActiveChannelId}/messages`,\n {\n method: \"POST\",\n body: JSON.stringify({\n content: trimmedContent,\n type: msgOptions.type || \"text\",\n parent_id: msgOptions.parent_id,\n metadata: msgOptions.metadata,\n }),\n },\n );\n } catch (error) {\n console.error(\"[AegisChat] Failed to send message:\", error);\n setMessages((prev) =>\n prev.map((m) =>\n m.tempId === tempId\n ? {\n ...m,\n status: \"failed\",\n errorMessage:\n error instanceof Error ? error.message : \"Failed to send\",\n }\n : m,\n ),\n );\n throw error;\n }\n },\n [fetchFromComms],\n );\n\n const uploadFile = useCallback(\n async (file: File): Promise<FileAttachment | null> => {\n const currentSession = sessionRef.current;\n if (!currentSession) return null;\n\n const fileId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\n setUploadProgress((prev) => [\n ...prev,\n { fileId, fileName: file.name, progress: 0, status: \"pending\" },\n ]);\n\n try {\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === fileId\n ? { ...p, status: \"uploading\", progress: 10 }\n : p,\n ),\n );\n\n const uploadUrlResponse = await fetchFromComms<{\n upload_url: string;\n file_id: string;\n expires_at: string;\n }>(\"/files/upload-url\", {\n method: \"POST\",\n body: JSON.stringify({\n file_name: file.name,\n file_type: file.type || \"application/octet-stream\",\n file_size: file.size,\n }),\n });\n\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === fileId\n ? { ...p, fileId: uploadUrlResponse.file_id, progress: 30 }\n : p,\n ),\n );\n\n const uploadResponse = await fetch(uploadUrlResponse.upload_url, {\n method: \"PUT\",\n body: file,\n headers: { \"Content-Type\": file.type || \"application/octet-stream\" },\n });\n\n if (!uploadResponse.ok)\n throw new Error(`Upload failed: ${uploadResponse.statusText}`);\n\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === uploadUrlResponse.file_id\n ? { ...p, status: \"confirming\", progress: 70 }\n : p,\n ),\n );\n\n const confirmResponse = await fetchFromComms<{ file: FileAttachment }>(\n \"/files\",\n {\n method: \"POST\",\n body: JSON.stringify({ file_id: uploadUrlResponse.file_id }),\n },\n );\n\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === uploadUrlResponse.file_id\n ? { ...p, status: \"complete\", progress: 100 }\n : p,\n ),\n );\n setTimeout(\n () =>\n setUploadProgress((prev) =>\n prev.filter((p) => p.fileId !== uploadUrlResponse.file_id),\n ),\n 2000,\n );\n\n return confirmResponse.file;\n } catch (error) {\n console.error(\"[AegisChat] Failed to upload file:\", error);\n setUploadProgress((prev) =>\n prev.map((p) =>\n p.fileId === fileId\n ? {\n ...p,\n status: \"error\",\n error:\n error instanceof Error ? error.message : \"Upload failed\",\n }\n : p,\n ),\n );\n setTimeout(\n () =>\n setUploadProgress((prev) =>\n prev.filter((p) => p.fileId !== fileId),\n ),\n 5000,\n );\n return null;\n }\n },\n [fetchFromComms],\n );\n\n const sendMessageWithFiles = useCallback(\n async (\n content: string,\n files: File[],\n msgOptions: {\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n } = {},\n ) => {\n const currentActiveChannelId = activeChannelIdRef.current;\n const currentSession = sessionRef.current;\n if (\n !currentActiveChannelId ||\n (!content.trim() && files.length === 0) ||\n !currentSession\n )\n return;\n\n const tempId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const trimmedContent = content.trim();\n\n const optimisticMessage: Message = {\n id: tempId,\n tempId,\n channel_id: currentActiveChannelId,\n sender_id: currentSession.comms_user_id,\n content: trimmedContent || `Uploading ${files.length} file(s)...`,\n type: \"file\",\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n status: \"sending\",\n metadata: {\n ...msgOptions.metadata,\n files: files.map((f) => ({\n id: `temp-${f.name}`,\n filename: f.name,\n mime_type: f.type,\n size: f.size,\n url: \"\",\n })),\n },\n };\n\n setMessages((prev) => [...prev, optimisticMessage]);\n\n try {\n const uploadedFiles: FileAttachment[] = [];\n for (const file of files) {\n const attachment = await uploadFile(file);\n if (attachment) uploadedFiles.push(attachment);\n }\n\n const messageType =\n uploadedFiles.length > 0 && !trimmedContent ? \"file\" : \"text\";\n\n await fetchFromComms<Message>(\n `/channels/${currentActiveChannelId}/messages`,\n {\n method: \"POST\",\n body: JSON.stringify({\n content:\n trimmedContent ||\n (uploadedFiles.length > 0\n ? `Shared ${uploadedFiles.length} file(s)`\n : \"\"),\n type: msgOptions.type || messageType,\n parent_id: msgOptions.parent_id,\n metadata: { ...msgOptions.metadata, files: uploadedFiles },\n file_ids: uploadedFiles.map((f) => f.id),\n }),\n },\n );\n } catch (error) {\n console.error(\"[AegisChat] Failed to send message with files:\", error);\n setMessages((prev) =>\n prev.map((m) =>\n m.tempId === tempId\n ? {\n ...m,\n status: \"failed\",\n errorMessage:\n error instanceof Error ? error.message : \"Failed to send\",\n }\n : m,\n ),\n );\n throw error;\n }\n },\n [fetchFromComms, uploadFile],\n );\n\n const stopTyping = useCallback(() => {\n const currentActiveChannelId = activeChannelIdRef.current;\n if (!currentActiveChannelId || !wsRef.current) return;\n wsRef.current.send(\n JSON.stringify({\n type: \"typing.stop\",\n payload: { channel_id: currentActiveChannelId },\n }),\n );\n if (typingTimeout.current) {\n clearTimeout(typingTimeout.current);\n typingTimeout.current = null;\n }\n }, []);\n\n const startTyping = useCallback(() => {\n const currentActiveChannelId = activeChannelIdRef.current;\n if (!currentActiveChannelId || !wsRef.current) return;\n wsRef.current.send(\n JSON.stringify({\n type: \"typing.start\",\n payload: { channel_id: currentActiveChannelId },\n }),\n );\n if (typingTimeout.current) clearTimeout(typingTimeout.current);\n typingTimeout.current = setTimeout(stopTyping, TYPING_TIMEOUT);\n }, [stopTyping]);\n\n const createDMWithUser = useCallback(\n async (userId: string): Promise<string | null> => {\n try {\n const channel = await fetchFromComms<{ id: string }>(\"/channels/dm\", {\n method: \"POST\",\n body: JSON.stringify({ user_id: userId }),\n });\n await refreshChannels();\n return channel.id;\n } catch (error) {\n console.error(\"[AegisChat] Failed to create DM:\", error);\n return null;\n }\n },\n [fetchFromComms, refreshChannels],\n );\n\n const retryMessage = useCallback(\n async (tempId: string) => {\n const failedMessage = messages.find(\n (m) => m.tempId === tempId && m.status === \"failed\",\n );\n const currentActiveChannelId = activeChannelIdRef.current;\n if (!failedMessage || !currentActiveChannelId) return;\n\n setMessages((prev) =>\n prev.map((m) =>\n m.tempId === tempId\n ? { ...m, status: \"sending\", errorMessage: undefined }\n : m,\n ),\n );\n\n try {\n await fetchFromComms<Message>(\n `/channels/${currentActiveChannelId}/messages`,\n {\n method: \"POST\",\n body: JSON.stringify({\n content: failedMessage.content,\n type: failedMessage.type,\n metadata: failedMessage.metadata,\n }),\n },\n );\n } catch (error) {\n console.error(\"[AegisChat] Failed to retry message:\", error);\n setMessages((prev) =>\n prev.map((m) =>\n m.tempId === tempId\n ? {\n ...m,\n status: \"failed\",\n errorMessage:\n error instanceof Error ? error.message : \"Failed to send\",\n }\n : m,\n ),\n );\n }\n },\n [messages, fetchFromComms],\n );\n\n const deleteFailedMessage = useCallback((tempId: string) => {\n setMessages((prev) => prev.filter((m) => m.tempId !== tempId));\n }, []);\n\n const setup = useCallback((options: UseChatOptions) => {\n const {\n config,\n role,\n clientId,\n initialSession,\n autoConnect = true,\n onMessage,\n onTyping,\n onConnectionChange,\n } = options;\n\n roleRef.current = role;\n clientIdRef.current = clientId;\n autoConnectRef.current = autoConnect;\n onMessageRef.current = onMessage;\n onTypingRef.current = onTyping;\n onConnectionChangeRef.current = onConnectionChange;\n\n if (initialSession) {\n sessionRef.current = initialSession;\n\n if (!config) {\n const url = initialSession.api_url;\n const normalizedUrl =\n url.includes(\"/api/v1\") || url.includes(\"/v\") ? url : `${url}/api/v1`;\n configureApiClient({\n baseUrl: normalizedUrl,\n getAccessToken: async () => sessionRef.current?.access_token || \"\",\n });\n }\n\n setSession(initialSession);\n }\n }, []);\n\n useEffect(() => {\n if (session && !isConnected && !isConnecting && autoConnectRef.current) {\n connectWebSocket();\n }\n }, [session, isConnected, isConnecting, connectWebSocket]);\n\n useEffect(() => {\n if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {\n wsRef.current.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data);\n handleWebSocketMessage(data);\n } catch (error) {\n console.error(\n \"[AegisChat] Failed to parse WebSocket message:\",\n error,\n );\n }\n };\n }\n }, [handleWebSocketMessage]);\n\n useEffect(() => {\n if (isConnected && channels.length === 0) {\n refreshChannels();\n }\n }, [isConnected, channels.length, refreshChannels]);\n\n useEffect(() => {\n const storedActiveChannel = getActiveChannelId();\n if (storedActiveChannel && !activeChannelId) {\n selectChannel(storedActiveChannel);\n }\n }, [getActiveChannelId, activeChannelId, selectChannel]);\n\n useEffect(() => {\n return () => {\n clearTimers();\n if (typingTimeout.current) clearTimeout(typingTimeout.current);\n if (wsRef.current) {\n isManualDisconnect.current = true;\n wsRef.current.close();\n wsRef.current = null;\n }\n };\n }, [clearTimers]);\n\n return {\n session,\n isConnected,\n isConnecting,\n channels,\n messages,\n activeChannelId,\n typingUsers: activeChannelId ? typingUsers[activeChannelId] || [] : [],\n isLoadingChannels,\n isLoadingMessages,\n hasMoreMessages,\n uploadProgress,\n connect,\n disconnect,\n selectChannel,\n sendMessage,\n sendMessageWithFiles,\n uploadFile,\n loadMoreMessages,\n startTyping,\n stopTyping,\n refreshChannels,\n createDMWithUser,\n retryMessage,\n deleteFailedMessage,\n markAsRead,\n updateChannel,\n setup,\n };\n}\n\nexport default useChat;\n","// ============================================================================\n// AegisChat React SDK - API Service\n// ============================================================================\n\nimport type {\n ChatSession,\n ChatConnectParams,\n Channel,\n ChannelListItem,\n Message,\n MessagesResponse,\n UserSummary,\n ReactionSummary,\n FileAttachment,\n UploadUrlResponse,\n} from \"../types\";\n\nlet baseUrl = \"\";\nlet getAccessToken: () => Promise<string> | string = () => \"\";\nlet onUnauthorized: (() => void) | undefined;\n\nexport function configureApiClient(config: {\n baseUrl: string;\n getAccessToken: () => Promise<string> | string;\n onUnauthorized?: () => void;\n}): void {\n baseUrl = config.baseUrl;\n getAccessToken = config.getAccessToken;\n onUnauthorized = config.onUnauthorized;\n}\n\nasync function fetchWithAuth<T>(\n path: string,\n options: RequestInit = {},\n): Promise<T> {\n const token = await (typeof getAccessToken === \"function\"\n ? getAccessToken()\n : getAccessToken);\n\n const response = await fetch(`${baseUrl}${path}`, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n ...options.headers,\n },\n });\n\n if (response.status === 401) {\n onUnauthorized?.();\n throw new Error(\"Unauthorized\");\n }\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.message || `HTTP ${response.status}`);\n }\n\n return response.json();\n}\n\nexport const chatApi = {\n /**\n * Connect to chat session\n */\n async connect(\n params: ChatConnectParams,\n signal?: AbortSignal,\n ): Promise<ChatSession> {\n return fetchWithAuth(\"/chat/connect\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal,\n });\n },\n\n /**\n * Refresh access token\n */\n async refreshToken(\n refreshToken: string,\n signal?: AbortSignal,\n ): Promise<{ access_token: string; expires_in: number }> {\n return fetchWithAuth(\"/chat/refresh\", {\n method: \"POST\",\n body: JSON.stringify({ refresh_token: refreshToken }),\n signal,\n });\n },\n};\n\nexport const channelsApi = {\n /**\n * List channels\n */\n async list(\n options: { type?: string; limit?: number } = {},\n signal?: AbortSignal,\n ): Promise<{ channels: ChannelListItem[] }> {\n const params = new URLSearchParams();\n if (options.type) params.append(\"type\", options.type);\n if (options.limit) params.append(\"limit\", String(options.limit));\n const query = params.toString() ? `?${params.toString()}` : \"\";\n return fetchWithAuth(`/channels${query}`, { signal });\n },\n\n /**\n * Get channel by ID\n */\n async get(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<Channel> {\n return fetchWithAuth(`/channels/${channelId}`, { signal });\n },\n\n /**\n * Get or create DM channel\n */\n async getOrCreateDM(\n userId: string,\n signal?: AbortSignal,\n ): Promise<Channel> {\n return fetchWithAuth(\"/channels/dm\", {\n method: \"POST\",\n body: JSON.stringify({ user_id: userId }),\n signal,\n });\n },\n\n /**\n * Create channel\n */\n async create(\n data: {\n name: string;\n type?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n },\n signal?: AbortSignal,\n ): Promise<Channel> {\n return fetchWithAuth(\"/channels\", {\n method: \"POST\",\n body: JSON.stringify(data),\n signal,\n });\n },\n\n /**\n * Mark channel as read\n */\n async markAsRead(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<{ unread_count: number }> {\n return fetchWithAuth(`/channels/${channelId}/read`, {\n method: \"POST\",\n signal,\n });\n },\n\n /**\n * Get channel members\n */\n async getMembers(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<{ members: UserSummary[] }> {\n return fetchWithAuth(`/channels/${channelId}/members`, { signal });\n },\n\n /**\n * Update channel\n */\n async update(\n channelId: string,\n data: {\n name?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n },\n signal?: AbortSignal,\n ): Promise<Channel> {\n return fetchWithAuth(`/channels/${channelId}`, {\n method: \"PATCH\",\n body: JSON.stringify(data),\n signal,\n });\n },\n};\n\nexport const messagesApi = {\n /**\n * List messages in a channel\n */\n async list(\n channelId: string,\n options: { limit?: number; before?: string } = {},\n signal?: AbortSignal,\n ): Promise<MessagesResponse> {\n const params = new URLSearchParams();\n if (options.limit) params.append(\"limit\", String(options.limit));\n if (options.before) params.append(\"before\", options.before);\n const query = params.toString() ? `?${params.toString()}` : \"\";\n return fetchWithAuth(`/channels/${channelId}/messages${query}`, {\n signal,\n });\n },\n\n /**\n * Send a message\n */\n async send(\n channelId: string,\n data: {\n content: string;\n type?: string;\n parent_id?: string;\n metadata?: Record<string, unknown>;\n file_ids?: string[];\n },\n signal?: AbortSignal,\n ): Promise<Message> {\n return fetchWithAuth(`/channels/${channelId}/messages`, {\n method: \"POST\",\n body: JSON.stringify(data),\n signal,\n });\n },\n\n /**\n * Update a message\n */\n async update(\n channelId: string,\n messageId: string,\n data: { content?: string; metadata?: Record<string, unknown> },\n signal?: AbortSignal,\n ): Promise<Message> {\n return fetchWithAuth(`/channels/${channelId}/messages/${messageId}`, {\n method: \"PATCH\",\n body: JSON.stringify(data),\n signal,\n });\n },\n\n /**\n * Delete a message\n */\n async delete(\n channelId: string,\n messageId: string,\n signal?: AbortSignal,\n ): Promise<{ success: boolean }> {\n return fetchWithAuth(`/channels/${channelId}/messages/${messageId}`, {\n method: \"DELETE\",\n signal,\n });\n },\n\n /**\n * Mark messages as delivered\n */\n async markDelivered(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<{ success: boolean }> {\n return fetchWithAuth(`/channels/${channelId}/messages/delivered`, {\n method: \"POST\",\n signal,\n });\n },\n\n /**\n * Mark messages as read\n */\n async markRead(\n channelId: string,\n signal?: AbortSignal,\n ): Promise<{ success: boolean }> {\n return fetchWithAuth(`/channels/${channelId}/messages/read`, {\n method: \"POST\",\n signal,\n });\n },\n};\n\nexport const reactionsApi = {\n /**\n * Add reaction to a message\n */\n async add(\n channelId: string,\n messageId: string,\n emoji: string,\n signal?: AbortSignal,\n ): Promise<{ reactions: ReactionSummary[] }> {\n return fetchWithAuth(\n `/channels/${channelId}/messages/${messageId}/reactions`,\n {\n method: \"POST\",\n body: JSON.stringify({ emoji }),\n signal,\n },\n );\n },\n\n /**\n * Remove reaction from a message\n */\n async remove(\n channelId: string,\n messageId: string,\n emoji: string,\n signal?: AbortSignal,\n ): Promise<{ reactions: ReactionSummary[] }> {\n return fetchWithAuth(\n `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`,\n { method: \"DELETE\", signal },\n );\n },\n};\n\nexport const filesApi = {\n /**\n * Get upload URL\n */\n async getUploadUrl(\n data: { file_name: string; file_type: string; file_size: number },\n signal?: AbortSignal,\n ): Promise<UploadUrlResponse> {\n return fetchWithAuth(\"/files/upload-url\", {\n method: \"POST\",\n body: JSON.stringify(data),\n signal,\n });\n },\n\n /**\n * Confirm file upload\n */\n async confirm(\n fileId: string,\n signal?: AbortSignal,\n ): Promise<{ file: FileAttachment }> {\n return fetchWithAuth(\"/files\", {\n method: \"POST\",\n body: JSON.stringify({ file_id: fileId }),\n signal,\n });\n },\n\n /**\n * Get download URL\n */\n async getDownloadUrl(\n fileId: string,\n signal?: AbortSignal,\n ): Promise<{ url: string; expires_at: string }> {\n return fetchWithAuth(`/files/${fileId}/download`, { signal });\n },\n};\n\nexport const usersApi = {\n /**\n * Search users\n */\n async search(\n query: string,\n signal?: AbortSignal,\n ): Promise<{ users: UserSummary[] }> {\n return fetchWithAuth(`/users/search?q=${encodeURIComponent(query)}`, {\n signal,\n });\n },\n\n /**\n * Get user by ID\n */\n async get(\n userId: string,\n signal?: AbortSignal,\n ): Promise<UserSummary> {\n return fetchWithAuth(`/users/${userId}`, { signal });\n },\n};\n\nexport default {\n chatApi,\n channelsApi,\n messagesApi,\n reactionsApi,\n filesApi,\n usersApi,\n configureApiClient,\n};\n","// ============================================================================\n// AegisChat React SDK - useAutoRead Hook\n// ============================================================================\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport { channelsApi } from '../services/api';\n\nconst SESSION_STORAGE_KEY = '@aegischat/activeChannel';\n\nexport interface UseAutoReadOptions {\n onMarkAsRead?: (channelId: string) => void;\n}\n\nexport interface UseAutoReadReturn {\n markAsRead: (channelId: string) => Promise<void>;\n markAllAsRead: () => Promise<void>;\n isFocused: boolean;\n}\n\nexport function useAutoRead(options: UseAutoReadOptions = {}): UseAutoReadReturn {\n const isFocusedRef = useRef(typeof document !== 'undefined' && document.hasFocus());\n\n useEffect(() => {\n const handleFocus = () => { isFocusedRef.current = true; };\n const handleBlur = () => { isFocusedRef.current = false; };\n\n window.addEventListener('focus', handleFocus);\n window.addEventListener('blur', handleBlur);\n\n return () => {\n window.removeEventListener('focus', handleFocus);\n window.removeEventListener('blur', handleBlur);\n };\n }, []);\n\n const markAsRead = useCallback(async (channelId: string) => {\n if (!isFocusedRef.current) return;\n try {\n await channelsApi.markAsRead(channelId);\n options.onMarkAsRead?.(channelId);\n } catch (error) {\n console.error('[AegisChat] useAutoRead: Failed to mark as read:', error);\n }\n }, [options.onMarkAsRead]);\n\n const markAllAsRead = useCallback(async () => {\n if (!isFocusedRef.current) return;\n try {\n const response = await channelsApi.list({});\n const channels = response.channels || [];\n await Promise.all(\n channels.filter((ch) => ch.unread_count > 0).map((ch) => channelsApi.markAsRead(ch.id))\n );\n } catch (error) {\n console.error('[AegisChat] useAutoRead: Failed to mark all as read:', error);\n }\n }, []);\n\n return { markAsRead, markAllAsRead, isFocused: isFocusedRef.current };\n}\n\nexport default useAutoRead;\n","// ============================================================================\n// AegisChat React SDK - useChannels Hook\n// ============================================================================\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { channelsApi } from '../services/api';\nimport type { ChannelListItem, Channel } from '../types';\n\nexport interface UseChannelsOptions {\n type?: 'direct' | 'public' | 'private';\n limit?: number;\n autoFetch?: boolean;\n onChannelCreated?: (channel: Channel) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseChannelsReturn {\n channels: ChannelListItem[];\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n getOrCreateDM: (userId: string) => Promise<Channel>;\n markAsRead: (channelId: string) => Promise<void>;\n}\n\nexport function useChannels(options: UseChannelsOptions = {}): UseChannelsReturn {\n const { type, limit = 20, autoFetch = true, onChannelCreated, onError } = options;\n\n const [channels, setChannels] = useState<ChannelListItem[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const fetchChannels = useCallback(async (signal?: AbortSignal) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const response = await channelsApi.list({ type, limit }, signal);\n if (signal?.aborted) return;\n setChannels(response.channels);\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') return;\n const error = err instanceof Error ? err : new Error('Failed to fetch channels');\n setError(error);\n onError?.(error);\n } finally {\n if (!signal?.aborted) setIsLoading(false);\n }\n }, [type, limit, onError]);\n\n const refetch = useCallback(async () => {\n if (abortControllerRef.current) abortControllerRef.current.abort();\n const controller = new AbortController();\n abortControllerRef.current = controller;\n await fetchChannels(controller.signal);\n }, [fetchChannels]);\n\n const getOrCreateDM = useCallback(async (userId: string): Promise<Channel> => {\n try {\n const response = await channelsApi.getOrCreateDM(userId);\n if (abortControllerRef.current) abortControllerRef.current.abort();\n const controller = new AbortController();\n abortControllerRef.current = controller;\n fetchChannels(controller.signal);\n onChannelCreated?.(response);\n return response;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to create DM');\n onError?.(error);\n throw error;\n }\n }, [fetchChannels, onChannelCreated, onError]);\n\n const markAsRead = useCallback(async (channelId: string): Promise<void> => {\n try {\n await channelsApi.markAsRead(channelId);\n setChannels((prev) => prev.map((ch) => ch.id === channelId ? { ...ch, unread_count: 0 } : ch));\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to mark as read');\n onError?.(error);\n throw error;\n }\n }, [onError]);\n\n useEffect(() => {\n if (autoFetch) {\n if (abortControllerRef.current) abortControllerRef.current.abort();\n const controller = new AbortController();\n abortControllerRef.current = controller;\n fetchChannels(controller.signal);\n return () => controller.abort();\n }\n }, [autoFetch, fetchChannels]);\n\n return { channels, isLoading, error, refetch, getOrCreateDM, markAsRead };\n}\n\nexport default useChannels;\n","// ============================================================================\n// AegisChat React SDK - useMessages Hook\n// ============================================================================\n\nimport { useCallback, useState } from 'react';\nimport { messagesApi } from '../services/api';\nimport type { Message, MessagesResponse } from '../types';\n\nexport interface UseMessagesOptions {\n channelId: string;\n}\n\nexport interface UseMessagesReturn {\n messages: Message[];\n isLoading: boolean;\n hasMore: boolean;\n sendMessage: (params: { content: string; type?: string; metadata?: Record<string, unknown> }) => Promise<void>;\n loadMore: () => Promise<void>;\n}\n\nexport function useMessages(_options: UseMessagesOptions): UseMessagesReturn {\n const [messages, setMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n\n const sendMessage = useCallback(async (params: { content: string; type?: string; metadata?: Record<string, unknown> }) => {\n // Implementation would go here\n }, []);\n\n const loadMore = useCallback(async () => {\n // Implementation would go here\n }, []);\n\n return { messages, isLoading, hasMore, sendMessage, loadMore };\n}\n\nexport default useMessages;\n","// ============================================================================\n// AegisChat React SDK - useTypingIndicator Hook\n// ============================================================================\n\nimport { useCallback, useState } from 'react';\nimport type { TypingUser } from '../types';\n\nexport interface UseTypingIndicatorOptions {\n channelId: string;\n ws?: WebSocket | null;\n}\n\nexport interface UseTypingIndicatorReturn {\n typingUsers: TypingUser[];\n startTyping: () => void;\n stopTyping: () => void;\n}\n\nexport function useTypingIndicator(_options: UseTypingIndicatorOptions): UseTypingIndicatorReturn {\n const [typingUsers, setTypingUsers] = useState<TypingUser[]>([]);\n\n const startTyping = useCallback(() => {}, []);\n const stopTyping = useCallback(() => {}, []);\n\n return { typingUsers, startTyping, stopTyping };\n}\n\nexport default useTypingIndicator;\n","// ============================================================================\n// AegisChat React SDK - useReactions Hook\n// ============================================================================\n\nimport { useState } from 'react';\nimport type { ReactionSummary } from '../types';\n\nexport interface UseReactionsOptions {\n channelId: string;\n messageId: string;\n}\n\nexport interface UseReactionsReturn {\n reactions: ReactionSummary[];\n addReaction: (emoji: string) => Promise<void>;\n removeReaction: (emoji: string) => Promise<void>;\n}\n\nexport function useReactions(_options: UseReactionsOptions): UseReactionsReturn {\n const [reactions, setReactions] = useState<ReactionSummary[]>([]);\n\n const addReaction = async (_emoji: string) => {};\n const removeReaction = async (_emoji: string) => {};\n\n return { reactions, addReaction, removeReaction };\n}\n\nexport default useReactions;\n","// ============================================================================\n// AegisChat React SDK - useFileUpload Hook\n// ============================================================================\n\nimport { useState } from 'react';\nimport type { FileAttachment, UploadProgress } from '../types';\n\nexport interface UseFileUploadOptions {\n channelId: string;\n}\n\nexport interface UseFileUploadReturn {\n uploadProgress: UploadProgress[];\n upload: (file: File) => Promise<FileAttachment | null>;\n}\n\nexport function useFileUpload(_options: UseFileUploadOptions): UseFileUploadReturn {\n const [uploadProgress, setUploadProgress] = useState<UploadProgress[]>([]);\n\n const upload = async (_file: File): Promise<FileAttachment | null> => null;\n\n return { uploadProgress, upload };\n}\n\nexport default useFileUpload;\n","// ============================================================================\n// AegisChat React SDK - useMentions Hook\n// ============================================================================\n\nexport interface UseMentionsOptions {}\n\nexport interface UseMentionsReturn {\n parseMentions: (content: string) => string[];\n highlightMentions: (content: string) => string;\n isUserMentioned: (content: string, userId: string) => boolean;\n}\n\nexport function useMentions(_options: UseMentionsOptions = {}): UseMentionsReturn {\n const parseMentions = (content: string): string[] => {\n const mentionRegex = /@\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n const mentions: string[] = [];\n let match;\n while ((match = mentionRegex.exec(content)) !== null) {\n mentions.push(match[2]);\n }\n return mentions;\n };\n\n const highlightMentions = (content: string): string => {\n return content.replace(/@\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<span class=\"mention\">@$1</span>');\n };\n\n const isUserMentioned = (content: string, userId: string): boolean => {\n const mentions = parseMentions(content);\n return mentions.includes(userId);\n };\n\n return { parseMentions, highlightMentions, isUserMentioned };\n}\n\nexport default useMentions;\n"],"mappings":"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","names":["options","config","role","clientId","initialSession","autoConnect","onMessage","onTyping","onConnectionChange","useCallback","useEffect","useRef","useRef","useEffect","useCallback","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","error","useEffect","useCallback","useState","useCallback","useState","useState","useState"]}
|