@nextclaw/agent-chat-ui 0.2.7 → 0.2.9

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
@@ -146,11 +146,8 @@ type ChatToolPartViewModel = {
146
146
  statusTone: "running" | "success" | "error" | "cancelled";
147
147
  statusLabel: string;
148
148
  titleLabel: string;
149
- inputLabel: string;
150
149
  outputLabel: string;
151
150
  emptyLabel: string;
152
- callIdLabel: string;
153
- callId?: string;
154
151
  };
155
152
  type ChatMessagePartViewModel = {
156
153
  type: "markdown";
package/dist/index.js CHANGED
@@ -2186,39 +2186,323 @@ function ChatMessageMarkdown(props) {
2186
2186
  return /* @__PURE__ */ jsx14("div", { className: cn("chat-markdown", isUser ? "chat-markdown-user" : "chat-markdown-assistant"), children: /* @__PURE__ */ jsx14(ReactMarkdown, { skipHtml: true, remarkPlugins: [remarkGfm], components: markdownComponents, children: trimMarkdown(props.text) }) });
2187
2187
  }
2188
2188
 
2189
- // src/components/chat/ui/chat-message-list/chat-message-file.tsx
2189
+ // src/components/chat/ui/chat-message-list/chat-message-file/meta.ts
2190
+ var FILE_CATEGORY_LABELS = {
2191
+ archive: "Archive",
2192
+ audio: "Audio",
2193
+ code: "Code",
2194
+ data: "Data",
2195
+ document: "Document",
2196
+ generic: "File",
2197
+ image: "Image",
2198
+ pdf: "PDF",
2199
+ sheet: "Sheet",
2200
+ video: "Video"
2201
+ };
2202
+ var FILE_CATEGORY_TILE_CLASSES = {
2203
+ archive: "border-amber-200/80 bg-amber-100 text-amber-700",
2204
+ audio: "border-fuchsia-200/80 bg-fuchsia-100 text-fuchsia-700",
2205
+ code: "border-cyan-200/80 bg-cyan-100 text-cyan-700",
2206
+ data: "border-slate-200/80 bg-slate-100 text-slate-700",
2207
+ document: "border-blue-200/80 bg-blue-100 text-blue-700",
2208
+ generic: "border-slate-200/80 bg-slate-100 text-slate-700",
2209
+ image: "border-emerald-200/80 bg-emerald-100 text-emerald-700",
2210
+ pdf: "border-rose-200/80 bg-rose-100 text-rose-700",
2211
+ sheet: "border-lime-200/80 bg-lime-100 text-lime-700",
2212
+ video: "border-violet-200/80 bg-violet-100 text-violet-700"
2213
+ };
2214
+ var CODE_EXTENSIONS = /* @__PURE__ */ new Set([
2215
+ "c",
2216
+ "cpp",
2217
+ "css",
2218
+ "go",
2219
+ "html",
2220
+ "java",
2221
+ "js",
2222
+ "jsx",
2223
+ "md",
2224
+ "php",
2225
+ "py",
2226
+ "rb",
2227
+ "rs",
2228
+ "sh",
2229
+ "sql",
2230
+ "svg",
2231
+ "ts",
2232
+ "tsx"
2233
+ ]);
2234
+ var DATA_EXTENSIONS = /* @__PURE__ */ new Set([
2235
+ "graphql",
2236
+ "json",
2237
+ "toml",
2238
+ "xml",
2239
+ "yaml",
2240
+ "yml"
2241
+ ]);
2242
+ var DOCUMENT_EXTENSIONS = /* @__PURE__ */ new Set([
2243
+ "doc",
2244
+ "docx",
2245
+ "odt",
2246
+ "pages",
2247
+ "rtf",
2248
+ "txt"
2249
+ ]);
2250
+ var SHEET_EXTENSIONS = /* @__PURE__ */ new Set([
2251
+ "csv",
2252
+ "numbers",
2253
+ "ods",
2254
+ "tsv",
2255
+ "xls",
2256
+ "xlsx"
2257
+ ]);
2258
+ var ARCHIVE_EXTENSIONS = /* @__PURE__ */ new Set([
2259
+ "7z",
2260
+ "bz2",
2261
+ "gz",
2262
+ "rar",
2263
+ "tar",
2264
+ "tgz",
2265
+ "zip"
2266
+ ]);
2267
+ function formatFileSize(sizeBytes) {
2268
+ if (!Number.isFinite(sizeBytes) || sizeBytes == null || sizeBytes < 0) {
2269
+ return null;
2270
+ }
2271
+ if (sizeBytes === 0) {
2272
+ return "0 B";
2273
+ }
2274
+ const units = ["B", "KB", "MB", "GB", "TB"];
2275
+ let value = sizeBytes;
2276
+ let unitIndex = 0;
2277
+ while (value >= 1024 && unitIndex < units.length - 1) {
2278
+ value /= 1024;
2279
+ unitIndex += 1;
2280
+ }
2281
+ const digits = value >= 10 || unitIndex === 0 ? 0 : 1;
2282
+ return `${value.toFixed(digits).replace(/\.0$/, "")} ${units[unitIndex]}`;
2283
+ }
2284
+ function getFileExtension(label, mimeType) {
2285
+ const match = /\.([a-z0-9]{1,12})$/i.exec(label.trim());
2286
+ if (match?.[1]) {
2287
+ return match[1].toUpperCase();
2288
+ }
2289
+ const subtype = mimeType.split("/")[1] ?? "";
2290
+ const cleaned = subtype.split(/[+.;-]/)[0]?.trim();
2291
+ if (!cleaned) {
2292
+ return "FILE";
2293
+ }
2294
+ return cleaned.slice(0, 6).toUpperCase();
2295
+ }
2296
+ function resolveFileCategory(label, mimeType) {
2297
+ const extension = /\.([a-z0-9]{1,12})$/i.exec(label.trim())?.[1]?.toLowerCase() ?? "";
2298
+ const normalizedMimeType = mimeType.toLowerCase();
2299
+ if (normalizedMimeType.startsWith("image/")) {
2300
+ return "image";
2301
+ }
2302
+ if (normalizedMimeType.startsWith("audio/")) {
2303
+ return "audio";
2304
+ }
2305
+ if (normalizedMimeType.startsWith("video/")) {
2306
+ return "video";
2307
+ }
2308
+ if (normalizedMimeType.includes("pdf") || extension === "pdf") {
2309
+ return "pdf";
2310
+ }
2311
+ if (ARCHIVE_EXTENSIONS.has(extension) || /(zip|tar|gzip|rar|compressed|archive)/.test(normalizedMimeType)) {
2312
+ return "archive";
2313
+ }
2314
+ if (SHEET_EXTENSIONS.has(extension) || /(spreadsheet|sheet|excel|csv)/.test(normalizedMimeType)) {
2315
+ return "sheet";
2316
+ }
2317
+ if (DATA_EXTENSIONS.has(extension) || /(json|xml|yaml|toml)/.test(normalizedMimeType)) {
2318
+ return "data";
2319
+ }
2320
+ if (CODE_EXTENSIONS.has(extension) || /(javascript|typescript|jsx|tsx|css|html)/.test(normalizedMimeType)) {
2321
+ return "code";
2322
+ }
2323
+ if (DOCUMENT_EXTENSIONS.has(extension) || /(msword|document|opendocument|rtf|text\/)/.test(normalizedMimeType)) {
2324
+ return "document";
2325
+ }
2326
+ return "generic";
2327
+ }
2328
+ function buildChatMessageFileMeta(file) {
2329
+ const category = resolveFileCategory(file.label, file.mimeType);
2330
+ const sizeLabel = formatFileSize(file.sizeBytes);
2331
+ return {
2332
+ category,
2333
+ extension: getFileExtension(file.label, file.mimeType),
2334
+ sizeLabel,
2335
+ metaBadges: [FILE_CATEGORY_LABELS[category], sizeLabel].filter(
2336
+ (value) => Boolean(value)
2337
+ )
2338
+ };
2339
+ }
2340
+
2341
+ // src/components/chat/ui/chat-message-list/chat-message-file/index.tsx
2190
2342
  import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
2191
- function ChatMessageFile({ file }) {
2343
+ function renderMetaBadge(label, isUser) {
2344
+ return /* @__PURE__ */ jsx15(
2345
+ "span",
2346
+ {
2347
+ className: cn(
2348
+ "inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium",
2349
+ isUser ? "border-white/12 bg-white/10 text-white/82" : "border-slate-200/80 bg-slate-950/[0.04] text-slate-600"
2350
+ ),
2351
+ children: label
2352
+ },
2353
+ label
2354
+ );
2355
+ }
2356
+ function renderMimeType(mimeType, isUser) {
2357
+ return /* @__PURE__ */ jsx15(
2358
+ "div",
2359
+ {
2360
+ className: cn(
2361
+ "truncate text-[11px]",
2362
+ isUser ? "text-white/58" : "text-slate-500"
2363
+ ),
2364
+ children: mimeType
2365
+ }
2366
+ );
2367
+ }
2368
+ function renderActionPill(label, isUser, isInteractive) {
2369
+ return /* @__PURE__ */ jsx15(
2370
+ "span",
2371
+ {
2372
+ className: cn(
2373
+ "inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium",
2374
+ isInteractive ? isUser ? "border-white/14 bg-white/12 text-white" : "border-slate-200/80 bg-white text-slate-700" : isUser ? "border-white/10 bg-white/6 text-white/62" : "border-slate-200/70 bg-slate-100/80 text-slate-500"
2375
+ ),
2376
+ children: label
2377
+ }
2378
+ );
2379
+ }
2380
+ function ChatMessageFile({
2381
+ file,
2382
+ isUser = false
2383
+ }) {
2384
+ const { category, extension, metaBadges, sizeLabel } = buildChatMessageFileMeta(file);
2385
+ const isInteractive = Boolean(file.dataUrl);
2386
+ const actionLabel = isInteractive ? file.isImage ? "Open preview" : "Open file" : "Attached";
2387
+ const tileLabel = extension.slice(0, 4);
2388
+ const shellClasses = cn(
2389
+ "block overflow-hidden rounded-[1.25rem] border transition duration-200",
2390
+ isUser ? "border-white/12 bg-white/10 text-white shadow-[0_18px_40px_-28px_rgba(15,23,42,0.85)]" : "border-slate-200/80 bg-white/95 text-slate-900 shadow-[0_20px_45px_-30px_rgba(15,23,42,0.28)]",
2391
+ isInteractive && (isUser ? "hover:border-white/18 hover:bg-white/13" : "hover:border-slate-300 hover:bg-white hover:shadow-[0_24px_50px_-30px_rgba(15,23,42,0.3)]")
2392
+ );
2192
2393
  if (file.isImage && file.dataUrl) {
2193
2394
  return /* @__PURE__ */ jsx15(
2194
- "img",
2195
- {
2196
- src: file.dataUrl,
2197
- alt: file.label,
2198
- className: "block max-h-80 max-w-full rounded-2xl object-contain"
2199
- }
2200
- );
2201
- }
2202
- if (file.dataUrl) {
2203
- return /* @__PURE__ */ jsxs8(
2204
2395
  "a",
2205
2396
  {
2206
2397
  href: file.dataUrl,
2207
- download: file.label,
2208
2398
  target: "_blank",
2209
2399
  rel: "noreferrer",
2210
- className: "block rounded-2xl border border-black/8 bg-black/6 px-3 py-2 text-sm transition hover:bg-black/8",
2211
- children: [
2212
- /* @__PURE__ */ jsx15("div", { className: "font-medium", children: file.label }),
2213
- /* @__PURE__ */ jsx15("div", { className: "text-xs opacity-75", children: file.mimeType })
2214
- ]
2400
+ "aria-label": `Open preview: ${file.label}`,
2401
+ className: cn(shellClasses, "group"),
2402
+ children: /* @__PURE__ */ jsxs8("figure", { children: [
2403
+ /* @__PURE__ */ jsxs8(
2404
+ "div",
2405
+ {
2406
+ className: cn(
2407
+ "relative overflow-hidden p-2",
2408
+ isUser ? "bg-white/[0.04]" : "bg-gradient-to-br from-slate-100 via-white to-slate-100"
2409
+ ),
2410
+ children: [
2411
+ /* @__PURE__ */ jsx15(
2412
+ "img",
2413
+ {
2414
+ src: file.dataUrl,
2415
+ alt: file.label,
2416
+ className: "block max-h-[22rem] w-full rounded-[1rem] object-cover shadow-[0_18px_40px_-26px_rgba(15,23,42,0.55)] transition duration-300 group-hover:scale-[1.01]"
2417
+ }
2418
+ ),
2419
+ /* @__PURE__ */ jsxs8("div", { className: "pointer-events-none absolute inset-x-4 top-4 flex items-center justify-between", children: [
2420
+ sizeLabel ? renderMetaBadge(sizeLabel, isUser) : /* @__PURE__ */ jsx15("span", {}),
2421
+ /* @__PURE__ */ jsx15(
2422
+ "span",
2423
+ {
2424
+ className: cn(
2425
+ "inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-semibold tracking-[0.22em]",
2426
+ isUser ? "border-white/12 bg-slate-950/20 text-white" : FILE_CATEGORY_TILE_CLASSES[category]
2427
+ ),
2428
+ children: tileLabel
2429
+ }
2430
+ )
2431
+ ] })
2432
+ ]
2433
+ }
2434
+ ),
2435
+ /* @__PURE__ */ jsxs8("figcaption", { className: "flex items-start gap-3 p-4", children: [
2436
+ /* @__PURE__ */ jsx15(
2437
+ "div",
2438
+ {
2439
+ className: cn(
2440
+ "flex h-11 w-11 shrink-0 items-center justify-center rounded-[1rem] border text-[11px] font-semibold tracking-[0.22em]",
2441
+ isUser ? "border-white/12 bg-white/10 text-white" : FILE_CATEGORY_TILE_CLASSES[category]
2442
+ ),
2443
+ children: tileLabel
2444
+ }
2445
+ ),
2446
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0 flex-1", children: [
2447
+ /* @__PURE__ */ jsx15("div", { className: "truncate text-sm font-semibold leading-5", children: file.label }),
2448
+ /* @__PURE__ */ jsx15("div", { className: "mt-2 flex flex-wrap gap-2", children: metaBadges.map((label) => renderMetaBadge(label, isUser)) }),
2449
+ /* @__PURE__ */ jsx15("div", { className: "mt-2", children: renderMimeType(file.mimeType, isUser) })
2450
+ ] }),
2451
+ renderActionPill(actionLabel, isUser, true)
2452
+ ] })
2453
+ ] })
2215
2454
  }
2216
2455
  );
2217
2456
  }
