@nextclaw/ui 0.5.45 → 0.5.46

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.
Files changed (28) hide show
  1. package/.eslintrc.cjs +9 -1
  2. package/CHANGELOG.md +6 -0
  3. package/dist/assets/{ChannelsList-CGlQJOKR.js → ChannelsList-C5IzoBSZ.js} +1 -1
  4. package/dist/assets/{ChatPage-DNQw6cPm.js → ChatPage-BEBmDqtw.js} +16 -16
  5. package/dist/assets/{CronConfig-CZE4jEWp.js → CronConfig-BdLVPoNw.js} +1 -1
  6. package/dist/assets/{DocBrowser-BCqnlevu.js → DocBrowser-DzsZUzgQ.js} +1 -1
  7. package/dist/assets/{MarketplacePage-_bRwL8Je.js → MarketplacePage-DmDTJ27k.js} +1 -1
  8. package/dist/assets/{ModelConfig-DHLdWlPT.js → ModelConfig-DQ1d3Dtn.js} +1 -1
  9. package/dist/assets/{ProvidersList-BS-3jQfk.js → ProvidersList-snuzM5CK.js} +1 -1
  10. package/dist/assets/{RuntimeConfig-C0kVY3Y0.js → RuntimeConfig-BSDP51k6.js} +1 -1
  11. package/dist/assets/{SecretsConfig-CBpnJpdi.js → SecretsConfig-DlNYyu9I.js} +1 -1
  12. package/dist/assets/{SessionsConfig-FmbzF3JO.js → SessionsConfig-Dt9heKTD.js} +1 -1
  13. package/dist/assets/{card-D79QtyfR.js → card-KmfXQ4Bm.js} +1 -1
  14. package/dist/assets/chat-message-pw9oafI4.js +5 -0
  15. package/dist/assets/{index-nfl5TEOq.js → index-BhpPLO5K.js} +2 -2
  16. package/dist/assets/{label-C0lAPrBs.js → label-iF47BkaM.js} +1 -1
  17. package/dist/assets/{logos-DdLfIYd-.js → logos-C8Yako2a.js} +1 -1
  18. package/dist/assets/{page-layout-BuP_1ihv.js → page-layout-sZk-HtoA.js} +1 -1
  19. package/dist/assets/{switch-Dmt2u3GV.js → switch-BnYsX3uS.js} +1 -1
  20. package/dist/assets/{tabs-custom-s1WUaOad.js → tabs-custom-BEBNjTRA.js} +1 -1
  21. package/dist/assets/{useConfig-BGr-ekoe.js → useConfig-DJ_KEVx0.js} +1 -1
  22. package/dist/assets/{useConfirmDialog-D_YoV8_w.js → useConfirmDialog-BwqRK1uy.js} +1 -1
  23. package/dist/index.html +1 -1
  24. package/package.json +1 -1
  25. package/src/components/chat/ChatPage.tsx +7 -2
  26. package/src/components/chat/ChatThread.tsx +23 -16
  27. package/src/lib/chat-message.ts +89 -65
  28. package/dist/assets/chat-message-D0s61C4e.js +0 -5
@@ -19,19 +19,28 @@ export type ChatTimelineMessageItem = {
19
19
  message: SessionMessageView;
20
20
  };
21
21
 
22
- export type ChatTimelineAssistantFlowItem = {
23
- kind: 'assistant_flow';
22
+ export type ChatTimelineAssistantTurnSegment =
23
+ | {
24
+ kind: 'assistant_message';
25
+ key: string;
26
+ text: string;
27
+ reasoning: string;
28
+ }
29
+ | {
30
+ kind: 'tool_card';
31
+ key: string;
32
+ card: ToolCard;
33
+ };
34
+
35
+ export type ChatTimelineAssistantTurnItem = {
36
+ kind: 'assistant_turn';
24
37
  key: string;
25
38
  role: 'assistant';
26
39
  timestamp: string;
27
- primaryText: string;
28
- primaryReasoning: string;
29
- followupText: string;
30
- followupReasoning: string;
31
- toolCards: ToolCard[];
40
+ segments: ChatTimelineAssistantTurnSegment[];
32
41
  };
33
42
 
34
- export type ChatTimelineItem = ChatTimelineMessageItem | ChatTimelineAssistantFlowItem;
43
+ export type ChatTimelineItem = ChatTimelineMessageItem | ChatTimelineAssistantTurnItem;
35
44
 
36
45
  const TOOL_DETAIL_FIELDS = ['cmd', 'command', 'query', 'q', 'path', 'url', 'to', 'channel', 'agentId', 'sessionKey'];
37
46
 
@@ -263,17 +272,54 @@ export function buildChatTimeline(events: SessionEventView[]): ChatTimelineItem[
263
272
  });
