@nextclaw/ui 0.5.24 → 0.5.26

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 (32) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/assets/{ChannelsList-CAuBEcOr.js → ChannelsList-D0Wk08Ki.js} +1 -1
  3. package/dist/assets/ChatPage-Deg2lBH4.js +32 -0
  4. package/dist/assets/{CronConfig-jOEPCnpf.js → CronConfig-D-3Y8kWb.js} +1 -1
  5. package/dist/assets/{DocBrowser-wov_cBSN.js → DocBrowser-BSPKhqrK.js} +1 -1
  6. package/dist/assets/{MarketplacePage-Cob6DGoO.js → MarketplacePage-Dkm2FTtN.js} +1 -1
  7. package/dist/assets/{ModelConfig-C_Y3UDYr.js → ModelConfig-2cpAmvGq.js} +1 -1
  8. package/dist/assets/{ProvidersList-6A6N2eDT.js → ProvidersList-Dot21pAy.js} +1 -1
  9. package/dist/assets/{RuntimeConfig-B3k_dMdJ.js → RuntimeConfig-BNw_Ms_Y.js} +1 -1
  10. package/dist/assets/{SecretsConfig-BeCRCCEW.js → SecretsConfig-z8M3PDJP.js} +1 -1
  11. package/dist/assets/{SessionsConfig-M32Qm7cL.js → SessionsConfig-XVHZ-FG5.js} +1 -1
  12. package/dist/assets/{action-link-DsAjsb68.js → action-link-CpPJJN-z.js} +1 -1
  13. package/dist/assets/{card-uTj7-9XS.js → card-DsZ2Am92.js} +1 -1
  14. package/dist/assets/chat-message-Jxa8JFA_.js +9 -0
  15. package/dist/assets/{dialog-FRtXcCmk.js → dialog-BysNu5hM.js} +1 -1
  16. package/dist/assets/index-B_OeEGic.css +1 -0
  17. package/dist/assets/index-Bny21Br0.js +2 -0
  18. package/dist/assets/{label-DAhEgM6-.js → label-q6RASlER.js} +1 -1
  19. package/dist/assets/{page-layout-DMpNQawS.js → page-layout-WiVrFc8t.js} +1 -1
  20. package/dist/assets/{switch-D8lSFzq4.js → switch-DM_YYUgB.js} +1 -1
  21. package/dist/assets/{tabs-custom-CsFrOXUS.js → tabs-custom-mlgm-IGH.js} +1 -1
  22. package/dist/assets/{useConfig-Cjlx5C-1.js → useConfig-BOn-kp8G.js} +1 -1
  23. package/dist/assets/{useConfirmDialog-D3eI0Hfj.js → useConfirmDialog-DamaA60g.js} +1 -1
  24. package/dist/index.html +2 -2
  25. package/package.json +1 -1
  26. package/src/components/chat/ChatPage.tsx +147 -46
  27. package/src/lib/chat-message.ts +72 -3
  28. package/src/lib/i18n.ts +3 -0
  29. package/dist/assets/ChatPage-Bxs3X5OC.js +0 -32
  30. package/dist/assets/chat-message-DZV2Z5oc.js +0 -5
  31. package/dist/assets/index-BsDasSXm.css +0 -1
  32. package/dist/assets/index-Dw8Ss2WH.js +0 -2
@@ -100,6 +100,34 @@ function toToolName(value: unknown): string {
100
100
  return value.trim();
101
101
  }
102
102
 
