mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-01-05 15:52:33 +08:00
Compare commits
7 Commits
v0.4.8
...
fix/docker
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb21d7e3fa | ||
|
|
8c1cc19d94 | ||
|
|
03c3ae6d5b | ||
|
|
ddde0654a6 | ||
|
|
bc5709267c | ||
|
|
6fbc7b340f | ||
|
|
3c8f420c3c |
@@ -943,10 +943,9 @@ export default function ChatPanel({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Toaster
|
<Toaster
|
||||||
position="bottom-center"
|
position="bottom-left"
|
||||||
richColors
|
richColors
|
||||||
expand
|
expand
|
||||||
style={{ position: "absolute" }}
|
|
||||||
toastOptions={{
|
toastOptions={{
|
||||||
style: {
|
style: {
|
||||||
maxWidth: "480px",
|
maxWidth: "480px",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ services:
|
|||||||
# - NEXT_PUBLIC_BASE_PATH=/nextaidrawio
|
# - NEXT_PUBLIC_BASE_PATH=/nextaidrawio
|
||||||
ports: ["3000:3000"]
|
ports: ["3000:3000"]
|
||||||
env_file: .env
|
env_file: .env
|
||||||
environment:
|
# environment:
|
||||||
# For subdirectory deployment, uncomment and set your path:
|
# # For subdirectory deployment, uncomment and set your path:
|
||||||
# NEXT_PUBLIC_BASE_PATH: /nextaidrawio
|
# NEXT_PUBLIC_BASE_PATH: /nextaidrawio
|
||||||
depends_on: [drawio]
|
depends_on: [drawio]
|
||||||
|
|||||||
3627
package-lock.json
generated
3627
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,7 @@
|
|||||||
"motion": "^12.23.25",
|
"motion": "^12.23.25",
|
||||||
"negotiator": "^1.0.0",
|
"negotiator": "^1.0.0",
|
||||||
"next": "^16.0.7",
|
"next": "^16.0.7",
|
||||||
"ollama-ai-provider-v2": "^1.5.4",
|
"ollama-ai-provider-v2": "^2.0.0",
|
||||||
"pako": "^2.1.0",
|
"pako": "^2.1.0",
|
||||||
"prism-react-renderer": "^2.4.1",
|
"prism-react-renderer": "^2.4.1",
|
||||||
"react": "^19.1.2",
|
"react": "^19.1.2",
|
||||||
|
|||||||
@@ -64,6 +64,24 @@ Add to Cursor MCP config (`~/.cursor/mcp.json`):
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Cline (VS Code Extension)
|
||||||
|
|
||||||
|
1. Click the **MCP Servers** icon in Cline's top menu bar
|
||||||
|
2. Select the **Configure** tab
|
||||||
|
3. Click **Configure MCP Servers** to edit `cline_mcp_settings.json`
|
||||||
|
4. Add the drawio server:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"drawio": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["@next-ai-drawio/mcp-server@latest"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Claude Code CLI
|
### Claude Code CLI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -29,12 +29,29 @@ function getOrigin(url: string): string {
|
|||||||
|
|
||||||
const DRAWIO_ORIGIN = getOrigin(DRAWIO_BASE_URL)
|
const DRAWIO_ORIGIN = getOrigin(DRAWIO_BASE_URL)
|
||||||
|
|
||||||
|
// Minimal blank diagram used to bootstrap new sessions.
|
||||||
|
// This avoids the draw.io embed spinner (spin=1) getting stuck when no `load(xml)` is ever sent.
|
||||||
|
const DEFAULT_DIAGRAM_XML = `<mxfile host="app.diagrams.net"><diagram id="blank" name="Page-1"><mxGraphModel><root><mxCell id="0"/><mxCell id="1" parent="0"/></root></mxGraphModel></diagram></mxfile>`
|
||||||
|
|
||||||
// Normalize URL for iframe src - ensure no double slashes
|
// Normalize URL for iframe src - ensure no double slashes
|
||||||
function normalizeUrl(url: string): string {
|
function normalizeUrl(url: string): string {
|
||||||
// Remove trailing slash to avoid double slashes
|
// Remove trailing slash to avoid double slashes
|
||||||
return url.replace(/\/$/, "")
|
return url.replace(/\/$/, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isLikelyMcpSessionId(sessionId: string): boolean {
|
||||||
|
// Keep this cheap and conservative to avoid creating state for arbitrary IDs.
|
||||||
|
return sessionId.startsWith("mcp-") && sessionId.length <= 128
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureSessionStateInitialized(sessionId: string): void {
|
||||||
|
if (!sessionId) return
|
||||||
|
if (!isLikelyMcpSessionId(sessionId)) return
|
||||||
|
if (stateStore.has(sessionId)) return
|
||||||
|
|
||||||
|
setState(sessionId, DEFAULT_DIAGRAM_XML)
|
||||||
|
}
|
||||||
|
|
||||||
interface SessionState {
|
interface SessionState {
|
||||||
xml: string
|
xml: string
|
||||||
version: number
|
version: number
|
||||||
@@ -177,8 +194,11 @@ function handleRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (url.pathname === "/" || url.pathname === "/index.html") {
|
if (url.pathname === "/" || url.pathname === "/index.html") {
|
||||||
|
const sessionId = url.searchParams.get("mcp") || ""
|
||||||
|
ensureSessionStateInitialized(sessionId)
|
||||||
|
|
||||||
res.writeHead(200, { "Content-Type": "text/html" })
|
res.writeHead(200, { "Content-Type": "text/html" })
|
||||||
res.end(getHtmlPage(url.searchParams.get("mcp") || ""))
|
res.end(getHtmlPage(sessionId))
|
||||||
} else if (url.pathname === "/api/state") {
|
} else if (url.pathname === "/api/state") {
|
||||||
handleStateApi(req, res, url)
|
handleStateApi(req, res, url)
|
||||||
} else if (url.pathname === "/api/history") {
|
} else if (url.pathname === "/api/history") {
|
||||||
@@ -205,6 +225,7 @@ function handleStateApi(
|
|||||||
res.end(JSON.stringify({ error: "sessionId required" }))
|
res.end(JSON.stringify({ error: "sessionId required" }))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ensureSessionStateInitialized(sessionId)
|
||||||
const state = stateStore.get(sessionId)
|
const state = stateStore.get(sessionId)
|
||||||
res.writeHead(200, { "Content-Type": "application/json" })
|
res.writeHead(200, { "Content-Type": "application/json" })
|
||||||
res.end(
|
res.end(
|
||||||
|
|||||||
Reference in New Issue
Block a user