264
273
 
265
274
  const timeline: ChatTimelineItem[] = [];
266
- let activeFlow:
275
+ let activeTurn:
267
276
  | {
268
- item: ChatTimelineAssistantFlowItem;
277
+ item: ChatTimelineAssistantTurnItem;
269
278
  cardByCallId: Map<string, ToolCard>;
270
- pendingCallIds: Set<string>;
271
- awaitingFollowup: boolean;
272
279
  }
273
280
  | null = null;
274
281
 
275
- const closeActiveFlow = () => {
276
- activeFlow = null;
282
+ const closeActiveTurn = () => {
283
+ activeTurn = null;
284
+ };
285
+
286
+ const ensureActiveTurn = (eventKey: string, timestamp: string) => {
287
+ if (activeTurn) {
288
+ activeTurn.item.timestamp = timestamp;
289
+ return activeTurn;
290
+ }
291
+ const item: ChatTimelineAssistantTurnItem = {
292
+ kind: 'assistant_turn',
293
+ key: `turn-${eventKey}`,
294
+ role: 'assistant',
295
+ timestamp,
296
+ segments: []
297
+ };
298
+ timeline.push(item);
299
+ activeTurn = {
300
+ item,
301
+ cardByCallId: new Map<string, ToolCard>()
302
+ };
303
+ return activeTurn;
304
+ };
305
+
306
+ const pushAssistantMessageSegment = (
307
+ target: { item: ChatTimelineAssistantTurnItem },
308
+ eventKey: string,
309
+ message: SessionMessageView
310
+ ) => {
311
+ const text = extractMessageText(message.content).trim();
312
+ const reasoning =
313
+ typeof message.reasoning_content === 'string' ? message.reasoning_content.trim() : '';
314
+ if (!text && !reasoning) {
315
+ return;
316
+ }
317
+ target.item.segments.push({
318
+ kind: 'assistant_message',
319
+ key: `assistant-${eventKey}-${target.item.segments.length}`,
320
+ text,
321
+ reasoning
322
+ });
277
323
  };
278
324
 
279
325
  for (const event of normalized) {
@@ -287,80 +333,58 @@ export function buildChatTimeline(events: SessionEventView[]): ChatTimelineItem[
287
333
  typeof message.timestamp === 'string' && message.timestamp
288
334
  ? message.timestamp
289
335
  : event.timestamp;
336
+ const eventKey = `${event._seq}-${event._idx}`;
337
+
338
+ if (role === 'assistant') {
339
+ const turn = ensureActiveTurn(eventKey, timestamp);
340
+ pushAssistantMessageSegment(turn, eventKey, message);
341
+ if (!hasToolCalls(message)) {
342
+ continue;
343
+ }
290
344
 
291
- if (role === 'assistant' && hasToolCalls(message)) {
292
- closeActiveFlow();
293
345
  const toolCards = buildToolCallCards(message);
294
- const item: ChatTimelineAssistantFlowItem = {
295
- kind: 'assistant_flow',
296
- key: `flow-${event._seq}-${event._idx}`,
297
- role: 'assistant',
298
- timestamp,
299
- primaryText: extractMessageText(message.content).trim(),
300
- primaryReasoning:
301
- typeof message.reasoning_content === 'string' ? message.reasoning_content.trim() : '',
302
- followupText: '',
303
- followupReasoning: '',
304
- toolCards
305
- };
306
-
307
- const cardByCallId = new Map<string, ToolCard>();
308
- const pendingCallIds = new Set<string>();
309
346
  for (const card of toolCards) {
347
+ turn.item.segments.push({
348
+ kind: 'tool_card',
349
+ key: `tool-call-${eventKey}-${turn.item.segments.length}`,
350
+ card
351
+ });
310
352
  if (typeof card.callId === 'string' && card.callId.trim()) {
311
- cardByCallId.set(card.callId, card);
312
- pendingCallIds.add(card.callId);
353
+ turn.cardByCallId.set(card.callId, card);
313
354
  }
314
355
  }
315
-
316
- timeline.push(item);
317
- activeFlow = {
318
- item,
319
- cardByCallId,
320
- pendingCallIds,
321
- awaitingFollowup: pendingCallIds.size === 0
322
- };
323
356
  continue;
324
357
  }
325
358
 
326
359
  if (role === 'tool') {
360
+ const turn = ensureActiveTurn(eventKey, timestamp);
327
361
  const callId =
328
362
  typeof message.tool_call_id === 'string' && message.tool_call_id.trim()
329
363
  ? message.tool_call_id.trim()
330
364
  : undefined;
331
- if (activeFlow && callId && activeFlow.cardByCallId.has(callId)) {
332
- const card = activeFlow.cardByCallId.get(callId)!;
365
+ if (callId && turn.cardByCallId.has(callId)) {
366
+ const card = turn.cardByCallId.get(callId)!;
333
367
  const resultText = extractMessageText(message.content).trim();
334
368
  card.text = appendText(card.text ?? '', resultText);
335
369
  card.hasResult = true;
336
370
  if (typeof message.name === 'string' && message.name.trim()) {
337
371
  card.name = message.name.trim();
338
372
  }
339
- activeFlow.pendingCallIds.delete(callId);
340
- activeFlow.awaitingFollowup = activeFlow.pendingCallIds.size === 0;
341
- activeFlow.item.timestamp = timestamp;
373
+ turn.item.timestamp = timestamp;
342
374
  continue;
343
375
  }
344
376
 
345
- timeline.push({
346
- kind: 'message',
347
- key: `message-${event._seq}-${event._idx}`,
348
- role,
349
- timestamp,
350
- message
377
+ turn.item.segments.push({
378
+ kind: 'tool_card',
379
+ key: `tool-result-${eventKey}-${turn.item.segments.length}`,
380
+ card: {
381
+ kind: 'result',
382
+ name: toToolName(message.name),
383
+ text: extractMessageText(message.content).trim(),
384
+ callId,
385
+ hasResult: true
386
+ }
351
387
  });
352
- closeActiveFlow();
353
- continue;
354
- }
355
-
356
- if (role === 'assistant' && activeFlow && activeFlow.awaitingFollowup && !hasToolCalls(message)) {
357
- const text = extractMessageText(message.content).trim();
358
- const reasoning =
359
- typeof message.reasoning_content === 'string' ? message.reasoning_content.trim() : '';
360
- activeFlow.item.followupText = appendText(activeFlow.item.followupText, text);
361
- activeFlow.item.followupReasoning = appendText(activeFlow.item.followupReasoning, reasoning);
362
- activeFlow.item.timestamp = timestamp;
363
- closeActiveFlow();
364
388
  continue;
365
389
  }
366
390
 
@@ -371,7 +395,7 @@ export function buildChatTimeline(events: SessionEventView[]): ChatTimelineItem[
371
395
  timestamp,
372
396
  message
373
397
  });
374
- closeActiveFlow();
398
+ closeActiveTurn();
375
399
  }
376
400
 
377
401
  return timeline;
@@ -1,5 +0,0 @@
1
- const q=["cmd","command","query","q","path","url","to","channel","agentId","sessionKey"];function m(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function _(t,n=2400){return t.length<=n?t:`${t.slice(0,n)}
2
- …`}function h(t){if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);if(t==null)return"";try{return _(JSON.stringify(t,null,2))}catch{return String(t)}}function A(t){if(m(t))return t;if(typeof t!="string")return null;const n=t.trim();if(!n.startsWith("{")&&!n.startsWith("["))return null;try{const r=JSON.parse(n);return m(r)?r:null}catch{return null}}function C(t){const n=A(t);if(!n){const o=h(t).trim();return o?_(o,120):void 0}const r=[];for(const o of q){const e=n[o];if(typeof e=="string"&&e.trim()?r.push(`${o}: ${e.trim()}`):(typeof e=="number"||typeof e=="boolean")&&r.push(`${o}: ${String(e)}`),r.length>=2)break}return r.length>0?r.join(" · "):_(h(n),140)}function T(t){return typeof t!="string"||!t.trim()?"tool":t.trim()}function w(t){return Array.isArray(t.tool_calls)&&t.tool_calls.length>0}function x(t){const n=t.role.toLowerCase().trim();return n==="user"?"user":n==="assistant"?"assistant":n==="system"?"system":n==="tool"||n==="tool_result"||n==="toolresult"||n==="function"||typeof t.tool_call_id=="string"||Array.isArray(t.tool_calls)||typeof t.name=="string"?"tool":"other"}function d(t){if(typeof t=="string")return t;if(Array.isArray(t)){const n=[];for(const r of t){if(typeof r=="string"){n.push(r);continue}if(m(r)){if(typeof r.text=="string"){n.push(r.text);continue}typeof r.content=="string"&&n.push(r.content)}}if(n.length>0)return n.join(`
3
- `)}return h(t)}function I(t){const n=[],r=Array.isArray(t.tool_calls)?t.tool_calls:[];for(const o of r){if(!m(o))continue;const e=m(o.function)?o.function:null,s=T((e==null?void 0:e.name)??o.name),i=(e==null?void 0:e.arguments)??o.arguments;n.push({kind:"call",name:s,detail:C(i),callId:typeof o.id=="string"&&o.id.trim()?o.id:void 0,hasResult:!1})}return n}function F(t){var o;const n=I(t);return(x(t)==="tool"||typeof t.tool_call_id=="string")&&n.push({kind:"result",name:T(t.name??((o=n[0])==null?void 0:o.name)),text:d(t.content).trim(),callId:typeof t.tool_call_id=="string"?t.tool_call_id:void 0,hasResult:!0}),n}function $(t,n){var e;const r=Number.isFinite(t.seq)&&t.seq>0?Math.trunc(t.seq):n+1,o=typeof t.timestamp=="string"&&t.timestamp?t.timestamp:((e=t.message)==null?void 0:e.timestamp)??new Date().toISOString();return{...t,timestamp:o,_idx:n,_seq:r}}function b(t){const n=x(t);return n==="assistant"&&w(t)?"assistant.tool_call":n==="tool"?"tool.result":`message.${n}`}function k(t){return t.map((n,r)=>({seq:r+1,type:b(n),timestamp:n.timestamp,message:n}))}function g(t,n){return n?t?`${t}
4
-
5
- ${n}`:n:t}function R(t){const n=t.map((s,i)=>$(s,i)).sort((s,i)=>{if(s._seq!==i._seq)return s._seq-i._seq;const l=Date.parse(s.timestamp),a=Date.parse(i.timestamp);return Number.isFinite(l)&&Number.isFinite(a)&&l!==a?l-a:s._idx-i._idx}),r=[];let o=null;const e=()=>{o=null};for(const s of n){const i=s.message;if(!i)continue;const l=x(i),a=typeof i.timestamp=="string"&&i.timestamp?i.timestamp:s.timestamp;if(l==="assistant"&&w(i)){e();const c=I(i),u={kind:"assistant_flow",key:`flow-${s._seq}-${s._idx}`,role:"assistant",timestamp:a,primaryText:d(i.content).trim(),primaryReasoning:typeof i.reasoning_content=="string"?i.reasoning_content.trim():"",followupText:"",followupReasoning:"",toolCards:c},p=new Map,y=new Set;for(const f of c)typeof f.callId=="string"&&f.callId.trim()&&(p.set(f.callId,f),y.add(f.callId));r.push(u),o={item:u,cardByCallId:p,pendingCallIds:y,awaitingFollowup:y.size===0};continue}if(l==="tool"){const c=typeof i.tool_call_id=="string"&&i.tool_call_id.trim()?i.tool_call_id.trim():void 0;if(o&&c&&o.cardByCallId.has(c)){const u=o.cardByCallId.get(c),p=d(i.content).trim();u.text=g(u.text??"",p),u.hasResult=!0,typeof i.name=="string"&&i.name.trim()&&(u.name=i.name.trim()),o.pendingCallIds.delete(c),o.awaitingFollowup=o.pendingCallIds.size===0,o.item.timestamp=a;continue}r.push({kind:"message",key:`message-${s._seq}-${s._idx}`,role:l,timestamp:a,message:i}),e();continue}if(l==="assistant"&&o&&o.awaitingFollowup&&!w(i)){const c=d(i.content).trim(),u=typeof i.reasoning_content=="string"?i.reasoning_content.trim():"";o.item.followupText=g(o.item.followupText,c),o.item.followupReasoning=g(o.item.followupReasoning,u),o.item.timestamp=a,e();continue}r.push({kind:"message",key:`message-${s._seq}-${s._idx}`,role:l,timestamp:a,message:i}),e()}return r}export{F as a,R as b,k as c,d as e,x as n};