@agentprojectcontext/apx 1.55.1 → 1.55.2
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/package.json +1 -1
- package/src/interfaces/web/dist/assets/{index-BxS9xYHB.js → index-p33JHkov.js} +27 -27
- package/src/interfaces/web/dist/assets/{index-BxS9xYHB.js.map → index-p33JHkov.js.map} +1 -1
- package/src/interfaces/web/dist/index.html +1 -1
- package/src/interfaces/web/src/components/chat/ChatList.tsx +6 -3
- package/src/interfaces/web/src/hooks/useChat.ts +22 -0
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +5 -2
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<link rel="apple-touch-icon" href="/favicon/dark/apple-touch-icon.png" media="(prefers-color-scheme: dark)" />
|
|
19
19
|
<link rel="manifest" href="/favicon/white/site.webmanifest" media="(prefers-color-scheme: light)" />
|
|
20
20
|
<link rel="manifest" href="/favicon/dark/site.webmanifest" media="(prefers-color-scheme: dark)" />
|
|
21
|
-
<script type="module" crossorigin src="/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/assets/index-p33JHkov.js"></script>
|
|
22
22
|
<link rel="stylesheet" crossorigin href="/assets/index-BwnMDZaD.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body class="bg-background text-foreground antialiased">
|
|
@@ -126,10 +126,13 @@ export function ChatList({
|
|
|
126
126
|
const [collapsed, setCollapsed] = useState<Partial<Record<ChannelGroupKey, boolean>>>({});
|
|
127
127
|
const [byAgent, setByAgent] = useState<Record<string, ConversationListEntry[]>>({});
|
|
128
128
|
|
|
129
|
-
// Super-agent channel threads (telegram, web quick-chat, desktop …) from
|
|
130
|
-
// global message ledger
|
|
129
|
+
// Super-agent channel threads (telegram, web quick-chat, desktop …) come from
|
|
130
|
+
// the global message ledger, which is daemon-level and NOT project-scoped.
|
|
131
|
+
// Only surface them in the Base workspace (pid "0"); inside a real project the
|
|
132
|
+
// sidebar shows just that project's own agent conversations.
|
|
133
|
+
const isBase = String(pid) === "0";
|
|
131
134
|
const threadsQ = useSWR(
|
|
132
|
-
`/projects/${pid}/super-agent/threads
|
|
135
|
+
isBase ? `/projects/${pid}/super-agent/threads` : null,
|
|
133
136
|
() => Conversations.threads(pid),
|
|
134
137
|
{ revalidateOnFocus: false },
|
|
135
138
|
);
|
|
@@ -250,6 +250,11 @@ export function useChat(pid: string, onError?: (msg: string) => void): UseChatRe
|
|
|
250
250
|
const [conversationId, setConversationId] = useState<string | undefined>(undefined);
|
|
251
251
|
const abortRef = useRef<AbortController | null>(null);
|
|
252
252
|
const convoRef = useRef<string | undefined>(undefined);
|
|
253
|
+
// Monotonic token guarding async history loads. Every load()/loadThread()/
|
|
254
|
+
// clear() bumps it; a load only applies its result if it's still the latest.
|
|
255
|
+
// Without this, clicking chat A then B could land A's (slower) response last
|
|
256
|
+
// and paint A's messages under B's header.
|
|
257
|
+
const loadSeqRef = useRef(0);
|
|
253
258
|
|
|
254
259
|
// Mutate the trailing assistant turn in place.
|
|
255
260
|
const patchLast = useCallback((fn: (m: ChatMsg) => ChatMsg) => {
|
|
@@ -348,6 +353,7 @@ export function useChat(pid: string, onError?: (msg: string) => void): UseChatRe
|
|
|
348
353
|
const stop = useCallback(() => abortRef.current?.abort(), []);
|
|
349
354
|
const clear = useCallback(() => {
|
|
350
355
|
if (streaming) return;
|
|
356
|
+
loadSeqRef.current++; // cancel any in-flight history load
|
|
351
357
|
convoRef.current = undefined;
|
|
352
358
|
setConversationId(undefined);
|
|
353
359
|
setMsgs([]);
|
|
@@ -356,8 +362,13 @@ export function useChat(pid: string, onError?: (msg: string) => void): UseChatRe
|
|
|
356
362
|
const load = useCallback(
|
|
357
363
|
async (agentSlug: string, conversationId: string) => {
|
|
358
364
|
if (streaming) return;
|
|
365
|
+
const seq = ++loadSeqRef.current;
|
|
366
|
+
// Blank the pane up front so it never shows the previous chat under the
|
|
367
|
+
// new header while the fetch is in flight.
|
|
368
|
+
setMsgs([]);
|
|
359
369
|
try {
|
|
360
370
|
const detail = await Conversations.get(pid, agentSlug, conversationId);
|
|
371
|
+
if (seq !== loadSeqRef.current) return; // superseded by a newer pick
|
|
361
372
|
const loaded: ChatMsg[] = (detail.messages ?? [])
|
|
362
373
|
.filter((m) => m.role === "user" || m.role === "assistant")
|
|
363
374
|
.map((m) => ({
|
|
@@ -369,6 +380,10 @@ export function useChat(pid: string, onError?: (msg: string) => void): UseChatRe
|
|
|
369
380
|
setConversationId(conversationId);
|
|
370
381
|
setMsgs(loaded);
|
|
371
382
|
} catch (e) {
|
|
383
|
+
if (seq !== loadSeqRef.current) return;
|
|
384
|
+
convoRef.current = undefined;
|
|
385
|
+
setConversationId(undefined);
|
|
386
|
+
setMsgs([]);
|
|
372
387
|
onError?.((e as Error)?.message || t("shared_ui.err_load_conversation"));
|
|
373
388
|
}
|
|
374
389
|
},
|
|
@@ -378,8 +393,11 @@ export function useChat(pid: string, onError?: (msg: string) => void): UseChatRe
|
|
|
378
393
|
const loadThread = useCallback(
|
|
379
394
|
async (channel: string, threadId: string) => {
|
|
380
395
|
if (streaming) return;
|
|
396
|
+
const seq = ++loadSeqRef.current;
|
|
397
|
+
setMsgs([]);
|
|
381
398
|
try {
|
|
382
399
|
const detail = await Conversations.thread(pid, channel, threadId);
|
|
400
|
+
if (seq !== loadSeqRef.current) return; // superseded by a newer pick
|
|
383
401
|
const loaded: ChatMsg[] = (detail.messages ?? [])
|
|
384
402
|
.filter((m) => m.role === "user" || m.role === "assistant")
|
|
385
403
|
.map((m) => ({
|
|
@@ -393,6 +411,10 @@ export function useChat(pid: string, onError?: (msg: string) => void): UseChatRe
|
|
|
393
411
|
setConversationId(undefined);
|
|
394
412
|
setMsgs(loaded);
|
|
395
413
|
} catch (e) {
|
|
414
|
+
if (seq !== loadSeqRef.current) return;
|
|
415
|
+
convoRef.current = undefined;
|
|
416
|
+
setConversationId(undefined);
|
|
417
|
+
setMsgs([]);
|
|
396
418
|
onError?.((e as Error)?.message || t("shared_ui.err_load_conversation"));
|
|
397
419
|
}
|
|
398
420
|
},
|
|
@@ -65,8 +65,11 @@ export function ChatTab({ pid }: { pid: string }) {
|
|
|
65
65
|
} else if (selected.kind === "thread") {
|
|
66
66
|
void loadThread(selected.channel, selected.threadId);
|
|
67
67
|
} else {
|
|
68
|
-
//
|
|
69
|
-
if (conversationId)
|
|
68
|
+
// Live session selected → always start from a clean slate. (Threads leave
|
|
69
|
+
// conversationId undefined, so an `if (conversationId)` guard would skip
|
|
70
|
+
// clearing and the previous chat's messages would linger under the new
|
|
71
|
+
// header — the "title changes but content stays" bug.)
|
|
72
|
+
clear();
|
|
70
73
|
}
|
|
71
74
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
72
75
|
}, [
|