Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commiteba7a21

Browse files
feat: add embed route
2 parentse19169d +39efc93 commiteba7a21

File tree

10 files changed

+144
-121
lines changed

10 files changed

+144
-121
lines changed

‎chat/next.config.mjs

Lines changed: 0 additions & 23 deletions
This file was deleted.

‎chat/next.config.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
importtype{NextConfig}from"next";
2+
constbasePath=process.env.BASE_PATH??"/chat";
23

34
constnextConfig:NextConfig={
4-
/* config options here */
5+
// Enable static exports
6+
output:"export",
7+
8+
// Disable image optimization since it's not supported in static exports
9+
images:{
10+
unoptimized:true,
11+
},
12+
13+
// Configure base path for GitHub Pages (repo/chat)
14+
basePath,
15+
16+
// Configure asset prefix for GitHub Pages - helps with static asset loading
17+
assetPrefix:`${basePath}/`,
18+
19+
// Configure trailing slashes (recommended for static exports)
20+
trailingSlash:true,
521
};
622

723
exportdefaultnextConfig;

‎chat/src/app/embed/page.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import{Chat}from"@/components/chat";
2+
import{ChatProvider}from"@/components/chat-provider";
3+
import{Suspense}from"react";
4+
5+
exportdefaultfunctionEmbedPage(){
6+
return(
7+
<Suspense
8+
fallback={
9+
<divclassName="text-center p-4 text-sm">Loading chat interface...</div>
10+
}
11+
>
12+
<ChatProvider>
13+
<divclassName="flex flex-col h-svh">
14+
<Chat/>
15+
</div>
16+
</ChatProvider>
17+
</Suspense>
18+
);
19+
}

‎chat/src/app/globals.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
}
8080

