@nextclaw/agent-chat-ui 0.2.5 → 0.2.7

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/dist/index.d.ts CHANGED
@@ -23,15 +23,15 @@ type ChatSelectedItem = {
23
23
  key: string;
24
24
  label: string;
25
25
  };
26
- type ChatComposerTokenKind = 'skill' | 'file';
26
+ type ChatComposerTokenKind = "skill" | "file";
27
27
  type ChatComposerTextNode = {
28
28
  id: string;
29
- type: 'text';
29
+ type: "text";
30
30
  text: string;
31
31
  };
32
32
  type ChatComposerTokenNode = {
33
33
  id: string;
34
- type: 'token';
34
+ type: "token";
35
35
  tokenKind: ChatComposerTokenKind;
36
36
  tokenKey: string;
37
37
  label: string;
@@ -41,8 +41,8 @@ type ChatComposerSelection = {
41
41
  start: number;
42
42
  end: number;
43
43
  };
44
- type ChatToolbarIcon = 'sparkles' | 'brain';
45
- type ChatToolbarAccessoryIcon = ChatToolbarIcon | 'paperclip';
44
+ type ChatToolbarIcon = "sparkles" | "brain";
45
+ type ChatToolbarAccessoryIcon = ChatToolbarIcon | "paperclip";
46
46
  type ChatToolbarSelectOption = {
47
47
  value: string;
48
48
  label: string;
@@ -106,7 +106,7 @@ type ChatInputBarToolbarProps = {
106
106
  actions: ChatInputBarActionsProps;
107
107
  };
108
108
  type ChatInlineHint = {
109
- tone: 'neutral' | 'warning';
109
+ tone: "neutral" | "warning";
110
110
  loading?: boolean;
111
111
  text?: string;
112
112
  actionLabel?: string;
@@ -118,7 +118,7 @@ type ChatSlashMenuProps = {
118
118
  items: ChatSlashItem[];
119
119
  activeIndex: number;
120
120
  activeItem: ChatSlashItem | null;
121
- texts: Pick<ChatTexts, 'slashLoadingLabel' | 'slashSectionLabel' | 'slashEmptyLabel' | 'slashHintLabel' | 'slashSkillHintLabel'>;
121
+ texts: Pick<ChatTexts, "slashLoadingLabel" | "slashSectionLabel" | "slashEmptyLabel" | "slashHintLabel" | "slashSkillHintLabel">;
122
122
  onSelectItem: (item: ChatSlashItem) => void;
123
123
  onOpenChange: (open: boolean) => void;
124
124
  onSetActiveIndex: (index: number) => void;
@@ -132,41 +132,47 @@ type ChatInputBarProps = {
132
132
  onFilesAdd?: (files: File[]) => Promise<void> | void;
133
133
  onSlashQueryChange?: (query: string | null) => void;
134
134
  };
135
- slashMenu: Pick<ChatSlashMenuProps, 'isLoading' | 'items' | 'texts'>;
135
+ slashMenu: Pick<ChatSlashMenuProps, "isLoading" | "items" | "texts">;
136
136
  hint?: ChatInlineHint | null;
137
137
  toolbar: ChatInputBarToolbarProps;
138
138
  };
139
- type ChatMessageRole = 'user' | 'assistant' | 'tool' | 'system' | 'message';
139
+ type ChatMessageRole = "user" | "assistant" | "tool" | "system" | "message";
140
140
  type ChatToolPartViewModel = {
141
- kind: 'call' | 'result';
141
+ kind: "call" | "result";
142
142
  toolName: string;
143
143
  summary?: string;
144
144
  output?: string;
145
145
  hasResult: boolean;
146
+ statusTone: "running" | "success" | "error" | "cancelled";
147
+ statusLabel: string;
146
148
  titleLabel: string;
149
+ inputLabel: string;
147
150
  outputLabel: string;
148
151
  emptyLabel: string;
152
+ callIdLabel: string;
153
+ callId?: string;
149
154
  };
150
155
  type ChatMessagePartViewModel = {
151
- type: 'markdown';
156
+ type: "markdown";
152
157
  text: string;
153
158
  } | {
154
- type: 'reasoning';
159
+ type: "reasoning";
155
160
  text: string;
156
161
  label: string;
157
162
  } | {
158
- type: 'tool-card';
163
+ type: "tool-card";
159
164
  card: ChatToolPartViewModel;
160
165
  } | {
161
- type: 'file';
166
+ type: "file";
162
167
  file: {
163
168
  label: string;
164
169
  mimeType: string;
165
170
  dataUrl?: string;
171
+ sizeBytes?: number;
166
172
  isImage: boolean;
167
173
  };
168
174
  } | {
169
- type: 'unknown';
175
+ type: "unknown";
170
176
  label: string;
171
177
  rawType: string;
172
178
  text?: string;
package/dist/index.js CHANGED
@@ -2240,9 +2240,24 @@ function ChatReasoningBlock(props) {
2240
2240
  }
2241
2241
 
2242
2242
  // src/components/chat/ui/chat-message-list/chat-tool-card.tsx
2243
- import { Clock3, FileSearch, Globe, Search as Search2, SendHorizontal, Terminal, Wrench as Wrench2 } from "lucide-react";
2243
+ import { AlertCircle, CheckCircle2, CircleSlash, Clock3, FileSearch, Globe, Loader2, Search as Search2, SendHorizontal, Terminal, Wrench as Wrench2 } from "lucide-react";
2244
2244
  import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
2245
2245
  var TOOL_OUTPUT_PREVIEW_MAX = 220;
2246
+ var TOOL_CALL_ID_PREVIEW_MAX = 18;
2247
+ var STATUS_STYLES = {
2248
+ running: {
2249
+ text: "text-amber-700/80"
2250
+ },
2251
+ success: {
2252
+ text: "text-amber-700/80"
2253
+ },
2254
+ error: {
2255
+ text: "text-amber-700/80"
2256
+ },
2257
+ cancelled: {
2258
+ text: "text-amber-700/80"
2259
+ }
2260
+ };
2246
2261
  function renderToolIcon(toolName) {
2247
2262
  const lowered = toolName.toLowerCase();
2248
2263
  if (lowered.includes("exec") || lowered.includes("shell") || lowered.includes("command")) {
@@ -2265,18 +2280,50 @@ function renderToolIcon(toolName) {
2265
2280
  }
2266
2281
  return /* @__PURE__ */ jsx17(Wrench2, { className: "h-3.5 w-3.5" });
2267
2282
  }
2283
+ function truncateMiddle(value, maxLength = TOOL_CALL_ID_PREVIEW_MAX) {
2284
+ if (value.length <= maxLength) {
2285
+ return value;
2286
+ }
2287
+ const head = Math.ceil((maxLength - 1) / 2);
2288
+ const tail = Math.floor((maxLength - 1) / 2);
2289
+ return `${value.slice(0, head)}\u2026${value.slice(value.length - tail)}`;
2290
+ }
2291
+ function renderStatusMeta(card) {
2292
+ const style = STATUS_STYLES[card.statusTone];
2293
+ if (card.statusTone === "running") {
2294
+ return /* @__PURE__ */ jsxs10("span", { className: cn("inline-flex items-center gap-1 text-[11px] font-medium leading-none", style.text), children: [
2295
+ /* @__PURE__ */ jsx17(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
2296
+ card.statusLabel
2297
+ ] });
2298
+ }
2299
+ const icon = card.statusTone === "success" ? /* @__PURE__ */ jsx17(CheckCircle2, { className: "h-3.5 w-3.5" }) : card.statusTone === "error" ? /* @__PURE__ */ jsx17(AlertCircle, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx17(CircleSlash, { className: "h-3.5 w-3.5" });
2300
+ return /* @__PURE__ */ jsxs10("span", { className: cn("inline-flex items-center gap-1 text-[11px] font-medium leading-none", style.text), children: [
2301
+ icon,
2302
+ card.statusTone === "success" ? null : card.statusLabel
2303
+ ] });
2304
+ }
2268
2305
  function ChatToolCard({ card }) {
2269
2306
  const output = card.output?.trim() ?? "";
2270
2307
  const showDetails = output.length > TOOL_OUTPUT_PREVIEW_MAX || output.includes("\n");
2271
2308
  const preview = showDetails ? `${output.slice(0, TOOL_OUTPUT_PREVIEW_MAX)}...` : output;
2272
2309
  const showOutputSection = card.kind === "result" || card.hasResult;
2310
+ const statusStyle = STATUS_STYLES[card.statusTone];
2273
2311
  return /* @__PURE__ */ jsxs10("div", { className: "rounded-xl border border-amber-200/80 bg-amber-50/60 px-3 py-2.5", children: [
2274
2312
  /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center gap-2 text-xs font-semibold text-amber-800", children: [
2275
2313
  renderToolIcon(card.toolName),
2276
2314
  /* @__PURE__ */ jsx17("span", { children: card.titleLabel }),
2277
- /* @__PURE__ */ jsx17("span", { className: "font-mono text-[11px] text-amber-900/80", children: card.toolName })
2315
+ /* @__PURE__ */ jsx17("span", { className: "font-mono text-[11px] text-amber-900/80", children: card.toolName }),
2316
+ renderStatusMeta(card)
2278
2317
  ] }),
2279
- card.summary ? /* @__PURE__ */ jsx17("div", { className: "mt-1 break-words font-mono text-[11px] text-amber-800/90", children: card.summary }) : null,
2318
+ card.summary ? /* @__PURE__ */ jsxs10("div", { className: "mt-1", children: [
2319
+ /* @__PURE__ */ jsx17("div", { className: "text-[10px] text-amber-700/75", children: card.inputLabel }),
2320
+ /* @__PURE__ */ jsx17("div", { className: "break-words font-mono text-[11px] text-amber-800/90", children: card.summary })
2321
+ ] }) : null,
2322
+ card.callId ? /* @__PURE__ */ jsxs10("div", { className: cn("mt-1 text-[10px]", statusStyle.text), children: [
2323
+ /* @__PURE__ */ jsx17("span", { children: card.callIdLabel }),
2324
+ /* @__PURE__ */ jsx17("span", { children: ": " }),
2325
+ /* @__PURE__ */ jsx17("span", { className: "font-mono", children: truncateMiddle(card.callId) })
2326
+ ] }) : null,
2280
2327
  showOutputSection ? /* @__PURE__ */ jsx17("div", { className: "mt-2", children: !output ? /* @__PURE__ */ jsx17("div", { className: "text-[11px] text-amber-700/80", children: card.emptyLabel }) : showDetails ? /* @__PURE__ */ jsxs10("details", { className: "group", children: [
2281
2328
  /* @__PURE__ */ jsx17("summary", { className: "cursor-pointer text-[11px] text-amber-700", children: card.outputLabel }),
2282
2329
  /* @__PURE__ */ jsx17("pre", { className: "mt-2 whitespace-pre-wrap break-words rounded-lg border border-amber-200 bg-amber-100/40 p-2 text-[11px] text-amber-900", children: output })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/agent-chat-ui",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "private": false,
5
5
  "description": "Reusable Nextclaw agent chat UI primitives and default skin.",
6
6
  "type": "module",