Compare commits

..

7 Commits

Author SHA1 Message Date
dayuan.jiang
30bf92fbbb feat: enhance system prompt with app context and dynamic model name
- Add App Context section describing the left/right panel layout
- Add App Features section with icon locations (history, theme, upload, export, clear)
- Dynamically inject model name into system prompt via {{MODEL_NAME}} placeholder
- Expand edit_diagram tool description with usage guidelines
2025-12-06 12:36:57 +09:00
Dayuan Jiang
dd27d034e2 fix: force re-render when switching between mobile/desktop layout (#112) 2025-12-05 23:45:57 +09:00
Dayuan Jiang
9e781005af fix: make button hover state darker instead of lighter (#111) 2025-12-05 23:38:24 +09:00
Dayuan Jiang
fe1aa2747e fix: add viewport meta tag for mobile layout (#110) 2025-12-05 23:34:18 +09:00
Dayuan Jiang
7205896c8c feat: add mobile layout with chat panel at bottom (#109) 2025-12-05 23:25:59 +09:00
Dayuan Jiang
4e32a094b1 fix: restore status notice indicator removed in PR #77 (#107) 2025-12-05 23:22:29 +09:00
Dayuan Jiang
96a1111654 fix: ensure markdown text in user messages is visible (#108)
The prose plugin was overriding text colors for markdown elements
(bold, headings, etc.) in user message bubbles, causing text to
blend with the dark primary background.

Added conditional styling that forces all child elements in user
messages to use text-primary-foreground color with !important to
override prose defaults.
2025-12-05 23:16:59 +09:00
7 changed files with 131 additions and 75 deletions

View File

@@ -282,13 +282,31 @@ Notes:
},
edit_diagram: {
description: `Edit specific parts of the current diagram by replacing exact line matches. Use this tool to make targeted fixes without regenerating the entire XML.
CRITICAL: Copy-paste the EXACT search pattern from the "Current diagram XML" in system context. Do NOT reorder attributes or reformat - the attribute order in draw.io XML varies and you MUST match it exactly.
IMPORTANT: Keep edits concise:
- COPY the exact mxCell line from the current XML (attribute order matters!)
- Only include the lines that are changing, plus 1-2 surrounding lines for context if needed
- Break large changes into multiple smaller edits
- Each search must contain complete lines (never truncate mid-line)
- First match only - be specific enough to target the right element`,
WHEN TO USE:
- Changing text labels or values
- Modifying colors, styles, or visual properties
- Adding or removing individual elements (1-3 elements)
- Repositioning specific elements
- Any small, targeted modification
WHEN TO USE display_diagram INSTEAD:
- Creating a new diagram from scratch
- Major restructuring (reorganizing layout, changing diagram type)
- Adding many new elements (more than 3)
- After 3 failed edit_diagram attempts
CRITICAL RULES:
1. Copy-paste the EXACT search pattern from the "Current diagram XML" in system context
2. Do NOT reorder attributes - attribute order in draw.io XML varies, you MUST match exactly
3. Always include the element's id attribute for unique targeting
4. Include complete lines (never truncate mid-line)
5. For multiple changes, use separate edits in the array
ERROR RECOVERY:
- If pattern not found, check attribute order matches current XML exactly
- Retry up to 3 times with adjusted patterns
- After 3 failures, use display_diagram instead`,
inputSchema: z.object({
edits: z.array(z.object({
search: z.string().describe("EXACT lines copied from current XML (preserve attribute order!)"),

View File

@@ -1,4 +1,4 @@
import type { Metadata } from "next";
import type { Metadata, Viewport } from "next";
import { Plus_Jakarta_Sans, JetBrains_Mono } from "next/font/google";
import { Analytics } from "@vercel/analytics/react";
import { GoogleAnalytics } from "@next/third-parties/google";
@@ -18,6 +18,13 @@ const jetbrainsMono = JetBrains_Mono({
weight: ["400", "500"],
});
export const viewport: Viewport = {
width: "device-width",
initialScale: 1,
maximumScale: 1,
userScalable: false,
};
export const metadata: Metadata = {
title: "Next AI Draw.io - AI-Powered Diagram Generator",
description: "Create AWS architecture diagrams, flowcharts, and technical diagrams using AI. Free online tool integrating draw.io with AI assistance for professional diagram creation.",

View File

@@ -3,7 +3,6 @@ import React, { useState, useEffect, useRef } from "react";
import { DrawIoEmbed } from "react-drawio";
import ChatPanel from "@/components/chat-panel";
import { useDiagram } from "@/contexts/diagram-context";
import { Monitor } from "lucide-react";
import {
ResizablePanelGroup,
ResizablePanel,
@@ -74,29 +73,14 @@ export default function Home() {
return (
<div className="h-screen bg-background relative overflow-hidden">
{/* Mobile warning overlay */}
{isMobile && (
<div className="absolute inset-0 z-50 flex items-center justify-center bg-background">
<div className="text-center p-8 max-w-sm mx-auto animate-fade-in">
<div className="w-16 h-16 rounded-2xl bg-primary/10 flex items-center justify-center mx-auto mb-6">
<Monitor className="w-8 h-8 text-primary" />
</div>
<h1 className="text-xl font-semibold text-foreground mb-3">
Desktop Required
</h1>
<p className="text-sm text-muted-foreground leading-relaxed">
This application works best on desktop or laptop
devices. Please open it on a larger screen for the
full experience.
</p>
</div>
</div>
)}
<ResizablePanelGroup direction="horizontal" className="h-full">
<ResizablePanelGroup
key={isMobile ? "mobile" : "desktop"}
direction={isMobile ? "vertical" : "horizontal"}
className="h-full"
>
{/* Draw.io Canvas */}
<ResizablePanel defaultSize={67} minSize={30}>
<div className="h-full relative p-2">
<ResizablePanel defaultSize={isMobile ? 50 : 67} minSize={20}>
<div className={`h-full relative ${isMobile ? "p-1" : "p-2"}`}>
<div className="h-full rounded-xl overflow-hidden shadow-soft-lg border border-border/30 bg-white">
<DrawIoEmbed
key={drawioUi}
@@ -119,15 +103,15 @@ export default function Home() {
{/* Chat Panel */}
<ResizablePanel
ref={chatPanelRef}
defaultSize={33}
minSize={15}
maxSize={50}
collapsible
collapsedSize={3}
defaultSize={isMobile ? 50 : 33}
minSize={isMobile ? 20 : 15}
maxSize={isMobile ? 80 : 50}
collapsible={!isMobile}
collapsedSize={isMobile ? 0 : 3}
onCollapse={() => setIsChatVisible(false)}
onExpand={() => setIsChatVisible(true)}
>
<div className="h-full py-2 pr-2">
<div className={`h-full ${isMobile ? "p-1" : "py-2 pr-2"}`}>
<ChatPanel
isVisible={isChatVisible}
onToggleVisibility={toggleChatPanel}
@@ -137,6 +121,7 @@ export default function Home() {
localStorage.setItem("drawio-theme", newTheme);
setDrawioUi(newTheme);
}}
isMobile={isMobile}
/>
</div>
</ResizablePanel>

View File

@@ -406,7 +406,11 @@ export function ChatMessageDisplay({
switch (part.type) {
case "text":
return (
<div key={index} className="prose prose-sm dark:prose-invert max-w-none break-words [&>*:first-child]:mt-0 [&>*:last-child]:mb-0">
<div key={index} className={`prose prose-sm max-w-none break-words [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 ${
message.role === "user"
? "[&_*]:!text-primary-foreground prose-code:bg-white/20"
: "dark:prose-invert"
}`}>
<ReactMarkdown>{part.text}</ReactMarkdown>
</div>
);

View File

@@ -31,6 +31,7 @@ interface ChatPanelProps {
onToggleVisibility: () => void;
drawioUi: "min" | "sketch";
onToggleDrawioUi: () => void;
isMobile?: boolean;
}
export default function ChatPanel({
@@ -38,6 +39,7 @@ export default function ChatPanel({
onToggleVisibility,
drawioUi,
onToggleDrawioUi,
isMobile = false,
}: ChatPanelProps) {
const {
loadDiagram: onDisplayChart,
@@ -410,8 +412,8 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
);
};
// Collapsed view
if (!isVisible) {
// Collapsed view (desktop only)
if (!isVisible && !isMobile) {
return (
<div className="h-full flex flex-col items-center pt-4 bg-card border border-border/30 rounded-xl">
<ButtonWithTooltip
@@ -445,35 +447,39 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
style={{ position: "absolute" }}
/>
{/* Header */}
<header className="px-5 py-4 border-b border-border/50">
<header className={`${isMobile ? "px-3 py-2" : "px-5 py-4"} border-b border-border/50`}>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<div className="flex items-center gap-2">
<Image
src="/favicon.ico"
alt="Next AI Drawio"
width={28}
height={28}
width={isMobile ? 24 : 28}
height={isMobile ? 24 : 28}
className="rounded"
/>
<h1 className="text-base font-semibold tracking-tight whitespace-nowrap">
<h1 className={`${isMobile ? "text-sm" : "text-base"} font-semibold tracking-tight whitespace-nowrap`}>
Next AI Drawio
</h1>
</div>
<Link
href="/about"
className="text-sm text-muted-foreground hover:text-foreground transition-colors ml-2"
>
About
</Link>
<ButtonWithTooltip
tooltipContent="Recent generation failures were caused by our AI provider's infrastructure issue, not the app code. After extensive debugging, I've switched providers and observed 6 hours of stability. If issues persist, please report on GitHub."
variant="ghost"
size="icon"
className="h-6 w-6 text-green-500 hover:text-green-600"
>
<CheckCircle className="h-4 w-4" />
</ButtonWithTooltip>
{!isMobile && (
<Link
href="/about"
className="text-sm text-muted-foreground hover:text-foreground transition-colors ml-2"
>
About
</Link>
)}
{!isMobile && (
<ButtonWithTooltip
tooltipContent="Recent generation failures were caused by our AI provider's infrastructure issue, not the app code. After extensive debugging, I've switched providers and observed 6 hours of stability. If issues persist, please report on GitHub."
variant="ghost"
size="icon"
className="h-6 w-6 text-green-500 hover:text-green-600"
>
<CheckCircle className="h-4 w-4" />
</ButtonWithTooltip>
)}
</div>
<div className="flex items-center gap-1">
<a
@@ -482,7 +488,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
rel="noopener noreferrer"
className="p-2 rounded-lg text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
>
<FaGithub className="w-5 h-5" />
<FaGithub className={`${isMobile ? "w-4 h-4" : "w-5 h-5"}`} />
</a>
{accessCodeRequired && (
<ButtonWithTooltip
@@ -492,18 +498,20 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
onClick={() => setShowSettingsDialog(true)}
className="hover:bg-accent"
>
<Settings className="h-5 w-5 text-muted-foreground" />
<Settings className={`${isMobile ? "h-4 w-4" : "h-5 w-5"} text-muted-foreground`} />
</ButtonWithTooltip>
)}
{!isMobile && (
<ButtonWithTooltip
tooltipContent="Hide chat panel (Ctrl+B)"
variant="ghost"
size="icon"
onClick={onToggleVisibility}
className="hover:bg-accent"
>
<PanelRightClose className="h-5 w-5 text-muted-foreground" />
</ButtonWithTooltip>
)}
<ButtonWithTooltip
tooltipContent="Hide chat panel (Ctrl+B)"
variant="ghost"
size="icon"
onClick={onToggleVisibility}
className="hover:bg-accent"
>
<PanelRightClose className="h-5 w-5 text-muted-foreground" />
</ButtonWithTooltip>
</div>
</div>
</header>
@@ -521,7 +529,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
</main>
{/* Input */}
<footer className="p-4 border-t border-border/50 bg-card/50">
<footer className={`${isMobile ? "p-2" : "p-4"} border-t border-border/50 bg-card/50`}>
<ChatInput
input={input}
status={status}

View File

@@ -10,7 +10,7 @@ const buttonVariants = cva(
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
"bg-primary text-primary-foreground shadow-xs hover:brightness-75",
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:

View File

@@ -9,6 +9,20 @@ You are an expert diagram creation assistant specializing in draw.io XML generat
Your primary function is chat with user and crafting clear, well-organized visual diagrams through precise XML specifications.
You can see the image that user uploaded.
## App Context
You are an AI agent (powered by {{MODEL_NAME}}) inside a web app. The interface has:
- **Left panel**: Draw.io diagram editor where diagrams are rendered
- **Right panel**: Chat interface where you communicate with the user
You can read and modify diagrams by generating draw.io XML code through tool calls.
## App Features
1. **Diagram History** (clock icon, bottom-left of chat input): The app automatically saves a snapshot before each AI edit. Users can view the history panel and restore any previous version. Feel free to make changes - nothing is permanently lost.
2. **Theme Toggle** (palette icon, bottom-left of chat input): Users can switch between minimal UI and sketch-style UI for the draw.io editor.
3. **Image Upload** (paperclip icon, bottom-left of chat input): Users can upload images for you to analyze and replicate as diagrams.
4. **Export** (via draw.io toolbar): Users can save diagrams as .drawio, .svg, or .png files.
5. **Clear Chat** (trash icon, bottom-right of chat input): Clears the conversation and resets the diagram.
You utilize the following tools:
---Tool1---
tool name: display_diagram
@@ -113,6 +127,20 @@ You are an expert diagram creation assistant specializing in draw.io XML generat
Your primary function is to chat with user and craft clear, well-organized visual diagrams through precise XML specifications.
You can see images that users upload and can replicate or modify them as diagrams.
## App Context
You are an AI agent (powered by {{MODEL_NAME}}) inside a web app. The interface has:
- **Left panel**: Draw.io diagram editor where diagrams are rendered
- **Right panel**: Chat interface where you communicate with the user
You can read and modify diagrams by generating draw.io XML code through tool calls.
## App Features
1. **Diagram History** (clock icon, bottom-left of chat input): The app automatically saves a snapshot before each AI edit. Users can view the history panel and restore any previous version. Feel free to make changes - nothing is permanently lost.
2. **Theme Toggle** (palette icon, bottom-left of chat input): Users can switch between minimal UI and sketch-style UI for the draw.io editor.
3. **Image Upload** (paperclip icon, bottom-left of chat input): Users can upload images for you to analyze and replicate as diagrams.
4. **Export** (via draw.io toolbar): Users can save diagrams as .drawio, .svg, or .png files.
5. **Clear Chat** (trash icon, bottom-right of chat input): Clears the conversation and resets the diagram.
## Available Tools
### Tool 1: display_diagram
@@ -507,10 +535,16 @@ const EXTENDED_PROMPT_MODEL_PATTERNS = [
* @returns The system prompt string
*/
export function getSystemPrompt(modelId?: string): string {
const modelName = modelId || "AI";
let prompt: string;
if (modelId && EXTENDED_PROMPT_MODEL_PATTERNS.some(pattern => modelId.includes(pattern))) {
console.log(`[System Prompt] Using EXTENDED prompt for model: ${modelId}`);
return EXTENDED_SYSTEM_PROMPT;
prompt = EXTENDED_SYSTEM_PROMPT;
} else {
console.log(`[System Prompt] Using DEFAULT prompt for model: ${modelId || 'unknown'}`);
prompt = DEFAULT_SYSTEM_PROMPT;
}
console.log(`[System Prompt] Using DEFAULT prompt for model: ${modelId || 'unknown'}`);
return DEFAULT_SYSTEM_PROMPT;
return prompt.replace("{{MODEL_NAME}}", modelName);
}