@yumiai/chat-widget 0.1.0 → 0.1.1
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/CHANGELOG.md +8 -0
- package/README.md +187 -0
- package/dist/index.cjs +48 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +49 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -139,6 +139,8 @@ interface Round {
|
|
|
139
139
|
plan?: TaskPlan;
|
|
140
140
|
messages: AggregatedMessage[];
|
|
141
141
|
topPosition?: number;
|
|
142
|
+
/** 本轮次内已收到 agent_end 的 agent_instance_id 集合,与 notification_turns 的 agent start/stop 对齐,用于子 Agent 卡片「已完成」判断 */
|
|
143
|
+
endedAgentInstanceIds?: Set<number>;
|
|
142
144
|
}
|
|
143
145
|
type ExecutionStatus = 'idle' | 'running' | 'compressing' | 'completed' | 'error';
|
|
144
146
|
interface ChatWidgetConfig {
|
|
@@ -273,6 +275,8 @@ interface ChildAgentCardProps {
|
|
|
273
275
|
config?: ChatWidgetConfig;
|
|
274
276
|
defaultExpanded?: boolean;
|
|
275
277
|
parentTaskPurpose?: string;
|
|
278
|
+
/** 本轮次已收到 agent_end 的 agent_instance_id(与 notification_turns 对齐),有则优先据此显示「已完成」 */
|
|
279
|
+
endedAgentInstanceIds?: Set<number>;
|
|
276
280
|
}
|
|
277
281
|
interface PlanCardProps {
|
|
278
282
|
plan: TaskPlan;
|
|
@@ -331,6 +335,8 @@ declare function useSSE(options: UseSSEOptions): UseSSEReturn;
|
|
|
331
335
|
interface MessageAggregatorState {
|
|
332
336
|
rounds: Map<string, Round>;
|
|
333
337
|
currentInteractionId: string | null;
|
|
338
|
+
/** 每轮次已收到 agent_end 的 agent_instance_id,与 notification_turns 的 turn_type=agent_end 对齐 */
|
|
339
|
+
endedAgentInstanceIdsByRound: Map<string, Set<number>>;
|
|
334
340
|
}
|
|
335
341
|
interface UseMessageAggregatorReturn {
|
|
336
342
|
state: MessageAggregatorState;
|
package/dist/index.d.ts
CHANGED
|
@@ -139,6 +139,8 @@ interface Round {
|
|
|
139
139
|
plan?: TaskPlan;
|
|
140
140
|
messages: AggregatedMessage[];
|
|
141
141
|
topPosition?: number;
|
|
142
|
+
/** 本轮次内已收到 agent_end 的 agent_instance_id 集合,与 notification_turns 的 agent start/stop 对齐,用于子 Agent 卡片「已完成」判断 */
|
|
143
|
+
endedAgentInstanceIds?: Set<number>;
|
|
142
144
|
}
|
|
143
145
|
type ExecutionStatus = 'idle' | 'running' | 'compressing' | 'completed' | 'error';
|
|
144
146
|
interface ChatWidgetConfig {
|
|
@@ -273,6 +275,8 @@ interface ChildAgentCardProps {
|
|
|
273
275
|
config?: ChatWidgetConfig;
|
|
274
276
|
defaultExpanded?: boolean;
|
|
275
277
|
parentTaskPurpose?: string;
|
|
278
|
+
/** 本轮次已收到 agent_end 的 agent_instance_id(与 notification_turns 对齐),有则优先据此显示「已完成」 */
|
|
279
|
+
endedAgentInstanceIds?: Set<number>;
|
|
276
280
|
}
|
|
277
281
|
interface PlanCardProps {
|
|
278
282
|
plan: TaskPlan;
|
|
@@ -331,6 +335,8 @@ declare function useSSE(options: UseSSEOptions): UseSSEReturn;
|
|
|
331
335
|
interface MessageAggregatorState {
|
|
332
336
|
rounds: Map<string, Round>;
|
|
333
337
|
currentInteractionId: string | null;
|
|
338
|
+
/** 每轮次已收到 agent_end 的 agent_instance_id,与 notification_turns 的 turn_type=agent_end 对齐 */
|
|
339
|
+
endedAgentInstanceIdsByRound: Map<string, Set<number>>;
|
|
334
340
|
}
|
|
335
341
|
interface UseMessageAggregatorReturn {
|
|
336
342
|
state: MessageAggregatorState;
|
package/dist/index.js
CHANGED
|
@@ -55,7 +55,8 @@ function extractTaskPurposeFromPreview(preview) {
|
|
|
55
55
|
function useMessageAggregator() {
|
|
56
56
|
const [state, setState] = useState({
|
|
57
57
|
rounds: /* @__PURE__ */ new Map(),
|
|
58
|
-
currentInteractionId: null
|
|
58
|
+
currentInteractionId: null,
|
|
59
|
+
endedAgentInstanceIdsByRound: /* @__PURE__ */ new Map()
|
|
59
60
|
});
|
|
60
61
|
const [todoMap, setTodoMap] = useState(/* @__PURE__ */ new Map());
|
|
61
62
|
const todoMapRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -65,6 +66,7 @@ function useMessageAggregator() {
|
|
|
65
66
|
const roundIndexRef = useRef(/* @__PURE__ */ new Map());
|
|
66
67
|
const processedChunksRef = useRef(/* @__PURE__ */ new Set());
|
|
67
68
|
const callBatchToRoundRef = useRef(/* @__PURE__ */ new Map());
|
|
69
|
+
const endedAgentInstanceIdsByRoundRef = useRef(/* @__PURE__ */ new Map());
|
|
68
70
|
const parsePlan = useCallback((content) => {
|
|
69
71
|
try {
|
|
70
72
|
const parsed = JSON.parse(content);
|
|
@@ -206,6 +208,18 @@ function useMessageAggregator() {
|
|
|
206
208
|
} else if (!existingRoundForBatch) {
|
|
207
209
|
callBatchToRoundRef.current.set(call_batch_id, interaction_id);
|
|
208
210
|
}
|
|
211
|
+
if (msg.notification_type === "agent_end") {
|
|
212
|
+
const iid = interaction_id;
|
|
213
|
+
const aid = msg.agent_instance_id;
|
|
214
|
+
if (iid != null && aid != null) {
|
|
215
|
+
const prev = endedAgentInstanceIdsByRoundRef.current;
|
|
216
|
+
const set = new Set(prev.get(iid) || []);
|
|
217
|
+
set.add(aid);
|
|
218
|
+
endedAgentInstanceIdsByRoundRef.current = new Map(prev).set(iid, set);
|
|
219
|
+
}
|
|
220
|
+
latestInteractionId = interaction_id;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
209
223
|
let round = roundIndexRef.current.get(interaction_id);
|
|
210
224
|
if (!round) {
|
|
211
225
|
round = {
|
|
@@ -353,9 +367,14 @@ function useMessageAggregator() {
|
|
|
353
367
|
}
|
|
354
368
|
setState(() => {
|
|
355
369
|
const newRounds = new Map(roundIndexRef.current);
|
|
370
|
+
const endedByRound = endedAgentInstanceIdsByRoundRef.current;
|
|
371
|
+
const endedAgentInstanceIdsByRound = new Map(
|
|
372
|
+
[...endedByRound.entries()].map(([k, v]) => [k, new Set(v)])
|
|
373
|
+
);
|
|
356
374
|
return {
|
|
357
375
|
rounds: newRounds,
|
|
358
|
-
currentInteractionId: latestInteractionId
|
|
376
|
+
currentInteractionId: latestInteractionId,
|
|
377
|
+
endedAgentInstanceIdsByRound
|
|
359
378
|
};
|
|
360
379
|
});
|
|
361
380
|
if (todoMapChanged) {
|
|
@@ -370,8 +389,12 @@ function useMessageAggregator() {
|
|
|
370
389
|
}
|
|
371
390
|
}, [flushUpdates]);
|
|
372
391
|
const getRoundsList = useCallback(() => {
|
|
373
|
-
|
|
374
|
-
|
|
392
|
+
const endedByRound = state.endedAgentInstanceIdsByRound;
|
|
393
|
+
return Array.from(state.rounds.values()).map((r) => ({
|
|
394
|
+
...r,
|
|
395
|
+
endedAgentInstanceIds: endedByRound.get(r.interactionId) || /* @__PURE__ */ new Set()
|
|
396
|
+
})).sort((a, b) => a.index - b.index);
|
|
397
|
+
}, [state.rounds, state.endedAgentInstanceIdsByRound]);
|
|
375
398
|
const getCurrentRound = useCallback(() => {
|
|
376
399
|
if (!state.currentInteractionId) return null;
|
|
377
400
|
return state.rounds.get(state.currentInteractionId) || null;
|
|
@@ -391,7 +414,8 @@ function useMessageAggregator() {
|
|
|
391
414
|
newRounds.set(interactionId, round);
|
|
392
415
|
return {
|
|
393
416
|
rounds: newRounds,
|
|
394
|
-
currentInteractionId: interactionId
|
|
417
|
+
currentInteractionId: interactionId,
|
|
418
|
+
endedAgentInstanceIdsByRound: prevState.endedAgentInstanceIdsByRound
|
|
395
419
|
};
|
|
396
420
|
});
|
|
397
421
|
}, []);
|
|
@@ -400,6 +424,7 @@ function useMessageAggregator() {
|
|
|
400
424
|
messageIndexRef.current.clear();
|
|
401
425
|
callBatchToRoundRef.current.clear();
|
|
402
426
|
processedChunksRef.current.clear();
|
|
427
|
+
endedAgentInstanceIdsByRoundRef.current.clear();
|
|
403
428
|
const newRounds = /* @__PURE__ */ new Map();
|
|
404
429
|
for (const round of rounds) {
|
|
405
430
|
newRounds.set(round.interactionId, round);
|
|
@@ -412,7 +437,7 @@ function useMessageAggregator() {
|
|
|
412
437
|
}
|
|
413
438
|
}
|
|
414
439
|
const lastId = rounds.length > 0 ? rounds[rounds.length - 1].interactionId : null;
|
|
415
|
-
setState({ rounds: newRounds, currentInteractionId: lastId });
|
|
440
|
+
setState({ rounds: newRounds, currentInteractionId: lastId, endedAgentInstanceIdsByRound: /* @__PURE__ */ new Map() });
|
|
416
441
|
}, []);
|
|
417
442
|
const finalizeRound = useCallback((interactionId) => {
|
|
418
443
|
const round = roundIndexRef.current.get(interactionId);
|
|
@@ -428,9 +453,11 @@ function useMessageAggregator() {
|
|
|
428
453
|
}
|
|
429
454
|
}
|
|
430
455
|
if (changed) {
|
|
456
|
+
const endedByRound = endedAgentInstanceIdsByRoundRef.current;
|
|
431
457
|
setState(() => ({
|
|
432
458
|
rounds: new Map(roundIndexRef.current),
|
|
433
|
-
currentInteractionId: interactionId
|
|
459
|
+
currentInteractionId: interactionId,
|
|
460
|
+
endedAgentInstanceIdsByRound: new Map([...endedByRound.entries()].map(([k, v]) => [k, new Set(v)]))
|
|
434
461
|
}));
|
|
435
462
|
}
|
|
436
463
|
}, []);
|
|
@@ -440,6 +467,7 @@ function useMessageAggregator() {
|
|
|
440
467
|
roundIndexRef.current.clear();
|
|
441
468
|
processedChunksRef.current.clear();
|
|
442
469
|
callBatchToRoundRef.current.clear();
|
|
470
|
+
endedAgentInstanceIdsByRoundRef.current.clear();
|
|
443
471
|
todoMapRef.current.clear();
|
|
444
472
|
if (rafId.current) {
|
|
445
473
|
cancelAnimationFrame(rafId.current);
|
|
@@ -447,7 +475,8 @@ function useMessageAggregator() {
|
|
|
447
475
|
}
|
|
448
476
|
setState({
|
|
449
477
|
rounds: /* @__PURE__ */ new Map(),
|
|
450
|
-
currentInteractionId: null
|
|
478
|
+
currentInteractionId: null,
|
|
479
|
+
endedAgentInstanceIdsByRound: /* @__PURE__ */ new Map()
|
|
451
480
|
});
|
|
452
481
|
setTodoMap(/* @__PURE__ */ new Map());
|
|
453
482
|
}, []);
|
|
@@ -2219,7 +2248,7 @@ var ArtifactCard = ({ artifact, onClick }) => {
|
|
|
2219
2248
|
var MessageContent_default = MessageContent;
|
|
2220
2249
|
|
|
2221
2250
|
// src/components/ChildAgentCard.tsx
|
|
2222
|
-
import { useState as useState10, useRef as useRef5, useEffect as useEffect3 } from "react";
|
|
2251
|
+
import { useState as useState10, useRef as useRef5, useEffect as useEffect3, useMemo as useMemo4 } from "react";
|
|
2223
2252
|
import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2224
2253
|
var ChildAgentCard = ({
|
|
2225
2254
|
message,
|
|
@@ -2228,14 +2257,20 @@ var ChildAgentCard = ({
|
|
|
2228
2257
|
config,
|
|
2229
2258
|
onArtifactClick,
|
|
2230
2259
|
defaultExpanded = false,
|
|
2231
|
-
parentTaskPurpose
|
|
2260
|
+
parentTaskPurpose,
|
|
2261
|
+
endedAgentInstanceIds
|
|
2232
2262
|
}) => {
|
|
2233
2263
|
const [isExpanded, setIsExpanded] = useState10(defaultExpanded);
|
|
2234
2264
|
const contentRef = useRef5(null);
|
|
2235
|
-
const
|
|
2265
|
+
const allMessages = useMemo4(() => [message, ...children], [message, children]);
|
|
2266
|
+
const hasExplicitEnd = endedAgentInstanceIds != null && endedAgentInstanceIds.has(message.agentInstanceId);
|
|
2267
|
+
const hasActiveContent = allMessages.some(
|
|
2236
2268
|
(m) => m.contentType === "text" && m.contentChunks.join("").trim()
|
|
2237
2269
|
);
|
|
2238
|
-
const
|
|
2270
|
+
const hasInProgressTool = allMessages.some(
|
|
2271
|
+
(m) => m.toolPhase === "generating" || m.toolPhase === "executing"
|
|
2272
|
+
);
|
|
2273
|
+
const status = hasExplicitEnd ? "completed" : hasActiveContent && !hasInProgressTool ? "completed" : "running";
|
|
2239
2274
|
useEffect3(() => {
|
|
2240
2275
|
if (isExpanded && contentRef.current) {
|
|
2241
2276
|
contentRef.current.scrollTop = contentRef.current.scrollHeight;
|
|
@@ -2711,7 +2746,8 @@ var ChatWidget = ({
|
|
|
2711
2746
|
config,
|
|
2712
2747
|
onArtifactClick: handleArtifactClick,
|
|
2713
2748
|
defaultExpanded: true,
|
|
2714
|
-
parentTaskPurpose: msg.taskPurpose
|
|
2749
|
+
parentTaskPurpose: msg.taskPurpose,
|
|
2750
|
+
endedAgentInstanceIds: round.endedAgentInstanceIds
|
|
2715
2751
|
},
|
|
2716
2752
|
`child-${childKey}-${agentInstanceId}`
|
|
2717
2753
|
)
|