@codrstudio/openclaude-chat 0.1.0 → 0.1.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/components/StreamingIndicator.js +5 -5
- package/dist/display/DisplayReactRenderer.js +12 -12
- package/dist/display/react-sandbox/bootstrap.js +150 -150
- package/dist/styles.css +1 -2
- package/package.json +64 -61
- package/src/components/Chat.tsx +107 -107
- package/src/components/ErrorNote.tsx +35 -35
- package/src/components/LazyRender.tsx +42 -42
- package/src/components/Markdown.tsx +114 -114
- package/src/components/MessageBubble.tsx +107 -107
- package/src/components/MessageInput.tsx +421 -421
- package/src/components/MessageList.tsx +153 -153
- package/src/components/StreamingIndicator.tsx +19 -19
- package/src/display/AlertRenderer.tsx +23 -23
- package/src/display/CarouselRenderer.tsx +141 -141
- package/src/display/ChartRenderer.tsx +195 -195
- package/src/display/ChoiceButtonsRenderer.tsx +114 -114
- package/src/display/CodeBlockRenderer.tsx +49 -49
- package/src/display/ComparisonTableRenderer.tsx +132 -132
- package/src/display/DataTableRenderer.tsx +144 -144
- package/src/display/DisplayReactRenderer.tsx +269 -269
- package/src/display/FileCardRenderer.tsx +55 -55
- package/src/display/GalleryRenderer.tsx +65 -65
- package/src/display/ImageViewerRenderer.tsx +114 -114
- package/src/display/LinkPreviewRenderer.tsx +74 -74
- package/src/display/MapViewRenderer.tsx +75 -75
- package/src/display/MetricCardRenderer.tsx +29 -29
- package/src/display/PriceHighlightRenderer.tsx +62 -62
- package/src/display/ProductCardRenderer.tsx +112 -112
- package/src/display/ProgressStepsRenderer.tsx +59 -59
- package/src/display/SourcesListRenderer.tsx +47 -47
- package/src/display/SpreadsheetRenderer.tsx +86 -86
- package/src/display/StepTimelineRenderer.tsx +75 -75
- package/src/display/index.ts +21 -21
- package/src/display/react-sandbox/bootstrap.ts +155 -155
- package/src/display/registry.ts +84 -84
- package/src/display/sdk-types.ts +217 -217
- package/src/hooks/ChatProvider.tsx +21 -21
- package/src/hooks/useIsMobile.ts +15 -15
- package/src/hooks/useOpenClaudeChat.ts +476 -476
- package/src/index.ts +76 -76
- package/src/lib/utils.ts +6 -6
- package/src/parts/PartErrorBoundary.tsx +51 -51
- package/src/parts/PartRenderer.tsx +145 -145
- package/src/parts/ReasoningBlock.tsx +41 -41
- package/src/parts/ToolActivity.tsx +78 -78
- package/src/parts/ToolResult.tsx +79 -79
- package/src/styles.css +2 -2
- package/src/types.ts +41 -41
- package/src/ui/alert.tsx +77 -77
- package/src/ui/badge.tsx +36 -36
- package/src/ui/button.tsx +54 -54
- package/src/ui/card.tsx +68 -68
- package/src/ui/collapsible.tsx +7 -7
- package/src/ui/dialog.tsx +122 -122
- package/src/ui/dropdown-menu.tsx +76 -76
- package/src/ui/input.tsx +24 -24
- package/src/ui/progress.tsx +36 -36
- package/src/ui/scroll-area.tsx +48 -48
- package/src/ui/separator.tsx +31 -31
- package/src/ui/skeleton.tsx +9 -9
- package/src/ui/table.tsx +114 -114
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
import { Check, Download, FileText, FilePlus, FolderSearch, Globe, Loader2, Pencil, Search, Terminal, Wrench, type LucideIcon } from "lucide-react";
|
|
2
|
-
import { cn } from "../lib/utils.js";
|
|
3
|
-
|
|
4
|
-
export type ToolActivityState = "call" | "partial-call" | "result";
|
|
5
|
-
|
|
6
|
-
export interface ToolActivityProps {
|
|
7
|
-
toolName: string;
|
|
8
|
-
state: ToolActivityState;
|
|
9
|
-
args?: Record<string, unknown>;
|
|
10
|
-
className?: string;
|
|
11
|
-
iconMap?: Partial<Record<string, LucideIcon>>;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const defaultToolIconMap: Record<string, LucideIcon> = {
|
|
15
|
-
WebSearch: Globe,
|
|
16
|
-
Bash: Terminal,
|
|
17
|
-
Read: FileText,
|
|
18
|
-
Edit: Pencil,
|
|
19
|
-
Write: FilePlus,
|
|
20
|
-
Grep: Search,
|
|
21
|
-
Glob: FolderSearch,
|
|
22
|
-
WebFetch: Download,
|
|
23
|
-
ListDir: FolderSearch,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
function formatToolName(name: string): string {
|
|
27
|
-
return name
|
|
28
|
-
.replace(/_/g, " ")
|
|
29
|
-
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
30
|
-
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function resolveIcon(toolName: string, iconMap: Record<string, LucideIcon | undefined>): LucideIcon {
|
|
34
|
-
return iconMap[toolName] ?? Wrench;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function formatArgs(toolName: string, args?: Record<string, unknown>): string | null {
|
|
38
|
-
if (!args) return null;
|
|
39
|
-
if (toolName === "Bash" && args.command) return String(args.command);
|
|
40
|
-
if (toolName === "Read" && args.path) return String(args.path);
|
|
41
|
-
if (toolName === "Edit" && args.file_path) return String(args.file_path);
|
|
42
|
-
if (toolName === "Write" && args.file_path) return String(args.file_path);
|
|
43
|
-
if (toolName === "Grep" && args.pattern) return String(args.pattern);
|
|
44
|
-
if (toolName === "Glob" && args.pattern) return String(args.pattern);
|
|
45
|
-
if (toolName === "WebSearch" && args.query) return String(args.query);
|
|
46
|
-
if (toolName === "ListDir" && args.path) return String(args.path);
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function ToolActivity({ toolName, state, args, className, iconMap }: ToolActivityProps) {
|
|
51
|
-
const mergedIconMap = iconMap ? { ...defaultToolIconMap, ...iconMap } : defaultToolIconMap;
|
|
52
|
-
const Icon = resolveIcon(toolName, mergedIconMap);
|
|
53
|
-
const isActive = state === "call" || state === "partial-call";
|
|
54
|
-
const displayName = formatToolName(toolName);
|
|
55
|
-
const argsPreview = formatArgs(toolName, args);
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<div className={cn(
|
|
59
|
-
"flex items-center gap-2 rounded-md border border-border bg-muted/40 px-3 py-2 text-sm",
|
|
60
|
-
className
|
|
61
|
-
)}>
|
|
62
|
-
<span className="text-muted-foreground shrink-0" aria-hidden="true">
|
|
63
|
-
<Icon size={14} />
|
|
64
|
-
</span>
|
|
65
|
-
<span className="font-medium font-mono text-foreground">{displayName}</span>
|
|
66
|
-
{argsPreview && (
|
|
67
|
-
<span className="truncate text-xs text-muted-foreground font-mono max-w-[300px]">{argsPreview}</span>
|
|
68
|
-
)}
|
|
69
|
-
<span className="ml-auto text-muted-foreground">
|
|
70
|
-
{isActive ? (
|
|
71
|
-
<Loader2 size={14} className="animate-spin" aria-label="Executando..." />
|
|
72
|
-
) : (
|
|
73
|
-
<Check size={14} aria-label="Concluido" />
|
|
74
|
-
)}
|
|
75
|
-
</span>
|
|
76
|
-
</div>
|
|
77
|
-
);
|
|
78
|
-
}
|
|
1
|
+
import { Check, Download, FileText, FilePlus, FolderSearch, Globe, Loader2, Pencil, Search, Terminal, Wrench, type LucideIcon } from "lucide-react";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
|
|
4
|
+
export type ToolActivityState = "call" | "partial-call" | "result";
|
|
5
|
+
|
|
6
|
+
export interface ToolActivityProps {
|
|
7
|
+
toolName: string;
|
|
8
|
+
state: ToolActivityState;
|
|
9
|
+
args?: Record<string, unknown>;
|
|
10
|
+
className?: string;
|
|
11
|
+
iconMap?: Partial<Record<string, LucideIcon>>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const defaultToolIconMap: Record<string, LucideIcon> = {
|
|
15
|
+
WebSearch: Globe,
|
|
16
|
+
Bash: Terminal,
|
|
17
|
+
Read: FileText,
|
|
18
|
+
Edit: Pencil,
|
|
19
|
+
Write: FilePlus,
|
|
20
|
+
Grep: Search,
|
|
21
|
+
Glob: FolderSearch,
|
|
22
|
+
WebFetch: Download,
|
|
23
|
+
ListDir: FolderSearch,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function formatToolName(name: string): string {
|
|
27
|
+
return name
|
|
28
|
+
.replace(/_/g, " ")
|
|
29
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
30
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolveIcon(toolName: string, iconMap: Record<string, LucideIcon | undefined>): LucideIcon {
|
|
34
|
+
return iconMap[toolName] ?? Wrench;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function formatArgs(toolName: string, args?: Record<string, unknown>): string | null {
|
|
38
|
+
if (!args) return null;
|
|
39
|
+
if (toolName === "Bash" && args.command) return String(args.command);
|
|
40
|
+
if (toolName === "Read" && args.path) return String(args.path);
|
|
41
|
+
if (toolName === "Edit" && args.file_path) return String(args.file_path);
|
|
42
|
+
if (toolName === "Write" && args.file_path) return String(args.file_path);
|
|
43
|
+
if (toolName === "Grep" && args.pattern) return String(args.pattern);
|
|
44
|
+
if (toolName === "Glob" && args.pattern) return String(args.pattern);
|
|
45
|
+
if (toolName === "WebSearch" && args.query) return String(args.query);
|
|
46
|
+
if (toolName === "ListDir" && args.path) return String(args.path);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function ToolActivity({ toolName, state, args, className, iconMap }: ToolActivityProps) {
|
|
51
|
+
const mergedIconMap = iconMap ? { ...defaultToolIconMap, ...iconMap } : defaultToolIconMap;
|
|
52
|
+
const Icon = resolveIcon(toolName, mergedIconMap);
|
|
53
|
+
const isActive = state === "call" || state === "partial-call";
|
|
54
|
+
const displayName = formatToolName(toolName);
|
|
55
|
+
const argsPreview = formatArgs(toolName, args);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div className={cn(
|
|
59
|
+
"flex items-center gap-2 rounded-md border border-border bg-muted/40 px-3 py-2 text-sm",
|
|
60
|
+
className
|
|
61
|
+
)}>
|
|
62
|
+
<span className="text-muted-foreground shrink-0" aria-hidden="true">
|
|
63
|
+
<Icon size={14} />
|
|
64
|
+
</span>
|
|
65
|
+
<span className="font-medium font-mono text-foreground">{displayName}</span>
|
|
66
|
+
{argsPreview && (
|
|
67
|
+
<span className="truncate text-xs text-muted-foreground font-mono max-w-[300px]">{argsPreview}</span>
|
|
68
|
+
)}
|
|
69
|
+
<span className="ml-auto text-muted-foreground">
|
|
70
|
+
{isActive ? (
|
|
71
|
+
<Loader2 size={14} className="animate-spin" aria-label="Executando..." />
|
|
72
|
+
) : (
|
|
73
|
+
<Check size={14} aria-label="Concluido" />
|
|
74
|
+
)}
|
|
75
|
+
</span>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
package/src/parts/ToolResult.tsx
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
import { AlertCircle, CheckCircle, ChevronDown, ChevronRight } from "lucide-react";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible.js";
|
|
4
|
-
import { cn } from "../lib/utils.js";
|
|
5
|
-
|
|
6
|
-
export interface ToolResultProps {
|
|
7
|
-
toolName: string;
|
|
8
|
-
result: unknown;
|
|
9
|
-
isError?: boolean;
|
|
10
|
-
className?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function serializeResult(result: unknown): string {
|
|
14
|
-
try {
|
|
15
|
-
if (typeof result === "object" && result !== null && "value" in (result as Record<string, unknown>)) {
|
|
16
|
-
return String((result as Record<string, unknown>).value);
|
|
17
|
-
}
|
|
18
|
-
return JSON.stringify(result, null, 2);
|
|
19
|
-
} catch {
|
|
20
|
-
return String(result);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function extractPreview(result: unknown): string | null {
|
|
25
|
-
if (typeof result === "string") return result.length > 120 ? result.slice(0, 120) + "..." : result;
|
|
26
|
-
if (typeof result === "object" && result !== null) {
|
|
27
|
-
const r = result as Record<string, unknown>;
|
|
28
|
-
if (typeof r.value === "string") {
|
|
29
|
-
const v = r.value as string;
|
|
30
|
-
return v.length > 120 ? v.slice(0, 120) + "..." : v;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function ToolResult({ toolName, result, isError = false, className }: ToolResultProps) {
|
|
37
|
-
const [expanded, setExpanded] = useState(false);
|
|
38
|
-
const serialized = serializeResult(result);
|
|
39
|
-
const preview = extractPreview(result);
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<Collapsible open={expanded} onOpenChange={setExpanded} className={className}>
|
|
43
|
-
<div className={cn(
|
|
44
|
-
"rounded-md border text-sm overflow-hidden",
|
|
45
|
-
isError
|
|
46
|
-
? "border-destructive/40 bg-destructive/5"
|
|
47
|
-
: "border-border bg-muted/40"
|
|
48
|
-
)}>
|
|
49
|
-
<CollapsibleTrigger
|
|
50
|
-
className={cn(
|
|
51
|
-
"flex items-center gap-2 w-full px-3 py-2 text-left font-medium hover:bg-muted/60 cursor-pointer",
|
|
52
|
-
)}
|
|
53
|
-
aria-expanded={expanded}
|
|
54
|
-
>
|
|
55
|
-
{isError ? (
|
|
56
|
-
<AlertCircle className="h-3.5 w-3.5 shrink-0 text-destructive" aria-hidden="true" />
|
|
57
|
-
) : (
|
|
58
|
-
<CheckCircle className="h-3.5 w-3.5 shrink-0 text-muted-foreground" aria-hidden="true" />
|
|
59
|
-
)}
|
|
60
|
-
<span className={cn("font-mono text-xs", isError ? "text-destructive" : "text-foreground")}>
|
|
61
|
-
{isError ? `${toolName} erro` : `${toolName} ok`}
|
|
62
|
-
</span>
|
|
63
|
-
{!expanded && preview && (
|
|
64
|
-
<span className="truncate text-xs text-muted-foreground font-mono max-w-[400px] ml-1">{preview}</span>
|
|
65
|
-
)}
|
|
66
|
-
{expanded
|
|
67
|
-
? <ChevronDown className="h-3.5 w-3.5 shrink-0 text-muted-foreground ml-auto" aria-hidden="true" />
|
|
68
|
-
: <ChevronRight className="h-3.5 w-3.5 shrink-0 text-muted-foreground ml-auto" aria-hidden="true" />
|
|
69
|
-
}
|
|
70
|
-
</CollapsibleTrigger>
|
|
71
|
-
<CollapsibleContent>
|
|
72
|
-
<pre className="max-h-80 overflow-y-auto p-3 font-mono text-xs whitespace-pre-wrap break-all bg-muted/30 border-t border-border">
|
|
73
|
-
{serialized}
|
|
74
|
-
</pre>
|
|
75
|
-
</CollapsibleContent>
|
|
76
|
-
</div>
|
|
77
|
-
</Collapsible>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
1
|
+
import { AlertCircle, CheckCircle, ChevronDown, ChevronRight } from "lucide-react";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible.js";
|
|
4
|
+
import { cn } from "../lib/utils.js";
|
|
5
|
+
|
|
6
|
+
export interface ToolResultProps {
|
|
7
|
+
toolName: string;
|
|
8
|
+
result: unknown;
|
|
9
|
+
isError?: boolean;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function serializeResult(result: unknown): string {
|
|
14
|
+
try {
|
|
15
|
+
if (typeof result === "object" && result !== null && "value" in (result as Record<string, unknown>)) {
|
|
16
|
+
return String((result as Record<string, unknown>).value);
|
|
17
|
+
}
|
|
18
|
+
return JSON.stringify(result, null, 2);
|
|
19
|
+
} catch {
|
|
20
|
+
return String(result);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function extractPreview(result: unknown): string | null {
|
|
25
|
+
if (typeof result === "string") return result.length > 120 ? result.slice(0, 120) + "..." : result;
|
|
26
|
+
if (typeof result === "object" && result !== null) {
|
|
27
|
+
const r = result as Record<string, unknown>;
|
|
28
|
+
if (typeof r.value === "string") {
|
|
29
|
+
const v = r.value as string;
|
|
30
|
+
return v.length > 120 ? v.slice(0, 120) + "..." : v;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function ToolResult({ toolName, result, isError = false, className }: ToolResultProps) {
|
|
37
|
+
const [expanded, setExpanded] = useState(false);
|
|
38
|
+
const serialized = serializeResult(result);
|
|
39
|
+
const preview = extractPreview(result);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Collapsible open={expanded} onOpenChange={setExpanded} className={className}>
|
|
43
|
+
<div className={cn(
|
|
44
|
+
"rounded-md border text-sm overflow-hidden",
|
|
45
|
+
isError
|
|
46
|
+
? "border-destructive/40 bg-destructive/5"
|
|
47
|
+
: "border-border bg-muted/40"
|
|
48
|
+
)}>
|
|
49
|
+
<CollapsibleTrigger
|
|
50
|
+
className={cn(
|
|
51
|
+
"flex items-center gap-2 w-full px-3 py-2 text-left font-medium hover:bg-muted/60 cursor-pointer",
|
|
52
|
+
)}
|
|
53
|
+
aria-expanded={expanded}
|
|
54
|
+
>
|
|
55
|
+
{isError ? (
|
|
56
|
+
<AlertCircle className="h-3.5 w-3.5 shrink-0 text-destructive" aria-hidden="true" />
|
|
57
|
+
) : (
|
|
58
|
+
<CheckCircle className="h-3.5 w-3.5 shrink-0 text-muted-foreground" aria-hidden="true" />
|
|
59
|
+
)}
|
|
60
|
+
<span className={cn("font-mono text-xs", isError ? "text-destructive" : "text-foreground")}>
|
|
61
|
+
{isError ? `${toolName} erro` : `${toolName} ok`}
|
|
62
|
+
</span>
|
|
63
|
+
{!expanded && preview && (
|
|
64
|
+
<span className="truncate text-xs text-muted-foreground font-mono max-w-[400px] ml-1">{preview}</span>
|
|
65
|
+
)}
|
|
66
|
+
{expanded
|
|
67
|
+
? <ChevronDown className="h-3.5 w-3.5 shrink-0 text-muted-foreground ml-auto" aria-hidden="true" />
|
|
68
|
+
: <ChevronRight className="h-3.5 w-3.5 shrink-0 text-muted-foreground ml-auto" aria-hidden="true" />
|
|
69
|
+
}
|
|
70
|
+
</CollapsibleTrigger>
|
|
71
|
+
<CollapsibleContent>
|
|
72
|
+
<pre className="max-h-80 overflow-y-auto p-3 font-mono text-xs whitespace-pre-wrap break-all bg-muted/30 border-t border-border">
|
|
73
|
+
{serialized}
|
|
74
|
+
</pre>
|
|
75
|
+
</CollapsibleContent>
|
|
76
|
+
</div>
|
|
77
|
+
</Collapsible>
|
|
78
|
+
);
|
|
79
|
+
}
|
package/src/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
@import "tailwindcss/utilities" layer(utilities);
|
|
2
|
-
@source "./**/*.tsx";
|
|
1
|
+
@import "tailwindcss/utilities" layer(utilities);
|
|
2
|
+
@source "./**/*.tsx";
|
package/src/types.ts
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
// Tipos locais usados pelo @codrstudio/openclaude-chat.
|
|
2
|
-
// Nao depende de @ai-sdk/react. Modelo inspirado nos "parts" do ai-sdk,
|
|
3
|
-
// mas alimentado a partir de SDKMessage do @codrstudio/openclaude-sdk.
|
|
4
|
-
|
|
5
|
-
export type TextPart = { type: "text"; text: string };
|
|
6
|
-
|
|
7
|
-
export type ReasoningPart = { type: "reasoning"; reasoning: string };
|
|
8
|
-
|
|
9
|
-
export type ToolInvocationState = "call" | "partial-call" | "result";
|
|
10
|
-
|
|
11
|
-
export type ToolInvocationPart = {
|
|
12
|
-
type: "tool-invocation";
|
|
13
|
-
toolInvocation: {
|
|
14
|
-
toolName: string;
|
|
15
|
-
toolCallId: string;
|
|
16
|
-
state: ToolInvocationState;
|
|
17
|
-
args?: Record<string, unknown>;
|
|
18
|
-
result?: unknown;
|
|
19
|
-
isError?: boolean;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export type ImageAttachmentPart = { type: "image"; _ref?: string; mimeType?: string };
|
|
24
|
-
export type FileAttachmentPart = { type: "file"; _ref?: string; mimeType?: string };
|
|
25
|
-
|
|
26
|
-
export type MessagePart =
|
|
27
|
-
| TextPart
|
|
28
|
-
| ReasoningPart
|
|
29
|
-
| ToolInvocationPart
|
|
30
|
-
| ImageAttachmentPart
|
|
31
|
-
| FileAttachmentPart
|
|
32
|
-
| { type: string };
|
|
33
|
-
|
|
34
|
-
export type MessageRole = "user" | "assistant";
|
|
35
|
-
|
|
36
|
-
export interface Message {
|
|
37
|
-
id: string;
|
|
38
|
-
role: MessageRole;
|
|
39
|
-
content: string;
|
|
40
|
-
parts: MessagePart[];
|
|
41
|
-
}
|
|
1
|
+
// Tipos locais usados pelo @codrstudio/openclaude-chat.
|
|
2
|
+
// Nao depende de @ai-sdk/react. Modelo inspirado nos "parts" do ai-sdk,
|
|
3
|
+
// mas alimentado a partir de SDKMessage do @codrstudio/openclaude-sdk.
|
|
4
|
+
|
|
5
|
+
export type TextPart = { type: "text"; text: string };
|
|
6
|
+
|
|
7
|
+
export type ReasoningPart = { type: "reasoning"; reasoning: string };
|
|
8
|
+
|
|
9
|
+
export type ToolInvocationState = "call" | "partial-call" | "result";
|
|
10
|
+
|
|
11
|
+
export type ToolInvocationPart = {
|
|
12
|
+
type: "tool-invocation";
|
|
13
|
+
toolInvocation: {
|
|
14
|
+
toolName: string;
|
|
15
|
+
toolCallId: string;
|
|
16
|
+
state: ToolInvocationState;
|
|
17
|
+
args?: Record<string, unknown>;
|
|
18
|
+
result?: unknown;
|
|
19
|
+
isError?: boolean;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type ImageAttachmentPart = { type: "image"; _ref?: string; mimeType?: string };
|
|
24
|
+
export type FileAttachmentPart = { type: "file"; _ref?: string; mimeType?: string };
|
|
25
|
+
|
|
26
|
+
export type MessagePart =
|
|
27
|
+
| TextPart
|
|
28
|
+
| ReasoningPart
|
|
29
|
+
| ToolInvocationPart
|
|
30
|
+
| ImageAttachmentPart
|
|
31
|
+
| FileAttachmentPart
|
|
32
|
+
| { type: string };
|
|
33
|
+
|
|
34
|
+
export type MessageRole = "user" | "assistant";
|
|
35
|
+
|
|
36
|
+
export interface Message {
|
|
37
|
+
id: string;
|
|
38
|
+
role: MessageRole;
|
|
39
|
+
content: string;
|
|
40
|
+
parts: MessagePart[];
|
|
41
|
+
}
|
package/src/ui/alert.tsx
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
import { cn } from "../lib/utils.js";
|
|
4
|
-
|
|
5
|
-
const alertVariants = cva(
|
|
6
|
-
"group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
|
|
7
|
-
{
|
|
8
|
-
variants: {
|
|
9
|
-
variant: {
|
|
10
|
-
default: "bg-card text-card-foreground",
|
|
11
|
-
destructive:
|
|
12
|
-
"bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
defaultVariants: {
|
|
16
|
-
variant: "default",
|
|
17
|
-
},
|
|
18
|
-
}
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
function Alert({
|
|
22
|
-
className,
|
|
23
|
-
variant,
|
|
24
|
-
...props
|
|
25
|
-
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
26
|
-
return (
|
|
27
|
-
<div
|
|
28
|
-
data-slot="alert"
|
|
29
|
-
role="alert"
|
|
30
|
-
className={cn(alertVariants({ variant }), className)}
|
|
31
|
-
{...props}
|
|
32
|
-
/>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
37
|
-
return (
|
|
38
|
-
<div
|
|
39
|
-
data-slot="alert-title"
|
|
40
|
-
className={cn(
|
|
41
|
-
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
|
|
42
|
-
className
|
|
43
|
-
)}
|
|
44
|
-
{...props}
|
|
45
|
-
/>
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function AlertDescription({
|
|
50
|
-
className,
|
|
51
|
-
...props
|
|
52
|
-
}: React.ComponentProps<"div">) {
|
|
53
|
-
return (
|
|
54
|
-
<div
|
|
55
|
-
data-slot="alert-description"
|
|
56
|
-
className={cn(
|
|
57
|
-
"text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
|
58
|
-
className
|
|
59
|
-
)}
|
|
60
|
-
{...props}
|
|
61
|
-
/>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
66
|
-
return (
|
|
67
|
-
<div
|
|
68
|
-
data-slot="alert-action"
|
|
69
|
-
className={cn("absolute top-2 right-2", className)}
|
|
70
|
-
{...props}
|
|
71
|
-
/>
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export { Alert, AlertTitle, AlertDescription, AlertAction };
|
|
76
|
-
export type { VariantProps };
|
|
77
|
-
export { alertVariants };
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
|
|
5
|
+
const alertVariants = cva(
|
|
6
|
+
"group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
|
|
7
|
+
{
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
default: "bg-card text-card-foreground",
|
|
11
|
+
destructive:
|
|
12
|
+
"bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
variant: "default",
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
function Alert({
|
|
22
|
+
className,
|
|
23
|
+
variant,
|
|
24
|
+
...props
|
|
25
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
26
|
+
return (
|
|
27
|
+
<div
|
|
28
|
+
data-slot="alert"
|
|
29
|
+
role="alert"
|
|
30
|
+
className={cn(alertVariants({ variant }), className)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
37
|
+
return (
|
|
38
|
+
<div
|
|
39
|
+
data-slot="alert-title"
|
|
40
|
+
className={cn(
|
|
41
|
+
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function AlertDescription({
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}: React.ComponentProps<"div">) {
|
|
53
|
+
return (
|
|
54
|
+
<div
|
|
55
|
+
data-slot="alert-description"
|
|
56
|
+
className={cn(
|
|
57
|
+
"text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
|
58
|
+
className
|
|
59
|
+
)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
data-slot="alert-action"
|
|
69
|
+
className={cn("absolute top-2 right-2", className)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction };
|
|
76
|
+
export type { VariantProps };
|
|
77
|
+
export { alertVariants };
|
package/src/ui/badge.tsx
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
-
import * as React from "react"
|
|
3
|
-
|
|
4
|
-
import { cn } from "../lib/utils"
|
|
5
|
-
|
|
6
|
-
const badgeVariants = cva(
|
|
7
|
-
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
8
|
-
{
|
|
9
|
-
variants: {
|
|
10
|
-
variant: {
|
|
11
|
-
default:
|
|
12
|
-
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
13
|
-
secondary:
|
|
14
|
-
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
15
|
-
destructive:
|
|
16
|
-
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
17
|
-
outline: "text-foreground",
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
defaultVariants: {
|
|
21
|
-
variant: "default",
|
|
22
|
-
},
|
|
23
|
-
}
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
export interface BadgeProps
|
|
27
|
-
extends React.HTMLAttributes<HTMLDivElement>,
|
|
28
|
-
VariantProps<typeof badgeVariants> {}
|
|
29
|
-
|
|
30
|
-
function Badge({ className, variant, ...props }: BadgeProps) {
|
|
31
|
-
return (
|
|
32
|
-
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
|
33
|
-
)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export { Badge, badgeVariants }
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../lib/utils"
|
|
5
|
+
|
|
6
|
+
const badgeVariants = cva(
|
|
7
|
+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default:
|
|
12
|
+
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
13
|
+
secondary:
|
|
14
|
+
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
15
|
+
destructive:
|
|
16
|
+
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
17
|
+
outline: "text-foreground",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
variant: "default",
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
export interface BadgeProps
|
|
27
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
28
|
+
VariantProps<typeof badgeVariants> {}
|
|
29
|
+
|
|
30
|
+
function Badge({ className, variant, ...props }: BadgeProps) {
|
|
31
|
+
return (
|
|
32
|
+
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { Badge, badgeVariants }
|