@ocai/app-sdk-ui 0.3.0 → 0.4.0

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.
@@ -1,5 +1,5 @@
1
1
  import { LucideIcon } from 'lucide-react';
2
- import { ReactElement } from 'react';
2
+ import { ReactElement, ReactNode } from 'react';
3
3
  import { AiActivity } from './activity-labels';
4
4
  import { TracePart } from './segments';
5
5
  export declare function humanizeToolName(type: string): string;
@@ -11,7 +11,8 @@ export type MessageTraceProps = {
11
11
  getToolLabel?: (type: string) => string | undefined;
12
12
  getToolIcon?: (type: string) => LucideIcon | undefined;
13
13
  getActivityOverride?: (runningToolType: string | undefined) => string | undefined;
14
+ renderStepDetail?: (part: TracePart) => ReactNode;
14
15
  defaultOpen?: boolean;
15
16
  className?: string;
16
17
  };
17
- export declare const MessageTrace: import('react').MemoExoticComponent<({ parts, isLoading, messageId, activity, getToolLabel, getToolIcon, getActivityOverride, defaultOpen, className, }: MessageTraceProps) => ReactElement>;
18
+ export declare const MessageTrace: import('react').MemoExoticComponent<({ parts, isLoading, messageId, activity, getToolLabel, getToolIcon, getActivityOverride, renderStepDetail, defaultOpen, className, }: MessageTraceProps) => ReactElement>;
@@ -4,6 +4,12 @@ export type SourceItem = {
4
4
  url: string;
5
5
  title?: string;
6
6
  };
7
+ export type SourceListProps = {
8
+ sources: readonly SourceItem[];
9
+ getFaviconUrl?: (url: string) => string | null;
10
+ className?: string;
11
+ };
12
+ export declare const SourceList: ({ sources, getFaviconUrl, className, }: SourceListProps) => ReactElement | null;
7
13
  export type SourcesProps = Omit<ComponentProps<typeof Collapsible>, "children"> & {
8
14
  sources: readonly SourceItem[];
9
15
  getLabel?: (count: number) => string;
package/dist/index.d.ts CHANGED
@@ -8,6 +8,6 @@ export { MessageTrace, humanizeToolName, type MessageTraceProps, } from './chat/
8
8
  export { buildSegments, traceIsLoading, type BuildSegmentsOptions, type MessageSegment, type TracePart, } from './chat/segments';
9
9
  export { getAiActivityLabel, getAiActivityLabelParts, labelSeedFromString, traceElapsedSeconds, type AiActivity, type AiActivityKind, type ActivityLabelParts, type GetAiActivityLabelArgs, } from './chat/activity-labels';
10
10
  export { useActivityClock } from './chat/use-activity-clock';
11
- export { Sources, citationClassName, type SourceItem, type SourcesProps, } from './chat/sources';
11
+ export { Sources, SourceList, citationClassName, type SourceItem, type SourcesProps, type SourceListProps, } from './chat/sources';
12
12
  export { extractWebSearchSources, isWebSearchError, stripCitationParens, type WebSearchErrorOutput, type WebSearchInput, type WebSearchOutput, type WebSearchResult, type WebSearchSuccessOutput, type WebSearchUIPart, type WebSearchUITool, } from './chat/web-search';
13
13
  export { WebSearchToggle, type WebSearchToggleProps, } from './chat/web-search-toggle';
package/dist/index.js CHANGED
@@ -6,19 +6,19 @@ import { twMerge as r } from "tailwind-merge";
6
6
  import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
7
7
  import { CheckIcon as s, ChevronDownIcon as c, CircleCheckIcon as l, ClockIcon as u, GlobeIcon as d, Loader2Icon as f, WrenchIcon as p, XIcon as m } from "lucide-react";
8
8
  import { createContext as h, isValidElement as g, memo as _, useContext as v, useEffect as y, useId as ee, useRef as b, useState as x } from "react";
9
- import { Collapsible as S, Slot as te, Tooltip as C } from "radix-ui";
10
- import { cva as w } from "class-variance-authority";
9
+ import { Collapsible as S, Slot as C, Tooltip as w } from "radix-ui";
10
+ import { cva as T } from "class-variance-authority";
11
11
  //#region src/lib/cn.ts
12
- function T(...e) {
12
+ function E(...e) {
13
13
  return r(n(e));
14
14
  }
15
15
  //#endregion
16
16
  //#region src/chat/response.tsx
17
- var E = e({ singleDollarTextMath: !0 });
17
+ var te = e({ singleDollarTextMath: !0 });
18
18
  function ne({ className: e, ...n }) {
19
19
  return /* @__PURE__ */ a(t, {
20
- className: T("ocui-md size-full text-base font-normal leading-6 [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 [&_code]:whitespace-pre-wrap [&_code]:wrap-break-word [&_pre]:max-w-full [&_pre]:overflow-x-auto", e),
21
- plugins: { math: E },
20
+ className: E("ocui-md size-full text-base font-normal leading-6 [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 [&_code]:whitespace-pre-wrap [&_code]:wrap-break-word [&_pre]:max-w-full [&_pre]:overflow-x-auto", e),
21
+ plugins: { math: te },
22
22
  controls: {
23
23
  table: !1,
24
24
  code: { download: !1 }
@@ -32,7 +32,7 @@ var D = {
32
32
  user: "w-fit wrap-break-word rounded-md bg-card px-3 py-1.5 text-primary",
33
33
  assistant: "bg-transparent px-0 py-0 text-left text-foreground"
34
34
  }, O = ({ children: e, className: t, variant: n = "user", ...r }) => /* @__PURE__ */ a("div", {
35
- className: T("flex flex-col gap-2 overflow-hidden text-base font-normal leading-6", D[n], t),
35
+ className: E("flex flex-col gap-2 overflow-hidden text-base font-normal leading-6", D[n], t),
36
36
  ...r,
37
37
  children: e
38
38
  });
@@ -94,7 +94,7 @@ var M = h(null), ie = () => {
94
94
  duration: n
95
95
  },
96
96
  children: /* @__PURE__ */ a(k, {
97
- className: T("not-prose", e),
97
+ className: E("not-prose", e),
98
98
  onOpenChange: u,
99
99
  open: l,
100
100
  ...c,
@@ -113,19 +113,19 @@ var P = _(({ className: e, children: t, variant: n = "reasoning", label: r, ...s
113
113
  duration: d
114
114
  });
115
115
  return /* @__PURE__ */ a(A, {
116
- className: T("flex items-center gap-1 rounded-md px-1.5 py-0.5 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", e),
116
+ className: E("flex items-center gap-1 rounded-md px-1.5 py-0.5 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", e),
117
117
  ...s,
118
118
  children: t ?? /* @__PURE__ */ o(i, { children: [
119
119
  n === "tools" && /* @__PURE__ */ a(p, { className: "size-3" }),
120
120
  /* @__PURE__ */ a("span", {
121
- className: T(l && "ocui-shimmer"),
121
+ className: E(l && "ocui-shimmer"),
122
122
  children: f
123
123
  }),
124
- /* @__PURE__ */ a(c, { className: T("size-2.5 transition-transform", u ? "rotate-180" : "rotate-0") })
124
+ /* @__PURE__ */ a(c, { className: E("size-2.5 transition-transform", u ? "rotate-180" : "rotate-0") })
125
125
  ] })
126
126
  });
127
127
  }), F = "grid gap-1 text-sm text-muted-foreground/80 **:text-sm [&_code]:bg-transparent [&_code]:p-0 [&_code]:font-semibold [&_code]:text-foreground [&_li]:my-0 [&_ol]:my-1 [&_p]:my-0 [&_ul]:my-1", I = _(({ className: e, ...t }) => /* @__PURE__ */ a(j, {
128
- className: T(F, "mt-1.5", e),
128
+ className: E(F, "mt-1.5", e),
129
129
  ...t
130
130
  }));
131
131
  N.displayName = "Reasoning", P.displayName = "ReasoningTrigger", I.displayName = "ReasoningContent";
@@ -199,7 +199,7 @@ var se = 8, L = 240, ce = 2e4, R = (e) => e === null || typeof e != "object" &&
199
199
  className: "text-xs",
200
200
  children: /* @__PURE__ */ a(W, { value: e })
201
201
  }) : /* @__PURE__ */ a(fe, { value: e }), pe = ({ className: e, ...t }) => /* @__PURE__ */ a(k, {
202
- className: T("not-prose w-full rounded-md border border-border", e),
202
+ className: E("not-prose w-full rounded-md border border-border", e),
203
203
  ...t
204
204
  }), me = {
205
205
  "input-streaming": "Pending",
@@ -221,7 +221,7 @@ var se = 8, L = 240, ce = 2e4, R = (e) => e === null || typeof e != "object" &&
221
221
  className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground",
222
222
  children: [he[e], me[e]]
223
223
  }), _e = ({ className: e, type: t, state: n, title: r, ...i }) => /* @__PURE__ */ o(A, {
224
- className: T("group flex w-full min-w-0 items-center justify-between gap-2 rounded-md p-2.5 transition-colors hover:bg-muted/50", e),
224
+ className: E("group flex w-full min-w-0 items-center justify-between gap-2 rounded-md p-2.5 transition-colors hover:bg-muted/50", e),
225
225
  ...i,
226
226
  children: [/* @__PURE__ */ o("div", {
227
227
  className: "flex min-w-0 flex-1 items-center gap-2",
@@ -234,17 +234,17 @@ var se = 8, L = 240, ce = 2e4, R = (e) => e === null || typeof e != "object" &&
234
234
  children: [/* @__PURE__ */ a(ge, { state: n }), /* @__PURE__ */ a(c, { className: "size-3.5 text-muted-foreground transition-transform group-data-[state=open]:rotate-180" })]
235
235
  })]
236
236
  }), ve = ({ className: e, ...t }) => /* @__PURE__ */ a(j, {
237
- className: T("data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-hidden data-[state=closed]:animate-out data-[state=open]:animate-in", e),
237
+ className: E("data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-hidden data-[state=closed]:animate-out data-[state=open]:animate-in", e),
238
238
  ...t
239
239
  }), ye = ({ className: e, input: t, ...n }) => V(t) ? /* @__PURE__ */ o("div", {
240
- className: T("space-y-1.5 overflow-hidden px-2.5 pb-2.5", e),
240
+ className: E("space-y-1.5 overflow-hidden px-2.5 pb-2.5", e),
241
241
  ...n,
242
242
  children: [/* @__PURE__ */ a("h4", {
243
243
  className: "text-xs font-medium tracking-wide text-muted-foreground uppercase",
244
244
  children: "Parameters"
245
245
  }), /* @__PURE__ */ a(G, { value: t })]
246
246
  }) : null, be = ({ className: e, output: t, errorText: n, ...r }) => V(t) || n ? /* @__PURE__ */ o("div", {
247
- className: T("space-y-1.5 px-2.5 pb-2.5", e),
247
+ className: E("space-y-1.5 px-2.5 pb-2.5", e),
248
248
  ...r,
249
249
  children: [/* @__PURE__ */ a("h4", {
250
250
  className: "text-xs font-medium tracking-wide text-muted-foreground uppercase",
@@ -256,7 +256,7 @@ var se = 8, L = 240, ce = 2e4, R = (e) => e === null || typeof e != "object" &&
256
256
  className: "text-xs [&_table]:w-full",
257
257
  children: /* @__PURE__ */ a(G, { value: t })
258
258
  })]
259
- }) : null, xe = w("group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
259
+ }) : null, xe = T("group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
260
260
  variants: {
261
261
  variant: {
262
262
  default: "bg-primary text-primary-foreground hover:bg-primary/90",
@@ -283,11 +283,11 @@ var se = 8, L = 240, ce = 2e4, R = (e) => e === null || typeof e != "object" &&
283
283
  }
284
284
  });
285
285
  function K({ className: e, variant: t = "default", size: n = "default", asChild: r = !1, ...i }) {
286
- return /* @__PURE__ */ a(r ? te.Root : "button", {
286
+ return /* @__PURE__ */ a(r ? C.Root : "button", {
287
287
  "data-slot": "button",
288
288
  "data-variant": t,
289
289
  "data-size": n,
290
- className: T(xe({
290
+ className: E(xe({
291
291
  variant: t,
292
292
  size: n,
293
293
  className: e
@@ -298,42 +298,42 @@ function K({ className: e, variant: t = "default", size: n = "default", asChild:
298
298
  //#endregion
299
299
  //#region src/internal/tooltip.tsx
300
300
  function q({ delayDuration: e = 0, ...t }) {
301
- return /* @__PURE__ */ a(C.Provider, {
301
+ return /* @__PURE__ */ a(w.Provider, {
302
302
  "data-slot": "tooltip-provider",
303
303
  delayDuration: e,
304
304
  ...t
305
305
  });
306
306
  }
307
307
  function J({ ...e }) {
308
- return /* @__PURE__ */ a(C.Root, {
308
+ return /* @__PURE__ */ a(w.Root, {
309
309
  "data-slot": "tooltip",
310
310
  ...e
311
311
  });
312
312
  }
313
313
  function Y({ ...e }) {
314
- return /* @__PURE__ */ a(C.Trigger, {
314
+ return /* @__PURE__ */ a(w.Trigger, {
315
315
  "data-slot": "tooltip-trigger",
316
316
  ...e
317
317
  });
318
318
  }
319
319
  function X({ className: e, sideOffset: t = 0, children: n, ...r }) {
320
- return /* @__PURE__ */ a(C.Portal, { children: /* @__PURE__ */ o(C.Content, {
320
+ return /* @__PURE__ */ a(w.Portal, { children: /* @__PURE__ */ o(w.Content, {
321
321
  "data-slot": "tooltip-content",
322
322
  sideOffset: t,
323
- className: T("z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md border border-border bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-[state=instant-open]:animate-in data-[state=instant-open]:fade-in-0 data-[state=instant-open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", e),
323
+ className: E("z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md border border-border bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-[state=instant-open]:animate-in data-[state=instant-open]:fade-in-0 data-[state=instant-open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", e),
324
324
  ...r,
325
- children: [n, /* @__PURE__ */ a(C.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] border-r border-b border-border bg-popover fill-popover" })]
325
+ children: [n, /* @__PURE__ */ a(w.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] border-r border-b border-border bg-popover fill-popover" })]
326
326
  }) });
327
327
  }
328
328
  //#endregion
329
329
  //#region src/chat/actions.tsx
330
330
  var Se = ({ className: e, children: t, ...n }) => /* @__PURE__ */ a("div", {
331
- className: T("-ml-1.5 flex items-center", e),
331
+ className: E("-ml-1.5 flex items-center", e),
332
332
  ...n,
333
333
  children: t
334
334
  }), Ce = ({ tooltip: e, children: t, label: n, className: r, variant: i = "ghost", size: s = "icon", ...c }) => {
335
335
  let l = /* @__PURE__ */ o(K, {
336
- className: T("relative", r),
336
+ className: E("relative", r),
337
337
  size: s,
338
338
  type: "button",
339
339
  variant: i,
@@ -487,8 +487,16 @@ var Pe = [
487
487
  done: "Refined"
488
488
  },
489
489
  {
490
- active: "Working",
491
- done: "Done"
490
+ active: "Musing",
491
+ done: "Mused"
492
+ },
493
+ {
494
+ active: "Scurrying",
495
+ done: "Scurried"
496
+ },
497
+ {
498
+ active: "Crunching",
499
+ done: "Crunched"
492
500
  }
493
501
  ], Fe = {
494
502
  waiting: Pe,
@@ -510,108 +518,131 @@ function Z({ kind: e, active: t, seed: n, elapsedSeconds: r, verb: i }) {
510
518
  elapsedSeconds: r > 0 ? r : 0
511
519
  };
512
520
  }
513
- function Q(e) {
521
+ function Ie(e) {
514
522
  let { verb: t, elapsedSeconds: n } = Z(e);
515
523
  return n <= 0 ? t : `${t} for ${n}s`;
516
524
  }
517
- function Ie(e, t) {
525
+ function Le(e, t) {
518
526
  let n = Infinity, r = -Infinity, i = !1;
519
527
  for (let t of e) Number.isFinite(t.startedAtMs) && (n = Math.min(n, t.startedAtMs), Number.isFinite(t.completedAtMs) ? r = Math.max(r, t.completedAtMs) : i = !0);
520
528
  if (n === Infinity) return 0;
521
529
  let a = i && Number.isFinite(t) ? t : r;
522
530
  return a === -Infinity ? 0 : Math.max(0, Math.floor((a - n) / 1e3));
523
531
  }
524
- function Le(e) {
532
+ function Re(e) {
525
533
  let t = 0;
526
534
  for (let n = 0; n < e.length; n += 1) t = t * 31 + e.charCodeAt(n) | 0;
527
535
  return t;
528
536
  }
529
537
  //#endregion
530
538
  //#region src/chat/message-trace.tsx
531
- function Re(e) {
539
+ function Q(e) {
532
540
  let t = e.replace(/^tool-/, "").replace(/[_-]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").trim();
533
541
  return t.charAt(0).toUpperCase() + t.slice(1);
534
542
  }
535
- var ze = _(({ parts: e, isLoading: t, messageId: n, activity: r, getToolLabel: i, getToolIcon: s, getActivityOverride: c, defaultOpen: l = !1, className: u }) => {
536
- let d = e.filter((e) => e.type === "reasoning").map((e) => String(e.text ?? "")).filter((e) => e.trim()).join("\n\n"), f = d.trim().length > 0, p = [], m = !1, h;
543
+ var ze = _(({ parts: e, isLoading: t, messageId: n, activity: r, getToolLabel: i, getToolIcon: s, getActivityOverride: c, renderStepDetail: l, defaultOpen: u = !1, className: d }) => {
544
+ let f = e.filter((e) => e.type === "reasoning").map((e) => String(e.text ?? "")).filter((e) => e.trim()).join("\n\n"), p = f.trim().length > 0, m = [], h = !1, g;
537
545
  for (let t of e) if (t.type.startsWith("tool-")) {
538
- m = !0;
546
+ h = !0;
539
547
  let e = String(t.state ?? "");
540
- e === "output-available" || e === "output-error" || e === "output-denied" || (h = t.type), p.push({
548
+ e === "output-available" || e === "output-error" || e === "output-denied" || (g = t.type), m.push({
541
549
  kind: "tool",
542
- label: i?.(t.type) ?? Re(t.type),
550
+ label: i?.(t.type) ?? Q(t.type),
543
551
  state: e,
544
- toolType: t.type
552
+ toolType: t.type,
553
+ part: t
545
554
  });
546
- } else t.type === "text" && String(t.text ?? "").trim() && p.push({
555
+ } else t.type === "text" && String(t.text ?? "").trim() && m.push({
547
556
  kind: "note",
548
557
  text: String(t.text)
549
558
  });
550
- m && !t && p.push({ kind: "done" });
551
- let g = e.some((e) => Number.isFinite(e.startedAtMs)) ? Ie(e, r?.nowMs) : r?.elapsedSeconds ?? 0, _ = r?.seed ?? Le(n), v = t ? g : 0, y = t ? c?.(h) : void 0, b = {
552
- kind: f ? "reasoning" : "tools",
559
+ h && !t && m.push({ kind: "done" });
560
+ let _ = e.some((e) => Number.isFinite(e.startedAtMs)) ? Le(e, r?.nowMs) : r?.elapsedSeconds ?? 0, v = r?.seed ?? Re(n), y = t ? _ : 0, b = t ? c?.(g) : void 0, S = {
561
+ kind: p ? "reasoning" : "tools",
553
562
  active: t,
554
- seed: _,
555
- elapsedSeconds: v,
556
- verb: y
557
- }, S = Q(b), { elapsedSeconds: te } = Z(b), C = f || p.length > 0, w = C && t && te === 0, [E, D] = x(l), O = ee();
563
+ seed: v,
564
+ elapsedSeconds: y,
565
+ verb: b
566
+ }, C = Ie(S), { elapsedSeconds: w } = Z(S), T = p || m.length > 0, te = T && t && w === 0, [D, O] = x(u), k = ee();
558
567
  return /* @__PURE__ */ o("div", {
559
- className: T("not-prose flex flex-col", u),
568
+ className: E("not-prose flex flex-col", d),
560
569
  children: [/* @__PURE__ */ a("button", {
561
570
  type: "button",
562
571
  "data-testid": "message-reasoning",
563
- onClick: () => D((e) => !e),
564
- "aria-expanded": E,
565
- "aria-controls": C ? O : void 0,
566
- className: "flex items-center gap-1 self-start text-sm text-muted-foreground transition-colors hover:text-foreground",
572
+ onClick: () => O((e) => !e),
573
+ "aria-expanded": D,
574
+ "aria-controls": T ? k : void 0,
575
+ className: "flex items-center gap-1 self-start text-[13px] leading-5 text-muted-foreground transition-colors hover:text-foreground",
567
576
  children: /* @__PURE__ */ o("span", {
568
- className: T(t && "ocui-shimmer"),
569
- children: [S, w ? "..." : ""]
577
+ className: E(t && "ocui-shimmer"),
578
+ children: [C, te ? "..." : ""]
570
579
  })
571
- }), E && C && /* @__PURE__ */ o("div", {
572
- id: O,
580
+ }), D && T && /* @__PURE__ */ o("div", {
581
+ id: k,
573
582
  className: "mt-2 flex flex-col gap-2",
574
- children: [f && /* @__PURE__ */ a(ne, {
583
+ children: [p && /* @__PURE__ */ a(ne, {
575
584
  className: "grid gap-1 text-sm text-muted-foreground/80 **:text-sm [&_code]:bg-transparent [&_code]:p-0 [&_code]:font-semibold [&_code]:text-foreground [&_li]:my-0 [&_ol]:my-1 [&_p]:my-0 [&_ul]:my-1",
576
- children: d
577
- }), p.length > 0 && /* @__PURE__ */ a("div", {
585
+ children: f
586
+ }), m.length > 0 && /* @__PURE__ */ a("div", {
578
587
  className: "flex flex-col",
579
- children: p.map((e, t) => /* @__PURE__ */ a(Be, {
588
+ children: m.map((e, t) => /* @__PURE__ */ a(Be, {
580
589
  node: e,
581
590
  isFirst: t === 0,
582
- isLast: t === p.length - 1,
583
- getToolIcon: s
591
+ isLast: t === m.length - 1,
592
+ getToolIcon: s,
593
+ renderStepDetail: l
584
594
  }, `step-${t}`))
585
595
  })]
586
596
  })]
587
597
  });
588
598
  });
589
599
  ze.displayName = "MessageTrace";
590
- function Be({ node: e, isFirst: t, isLast: n, getToolIcon: r }) {
600
+ function Be({ node: e, isFirst: t, isLast: n, getToolIcon: r, renderStepDetail: i }) {
601
+ let s = e.kind === "tool" && i ? i(e.part) : null, l = s != null, [u, d] = x(!1), f = ee();
591
602
  return /* @__PURE__ */ o("div", {
592
- className: "flex items-stretch gap-2.5",
603
+ className: "flex flex-col",
593
604
  children: [/* @__PURE__ */ o("div", {
594
- className: "flex w-4 flex-col items-center",
595
- children: [
596
- /* @__PURE__ */ a("div", { className: T("w-px flex-1", t ? "bg-transparent" : "bg-border") }),
597
- /* @__PURE__ */ a(Ve, {
598
- node: e,
599
- getToolIcon: r
600
- }),
601
- /* @__PURE__ */ a("div", { className: T("w-px flex-1", n ? "bg-transparent" : "bg-border") })
602
- ]
603
- }), /* @__PURE__ */ a("div", {
604
- className: "min-w-0 py-1 text-sm leading-5",
605
- children: e.kind === "tool" ? /* @__PURE__ */ a("span", {
606
- className: "text-muted-foreground",
607
- children: e.label
608
- }) : e.kind === "note" ? /* @__PURE__ */ a("span", {
609
- className: "text-muted-foreground/80",
610
- children: e.text
611
- }) : /* @__PURE__ */ a("span", {
612
- className: "text-muted-foreground",
613
- children: "Done"
614
- })
605
+ className: "flex items-stretch gap-2.5",
606
+ children: [/* @__PURE__ */ o("div", {
607
+ className: "flex w-4 flex-col items-center",
608
+ children: [
609
+ /* @__PURE__ */ a("div", { className: E("w-px flex-1", t ? "bg-transparent" : "bg-border") }),
610
+ /* @__PURE__ */ a(Ve, {
611
+ node: e,
612
+ getToolIcon: r
613
+ }),
614
+ /* @__PURE__ */ a("div", { className: E("w-px flex-1", n ? "bg-transparent" : "bg-border") })
615
+ ]
616
+ }), /* @__PURE__ */ a("div", {
617
+ className: "min-w-0 py-1 text-sm leading-5",
618
+ children: e.kind === "tool" ? l ? /* @__PURE__ */ o("button", {
619
+ type: "button",
620
+ onClick: () => d((e) => !e),
621
+ "aria-expanded": u,
622
+ "aria-controls": f,
623
+ className: "group inline-flex items-center gap-1 text-sm text-muted-foreground transition-colors hover:text-foreground",
624
+ children: [/* @__PURE__ */ a("span", { children: e.label }), /* @__PURE__ */ a(c, { className: E("size-2.5 transition-[transform,opacity]", u ? "rotate-180 opacity-100" : "opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100") })]
625
+ }) : /* @__PURE__ */ a("span", {
626
+ className: "text-muted-foreground",
627
+ children: e.label
628
+ }) : e.kind === "note" ? /* @__PURE__ */ a("span", {
629
+ className: "text-muted-foreground/80",
630
+ children: e.text
631
+ }) : /* @__PURE__ */ a("span", {
632
+ className: "text-muted-foreground",
633
+ children: "Done"
634
+ })
635
+ })]
636
+ }), l && u && /* @__PURE__ */ o("div", {
637
+ className: "flex items-stretch gap-2.5",
638
+ children: [/* @__PURE__ */ a("div", {
639
+ className: "flex w-4 flex-col items-center",
640
+ children: /* @__PURE__ */ a("div", { className: E("w-px flex-1", n ? "bg-transparent" : "bg-border") })
641
+ }), /* @__PURE__ */ a("div", {
642
+ id: f,
643
+ className: "min-w-0 flex-1 pb-1",
644
+ children: s
645
+ })]
615
646
  })]
616
647
  });
617
648
  }
@@ -681,17 +712,17 @@ function He(e, t) {
681
712
  function Ue(e) {
682
713
  return `Searched ${e} source${e === 1 ? "" : "s"}`;
683
714
  }
684
- function $(e) {
715
+ function We(e) {
685
716
  try {
686
717
  return new URL(e).hostname;
687
718
  } catch {
688
719
  return e;
689
720
  }
690
721
  }
691
- function We(e) {
692
- return `https://www.google.com/s2/favicons?domain=${$(e)}&sz=32`;
722
+ function Ge(e) {
723
+ return `https://www.google.com/s2/favicons?domain=${We(e)}&sz=32`;
693
724
  }
694
- function Ge({ url: e, getFaviconUrl: t }) {
725
+ function Ke({ url: e, getFaviconUrl: t }) {
695
726
  let n = t(e), [r, i] = x(!1);
696
727
  return !n || r ? /* @__PURE__ */ a(d, { className: "size-3.5 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ a("img", {
697
728
  src: n,
@@ -700,44 +731,50 @@ function Ge({ url: e, getFaviconUrl: t }) {
700
731
  onError: () => i(!0)
701
732
  });
702
733
  }
703
- var Ke = ({ sources: e, getLabel: t = Ue, getFaviconUrl: n = We, className: r, ...i }) => e.length === 0 ? null : /* @__PURE__ */ o(k, {
704
- className: T("not-prose", r),
734
+ var $ = ({ sources: e, getFaviconUrl: t = Ge, className: n }) => e.length === 0 ? null : /* @__PURE__ */ a("div", {
735
+ className: E("flex flex-col gap-0.5", n),
736
+ children: e.map((e, n) => {
737
+ let r = We(e.url), i = e.title || r;
738
+ return /* @__PURE__ */ o("a", {
739
+ href: e.url,
740
+ target: "_blank",
741
+ rel: "noreferrer",
742
+ className: "flex min-w-0 items-center gap-1.5 rounded-md px-1.5 py-1 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
743
+ children: [
744
+ /* @__PURE__ */ a(Ke, {
745
+ getFaviconUrl: t,
746
+ url: e.url
747
+ }),
748
+ /* @__PURE__ */ a("span", {
749
+ className: "truncate",
750
+ children: i
751
+ }),
752
+ i !== r && /* @__PURE__ */ a("span", {
753
+ className: "shrink-0 truncate text-xs text-muted-foreground/70",
754
+ children: r
755
+ })
756
+ ]
757
+ }, `${e.url}-${n}`);
758
+ })
759
+ }), qe = ({ sources: e, getLabel: t = Ue, getFaviconUrl: n = Ge, className: r, ...i }) => e.length === 0 ? null : /* @__PURE__ */ o(k, {
760
+ className: E("not-prose", r),
705
761
  ...i,
706
762
  children: [/* @__PURE__ */ o(A, {
707
- className: "group flex items-center gap-1 self-start text-sm text-muted-foreground transition-colors hover:text-foreground",
763
+ className: "group flex items-center gap-1 self-start text-[13px] leading-5 text-muted-foreground transition-colors hover:text-foreground",
708
764
  children: [/* @__PURE__ */ a("span", { children: t(e.length) }), /* @__PURE__ */ a(c, { className: "size-2.5 transition-transform group-data-[state=open]:rotate-180" })]
709
765
  }), /* @__PURE__ */ a(j, {
710
- className: "mt-1 flex flex-col gap-0.5 data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 data-[state=closed]:animate-out data-[state=open]:animate-in",
711
- children: e.map((e, t) => {
712
- let r = $(e.url), i = e.title || r;
713
- return /* @__PURE__ */ o("a", {
714
- href: e.url,
715
- target: "_blank",
716
- rel: "noreferrer",
717
- className: "flex min-w-0 items-center gap-1.5 rounded-md px-1.5 py-1 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
718
- children: [
719
- /* @__PURE__ */ a(Ge, {
720
- getFaviconUrl: n,
721
- url: e.url
722
- }),
723
- /* @__PURE__ */ a("span", {
724
- className: "truncate",
725
- children: i
726
- }),
727
- i !== r && /* @__PURE__ */ a("span", {
728
- className: "shrink-0 truncate text-xs text-muted-foreground/70",
729
- children: r
730
- })
731
- ]
732
- }, `${e.url}-${t}`);
766
+ className: "mt-1 data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 data-[state=closed]:animate-out data-[state=open]:animate-in",
767
+ children: /* @__PURE__ */ a($, {
768
+ sources: e,
769
+ getFaviconUrl: n
733
770
  })
734
771
  })]
735
- }), qe = "ocui-cite", Je = ({ pressed: e, onPressedChange: t, label: n = "Search the web", tooltip: r, className: i, variant: s, size: c = "icon", onClick: l, ...u }) => {
772
+ }), Je = "ocui-cite", Ye = ({ pressed: e, onPressedChange: t, label: n = "Search the web", tooltip: r, className: i, variant: s, size: c = "icon", onClick: l, ...u }) => {
736
773
  let f = s ?? (e ? "default" : "ghost"), p = /* @__PURE__ */ a(K, {
737
774
  ...u,
738
775
  "aria-label": n,
739
776
  "aria-pressed": e,
740
- className: T(i),
777
+ className: E(i),
741
778
  size: c,
742
779
  type: "button",
743
780
  variant: f,
@@ -755,4 +792,4 @@ var Ke = ({ sources: e, getLabel: t = Ue, getFaviconUrl: n = We, className: r, .
755
792
  }) : p;
756
793
  };
757
794
  //#endregion
758
- export { Ce as Action, Se as Actions, O as MessageContent, ze as MessageTrace, N as Reasoning, I as ReasoningContent, P as ReasoningTrigger, ne as Response, Ke as Sources, pe as Tool, ve as ToolContent, _e as ToolHeader, ye as ToolInput, be as ToolOutput, Je as WebSearchToggle, Te as buildSegments, qe as citationClassName, Ne as deriveTurnView, Me as extractWebSearchSources, Q as getAiActivityLabel, Z as getAiActivityLabelParts, Re as humanizeToolName, De as isWebSearchError, Le as labelSeedFromString, F as reasoningTextClassName, ke as stripCitationParens, Ie as traceElapsedSeconds, Ee as traceIsLoading, He as useActivityClock };
795
+ export { Ce as Action, Se as Actions, O as MessageContent, ze as MessageTrace, N as Reasoning, I as ReasoningContent, P as ReasoningTrigger, ne as Response, $ as SourceList, qe as Sources, pe as Tool, ve as ToolContent, _e as ToolHeader, ye as ToolInput, be as ToolOutput, Ye as WebSearchToggle, Te as buildSegments, Je as citationClassName, Ne as deriveTurnView, Me as extractWebSearchSources, Ie as getAiActivityLabel, Z as getAiActivityLabelParts, Q as humanizeToolName, De as isWebSearchError, Re as labelSeedFromString, F as reasoningTextClassName, ke as stripCitationParens, Le as traceElapsedSeconds, Ee as traceIsLoading, He as useActivityClock };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ocai/app-sdk-ui",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Shared design tokens and AI-app UI primitives for OceanAI products.",
5
5
  "license": "MIT",
6
6
  "type": "module",