8181
.dark {
82-
--background:oklch(0.1290.042264.695);
82+
--background:oklch(0.1400);
8383
--foreground:oklch(0.9840.003247.858);
8484
--card:oklch(0.2080.042265.755);
8585
--card-foreground:oklch(0.9840.003247.858);
@@ -90,11 +90,11 @@
9090
--secondary:oklch(0.2790.041260.031);
9191
--secondary-foreground:oklch(0.9840.003247.858);
9292
--muted:oklch(0.2790.041260.031);
93-
--muted-foreground:oklch(0.7040.04256.788);
93+
--muted-foreground:oklch(0.71180.0129286.07);
9494
--accent:oklch(0.2790.041260.031);
9595
--accent-foreground:oklch(0.9840.003247.858);
9696
--destructive:oklch(0.7040.19122.216);
97-
--border:oklch(100/10%);
97+
--border:oklch(0.270.010);
9898
--input:oklch(100/15%);
9999
--ring:oklch(0.5510.027264.364);
100100
--chart-1:oklch(0.4880.243264.376);

‎chat/src/app/header.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"use client";
2+
3+
import{useChat}from"@/components/chat-provider";
4+
import{ModeToggle}from"../components/mode-toggle";
5+
6+
exportfunctionHeader(){
7+
const{ serverStatus}=useChat();
8+
9+
return(
10+
<headerclassName="p-4 flex items-center justify-between border-b">
11+
<spanclassName="font-bold">AgentAPI Chat</span>
12+
13+
<divclassName="flex items-center gap-4">
14+
{serverStatus!=="unknown"&&(
15+
<divclassName="flex items-center gap-2 text-sm font-medium">
16+
<span
17+
className={`text-secondary w-2 h-2 rounded-full${
18+
["offline","unknown"].includes(serverStatus)
19+
?"bg-red-500 ring-2 ring-red-500/35"
20+
:"bg-green-500 ring-2 ring-green-500/35"
21+
}`}
22+
/>
23+
<spanclassName="sr-only">Status:</span>
24+
<spanclassName="first-letter:uppercase">{serverStatus}</span>
25+
</div>
26+
)}
27+
<ModeToggle/>
28+
</div>
29+
</header>
30+
);
31+
}

‎chat/src/app/page.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1+
import{Chat}from"@/components/chat";
2+
import{ChatProvider}from"@/components/chat-provider";
3+
import{Header}from"./header";
14
import{Suspense}from"react";
2-
importChatInterfacefrom"@/components/ChatInterface";
35

46
exportdefaultfunctionHome(){
57
return(
68
<Suspense
79
fallback={
8-
<divclassName="text-center p-4">Loading chat interface...</div>
10+
<divclassName="text-center p-4 text-sm">Loading chat interface...</div>
911
}
1012
>
11-
<ChatInterface/>
13+
<ChatProvider>
14+
<divclassName="flex flex-col h-svh">
15+
<Header/>
16+
<Chat/>
17+
</div>
18+
</ChatProvider>
1219
</Suspense>
1320
);
1421
}

‎chat/src/components/ChatInterface.tsxrenamed to‎chat/src/components/chat-provider.tsx

Lines changed: 45 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"use client";
22

3-
import{useState,useEffect,useRef,useCallback}from"react";
4-
importMessageListfrom"./MessageList";
5-
importMessageInputfrom"./MessageInput";
63
import{useSearchParams}from"next/navigation";
4+
import{
5+
useState,
6+
useEffect,
7+
useRef,
8+
createContext,
9+
PropsWithChildren,
10+
useContext,
11+
}from"react";
712
import{toast}from"sonner";
8-
import{Button}from"./ui/button";
9-
import{TriangleAlertIcon}from"lucide-react";
10-
import{Alert,AlertTitle,AlertDescription}from"./ui/alert";
11-
import{ModeToggle}from"./mode-toggle";
1213

1314
interfaceMessage{
1415
id:number;
@@ -33,42 +34,30 @@ interface StatusChangeEvent {
3334
status:string;
3435
}
3536

36-
constisDraftMessage=(message:Message|DraftMessage):boolean=>{
37+
functionisDraftMessage(message:Message|DraftMessage):boolean{
3738
returnmessage.id===undefined;
38-
};
39+
}
3940

40-
exportdefaultfunctionChatInterface(){
41-
const[messages,setMessages]=useState<(Message|DraftMessage)[]>([]);
42-
const[loading,setLoading]=useState<boolean>(false);
43-
const[serverStatus,setServerStatus]=useState<string>("unknown");
44-
constsearchParams=useSearchParams();
41+
typeMessageType="user"|"raw";
4542

46-
constgetAgentApiUrl=useCallback(()=>{
47-
constapiUrlFromParam=searchParams.get("url");
48-
if(apiUrlFromParam){
49-
try{
50-
// Validate if it's a proper URL
51-
newURL(apiUrlFromParam);
52-
returnapiUrlFromParam;
53-
}catch(e){
54-
console.warn("Invalid url parameter, defaulting...",e);
55-
// Fallback if parsing fails or it's not a valid URL.
56-
// Ensure window is defined (for SSR/Node.js environments during build)
57-
returntypeofwindow!=="undefined" ?window.location.origin :"";
58-
}
59-
}
60-
// Ensure window is defined
61-
returntypeofwindow!=="undefined" ?window.location.origin :"";
62-
},[searchParams]);
43+
typeServerStatus="online"|"offline"|"unknown";
6344

64-
const[agentAPIUrl,setAgentAPIUrl]=useState<string>(getAgentApiUrl());
45+
interfaceChatContextValue{
46+
messages:(Message|DraftMessage)[];
47+
loading:boolean;
48+
serverStatus:ServerStatus;
49+
sendMessage:(message:string,type?:MessageType)=>void;
50+
}
6551

66-
consteventSourceRef=useRef<EventSource|null>(null);
52+
constChatContext=createContext<ChatContextValue|undefined>(undefined);
6753

68-
// Update agentAPIUrl when searchParams change (e.g. url is added/removed)
69-
useEffect(()=>{
70-
setAgentAPIUrl(getAgentApiUrl());
71-
},[getAgentApiUrl,searchParams]);
54+
exportfunctionChatProvider({ children}:PropsWithChildren){
55+
const[messages,setMessages]=useState<(Message|DraftMessage)[]>([]);
56+
const[loading,setLoading]=useState<boolean>(false);
57+
const[serverStatus,setServerStatus]=useState<ServerStatus>("unknown");
58+
consteventSourceRef=useRef<EventSource|null>(null);
59+
constsearchParams=useSearchParams();
60+
constagentAPIUrl=searchParams.get("url");
7261

7362
// Set up SSE connection to the events endpoint
7463
useEffect(()=>{
@@ -132,7 +121,7 @@ export default function ChatInterface() {
132121
// Handle status changes
133122
eventSource.addEventListener("status_change",(event)=>{
134123
constdata:StatusChangeEvent=JSON.parse(event.data);
135-
setServerStatus(data.status);
124+
setServerStatus(data.statusasServerStatus);
136125
});
137126

138127
// Handle connection open (server is online)
@@ -240,55 +229,23 @@ export default function ChatInterface() {
240229
};
241230

242231
return(
243-
<divclassName="flex flex-col h-svh">
244-
<headerclassName="p-4 flex items-center justify-between border-b">
245-
<spanclassName="font-bold">AgentAPI Chat</span>
246-
247-
<divclassName="flex items-center gap-4">
248-
{serverStatus!=="unknown"&&(
249-
<divclassName="flex items-center gap-2 text-sm font-medium">
250-
<span
251-
className={`text-secondary w-2 h-2 rounded-full${
252-
["offline","unknown"].includes(serverStatus)
253-
?"bg-red-500 ring-2 ring-red-500/35"
254-
:"bg-green-500 ring-2 ring-green-500/35"
255-
}`}
256-
/>
257-
<spanclassName="sr-only">Status:</span>
258-
<spanclassName="first-letter:uppercase">{serverStatus}</span>
259-
</div>
260-
)}
261-
<ModeToggle/>
262-
</div>
263-
</header>
264-
265-
<mainclassName="flex flex-1 flex-col w-full overflow-auto">
266-
{serverStatus==="offline"&&(
267-
<divclassName="p-4 w-full max-w-4xl mx-auto">
268-
<AlertclassName="flex border-yellow-500">
269-
<TriangleAlertIconclassName="h-4 w-4 stroke-yellow-600"/>
270-
<div>
271-
<AlertTitle>API server is offline</AlertTitle>
272-
<AlertDescription>
273-
Please start the AgentAPI server. Attempting to connect to:{" "}
274-
{agentAPIUrl||"N/A"}.
275-
</AlertDescription>
276-
</div>
277-
<Button
278-
variant="ghost"
279-
size="sm"
280-
className="ml-auto"
281-
onClick={()=>window.location.reload()}
282-
>
283-
Retry
284-
</Button>
285-
</Alert>
286-
</div>
287-
)}
288-
289-
<MessageListmessages={messages}/>
290-
<MessageInputonSendMessage={sendMessage}disabled={loading}/>
291-
</main>
292-
</div>
232+
<ChatContext.Provider
233+
value={{
234+
messages,
235+
loading,
236+
sendMessage,
237+
serverStatus,
238+
}}
239+
>
240+
{children}
241+
</ChatContext.Provider>
293242
);
294243
}
244+
245+
exportfunctionuseChat(){
246+
constcontext=useContext(ChatContext);
247+
if(!context){
248+
thrownewError("useChat must be used within a ChatProvider");
249+
}
250+
returncontext;
251+
}

‎chat/src/components/chat.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"use client";
2+
3+
import{useChat}from"./chat-provider";
4+
importMessageInputfrom"./message-input";
5+
importMessageListfrom"./message-list";
6+
7+
exportfunctionChat(){
8+
const{ messages, loading, sendMessage}=useChat();
9+
10+
return(
11+
<>
12+
<MessageListmessages={messages}/>
13+
<MessageInputonSendMessage={sendMessage}disabled={loading}/>
14+
</>
15+
);
16+
}

‎chat/src/components/MessageInput.tsxrenamed to‎chat/src/components/message-input.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export default function MessageInput({
155155
onKeyDown={handleKeyDownasany}
156156
onFocus={()=>setControlAreaFocused(true)}
157157
onBlur={()=>setControlAreaFocused(false)}
158-
className="cursor-text p-4 h-20 text-muted-foreground flex items-center justify-center w-full outline-none"
158+
className="cursor-text p-4 h-20 text-muted-foreground flex items-center justify-center w-full outline-none text-sm"
159159
>
160160
{controlAreaFocused
161161
?"Press any key to send to terminal (arrows, Ctrl+C, Ctrl+R, etc.)"
@@ -175,7 +175,7 @@ export default function MessageInput({
175175
</div>
176176

177177
<divclassName="flex items-center justify-between p-4">
178-
<TabsList>
178+
<TabsListclassName="bg-transparent">
179179
<TabsTrigger
180180
value="text"
181181
onClick={()=>{

‎chat/src/components/MessageList.tsxrenamed to‎chat/src/components/message-list.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export default function MessageList({ messages }: MessageListProps) {
120120
}${message.id===undefined ?"animate-pulse" :""}`}
121121
>
122122
<div
123-
className={`whitespace-pre-wrap break-words text-left text-sm${
123+
className={`whitespace-pre-wrap break-words text-left text-xs md:text-sm leading-relaxed md:leading-normal${
124124
message.role==="user" ?"" :"font-mono"
125125
}`}
126126
>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp