@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.
- package/.eslintrc.cjs +9 -1
- package/CHANGELOG.md +6 -0
- package/dist/assets/{ChannelsList-CGlQJOKR.js → ChannelsList-C5IzoBSZ.js} +1 -1
- package/dist/assets/{ChatPage-DNQw6cPm.js → ChatPage-BEBmDqtw.js} +16 -16
- package/dist/assets/{CronConfig-CZE4jEWp.js → CronConfig-BdLVPoNw.js} +1 -1
- package/dist/assets/{DocBrowser-BCqnlevu.js → DocBrowser-DzsZUzgQ.js} +1 -1
- package/dist/assets/{MarketplacePage-_bRwL8Je.js → MarketplacePage-DmDTJ27k.js} +1 -1
- package/dist/assets/{ModelConfig-DHLdWlPT.js → ModelConfig-DQ1d3Dtn.js} +1 -1
- package/dist/assets/{ProvidersList-BS-3jQfk.js → ProvidersList-snuzM5CK.js} +1 -1
- package/dist/assets/{RuntimeConfig-C0kVY3Y0.js → RuntimeConfig-BSDP51k6.js} +1 -1
- package/dist/assets/{SecretsConfig-CBpnJpdi.js → SecretsConfig-DlNYyu9I.js} +1 -1
- package/dist/assets/{SessionsConfig-FmbzF3JO.js → SessionsConfig-Dt9heKTD.js} +1 -1
- package/dist/assets/{card-D79QtyfR.js → card-KmfXQ4Bm.js} +1 -1
- package/dist/assets/chat-message-pw9oafI4.js +5 -0
- package/dist/assets/{index-nfl5TEOq.js → index-BhpPLO5K.js} +2 -2
- package/dist/assets/{label-C0lAPrBs.js → label-iF47BkaM.js} +1 -1
- package/dist/assets/{logos-DdLfIYd-.js → logos-C8Yako2a.js} +1 -1
- package/dist/assets/{page-layout-BuP_1ihv.js → page-layout-sZk-HtoA.js} +1 -1
- package/dist/assets/{switch-Dmt2u3GV.js → switch-BnYsX3uS.js} +1 -1
- package/dist/assets/{tabs-custom-s1WUaOad.js → tabs-custom-BEBNjTRA.js} +1 -1
- package/dist/assets/{useConfig-BGr-ekoe.js → useConfig-DJ_KEVx0.js} +1 -1
- package/dist/assets/{useConfirmDialog-D_YoV8_w.js → useConfirmDialog-BwqRK1uy.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/components/chat/ChatPage.tsx +7 -2
- package/src/components/chat/ChatThread.tsx +23 -16
- package/src/lib/chat-message.ts +89 -65
- package/dist/assets/chat-message-D0s61C4e.js +0 -5
package/src/lib/chat-message.ts
CHANGED
|
@@ -19,19 +19,28 @@ export type ChatTimelineMessageItem = {
|
|
|
19
19
|
message: SessionMessageView;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
export type
|
|
23
|
-
|
|
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
|
-
|
|
28
|
-
primaryReasoning: string;
|
|
29
|
-
followupText: string;
|
|
30
|
-
followupReasoning: string;
|
|
31
|
-
toolCards: ToolCard[];
|
|
40
|
+
segments: ChatTimelineAssistantTurnSegment[];
|
|
32
41
|
};
|
|
33
42
|
|
|
34
|
-
export type ChatTimelineItem = ChatTimelineMessageItem |
|
|
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
|
|
275
|
+
let activeTurn:
|
|
267
276
|
| {
|
|
268
|
-
item:
|
|
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
|
|
276
|
-
|
|
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 (
|
|
332
|
-
const card =
|
|
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
|
-
|
|
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
|
-
|
|
346
|
-
kind: '
|
|
347
|
-
key: `
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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
|
-
|
|
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};
|