2218
- return /* @__PURE__ */ jsxs8("div", { className: "rounded-2xl border border-black/8 bg-black/6 px-3 py-2 text-sm", children: [
2219
- /* @__PURE__ */ jsx15("div", { className: "font-medium", children: file.label }),
2220
- /* @__PURE__ */ jsx15("div", { className: "text-xs opacity-75", children: file.mimeType })
2457
+ const content = /* @__PURE__ */ jsxs8("div", { className: "flex items-start gap-3 p-3.5", children: [
2458
+ /* @__PURE__ */ jsx15(
2459
+ "div",
2460
+ {
2461
+ className: cn(
2462
+ "flex h-14 w-14 shrink-0 items-center justify-center rounded-[1rem] border text-xs font-semibold tracking-[0.22em]",
2463
+ isUser ? "border-white/12 bg-white/10 text-white" : FILE_CATEGORY_TILE_CLASSES[category]
2464
+ ),
2465
+ children: tileLabel
2466
+ }
2467
+ ),
2468
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0 flex-1", children: [
2469
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-start gap-3", children: [
2470
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0 flex-1", children: [
2471
+ /* @__PURE__ */ jsx15("div", { className: "truncate text-sm font-semibold leading-5", children: file.label }),
2472
+ /* @__PURE__ */ jsxs8(
2473
+ "div",
2474
+ {
2475
+ className: cn(
2476
+ "mt-1 text-xs",
2477
+ isUser ? "text-white/68" : "text-slate-500"
2478
+ ),
2479
+ children: [
2480
+ FILE_CATEGORY_LABELS[category],
2481
+ " attachment"
2482
+ ]
2483
+ }
2484
+ )
2485
+ ] }),
2486
+ renderActionPill(actionLabel, isUser, isInteractive)
2487
+ ] }),
2488
+ /* @__PURE__ */ jsx15("div", { className: "mt-3 flex flex-wrap gap-2", children: metaBadges.map((label) => renderMetaBadge(label, isUser)) }),
2489
+ /* @__PURE__ */ jsx15("div", { className: "mt-2", children: renderMimeType(file.mimeType, isUser) })
2490
+ ] })
2221
2491
  ] });
