create-supyagent-app 0.1.30 → 0.1.31

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-supyagent-app",
3
- "version": "0.1.30",
3
+ "version": "0.1.31",
4
4
  "description": "Create a supyagent-powered chatbot app",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,6 +21,31 @@ export async function POST(req: Request) {
21
21
  messages: await convertToModelMessages(messages),
22
22
  tools,
23
23
  stopWhen: stepCountIs(5),
24
+ prepareStep: async ({ steps, messages: stepMessages }) => {
25
+ const imageUrls: string[] = [];
26
+ for (const step of steps) {
27
+ for (const call of step.toolCalls) {
28
+ if (call.toolName === 'viewImage' && call.input?.url) {
29
+ imageUrls.push(call.input.url as string);
30
+ }
31
+ }
32
+ }
33
+ if (imageUrls.length === 0) return undefined;
34
+
35
+ return {
36
+ messages: [
37
+ ...stepMessages,
38
+ {
39
+ role: 'user' as const,
40
+ content: imageUrls.map(url => ({
41
+ type: 'file' as const,
42
+ data: new URL(url),
43
+ mediaType: 'image/jpeg',
44
+ })),
45
+ },
46
+ ],
47
+ };
48
+ },
24
49
  });
25
50
 
26
51
  return result.toUIMessageStreamResponse({
@@ -21,6 +21,31 @@ export async function POST(req: Request) {
21
21
  messages: await convertToModelMessages(messages),
22
22
  tools,
23
23
  stopWhen: stepCountIs(5),
24
+ prepareStep: async ({ steps, messages: stepMessages }) => {
25
+ const imageUrls: string[] = [];
26
+ for (const step of steps) {
27
+ for (const call of step.toolCalls) {
28
+ if (call.toolName === 'viewImage' && call.input?.url) {
29
+ imageUrls.push(call.input.url as string);
30
+ }
31
+ }
32
+ }
33
+ if (imageUrls.length === 0) return undefined;
34
+
35
+ return {
36
+ messages: [
37
+ ...stepMessages,
38
+ {
39
+ role: 'user' as const,
40
+ content: imageUrls.map(url => ({
41
+ type: 'file' as const,
42
+ data: new URL(url),
43
+ mediaType: 'image/jpeg',
44
+ })),
45
+ },
46
+ ],
47
+ };
48
+ },
24
49
  });
25
50
 
26
51
  return result.toUIMessageStreamResponse({
@@ -101,10 +101,6 @@ export function ChatMessage({ message, addToolApprovalResponse }: ChatMessagePro
101
101
  }
102
102
 
103
103
  if (isToolUIPart(part)) {
104
- const inv = (part as any).toolInvocation;
105
- if (inv?.toolName === "viewImage") {
106
- return null;
107
- }
108
104
  return <ToolMessage key={i} part={part} addToolApprovalResponse={addToolApprovalResponse} />;
109
105
  }
110
106
 
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useChat } from "@ai-sdk/react";
4
- import { DefaultChatTransport, isToolUIPart, lastAssistantMessageIsCompleteWithApprovalResponses, type UIMessage } from "ai";
4
+ import { DefaultChatTransport, lastAssistantMessageIsCompleteWithApprovalResponses, type UIMessage } from "ai";
5
5
  import { ChatMessage } from "./chat-message";
6
6
  import { ChatInput } from "./chat-input";
7
7
  import { ChatSidebar } from "./chat-sidebar";
@@ -23,7 +23,7 @@ export function Chat({ chatId, initialMessages }: ChatProps) {
23
23
  [chatId]
24
24
  );
25
25
 
26
- const { messages, sendMessage, status, stop, addToolApprovalResponse, setMessages } = useChat({
26
+ const { messages, sendMessage, status, stop, addToolApprovalResponse } = useChat({
27
27
  id: chatId,
28
28
  transport,
29
29
  messages: initialMessages,
@@ -32,38 +32,6 @@ export function Chat({ chatId, initialMessages }: ChatProps) {
32
32
 
33
33
  const isLoading = status === "submitted" || status === "streaming";
34
34
 
35
- // viewImage: inject images as FileUIPart messages so the model can see them
36
- const processedImageCallsRef = useRef<Set<string>>(new Set());
37
-
38
- useEffect(() => {
39
- if (status !== "ready") return;
40
-
41
- const newImageMessages: UIMessage[] = [];
42
-
43
- for (const msg of messages) {
44
- for (const part of msg.parts) {
45
- if (!isToolUIPart(part)) continue;
46
- const inv = (part as any).toolInvocation;
47
- if (!inv || inv.toolName !== "viewImage") continue;
48
- if (inv.state !== "result" && inv.state !== "output-available") continue;
49
- if (processedImageCallsRef.current.has(inv.toolCallId)) continue;
50
-
51
- const url = inv.args?.url ?? inv.input?.url;
52
- if (!url) continue;
53
-
54
- processedImageCallsRef.current.add(inv.toolCallId);
55
- newImageMessages.push({
56
- id: `image-${inv.toolCallId}`,
57
- role: "assistant",
58
- parts: [{ type: "file" as const, mediaType: "image/jpeg", url }],
59
- } as UIMessage);
60
- }
61
- }
62
-
63
- if (newImageMessages.length > 0) {
64
- setMessages((prev) => [...prev, ...newImageMessages]);
65
- }
66
- }, [messages, status, setMessages]);
67
35
  const scrollRef = useRef<HTMLDivElement>(null);
68
36
  const bottomRef = useRef<HTMLDivElement>(null);
69
37
  const [isAtBottom, setIsAtBottom] = useState(true);