@ocai/app-sdk-ui 0.1.0 → 0.3.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.
- package/dist/chat/activity-labels.d.ts +22 -0
- package/dist/chat/message-trace.d.ts +17 -0
- package/dist/chat/response.d.ts +1 -2
- package/dist/chat/segments.d.ts +23 -0
- package/dist/chat/sources.d.ts +13 -0
- package/dist/chat/tool-value.d.ts +6 -0
- package/dist/chat/tool.d.ts +3 -3
- package/dist/chat/turn-view.d.ts +21 -0
- package/dist/chat/use-activity-clock.d.ts +2 -0
- package/dist/chat/web-search-toggle.d.ts +9 -0
- package/dist/chat/web-search.d.ts +35 -0
- package/dist/chat.css +109 -6
- package/dist/index.d.ts +9 -1
- package/dist/index.js +571 -99
- package/dist/tokens.css +1 -1
- package/package.json +8 -3
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type AiActivityKind = "waiting" | "reasoning" | "tools";
|
|
2
|
+
export interface AiActivity {
|
|
3
|
+
seed: number;
|
|
4
|
+
elapsedSeconds: number;
|
|
5
|
+
nowMs: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ActivityLabelParts {
|
|
8
|
+
verb: string;
|
|
9
|
+
elapsedSeconds: number;
|
|
10
|
+
}
|
|
11
|
+
export interface GetAiActivityLabelArgs extends Pick<AiActivity, "seed" | "elapsedSeconds"> {
|
|
12
|
+
kind: AiActivityKind;
|
|
13
|
+
active: boolean;
|
|
14
|
+
verb?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function getAiActivityLabelParts({ kind, active, seed, elapsedSeconds, verb, }: GetAiActivityLabelArgs): ActivityLabelParts;
|
|
17
|
+
export declare function getAiActivityLabel(args: GetAiActivityLabelArgs): string;
|
|
18
|
+
export declare function traceElapsedSeconds(parts: ReadonlyArray<{
|
|
19
|
+
startedAtMs?: number;
|
|
20
|
+
completedAtMs?: number;
|
|
21
|
+
}>, nowMs?: number): number;
|
|
22
|
+
export declare function labelSeedFromString(value: string): number;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
import { ReactElement } from 'react';
|
|
3
|
+
import { AiActivity } from './activity-labels';
|
|
4
|
+
import { TracePart } from './segments';
|
|
5
|
+
export declare function humanizeToolName(type: string): string;
|
|
6
|
+
export type MessageTraceProps = {
|
|
7
|
+
parts: readonly TracePart[];
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
messageId: string;
|
|
10
|
+
activity?: AiActivity;
|
|
11
|
+
getToolLabel?: (type: string) => string | undefined;
|
|
12
|
+
getToolIcon?: (type: string) => LucideIcon | undefined;
|
|
13
|
+
getActivityOverride?: (runningToolType: string | undefined) => string | undefined;
|
|
14
|
+
defaultOpen?: boolean;
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare const MessageTrace: import('react').MemoExoticComponent<({ parts, isLoading, messageId, activity, getToolLabel, getToolIcon, getActivityOverride, defaultOpen, className, }: MessageTraceProps) => ReactElement>;
|
package/dist/chat/response.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ComponentProps } from 'react';
|
|
2
2
|
import { Streamdown } from 'streamdown';
|
|
3
|
-
type ResponseProps = ComponentProps<typeof Streamdown>;
|
|
3
|
+
export type ResponseProps = ComponentProps<typeof Streamdown>;
|
|
4
4
|
export declare function Response({ className, ...props }: ResponseProps): import("react").JSX.Element;
|
|
5
|
-
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type TracePart = {
|
|
2
|
+
type: string;
|
|
3
|
+
startedAtMs?: number;
|
|
4
|
+
completedAtMs?: number;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
};
|
|
7
|
+
export type MessageSegment = {
|
|
8
|
+
kind: "trace";
|
|
9
|
+
parts: TracePart[];
|
|
10
|
+
} | {
|
|
11
|
+
kind: "images";
|
|
12
|
+
parts: TracePart[];
|
|
13
|
+
index: number;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "part";
|
|
16
|
+
part: TracePart;
|
|
17
|
+
index: number;
|
|
18
|
+
};
|
|
19
|
+
export type BuildSegmentsOptions = {
|
|
20
|
+
isPresentationalTool?: (type: string) => boolean;
|
|
21
|
+
};
|
|
22
|
+
export declare function buildSegments(parts: readonly TracePart[], options?: BuildSegmentsOptions): MessageSegment[];
|
|
23
|
+
export declare function traceIsLoading(parts: readonly TracePart[], messageLoading: boolean): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ComponentProps, ReactElement } from 'react';
|
|
2
|
+
import { Collapsible } from '../internal/collapsible';
|
|
3
|
+
export type SourceItem = {
|
|
4
|
+
url: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
};
|
|
7
|
+
export type SourcesProps = Omit<ComponentProps<typeof Collapsible>, "children"> & {
|
|
8
|
+
sources: readonly SourceItem[];
|
|
9
|
+
getLabel?: (count: number) => string;
|
|
10
|
+
getFaviconUrl?: (url: string) => string | null;
|
|
11
|
+
};
|
|
12
|
+
export declare const Sources: ({ sources, getLabel, getFaviconUrl, className, ...props }: SourcesProps) => ReactElement | null;
|
|
13
|
+
export declare const citationClassName = "ocui-cite";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
export declare const hasRenderableValue: (v: unknown) => boolean;
|
|
3
|
+
export declare const capText: (value: string, max?: number) => string;
|
|
4
|
+
export declare const ToolValue: ({ value }: {
|
|
5
|
+
value: unknown;
|
|
6
|
+
}) => ReactElement | null;
|
package/dist/chat/tool.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ToolUIPart } from 'ai';
|
|
2
|
-
import { ComponentProps
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
3
|
import { Collapsible, CollapsibleContent } from '../internal/collapsible';
|
|
4
4
|
export type ToolProps = ComponentProps<typeof Collapsible>;
|
|
5
5
|
export declare const Tool: ({ className, ...props }: ToolProps) => import("react").JSX.Element;
|
|
@@ -15,9 +15,9 @@ export declare const ToolContent: ({ className, ...props }: ToolContentProps) =>
|
|
|
15
15
|
export type ToolInputProps = ComponentProps<"div"> & {
|
|
16
16
|
input: ToolUIPart["input"];
|
|
17
17
|
};
|
|
18
|
-
export declare const ToolInput: ({ className, input, ...props }: ToolInputProps) => import("react").JSX.Element;
|
|
18
|
+
export declare const ToolInput: ({ className, input, ...props }: ToolInputProps) => import("react").JSX.Element | null;
|
|
19
19
|
export type ToolOutputProps = ComponentProps<"div"> & {
|
|
20
|
-
output:
|
|
20
|
+
output: unknown;
|
|
21
21
|
errorText: ToolUIPart["errorText"];
|
|
22
22
|
};
|
|
23
23
|
export declare const ToolOutput: ({ className, output, errorText, ...props }: ToolOutputProps) => import("react").JSX.Element | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { MessageSegment, TracePart } from './segments';
|
|
2
|
+
import { SourceItem } from './sources';
|
|
3
|
+
import { AiActivityKind } from './activity-labels';
|
|
4
|
+
export type TurnPhase = "waiting" | "reasoning" | "searching" | "tooling" | "answering" | "settled";
|
|
5
|
+
export interface TurnView {
|
|
6
|
+
phase: TurnPhase;
|
|
7
|
+
segments: MessageSegment[];
|
|
8
|
+
trace: {
|
|
9
|
+
parts: TracePart[];
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
} | null;
|
|
12
|
+
sources: SourceItem[];
|
|
13
|
+
activityKind: AiActivityKind;
|
|
14
|
+
hasFinalAnswer: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface DeriveTurnViewOptions {
|
|
17
|
+
isPresentationalTool?: (type: string) => boolean;
|
|
18
|
+
isSearchTool?: (type: string) => boolean;
|
|
19
|
+
messageLoading?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function deriveTurnView(parts: readonly TracePart[], options?: DeriveTurnViewOptions): TurnView;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
2
|
+
import { Button } from '../internal/button';
|
|
3
|
+
export type WebSearchToggleProps = Omit<ComponentProps<typeof Button>, "children"> & {
|
|
4
|
+
pressed: boolean;
|
|
5
|
+
onPressedChange: (pressed: boolean) => void;
|
|
6
|
+
label?: string;
|
|
7
|
+
tooltip?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const WebSearchToggle: ({ pressed, onPressedChange, label, tooltip, className, variant, size, onClick, ...props }: WebSearchToggleProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ToolUIPart } from 'ai';
|
|
2
|
+
import { SourceItem } from './sources';
|
|
3
|
+
export interface WebSearchInput {
|
|
4
|
+
query: string;
|
|
5
|
+
}
|
|
6
|
+
export interface WebSearchResult {
|
|
7
|
+
title: string;
|
|
8
|
+
url: string;
|
|
9
|
+
content: string;
|
|
10
|
+
score: number;
|
|
11
|
+
}
|
|
12
|
+
export interface WebSearchSuccessOutput {
|
|
13
|
+
query: string;
|
|
14
|
+
results: WebSearchResult[];
|
|
15
|
+
}
|
|
16
|
+
export interface WebSearchErrorOutput {
|
|
17
|
+
error: string;
|
|
18
|
+
}
|
|
19
|
+
export type WebSearchOutput = WebSearchSuccessOutput | WebSearchErrorOutput;
|
|
20
|
+
export type WebSearchUITool = {
|
|
21
|
+
input: WebSearchInput;
|
|
22
|
+
output: WebSearchOutput;
|
|
23
|
+
};
|
|
24
|
+
export type WebSearchUIPart = ToolUIPart<{
|
|
25
|
+
webSearch: WebSearchUITool;
|
|
26
|
+
}>;
|
|
27
|
+
export declare function isWebSearchError(output: unknown): output is WebSearchErrorOutput;
|
|
28
|
+
export declare function stripCitationParens(text: string): string;
|
|
29
|
+
export declare function extractWebSearchSources(parts: ReadonlyArray<{
|
|
30
|
+
type?: string;
|
|
31
|
+
state?: string;
|
|
32
|
+
output?: unknown;
|
|
33
|
+
}>, options?: {
|
|
34
|
+
toolType?: string;
|
|
35
|
+
}): SourceItem[];
|
package/dist/chat.css
CHANGED
|
@@ -60,16 +60,119 @@
|
|
|
60
60
|
@apply font-medium text-foreground;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
/* --- Code block:
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
/* --- Code block: Claude.ai-style shell. ONE subtle card; the language is a
|
|
64
|
+
plain muted label (no header bar, no divider); and a single copy button
|
|
65
|
+
fades in on hover at the top-right (download is turned off via the
|
|
66
|
+
`controls` prop in chat/response.tsx). Streamdown frames the block with its
|
|
67
|
+
own utility classes as a padded `bg-sidebar` card wrapping a SECOND bordered
|
|
68
|
+
`bg-background` card, plus an always-visible copy/download pill floated up
|
|
69
|
+
by -mt-10 — we flatten both cards into one and re-home the copy overlay. */
|
|
66
70
|
.ocui-md [data-streamdown="code-block"] {
|
|
67
|
-
@apply my-4 overflow-hidden rounded-lg border border-border;
|
|
71
|
+
@apply relative my-4 gap-0 overflow-hidden rounded-lg border border-border bg-muted/40 p-0;
|
|
68
72
|
}
|
|
73
|
+
/* Language label: not a bar — small muted text with padding, no divider. The
|
|
74
|
+
inner <span> is Streamdown's `font-mono lowercase ml-1`; drop the mono and
|
|
75
|
+
the indent so the label lines up with the code's left edge. */
|
|
69
76
|
.ocui-md [data-streamdown="code-block-header"] {
|
|
70
|
-
@apply
|
|
77
|
+
@apply h-auto px-4 pt-3 pb-0 text-xs font-normal text-muted-foreground;
|
|
71
78
|
}
|
|
79
|
+
.ocui-md [data-streamdown="code-block-header"] span {
|
|
80
|
+
@apply ml-0 font-sans;
|
|
81
|
+
}
|
|
82
|
+
/* Copy overlay: Streamdown wraps the buttons in an un-hooked div (no
|
|
83
|
+
data-streamdown), floated by `-mt-10` and always visible. Target it as the
|
|
84
|
+
div directly wrapping `code-block-actions` (mirrors the table's :has hook),
|
|
85
|
+
pin it top-right, and fade it in only on hover / keyboard focus. */
|
|
86
|
+
.ocui-md [data-streamdown="code-block"] > div:has(> [data-streamdown="code-block-actions"]) {
|
|
87
|
+
@apply absolute right-2 top-2 z-10 mt-0 h-auto opacity-0 transition-opacity;
|
|
88
|
+
}
|
|
89
|
+
.ocui-md [data-streamdown="code-block"]:hover > div:has(> [data-streamdown="code-block-actions"]),
|
|
90
|
+
.ocui-md [data-streamdown="code-block"]:focus-within > div:has(> [data-streamdown="code-block-actions"]) {
|
|
91
|
+
@apply opacity-100;
|
|
92
|
+
}
|
|
93
|
+
/* Drop the pill chrome (border + tinted bg) around the button. */
|
|
94
|
+
.ocui-md [data-streamdown="code-block-actions"] {
|
|
95
|
+
@apply gap-1 rounded-md border-0 bg-transparent p-0;
|
|
96
|
+
}
|
|
97
|
+
/* Copy button: 32px square, subtle hover fill, blur so it reads over code. */
|
|
98
|
+
.ocui-md [data-streamdown="code-block-copy-button"] {
|
|
99
|
+
@apply inline-flex h-8 w-8 items-center justify-center rounded-md p-0 backdrop-blur-md hover:bg-muted;
|
|
100
|
+
}
|
|
101
|
+
/* Body: strip Streamdown's inner card (border + rounding + bg) so the code
|
|
102
|
+
sits flush in the single shell; keep horizontal scroll + a code padding. */
|
|
72
103
|
.ocui-md [data-streamdown="code-block-body"] {
|
|
73
|
-
@apply text-sm;
|
|
104
|
+
@apply rounded-none border-0 bg-transparent px-4 pb-4 pt-2 text-sm;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Opt-in inline-citation chips: <Response className={citationClassName}>
|
|
108
|
+
renders model-emitted "[title](url)" citations as compact pills. Opt-in so
|
|
109
|
+
ordinary markdown links elsewhere keep their default look. Streamdown 2.x
|
|
110
|
+
renders markdown links as <button data-streamdown="link"> (click-to-
|
|
111
|
+
confirm hardening), NOT <a href> — so target its data hook like every
|
|
112
|
+
other rule in this file; an href-based selector matches nothing. Stays
|
|
113
|
+
`inline` (never inline-flex) so the pill breaks with the surrounding text
|
|
114
|
+
like any other word instead of forcing a rigid box. */
|
|
115
|
+
.ocui-md.ocui-cite [data-streamdown="link"] {
|
|
116
|
+
@apply inline cursor-pointer rounded-sm bg-muted px-1.5 py-0.5 align-baseline text-xs font-normal text-muted-foreground no-underline transition-colors hover:bg-accent hover:text-accent-foreground;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* Activity-label shimmer: while the model streams, the trigger label
|
|
120
|
+
("Thinking…", "Shaping for 4s") sweeps a full-contrast highlight
|
|
121
|
+
left→right across the muted label text, instead of pulsing the whole word.
|
|
122
|
+
Codex-style (a moving highlight band clipped to the glyphs). Base is the
|
|
123
|
+
muted label color; the highlight is the foreground seed. Applied by
|
|
124
|
+
Reasoning/MessageTrace's trigger only while streaming; reduced-motion
|
|
125
|
+
falls back to solid muted text. */
|
|
126
|
+
.ocui-shimmer {
|
|
127
|
+
/* Two glyph-clipped layers. LAYER 1 (background-color) is a SOLID base that
|
|
128
|
+
always fills every glyph, so text is never transparent. LAYER 2 (gradient,
|
|
129
|
+
painted on top) is transparent at both ends with an opaque --foreground band
|
|
130
|
+
in the middle — only that band tints the glyphs; elsewhere the base shows. */
|
|
131
|
+
background-color: var(--muted-foreground);
|
|
132
|
+
background-image: linear-gradient(
|
|
133
|
+
to right,
|
|
134
|
+
transparent 0%,
|
|
135
|
+
var(--foreground) 40%,
|
|
136
|
+
var(--foreground) 60%,
|
|
137
|
+
transparent 100%
|
|
138
|
+
);
|
|
139
|
+
background-size: 50% 100%;
|
|
140
|
+
background-repeat: no-repeat;
|
|
141
|
+
background-position: -100% 0;
|
|
142
|
+
-webkit-background-clip: text;
|
|
143
|
+
background-clip: text;
|
|
144
|
+
-webkit-text-fill-color: transparent;
|
|
145
|
+
color: transparent;
|
|
146
|
+
display: inline-block;
|
|
147
|
+
animation: ocui-shimmer-sweep 1.6s linear infinite;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* --- Tool call params/results (chat/tool-value.tsx). Structured shallow
|
|
151
|
+
objects render as aligned key–value rows; deep/large values fall back to
|
|
152
|
+
this single muted mono block — a refined replacement for the old heavy
|
|
153
|
+
bg-muted/50 JSON.stringify dump. --- */
|
|
154
|
+
.ocui-tool-json {
|
|
155
|
+
tab-size: 2;
|
|
156
|
+
line-height: 1.5;
|
|
157
|
+
max-height: 22rem;
|
|
158
|
+
overflow: auto;
|
|
159
|
+
}
|
|
160
|
+
/* Key column top-aligns with the first line of a wrapping value. */
|
|
161
|
+
.ocui-tool-kv > li > span:first-child {
|
|
162
|
+
align-self: start;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@keyframes ocui-shimmer-sweep {
|
|
167
|
+
from { background-position: -100% 0; }
|
|
168
|
+
to { background-position: 250% 0; }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@media (prefers-reduced-motion: reduce) {
|
|
172
|
+
.ocui-shimmer {
|
|
173
|
+
animation: none;
|
|
174
|
+
background-image: none;
|
|
175
|
+
-webkit-text-fill-color: var(--muted-foreground);
|
|
176
|
+
color: var(--muted-foreground);
|
|
74
177
|
}
|
|
75
178
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
export { Response } from './chat/response';
|
|
1
|
+
export { Response, type ResponseProps } from './chat/response';
|
|
2
2
|
export { MessageContent, type MessageContentProps, type MessageContentVariant, } from './chat/message';
|
|
3
3
|
export { Reasoning, ReasoningContent, ReasoningTrigger, reasoningTextClassName, type ReasoningProps, type ReasoningTriggerProps, } from './chat/reasoning';
|
|
4
4
|
export { Tool, ToolContent, ToolHeader, ToolInput, ToolOutput, type ToolContentProps, type ToolHeaderProps, type ToolInputProps, type ToolOutputProps, type ToolProps, } from './chat/tool';
|
|
5
5
|
export { Action, Actions, type ActionProps, type ActionsProps, } from './chat/actions';
|
|
6
|
+
export { deriveTurnView, type TurnView, type TurnPhase, type DeriveTurnViewOptions, } from './chat/turn-view';
|
|
7
|
+
export { MessageTrace, humanizeToolName, type MessageTraceProps, } from './chat/message-trace';
|
|
8
|
+
export { buildSegments, traceIsLoading, type BuildSegmentsOptions, type MessageSegment, type TracePart, } from './chat/segments';
|
|
9
|
+
export { getAiActivityLabel, getAiActivityLabelParts, labelSeedFromString, traceElapsedSeconds, type AiActivity, type AiActivityKind, type ActivityLabelParts, type GetAiActivityLabelArgs, } from './chat/activity-labels';
|
|
10
|
+
export { useActivityClock } from './chat/use-activity-clock';
|
|
11
|
+
export { Sources, citationClassName, type SourceItem, type SourcesProps, } from './chat/sources';
|
|
12
|
+
export { extractWebSearchSources, isWebSearchError, stripCitationParens, type WebSearchErrorOutput, type WebSearchInput, type WebSearchOutput, type WebSearchResult, type WebSearchSuccessOutput, type WebSearchUIPart, type WebSearchUITool, } from './chat/web-search';
|
|
13
|
+
export { WebSearchToggle, type WebSearchToggleProps, } from './chat/web-search-toggle';
|
package/dist/index.js
CHANGED
|
@@ -4,95 +4,97 @@ import { Streamdown as t } from "streamdown";
|
|
|
4
4
|
import { clsx as n } from "clsx";
|
|
5
5
|
import { twMerge as r } from "tailwind-merge";
|
|
6
6
|
import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
7
|
-
import { CheckIcon as s, ChevronDownIcon as c,
|
|
8
|
-
import { createContext as
|
|
9
|
-
import { Collapsible as
|
|
10
|
-
import { cva as
|
|
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
|
+
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";
|
|
11
11
|
//#region src/lib/cn.ts
|
|
12
|
-
function
|
|
12
|
+
function T(...e) {
|
|
13
13
|
return r(n(e));
|
|
14
14
|
}
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/chat/response.tsx
|
|
17
|
-
var
|
|
18
|
-
function
|
|
17
|
+
var E = e({ singleDollarTextMath: !0 });
|
|
18
|
+
function ne({ className: e, ...n }) {
|
|
19
19
|
return /* @__PURE__ */ a(t, {
|
|
20
|
-
className:
|
|
21
|
-
plugins: { math:
|
|
22
|
-
controls: {
|
|
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 },
|
|
22
|
+
controls: {
|
|
23
|
+
table: !1,
|
|
24
|
+
code: { download: !1 }
|
|
25
|
+
},
|
|
23
26
|
...n
|
|
24
27
|
});
|
|
25
28
|
}
|
|
26
29
|
//#endregion
|
|
27
30
|
//#region src/chat/message.tsx
|
|
28
|
-
var
|
|
31
|
+
var D = {
|
|
29
32
|
user: "w-fit wrap-break-word rounded-md bg-card px-3 py-1.5 text-primary",
|
|
30
33
|
assistant: "bg-transparent px-0 py-0 text-left text-foreground"
|
|
31
|
-
},
|
|
32
|
-
className:
|
|
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),
|
|
33
36
|
...r,
|
|
34
37
|
children: e
|
|
35
38
|
});
|
|
36
39
|
//#endregion
|
|
37
40
|
//#region src/internal/collapsible.tsx
|
|
38
|
-
function
|
|
39
|
-
return /* @__PURE__ */ a(
|
|
41
|
+
function k({ ...e }) {
|
|
42
|
+
return /* @__PURE__ */ a(S.Root, {
|
|
40
43
|
"data-slot": "collapsible",
|
|
41
44
|
...e
|
|
42
45
|
});
|
|
43
46
|
}
|
|
44
|
-
function
|
|
45
|
-
return /* @__PURE__ */ a(
|
|
47
|
+
function A({ ...e }) {
|
|
48
|
+
return /* @__PURE__ */ a(S.CollapsibleTrigger, {
|
|
46
49
|
"data-slot": "collapsible-trigger",
|
|
47
50
|
...e
|
|
48
51
|
});
|
|
49
52
|
}
|
|
50
|
-
function
|
|
51
|
-
return /* @__PURE__ */ a(
|
|
53
|
+
function j({ ...e }) {
|
|
54
|
+
return /* @__PURE__ */ a(S.CollapsibleContent, {
|
|
52
55
|
"data-slot": "collapsible-content",
|
|
53
56
|
...e
|
|
54
57
|
});
|
|
55
58
|
}
|
|
56
59
|
//#endregion
|
|
57
60
|
//#region src/chat/reasoning.tsx
|
|
58
|
-
function
|
|
59
|
-
let [r, i] =
|
|
61
|
+
function re({ prop: e, defaultProp: t, onChange: n }) {
|
|
62
|
+
let [r, i] = x(t), a = e !== void 0;
|
|
60
63
|
return [a ? e : r, (e) => {
|
|
61
64
|
a || i(e), n?.(e);
|
|
62
65
|
}];
|
|
63
66
|
}
|
|
64
|
-
var
|
|
65
|
-
let e =
|
|
67
|
+
var M = h(null), ie = () => {
|
|
68
|
+
let e = v(M);
|
|
66
69
|
if (!e) throw Error("Reasoning components must be used within Reasoning");
|
|
67
70
|
return e;
|
|
68
|
-
},
|
|
69
|
-
let [l, u] =
|
|
71
|
+
}, ae = 500, N = _(({ className: e, isStreaming: t = !1, duration: n = 0, open: r, defaultOpen: i = !0, onOpenChange: o, children: s, ...c }) => {
|
|
72
|
+
let [l, u] = re({
|
|
70
73
|
prop: r,
|
|
71
74
|
defaultProp: i,
|
|
72
75
|
onChange: o
|
|
73
|
-
}), [d, f] =
|
|
74
|
-
return
|
|
76
|
+
}), [d, f] = x(!1), p = b(u);
|
|
77
|
+
return p.current = u, y(() => {
|
|
75
78
|
if (i && !t && l && !d) {
|
|
76
79
|
let e = setTimeout(() => {
|
|
77
|
-
|
|
78
|
-
},
|
|
80
|
+
p.current(!1), f(!0);
|
|
81
|
+
}, ae);
|
|
79
82
|
return () => clearTimeout(e);
|
|
80
83
|
}
|
|
81
84
|
}, [
|
|
82
85
|
t,
|
|
83
86
|
l,
|
|
84
87
|
i,
|
|
85
|
-
u,
|
|
86
88
|
d
|
|
87
|
-
]), /* @__PURE__ */ a(
|
|
89
|
+
]), /* @__PURE__ */ a(M.Provider, {
|
|
88
90
|
value: {
|
|
89
91
|
isStreaming: t,
|
|
90
92
|
isOpen: l,
|
|
91
93
|
setIsOpen: u,
|
|
92
94
|
duration: n
|
|
93
95
|
},
|
|
94
|
-
children: /* @__PURE__ */ a(
|
|
95
|
-
className:
|
|
96
|
+
children: /* @__PURE__ */ a(k, {
|
|
97
|
+
className: T("not-prose", e),
|
|
96
98
|
onOpenChange: u,
|
|
97
99
|
open: l,
|
|
98
100
|
...c,
|
|
@@ -100,39 +102,106 @@ var j = p(null), M = () => {
|
|
|
100
102
|
})
|
|
101
103
|
});
|
|
102
104
|
});
|
|
103
|
-
function
|
|
105
|
+
function oe({ variant: e, isStreaming: t, duration: n }) {
|
|
104
106
|
let r = e === "tools";
|
|
105
107
|
return t ? r ? "Working…" : "Thinking…" : n > 0 ? r ? `Worked for ${n}s` : `Thought for ${n}s` : r ? "Worked" : "Thought";
|
|
106
108
|
}
|
|
107
|
-
var
|
|
108
|
-
let { isStreaming: l, isOpen: u, duration:
|
|
109
|
+
var P = _(({ className: e, children: t, variant: n = "reasoning", label: r, ...s }) => {
|
|
110
|
+
let { isStreaming: l, isOpen: u, duration: d } = ie(), f = r ?? oe({
|
|
109
111
|
variant: n,
|
|
110
112
|
isStreaming: l,
|
|
111
|
-
duration:
|
|
113
|
+
duration: d
|
|
112
114
|
});
|
|
113
|
-
return /* @__PURE__ */ a(
|
|
114
|
-
className:
|
|
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),
|
|
115
117
|
...s,
|
|
116
118
|
children: t ?? /* @__PURE__ */ o(i, { children: [
|
|
117
|
-
n === "tools" && /* @__PURE__ */ a(
|
|
119
|
+
n === "tools" && /* @__PURE__ */ a(p, { className: "size-3" }),
|
|
118
120
|
/* @__PURE__ */ a("span", {
|
|
119
|
-
className:
|
|
120
|
-
children:
|
|
121
|
+
className: T(l && "ocui-shimmer"),
|
|
122
|
+
children: f
|
|
121
123
|
}),
|
|
122
|
-
/* @__PURE__ */ a(c, { className:
|
|
124
|
+
/* @__PURE__ */ a(c, { className: T("size-2.5 transition-transform", u ? "rotate-180" : "rotate-0") })
|
|
123
125
|
] })
|
|
124
126
|
});
|
|
125
|
-
}),
|
|
126
|
-
className:
|
|
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),
|
|
127
129
|
...t
|
|
128
130
|
}));
|
|
129
|
-
|
|
131
|
+
N.displayName = "Reasoning", P.displayName = "ReasoningTrigger", I.displayName = "ReasoningContent";
|
|
130
132
|
//#endregion
|
|
131
|
-
//#region src/chat/tool.tsx
|
|
132
|
-
var
|
|
133
|
-
|
|
133
|
+
//#region src/chat/tool-value.tsx
|
|
134
|
+
var se = 8, L = 240, ce = 2e4, R = (e) => e === null || typeof e != "object" && typeof e != "function", z = (e) => {
|
|
135
|
+
if (typeof e != "object" || !e) return !1;
|
|
136
|
+
let t = Object.getPrototypeOf(e);
|
|
137
|
+
return t === Object.prototype || t === null;
|
|
138
|
+
}, B = (e) => Array.isArray(e) && e.every(R), le = (e) => {
|
|
139
|
+
if (!z(e)) return !1;
|
|
140
|
+
let t = Object.keys(e);
|
|
141
|
+
return t.length === 0 || t.length > se ? !1 : t.every((t) => R(e[t]) || B(e[t]));
|
|
142
|
+
}, V = (e) => g(e) ? !0 : e == null ? !1 : typeof e == "string" ? e.trim().length > 0 : R(e) ? !0 : Array.isArray(e) ? e.length > 0 : z(e) ? Object.keys(e).length > 0 : !0, H = (e, t = ce) => e.length > t ? `${e.slice(0, t)}\n… (truncated)` : e, ue = (e) => {
|
|
143
|
+
try {
|
|
144
|
+
let t = JSON.stringify(e, null, 2);
|
|
145
|
+
return t === void 0 ? String(e) : H(t);
|
|
146
|
+
} catch {
|
|
147
|
+
return String(e);
|
|
148
|
+
}
|
|
149
|
+
}, U = ({ value: e }) => {
|
|
150
|
+
if (e == null) return /* @__PURE__ */ a("span", {
|
|
151
|
+
className: "font-mono text-muted-foreground",
|
|
152
|
+
children: "null"
|
|
153
|
+
});
|
|
154
|
+
if (typeof e != "string") return /* @__PURE__ */ a("span", {
|
|
155
|
+
className: "font-mono text-foreground",
|
|
156
|
+
children: String(e)
|
|
157
|
+
});
|
|
158
|
+
if (e === "") return /* @__PURE__ */ a("span", {
|
|
159
|
+
className: "text-muted-foreground italic",
|
|
160
|
+
children: "empty"
|
|
161
|
+
});
|
|
162
|
+
let t = e.length > L;
|
|
163
|
+
return /* @__PURE__ */ a("span", {
|
|
164
|
+
className: "text-foreground",
|
|
165
|
+
title: t ? e : void 0,
|
|
166
|
+
children: t ? `${e.slice(0, L)}…` : e
|
|
167
|
+
});
|
|
168
|
+
}, W = ({ value: e }) => e.length === 0 ? /* @__PURE__ */ a("span", {
|
|
169
|
+
className: "text-muted-foreground italic",
|
|
170
|
+
children: "none"
|
|
171
|
+
}) : /* @__PURE__ */ a("span", {
|
|
172
|
+
className: "text-foreground",
|
|
173
|
+
children: e.map((e, t) => /* @__PURE__ */ o("span", { children: [t > 0 && /* @__PURE__ */ a("span", {
|
|
174
|
+
className: "px-1 text-muted-foreground/70",
|
|
175
|
+
children: "·"
|
|
176
|
+
}), /* @__PURE__ */ a(U, { value: e })] }, t))
|
|
177
|
+
}), de = ({ data: e }) => /* @__PURE__ */ a("ul", {
|
|
178
|
+
className: "ocui-tool-kv grid min-w-0 grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1 text-xs",
|
|
179
|
+
children: Object.entries(e).map(([e, t]) => /* @__PURE__ */ o("li", {
|
|
180
|
+
className: "contents",
|
|
181
|
+
children: [/* @__PURE__ */ a("span", {
|
|
182
|
+
className: "break-words text-muted-foreground",
|
|
183
|
+
children: e
|
|
184
|
+
}), /* @__PURE__ */ a("span", {
|
|
185
|
+
className: "min-w-0 break-words whitespace-pre-wrap",
|
|
186
|
+
children: B(t) ? /* @__PURE__ */ a(W, { value: t }) : /* @__PURE__ */ a(U, { value: t })
|
|
187
|
+
})]
|
|
188
|
+
}, e))
|
|
189
|
+
}), fe = ({ value: e }) => /* @__PURE__ */ a("pre", {
|
|
190
|
+
className: "ocui-tool-json overflow-x-auto rounded-md bg-muted/40 px-2.5 py-2 font-mono text-xs text-muted-foreground",
|
|
191
|
+
children: ue(e)
|
|
192
|
+
}), G = ({ value: e }) => g(e) ? /* @__PURE__ */ a(i, { children: e }) : e == null ? null : typeof e == "string" ? e.trim() === "" ? null : /* @__PURE__ */ a("div", {
|
|
193
|
+
className: "whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-muted-foreground",
|
|
194
|
+
children: H(e)
|
|
195
|
+
}) : R(e) ? /* @__PURE__ */ a("div", {
|
|
196
|
+
className: "font-mono text-xs text-foreground",
|
|
197
|
+
children: String(e)
|
|
198
|
+
}) : le(e) ? /* @__PURE__ */ a(de, { data: e }) : B(e) ? /* @__PURE__ */ a("div", {
|
|
199
|
+
className: "text-xs",
|
|
200
|
+
children: /* @__PURE__ */ a(W, { value: e })
|
|
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),
|
|
134
203
|
...t
|
|
135
|
-
}),
|
|
204
|
+
}), me = {
|
|
136
205
|
"input-streaming": "Pending",
|
|
137
206
|
"input-available": "Running",
|
|
138
207
|
"approval-requested": "Pending",
|
|
@@ -140,54 +209,54 @@ var z = ({ className: e, ...t }) => /* @__PURE__ */ a(D, {
|
|
|
140
209
|
"output-available": "Completed",
|
|
141
210
|
"output-error": "Error",
|
|
142
211
|
"output-denied": "Denied"
|
|
143
|
-
},
|
|
144
|
-
"input-streaming": /* @__PURE__ */ a(
|
|
145
|
-
"input-available": /* @__PURE__ */ a(
|
|
146
|
-
"approval-requested": /* @__PURE__ */ a(
|
|
212
|
+
}, he = {
|
|
213
|
+
"input-streaming": /* @__PURE__ */ a(f, { className: "size-3.5 animate-spin motion-reduce:animate-none" }),
|
|
214
|
+
"input-available": /* @__PURE__ */ a(f, { className: "size-3.5 animate-spin motion-reduce:animate-none" }),
|
|
215
|
+
"approval-requested": /* @__PURE__ */ a(u, { className: "size-3.5" }),
|
|
147
216
|
"approval-responded": /* @__PURE__ */ a(s, { className: "size-3.5" }),
|
|
148
217
|
"output-available": /* @__PURE__ */ a(s, { className: "size-3.5" }),
|
|
149
|
-
"output-error": /* @__PURE__ */ a(
|
|
150
|
-
"output-denied": /* @__PURE__ */ a(
|
|
151
|
-
},
|
|
218
|
+
"output-error": /* @__PURE__ */ a(m, { className: "size-3.5 text-destructive" }),
|
|
219
|
+
"output-denied": /* @__PURE__ */ a(m, { className: "size-3.5 text-destructive" })
|
|
220
|
+
}, ge = ({ state: e }) => /* @__PURE__ */ o("span", {
|
|
152
221
|
className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground",
|
|
153
|
-
children: [
|
|
154
|
-
}),
|
|
155
|
-
className:
|
|
222
|
+
children: [he[e], me[e]]
|
|
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),
|
|
156
225
|
...i,
|
|
157
226
|
children: [/* @__PURE__ */ o("div", {
|
|
158
227
|
className: "flex min-w-0 flex-1 items-center gap-2",
|
|
159
|
-
children: [/* @__PURE__ */ a(
|
|
228
|
+
children: [/* @__PURE__ */ a(p, { className: "size-3.5 shrink-0 text-muted-foreground" }), /* @__PURE__ */ a("span", {
|
|
160
229
|
className: "truncate text-sm font-medium",
|
|
161
230
|
children: r ?? t
|
|
162
231
|
})]
|
|
163
232
|
}), /* @__PURE__ */ o("div", {
|
|
164
233
|
className: "flex shrink-0 items-center gap-2",
|
|
165
|
-
children: [/* @__PURE__ */ a(
|
|
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" })]
|
|
166
235
|
})]
|
|
167
|
-
}),
|
|
168
|
-
className:
|
|
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),
|
|
169
238
|
...t
|
|
170
|
-
}),
|
|
171
|
-
className:
|
|
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),
|
|
172
241
|
...n,
|
|
173
242
|
children: [/* @__PURE__ */ a("h4", {
|
|
174
243
|
className: "text-xs font-medium tracking-wide text-muted-foreground uppercase",
|
|
175
244
|
children: "Parameters"
|
|
176
|
-
}), /* @__PURE__ */ a(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
})]
|
|
180
|
-
}), K = ({ className: e, output: t, errorText: n, ...r }) => t || n ? /* @__PURE__ */ o("div", {
|
|
181
|
-
className: S("space-y-1.5 px-2.5 pb-2.5", e),
|
|
245
|
+
}), /* @__PURE__ */ a(G, { value: t })]
|
|
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),
|
|
182
248
|
...r,
|
|
183
249
|
children: [/* @__PURE__ */ a("h4", {
|
|
184
250
|
className: "text-xs font-medium tracking-wide text-muted-foreground uppercase",
|
|
185
251
|
children: n ? "Error" : "Result"
|
|
186
|
-
}), /* @__PURE__ */
|
|
187
|
-
className:
|
|
188
|
-
children:
|
|
252
|
+
}), n ? /* @__PURE__ */ a("div", {
|
|
253
|
+
className: "whitespace-pre-wrap break-words rounded-md bg-destructive/10 px-2.5 py-2 text-xs text-destructive",
|
|
254
|
+
children: n
|
|
255
|
+
}) : /* @__PURE__ */ a("div", {
|
|
256
|
+
className: "text-xs [&_table]:w-full",
|
|
257
|
+
children: /* @__PURE__ */ a(G, { value: t })
|
|
189
258
|
})]
|
|
190
|
-
}) : null,
|
|
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", {
|
|
191
260
|
variants: {
|
|
192
261
|
variant: {
|
|
193
262
|
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
@@ -213,12 +282,12 @@ var z = ({ className: e, ...t }) => /* @__PURE__ */ a(D, {
|
|
|
213
282
|
size: "default"
|
|
214
283
|
}
|
|
215
284
|
});
|
|
216
|
-
function
|
|
217
|
-
return /* @__PURE__ */ a(r ?
|
|
285
|
+
function K({ className: e, variant: t = "default", size: n = "default", asChild: r = !1, ...i }) {
|
|
286
|
+
return /* @__PURE__ */ a(r ? te.Root : "button", {
|
|
218
287
|
"data-slot": "button",
|
|
219
288
|
"data-variant": t,
|
|
220
289
|
"data-size": n,
|
|
221
|
-
className:
|
|
290
|
+
className: T(xe({
|
|
222
291
|
variant: t,
|
|
223
292
|
size: n,
|
|
224
293
|
className: e
|
|
@@ -228,43 +297,43 @@ function J({ className: e, variant: t = "default", size: n = "default", asChild:
|
|
|
228
297
|
}
|
|
229
298
|
//#endregion
|
|
230
299
|
//#region src/internal/tooltip.tsx
|
|
231
|
-
function
|
|
232
|
-
return /* @__PURE__ */ a(
|
|
300
|
+
function q({ delayDuration: e = 0, ...t }) {
|
|
301
|
+
return /* @__PURE__ */ a(C.Provider, {
|
|
233
302
|
"data-slot": "tooltip-provider",
|
|
234
303
|
delayDuration: e,
|
|
235
304
|
...t
|
|
236
305
|
});
|
|
237
306
|
}
|
|
238
|
-
function
|
|
239
|
-
return /* @__PURE__ */ a(
|
|
307
|
+
function J({ ...e }) {
|
|
308
|
+
return /* @__PURE__ */ a(C.Root, {
|
|
240
309
|
"data-slot": "tooltip",
|
|
241
310
|
...e
|
|
242
311
|
});
|
|
243
312
|
}
|
|
244
|
-
function
|
|
245
|
-
return /* @__PURE__ */ a(
|
|
313
|
+
function Y({ ...e }) {
|
|
314
|
+
return /* @__PURE__ */ a(C.Trigger, {
|
|
246
315
|
"data-slot": "tooltip-trigger",
|
|
247
316
|
...e
|
|
248
317
|
});
|
|
249
318
|
}
|
|
250
|
-
function
|
|
251
|
-
return /* @__PURE__ */ a(
|
|
319
|
+
function X({ className: e, sideOffset: t = 0, children: n, ...r }) {
|
|
320
|
+
return /* @__PURE__ */ a(C.Portal, { children: /* @__PURE__ */ o(C.Content, {
|
|
252
321
|
"data-slot": "tooltip-content",
|
|
253
322
|
sideOffset: t,
|
|
254
|
-
className:
|
|
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),
|
|
255
324
|
...r,
|
|
256
|
-
children: [n, /* @__PURE__ */ a(
|
|
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" })]
|
|
257
326
|
}) });
|
|
258
327
|
}
|
|
259
328
|
//#endregion
|
|
260
329
|
//#region src/chat/actions.tsx
|
|
261
|
-
var
|
|
262
|
-
className:
|
|
330
|
+
var Se = ({ className: e, children: t, ...n }) => /* @__PURE__ */ a("div", {
|
|
331
|
+
className: T("-ml-1.5 flex items-center", e),
|
|
263
332
|
...n,
|
|
264
333
|
children: t
|
|
265
|
-
}),
|
|
266
|
-
let l = /* @__PURE__ */ o(
|
|
267
|
-
className:
|
|
334
|
+
}), Ce = ({ tooltip: e, children: t, label: n, className: r, variant: i = "ghost", size: s = "icon", ...c }) => {
|
|
335
|
+
let l = /* @__PURE__ */ o(K, {
|
|
336
|
+
className: T("relative", r),
|
|
268
337
|
size: s,
|
|
269
338
|
type: "button",
|
|
270
339
|
variant: i,
|
|
@@ -274,13 +343,416 @@ var $ = ({ className: e, children: t, ...n }) => /* @__PURE__ */ a("div", {
|
|
|
274
343
|
children: n || e
|
|
275
344
|
})]
|
|
276
345
|
});
|
|
277
|
-
return e ? /* @__PURE__ */ a(
|
|
278
|
-
delayDuration:
|
|
279
|
-
children: /* @__PURE__ */ o(
|
|
346
|
+
return e ? /* @__PURE__ */ a(q, {
|
|
347
|
+
delayDuration: 500,
|
|
348
|
+
children: /* @__PURE__ */ o(J, { children: [/* @__PURE__ */ a(Y, {
|
|
280
349
|
asChild: !0,
|
|
281
350
|
children: l
|
|
282
|
-
}), /* @__PURE__ */ a(
|
|
351
|
+
}), /* @__PURE__ */ a(X, { children: /* @__PURE__ */ a("p", { children: e }) })] })
|
|
283
352
|
}) : l;
|
|
284
353
|
};
|
|
285
354
|
//#endregion
|
|
286
|
-
|
|
355
|
+
//#region src/chat/segments.ts
|
|
356
|
+
function we(e, t) {
|
|
357
|
+
return e.startsWith("tool-") && !t(e);
|
|
358
|
+
}
|
|
359
|
+
function Te(e, t) {
|
|
360
|
+
let n = t?.isPresentationalTool ?? (() => !1), r = -1;
|
|
361
|
+
e.forEach((e, t) => {
|
|
362
|
+
(e.type === "reasoning" || we(e.type, n)) && (r = t);
|
|
363
|
+
});
|
|
364
|
+
let i = [], a = null, o = null, s = (e) => {
|
|
365
|
+
o = null, a || (a = {
|
|
366
|
+
kind: "trace",
|
|
367
|
+
parts: []
|
|
368
|
+
}, i.push(a)), a.parts.push(e);
|
|
369
|
+
};
|
|
370
|
+
return e.forEach((e, t) => {
|
|
371
|
+
if (!(e.type === "step-start" || e.type === "step-finish")) if (e.type === "reasoning") {
|
|
372
|
+
let t = String(e.text ?? ""), n = e.state === "streaming";
|
|
373
|
+
if (!(t.trim() || n)) return;
|
|
374
|
+
s(e);
|
|
375
|
+
} else we(e.type, n) ? s(e) : e.type === "text" && t <= r ? String(e.text ?? "").trim() && s(e) : e.type === "file" ? (a = null, o || (o = {
|
|
376
|
+
kind: "images",
|
|
377
|
+
parts: [],
|
|
378
|
+
index: t
|
|
379
|
+
}, i.push(o)), o.parts.push(e)) : (a = null, o = null, i.push({
|
|
380
|
+
kind: "part",
|
|
381
|
+
part: e,
|
|
382
|
+
index: t
|
|
383
|
+
}));
|
|
384
|
+
}), i;
|
|
385
|
+
}
|
|
386
|
+
function Ee(e, t) {
|
|
387
|
+
return e.some((e) => {
|
|
388
|
+
let n = e.state;
|
|
389
|
+
return typeof n == "string" ? e.type === "reasoning" || e.type === "text" ? n === "streaming" : n === "input-streaming" || n === "input-available" : t;
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
//#endregion
|
|
393
|
+
//#region src/chat/web-search.ts
|
|
394
|
+
function De(e) {
|
|
395
|
+
return typeof e == "object" && !!e && "error" in e && typeof e.error == "string";
|
|
396
|
+
}
|
|
397
|
+
var Oe = /\(\s*(\[[^\]\n]*\]\((?:[^()\n]|\([^()\n]*\))*\))\s*\)/g;
|
|
398
|
+
function ke(e) {
|
|
399
|
+
return e.replace(Oe, "$1");
|
|
400
|
+
}
|
|
401
|
+
var Ae = "tool-webSearch";
|
|
402
|
+
function je(e) {
|
|
403
|
+
try {
|
|
404
|
+
let t = new URL(e);
|
|
405
|
+
return `${t.hostname.toLowerCase()}${t.pathname.replace(/\/$/, "")}${t.search}`;
|
|
406
|
+
} catch {
|
|
407
|
+
return e.replace(/#.*$/, "").replace(/\/$/, "");
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
function Me(e, t) {
|
|
411
|
+
let n = t?.toolType ?? Ae, r = /* @__PURE__ */ new Set(), i = [];
|
|
412
|
+
for (let t of e) {
|
|
413
|
+
if (t.type !== n || t.state !== "output-available" || De(t.output)) continue;
|
|
414
|
+
let e = t.output?.results;
|
|
415
|
+
if (Array.isArray(e)) for (let t of e) {
|
|
416
|
+
if (typeof t?.url != "string") continue;
|
|
417
|
+
let e = je(t.url);
|
|
418
|
+
r.has(e) || (r.add(e), i.push({
|
|
419
|
+
url: t.url,
|
|
420
|
+
title: typeof t.title == "string" ? t.title : void 0
|
|
421
|
+
}));
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return i;
|
|
425
|
+
}
|
|
426
|
+
//#endregion
|
|
427
|
+
//#region src/chat/turn-view.ts
|
|
428
|
+
function Ne(e, t) {
|
|
429
|
+
let n = t?.isSearchTool ?? (() => !1), r = t?.messageLoading, i = Te(e, { isPresentationalTool: t?.isPresentationalTool }), a = i.flatMap((e) => e.kind === "trace" ? e.parts : []), o = i.filter((e) => e.kind === "part" && e.part.type === "text"), s = o.some((e) => String(e.part.text ?? "").trim() !== ""), c = s && o.some((e) => e.part.state === "streaming"), l = a.some((e) => e.type === "reasoning" && String(e.text ?? "").trim() !== ""), u = a.some((e) => e.type.startsWith("tool-")), d = i.length > 0, f = a.some((e) => e.type === "reasoning" && e.state === "streaming"), p;
|
|
430
|
+
for (let e of a) {
|
|
431
|
+
if (!e.type.startsWith("tool-")) continue;
|
|
432
|
+
let t = String(e.state ?? "");
|
|
433
|
+
t === "output-available" || t === "output-error" || t === "output-denied" || (p = e.type);
|
|
434
|
+
}
|
|
435
|
+
let m = a.length > 0 && Ee(a, r ?? !1), h = (r ?? !0) && !s, g = a.length > 0 ? {
|
|
436
|
+
parts: a,
|
|
437
|
+
isLoading: h
|
|
438
|
+
} : null, _;
|
|
439
|
+
_ = d ? h ? m && f ? "reasoning" : m && p && n(p) ? "searching" : m && p ? "tooling" : l ? "reasoning" : u ? "tooling" : "reasoning" : c ? "answering" : "settled" : h ? "waiting" : "settled";
|
|
440
|
+
let v = d ? l ? "reasoning" : "tools" : "waiting";
|
|
441
|
+
return {
|
|
442
|
+
phase: _,
|
|
443
|
+
segments: i,
|
|
444
|
+
trace: g,
|
|
445
|
+
sources: Me(e),
|
|
446
|
+
activityKind: v,
|
|
447
|
+
hasFinalAnswer: s
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
//#endregion
|
|
451
|
+
//#region src/chat/activity-labels.ts
|
|
452
|
+
var Pe = [
|
|
453
|
+
{
|
|
454
|
+
active: "Thinking",
|
|
455
|
+
done: "Thought"
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
active: "Reading",
|
|
459
|
+
done: "Read"
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
active: "Drafting",
|
|
463
|
+
done: "Drafted"
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
active: "Shaping",
|
|
467
|
+
done: "Shaped"
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
active: "Composing",
|
|
471
|
+
done: "Composed"
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
active: "Polishing",
|
|
475
|
+
done: "Polished"
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
active: "Mapping",
|
|
479
|
+
done: "Mapped"
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
active: "Sorting",
|
|
483
|
+
done: "Sorted"
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
active: "Refining",
|
|
487
|
+
done: "Refined"
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
active: "Working",
|
|
491
|
+
done: "Done"
|
|
492
|
+
}
|
|
493
|
+
], Fe = {
|
|
494
|
+
waiting: Pe,
|
|
495
|
+
reasoning: Pe,
|
|
496
|
+
tools: [{
|
|
497
|
+
active: "Working",
|
|
498
|
+
done: "Worked"
|
|
499
|
+
}]
|
|
500
|
+
};
|
|
501
|
+
function Z({ kind: e, active: t, seed: n, elapsedSeconds: r, verb: i }) {
|
|
502
|
+
let a;
|
|
503
|
+
if (i !== void 0) a = i;
|
|
504
|
+
else {
|
|
505
|
+
let r = Fe[e], i = r[Math.abs(n) % r.length];
|
|
506
|
+
a = t ? i.active : i.done;
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
verb: a,
|
|
510
|
+
elapsedSeconds: r > 0 ? r : 0
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
function Q(e) {
|
|
514
|
+
let { verb: t, elapsedSeconds: n } = Z(e);
|
|
515
|
+
return n <= 0 ? t : `${t} for ${n}s`;
|
|
516
|
+
}
|
|
517
|
+
function Ie(e, t) {
|
|
518
|
+
let n = Infinity, r = -Infinity, i = !1;
|
|
519
|
+
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
|
+
if (n === Infinity) return 0;
|
|
521
|
+
let a = i && Number.isFinite(t) ? t : r;
|
|
522
|
+
return a === -Infinity ? 0 : Math.max(0, Math.floor((a - n) / 1e3));
|
|
523
|
+
}
|
|
524
|
+
function Le(e) {
|
|
525
|
+
let t = 0;
|
|
526
|
+
for (let n = 0; n < e.length; n += 1) t = t * 31 + e.charCodeAt(n) | 0;
|
|
527
|
+
return t;
|
|
528
|
+
}
|
|
529
|
+
//#endregion
|
|
530
|
+
//#region src/chat/message-trace.tsx
|
|
531
|
+
function Re(e) {
|
|
532
|
+
let t = e.replace(/^tool-/, "").replace(/[_-]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").trim();
|
|
533
|
+
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
534
|
+
}
|
|
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;
|
|
537
|
+
for (let t of e) if (t.type.startsWith("tool-")) {
|
|
538
|
+
m = !0;
|
|
539
|
+
let e = String(t.state ?? "");
|
|
540
|
+
e === "output-available" || e === "output-error" || e === "output-denied" || (h = t.type), p.push({
|
|
541
|
+
kind: "tool",
|
|
542
|
+
label: i?.(t.type) ?? Re(t.type),
|
|
543
|
+
state: e,
|
|
544
|
+
toolType: t.type
|
|
545
|
+
});
|
|
546
|
+
} else t.type === "text" && String(t.text ?? "").trim() && p.push({
|
|
547
|
+
kind: "note",
|
|
548
|
+
text: String(t.text)
|
|
549
|
+
});
|
|
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",
|
|
553
|
+
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();
|
|
558
|
+
return /* @__PURE__ */ o("div", {
|
|
559
|
+
className: T("not-prose flex flex-col", u),
|
|
560
|
+
children: [/* @__PURE__ */ a("button", {
|
|
561
|
+
type: "button",
|
|
562
|
+
"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",
|
|
567
|
+
children: /* @__PURE__ */ o("span", {
|
|
568
|
+
className: T(t && "ocui-shimmer"),
|
|
569
|
+
children: [S, w ? "..." : ""]
|
|
570
|
+
})
|
|
571
|
+
}), E && C && /* @__PURE__ */ o("div", {
|
|
572
|
+
id: O,
|
|
573
|
+
className: "mt-2 flex flex-col gap-2",
|
|
574
|
+
children: [f && /* @__PURE__ */ a(ne, {
|
|
575
|
+
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", {
|
|
578
|
+
className: "flex flex-col",
|
|
579
|
+
children: p.map((e, t) => /* @__PURE__ */ a(Be, {
|
|
580
|
+
node: e,
|
|
581
|
+
isFirst: t === 0,
|
|
582
|
+
isLast: t === p.length - 1,
|
|
583
|
+
getToolIcon: s
|
|
584
|
+
}, `step-${t}`))
|
|
585
|
+
})]
|
|
586
|
+
})]
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
ze.displayName = "MessageTrace";
|
|
590
|
+
function Be({ node: e, isFirst: t, isLast: n, getToolIcon: r }) {
|
|
591
|
+
return /* @__PURE__ */ o("div", {
|
|
592
|
+
className: "flex items-stretch gap-2.5",
|
|
593
|
+
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
|
+
})
|
|
615
|
+
})]
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
function Ve({ node: e, getToolIcon: t }) {
|
|
619
|
+
let n = "flex items-center justify-center bg-background py-0.5";
|
|
620
|
+
return e.kind === "note" ? /* @__PURE__ */ a("div", {
|
|
621
|
+
className: n,
|
|
622
|
+
children: /* @__PURE__ */ a("div", { className: "size-1 rounded-full bg-muted-foreground/60" })
|
|
623
|
+
}) : e.kind === "tool" ? e.state === "output-error" || e.state === "output-denied" ? /* @__PURE__ */ a("div", {
|
|
624
|
+
className: n,
|
|
625
|
+
children: /* @__PURE__ */ a(m, { className: "size-3.5 text-destructive" })
|
|
626
|
+
}) : e.state === "output-available" ? /* @__PURE__ */ a("div", {
|
|
627
|
+
className: n,
|
|
628
|
+
children: /* @__PURE__ */ a(t?.(e.toolType) ?? s, { className: "size-3.5 text-muted-foreground" })
|
|
629
|
+
}) : /* @__PURE__ */ a("div", {
|
|
630
|
+
className: n,
|
|
631
|
+
children: /* @__PURE__ */ a(f, { className: "size-3.5 animate-spin text-muted-foreground motion-reduce:animate-none" })
|
|
632
|
+
}) : /* @__PURE__ */ a("div", {
|
|
633
|
+
className: n,
|
|
634
|
+
children: /* @__PURE__ */ a(l, { className: "size-4 text-muted-foreground" })
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
//#endregion
|
|
638
|
+
//#region src/chat/use-activity-clock.ts
|
|
639
|
+
function He(e, t) {
|
|
640
|
+
let n = b(null), [r, i] = x(() => ({
|
|
641
|
+
seed: t,
|
|
642
|
+
elapsedSeconds: 0,
|
|
643
|
+
nowMs: Date.now()
|
|
644
|
+
}));
|
|
645
|
+
return y(() => {
|
|
646
|
+
if (!e) {
|
|
647
|
+
if (n.current === null) return;
|
|
648
|
+
let e = n.current;
|
|
649
|
+
n.current = null;
|
|
650
|
+
let t = setTimeout(() => {
|
|
651
|
+
i((t) => ({
|
|
652
|
+
...t,
|
|
653
|
+
elapsedSeconds: Math.max(1, Math.round((Date.now() - e) / 1e3)),
|
|
654
|
+
nowMs: Date.now()
|
|
655
|
+
}));
|
|
656
|
+
}, 0);
|
|
657
|
+
return () => clearTimeout(t);
|
|
658
|
+
}
|
|
659
|
+
let r;
|
|
660
|
+
n.current === null && (n.current = Date.now(), r = setTimeout(() => {
|
|
661
|
+
i({
|
|
662
|
+
seed: t,
|
|
663
|
+
elapsedSeconds: 0,
|
|
664
|
+
nowMs: Date.now()
|
|
665
|
+
});
|
|
666
|
+
}, 0));
|
|
667
|
+
let a = setInterval(() => {
|
|
668
|
+
n.current !== null && i((e) => ({
|
|
669
|
+
...e,
|
|
670
|
+
elapsedSeconds: Math.floor((Date.now() - n.current) / 1e3),
|
|
671
|
+
nowMs: Date.now()
|
|
672
|
+
}));
|
|
673
|
+
}, 1e3);
|
|
674
|
+
return () => {
|
|
675
|
+
r && clearTimeout(r), clearInterval(a);
|
|
676
|
+
};
|
|
677
|
+
}, [e, t]), r;
|
|
678
|
+
}
|
|
679
|
+
//#endregion
|
|
680
|
+
//#region src/chat/sources.tsx
|
|
681
|
+
function Ue(e) {
|
|
682
|
+
return `Searched ${e} source${e === 1 ? "" : "s"}`;
|
|
683
|
+
}
|
|
684
|
+
function $(e) {
|
|
685
|
+
try {
|
|
686
|
+
return new URL(e).hostname;
|
|
687
|
+
} catch {
|
|
688
|
+
return e;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
function We(e) {
|
|
692
|
+
return `https://www.google.com/s2/favicons?domain=${$(e)}&sz=32`;
|
|
693
|
+
}
|
|
694
|
+
function Ge({ url: e, getFaviconUrl: t }) {
|
|
695
|
+
let n = t(e), [r, i] = x(!1);
|
|
696
|
+
return !n || r ? /* @__PURE__ */ a(d, { className: "size-3.5 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ a("img", {
|
|
697
|
+
src: n,
|
|
698
|
+
alt: "",
|
|
699
|
+
className: "size-3.5 shrink-0 rounded-xs",
|
|
700
|
+
onError: () => i(!0)
|
|
701
|
+
});
|
|
702
|
+
}
|
|
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),
|
|
705
|
+
...i,
|
|
706
|
+
children: [/* @__PURE__ */ o(A, {
|
|
707
|
+
className: "group flex items-center gap-1 self-start text-sm text-muted-foreground transition-colors hover:text-foreground",
|
|
708
|
+
children: [/* @__PURE__ */ a("span", { children: t(e.length) }), /* @__PURE__ */ a(c, { className: "size-2.5 transition-transform group-data-[state=open]:rotate-180" })]
|
|
709
|
+
}), /* @__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}`);
|
|
733
|
+
})
|
|
734
|
+
})]
|
|
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 }) => {
|
|
736
|
+
let f = s ?? (e ? "default" : "ghost"), p = /* @__PURE__ */ a(K, {
|
|
737
|
+
...u,
|
|
738
|
+
"aria-label": n,
|
|
739
|
+
"aria-pressed": e,
|
|
740
|
+
className: T(i),
|
|
741
|
+
size: c,
|
|
742
|
+
type: "button",
|
|
743
|
+
variant: f,
|
|
744
|
+
onClick: (n) => {
|
|
745
|
+
l?.(n), t(!e);
|
|
746
|
+
},
|
|
747
|
+
children: /* @__PURE__ */ a(d, {})
|
|
748
|
+
});
|
|
749
|
+
return r ? /* @__PURE__ */ a(q, {
|
|
750
|
+
delayDuration: 300,
|
|
751
|
+
children: /* @__PURE__ */ o(J, { children: [/* @__PURE__ */ a(Y, {
|
|
752
|
+
asChild: !0,
|
|
753
|
+
children: p
|
|
754
|
+
}), /* @__PURE__ */ a(X, { children: /* @__PURE__ */ a("p", { children: r }) })] })
|
|
755
|
+
}) : p;
|
|
756
|
+
};
|
|
757
|
+
//#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 };
|
package/dist/tokens.css
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ocai/app-sdk-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Shared design tokens and AI-app UI primitives for OceanAI products.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -47,21 +47,26 @@
|
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@streamdown/math": "^1.0.2",
|
|
50
|
+
"@testing-library/dom": "^10.4.1",
|
|
51
|
+
"@testing-library/react": "^16.3.2",
|
|
50
52
|
"@types/node": "^22.0.0",
|
|
51
53
|
"@types/react": "^19.0.0",
|
|
52
54
|
"@types/react-dom": "^19.0.0",
|
|
53
55
|
"@vitejs/plugin-react": "^6.0.1",
|
|
54
56
|
"ai": "^6.0.0",
|
|
57
|
+
"jsdom": "^26.1.0",
|
|
55
58
|
"react": "^19.0.0",
|
|
56
59
|
"react-dom": "^19.0.0",
|
|
57
60
|
"streamdown": "^2.5.0",
|
|
58
61
|
"typescript": "~5.6.0",
|
|
59
62
|
"vite": "^8.0.16",
|
|
60
|
-
"vite-plugin-dts": "^4.5.4"
|
|
63
|
+
"vite-plugin-dts": "^4.5.4",
|
|
64
|
+
"vitest": "^4.1.10"
|
|
61
65
|
},
|
|
62
66
|
"scripts": {
|
|
63
67
|
"build": "vite build && cp src/tokens.css src/chat/chat.css dist/",
|
|
64
68
|
"dev": "vite build --watch",
|
|
65
|
-
"typecheck": "tsc --noEmit"
|
|
69
|
+
"typecheck": "tsc --noEmit",
|
|
70
|
+
"test": "vitest run"
|
|
66
71
|
}
|
|
67
72
|
}
|