103
+ function hasToolCalls(message: SessionMessageView): boolean {
104
+ return Array.isArray(message.tool_calls) && message.tool_calls.length > 0;
105
+ }
106
+
107
+ function mergeMessageContent(base: unknown, addition: unknown): unknown {
108
+ const left = extractMessageText(base).trim();
109
+ const right = extractMessageText(addition).trim();
110
+ if (!left) {
111
+ return right;
112
+ }
113
+ if (!right) {
114
+ return left;
115
+ }
116
+ return `${left}\n\n${right}`;
117
+ }
118
+
119
+ function mergeReasoningContent(base: unknown, addition: unknown): string | undefined {
120
+ const left = typeof base === 'string' ? base.trim() : '';
121
+ const right = typeof addition === 'string' ? addition.trim() : '';
122
+ if (!left) {
123
+ return right || undefined;
124
+ }
125
+ if (!right) {
126
+ return left;
127
+ }
128
+ return `${left}\n\n${right}`;
129
+ }
130
+
103
131
  export function normalizeChatRole(message: Pick<SessionMessageView, 'role' | 'name' | 'tool_call_id' | 'tool_calls'>): ChatRole {
104
132
  const role = message.role.toLowerCase().trim();
105
133
  if (role === 'user') {
@@ -225,11 +253,12 @@ export function combineToolCallAndResults(messages: SessionMessageView[]): Sessi
225
253
  const consumedCallIds = new Set<string>();
226
254
 
227
255
  for (const message of cloned) {
228
- if (normalizeChatRole(message) !== 'assistant' || !Array.isArray(message.tool_calls)) {
256
+ if (normalizeChatRole(message) !== 'assistant' || !hasToolCalls(message)) {
229
257
  continue;
230
258
  }
231
259
 
232
- message.tool_calls = message.tool_calls.map((call) => {
260
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
261
+ message.tool_calls = toolCalls.map((call) => {
233
262
  if (!isRecord(call) || typeof call.id !== 'string') {
234
263
  return call;
235
264
  }
@@ -247,7 +276,7 @@ export function combineToolCallAndResults(messages: SessionMessageView[]): Sessi
247
276
  }) as Array<Record<string, unknown>>;
248
277
  }
249
278
 
250
- return cloned.filter((message) => {
279
+ const mergedToolResults = cloned.filter((message) => {
251
280
  if (normalizeChatRole(message) !== 'tool') {
252
281
  return true;
253
282
  }
@@ -256,6 +285,46 @@ export function combineToolCallAndResults(messages: SessionMessageView[]): Sessi
256
285
  }
257
286
  return !consumedCallIds.has(message.tool_call_id.trim());
258
287
  });
288
+
289
+ const mergedFollowups: SessionMessageView[] = [];
290
+ for (let index = 0; index < mergedToolResults.length; index += 1) {
291
+ const current = mergedToolResults[index];
292
+ if (normalizeChatRole(current) !== 'assistant' || !hasToolCalls(current)) {
293
+ mergedFollowups.push(current);
294
+ continue;
295
+ }
296
+
297
+ let merged = current;
298
+ let cursor = index + 1;
299
+ while (cursor < mergedToolResults.length) {
300
+ const candidate = mergedToolResults[cursor];
301
+ if (normalizeChatRole(candidate) !== 'assistant') {
302
+ break;
303
+ }
304
+ if (hasToolCalls(candidate) || typeof candidate.tool_call_id === 'string') {
305
+ break;
306
+ }
307
+
308
+ const candidateText = extractMessageText(candidate.content).trim();
309
+ const candidateReasoning = typeof candidate.reasoning_content === 'string' && candidate.reasoning_content.trim();
310
+ if (!candidateText && !candidateReasoning) {
311
+ break;
312
+ }
313
+
314
+ merged = {
315
+ ...merged,
316
+ content: mergeMessageContent(merged.content, candidate.content),
317
+ reasoning_content: mergeReasoningContent(merged.reasoning_content, candidate.reasoning_content),
318
+ timestamp: candidate.timestamp
319
+ };
320
+ cursor += 1;
321
+ }
322
+
323
+ mergedFollowups.push(merged);
324
+ index = cursor - 1;
325
+ }
326
+
327
+ return mergedFollowups;
259
328
  }
260
329
 
261
330
  export function groupChatMessages(messages: SessionMessageView[]): GroupedChatMessage[] {
package/src/lib/i18n.ts CHANGED
@@ -422,6 +422,9 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
422
422
  chatInputHint: { zh: '支持多轮上下文,默认走当前会话。', en: 'Multi-turn context is preserved in the current session.' },
423
423
  chatSend: { zh: '发送', en: 'Send' },
424
424
  chatSending: { zh: '发送中...', en: 'Sending...' },
425
+ chatQueueSend: { zh: '排队发送', en: 'Queue' },
426
+ chatQueuedHintPrefix: { zh: '当前有', en: 'Queued' },
427
+ chatQueuedHintSuffix: { zh: '条消息待发送。', en: 'pending messages.' },
425
428
  chatDeleteSession: { zh: '删除会话', en: 'Delete Session' },
426
429
  chatDeleteSessionConfirm: { zh: '确认删除当前会话?', en: 'Delete the current session?' },
427
430
  chatSendFailed: { zh: '发送消息失败', en: 'Failed to send message' },