2492
+ if (!isInteractive) {
2493
+ return /* @__PURE__ */ jsx15("div", { className: shellClasses, children: content });
2494
+ }
2495
+ return /* @__PURE__ */ jsx15(
2496
+ "a",
2497
+ {
2498
+ href: file.dataUrl,
2499
+ target: "_blank",
2500
+ rel: "noreferrer",
2501
+ "aria-label": `Open file: ${file.label}`,
2502
+ className: cn(shellClasses, "group"),
2503
+ children: content
2504
+ }
2505
+ );
2222
2506
  }
2223
2507
 
2224
2508
  // src/components/chat/ui/chat-message-list/chat-reasoning-block.tsx
@@ -2243,7 +2527,6 @@ function ChatReasoningBlock(props) {
2243
2527
  import { AlertCircle, CheckCircle2, CircleSlash, Clock3, FileSearch, Globe, Loader2, Search as Search2, SendHorizontal, Terminal, Wrench as Wrench2 } from "lucide-react";
2244
2528
  import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
2245
2529
  var TOOL_OUTPUT_PREVIEW_MAX = 220;
2246
- var TOOL_CALL_ID_PREVIEW_MAX = 18;
2247
2530
  var STATUS_STYLES = {
2248
2531
  running: {
2249
2532
  text: "text-amber-700/80"
@@ -2280,14 +2563,6 @@ function renderToolIcon(toolName) {
2280
2563
  }
2281
2564
  return /* @__PURE__ */ jsx17(Wrench2, { className: "h-3.5 w-3.5" });
2282
2565
  }
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
2566
  function renderStatusMeta(card) {
2292
2567
  const style = STATUS_STYLES[card.statusTone];
2293
2568
  if (card.statusTone === "running") {
@@ -2307,7 +2582,6 @@ function ChatToolCard({ card }) {
2307
2582
  const showDetails = output.length > TOOL_OUTPUT_PREVIEW_MAX || output.includes("\n");
2308
2583
  const preview = showDetails ? `${output.slice(0, TOOL_OUTPUT_PREVIEW_MAX)}...` : output;
2309
2584
  const showOutputSection = card.kind === "result" || card.hasResult;
2310
- const statusStyle = STATUS_STYLES[card.statusTone];
2311
2585
  return /* @__PURE__ */ jsxs10("div", { className: "rounded-xl border border-amber-200/80 bg-amber-50/60 px-3 py-2.5", children: [
2312
2586
  /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center gap-2 text-xs font-semibold text-amber-800", children: [
2313
2587
  renderToolIcon(card.toolName),
@@ -2315,15 +2589,7 @@ function ChatToolCard({ card }) {
2315
2589
  /* @__PURE__ */ jsx17("span", { className: "font-mono text-[11px] text-amber-900/80", children: card.toolName }),
2316
2590
  renderStatusMeta(card)
2317
2591
  ] }),
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,
2592
+ card.summary ? /* @__PURE__ */ jsx17("div", { className: "mt-1 break-words font-mono text-[11px] text-amber-800/90", children: card.summary }) : null,
2327
2593
  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: [
2328
2594
  /* @__PURE__ */ jsx17("summary", { className: "cursor-pointer text-[11px] text-amber-700", children: card.outputLabel }),
2329
2595
  /* @__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 })
@@ -2359,19 +2625,50 @@ function ChatMessage(props) {
2359
2625
  ),
2360
2626
  children: /* @__PURE__ */ jsx19("div", { className: "space-y-2", children: message.parts.map((part, index) => {
2361
2627
  if (part.type === "markdown") {
2362
- return /* @__PURE__ */ jsx19(ChatMessageMarkdown, { text: part.text, role, texts }, `markdown-${index}`);
2628
+ return /* @__PURE__ */ jsx19(
2629
+ ChatMessageMarkdown,
2630
+ {
2631
+ text: part.text,
2632
+ role,
2633
+ texts
2634
+ },
2635
+ `markdown-${index}`
2636
+ );
2363
2637
  }
2364
2638
  if (part.type === "reasoning") {
2365
- return /* @__PURE__ */ jsx19(ChatReasoningBlock, { label: part.label, text: part.text, isUser }, `reasoning-${index}`);
2639
+ return /* @__PURE__ */ jsx19(
2640
+ ChatReasoningBlock,
2641
+ {
2642
+ label: part.label,
2643
+ text: part.text,
2644
+ isUser
2645
+ },
2646
+ `reasoning-${index}`
2647
+ );
2366
2648
  }
2367
2649
  if (part.type === "tool-card") {
2368
2650
  return /* @__PURE__ */ jsx19("div", { className: "mt-0.5", children: /* @__PURE__ */ jsx19(ChatToolCard, { card: part.card }) }, `tool-${index}`);
2369
2651
  }
2370
2652
  if (part.type === "file") {
2371
- return /* @__PURE__ */ jsx19(ChatMessageFile, { file: part.file }, `file-${index}`);
2653
+ return /* @__PURE__ */ jsx19(
2654
+ ChatMessageFile,
2655
+ {
2656
+ file: part.file,
2657
+ isUser
2658
+ },
2659
+ `file-${index}`
2660
+ );
2372
2661
  }
2373
2662
  if (part.type === "unknown") {
2374
- return /* @__PURE__ */ jsx19(ChatUnknownPart, { label: part.label, rawType: part.rawType, text: part.text }, `unknown-${index}`);
2663
+ return /* @__PURE__ */ jsx19(
2664
+ ChatUnknownPart,
2665
+ {
2666
+ label: part.label,
2667
+ rawType: part.rawType,
2668
+ text: part.text
2669
+ },
2670
+ `unknown-${index}`
2671
+ );
2375
2672
  }
2376
2673
  return null;
2377
2674
  }) })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/agent-chat-ui",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "private": false,
5
5
  "description": "Reusable Nextclaw agent chat UI primitives and default skin.",
6
6
  "type": "module",