mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-10 11:39:50 +08:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f39935821 | ||
|
|
f0f0bc0dc0 | ||
|
|
d5096b9628 |
@@ -12,13 +12,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '24'
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'npm'
|
||||
|
||||
@@ -26,14 +26,14 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
# Push to AWS ECR for App Runner auto-deploy
|
||||
- name: Configure AWS credentials
|
||||
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v6
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
@@ -26,10 +26,10 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 24
|
||||
cache: "npm"
|
||||
@@ -50,10 +50,10 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 24
|
||||
cache: "npm"
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload unsigned artifacts for signing
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
id: upload-unsigned
|
||||
with:
|
||||
name: windows-unsigned
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
retention-days: 1
|
||||
|
||||
- name: Sign with SignPath
|
||||
uses: signpath/github-action-submit-signing-request@v2
|
||||
uses: signpath/github-action-submit-signing-request@v3
|
||||
with:
|
||||
api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
|
||||
organization-id: '880a211d-2cd3-4e7b-8d04-3d1f8eb39df5'
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
output-artifact-directory: release-signed
|
||||
|
||||
- name: Upload signed artifacts to release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: release-signed/*.exe
|
||||
env:
|
||||
|
||||
@@ -28,10 +28,10 @@ jobs:
|
||||
working-directory: packages/mcp-server
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 24
|
||||
cache: "npm"
|
||||
|
||||
@@ -11,12 +11,12 @@ jobs:
|
||||
name: Lint & Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: "20"
|
||||
node-version: "24"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -52,19 +52,19 @@ jobs:
|
||||
matrix:
|
||||
shard: [1, 2, 3, 4, 5, 6]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: "20"
|
||||
node-version: "24"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Cache Playwright browsers
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@v6
|
||||
id: playwright-cache
|
||||
with:
|
||||
path: ~/.cache/ms-playwright
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
CI: true
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report-${{ matrix.shard }}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {
|
||||
ChevronDown,
|
||||
Download,
|
||||
FilePlus,
|
||||
MessageSquareDashed,
|
||||
PanelRightClose,
|
||||
Settings2,
|
||||
SquarePen,
|
||||
Settings,
|
||||
} from "lucide-react"
|
||||
import { useRef } from "react"
|
||||
import { DevXmlSimulator } from "@/components/dev-xml-simulator"
|
||||
@@ -139,14 +139,14 @@ export function ChatPanel({
|
||||
disabled={engine.isBusy}
|
||||
data-testid="new-chat-button"
|
||||
>
|
||||
<SquarePen />
|
||||
<FilePlus />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
label={dict.nav.settings}
|
||||
onClick={() => openSettings()}
|
||||
data-testid="settings-button"
|
||||
>
|
||||
<Settings2 />
|
||||
<Settings />
|
||||
</IconButton>
|
||||
{!mobile && (
|
||||
<IconButton
|
||||
@@ -173,7 +173,7 @@ export function ChatPanel({
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="shrink-0 p-2.5 pt-1">
|
||||
<div className="shrink-0 px-4 pt-1 pb-3">
|
||||
<Composer
|
||||
placeholder={
|
||||
engine.messages.length > 0 &&
|
||||
|
||||
@@ -18,14 +18,18 @@ interface Example {
|
||||
file?: { path: string; name: string; type: string }
|
||||
}
|
||||
|
||||
/** Secondary start buttons: outlined, so they read as clickable */
|
||||
const startButtonClass =
|
||||
"inline-flex h-8 items-center gap-1.5 rounded-lg border border-border bg-card px-3 text-[13px] text-foreground transition-colors hover:bg-accent [&_svg]:text-muted-foreground"
|
||||
|
||||
async function loadExampleFile(file: NonNullable<Example["file"]>) {
|
||||
const response = await fetch(getAssetUrl(file.path))
|
||||
const blob = await response.blob()
|
||||
return new File([blob], file.name, { type: file.type })
|
||||
}
|
||||
|
||||
/** One start-screen choice: a small picture, a title and one line */
|
||||
function ExampleCard({
|
||||
/** One start-screen example: a small picture over its title */
|
||||
function ExampleTile({
|
||||
onClick,
|
||||
title,
|
||||
description,
|
||||
@@ -35,6 +39,7 @@ function ExampleCard({
|
||||
}: {
|
||||
onClick: () => void
|
||||
title: string
|
||||
/** Shown as the tooltip: the title alone names the example */
|
||||
description: string
|
||||
picture: React.ReactNode
|
||||
/** An icon on a tinted tile instead of a diagram on paper */
|
||||
@@ -45,24 +50,20 @@ function ExampleCard({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className="group/example flex min-w-0 items-center gap-2.5 rounded-xl border border-border bg-card p-1.5 pr-2.5 text-left transition-colors hover:border-foreground/25"
|
||||
title={description}
|
||||
className="group/example flex min-w-0 flex-col gap-2 rounded-xl border border-border bg-card p-1.5 pb-2.5 text-left transition-colors hover:border-foreground/25"
|
||||
data-testid={testId}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"flex h-12 w-16 shrink-0 items-center justify-center overflow-hidden rounded-lg",
|
||||
"flex h-16 w-full items-center justify-center overflow-hidden rounded-lg",
|
||||
plain ? "bg-muted" : "sheet-light bg-white",
|
||||
)}
|
||||
>
|
||||
{picture}
|
||||
</span>
|
||||
<span className="min-w-0 flex-1">
|
||||
<span className="line-clamp-2 text-[13px] leading-snug font-medium text-foreground">
|
||||
{title}
|
||||
</span>
|
||||
<span className="mt-0.5 block truncate text-xs text-muted-foreground">
|
||||
{description}
|
||||
</span>
|
||||
<span className="px-1 text-[13px] leading-snug font-medium text-foreground">
|
||||
{title}
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
@@ -92,6 +93,7 @@ export function LobbyHero({
|
||||
key: "paper",
|
||||
title: dict.examples.paperToDiagram,
|
||||
description: dict.examples.paperDescription,
|
||||
image: "/paper_demo.svg",
|
||||
prompt: "Summarize this paper as a diagram",
|
||||
file: {
|
||||
path: "/chain-of-thought.txt",
|
||||
@@ -185,10 +187,12 @@ export function LobbyHero({
|
||||
placeholder={t.placeholder}
|
||||
/>
|
||||
|
||||
{/* Examples: one row of tiles; the ways to bring your own
|
||||
diagram follow as a separate group */}
|
||||
<div
|
||||
className={cn(
|
||||
"mt-5 grid gap-2",
|
||||
compact ? "grid-cols-1" : "grid-cols-3",
|
||||
compact ? "grid-cols-1" : "grid-cols-5",
|
||||
)}
|
||||
>
|
||||
{examples.map((example) =>
|
||||
@@ -209,7 +213,7 @@ export function LobbyHero({
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<ExampleCard
|
||||
<ExampleTile
|
||||
key={example.key}
|
||||
onClick={() => pickExample(example)}
|
||||
title={example.title}
|
||||
@@ -221,7 +225,7 @@ export function LobbyHero({
|
||||
<img
|
||||
src={getAssetUrl(example.image)}
|
||||
alt=""
|
||||
className="max-h-10 max-w-[56px] object-contain transition-transform duration-300 group-hover/example:scale-[1.06]"
|
||||
className="max-h-14 max-w-[88%] object-contain transition-transform duration-300 group-hover/example:scale-[1.06]"
|
||||
/>
|
||||
) : (
|
||||
<FileText className="size-5 text-muted-foreground" />
|
||||
@@ -231,48 +235,34 @@ export function LobbyHero({
|
||||
/>
|
||||
),
|
||||
)}
|
||||
{!compact && (
|
||||
<ExampleCard
|
||||
onClick={onOpenFile}
|
||||
title={dict.workspace.openFile}
|
||||
description={t.openFileHint}
|
||||
picture={
|
||||
<FileUp className="size-5 text-muted-foreground" />
|
||||
}
|
||||
plain
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<p className="mt-3 text-center text-xs text-faint">
|
||||
<p className="mt-2.5 text-center text-xs text-faint">
|
||||
{dict.examples.cachedNote}
|
||||
</p>
|
||||
|
||||
<div className="mt-6 flex flex-wrap items-center justify-center gap-x-5 gap-y-2 text-[13px] text-muted-foreground">
|
||||
{/* Ways to start without an example, as plain buttons */}
|
||||
<div className="mt-6 flex flex-wrap items-center justify-center gap-2">
|
||||
{engine.sessions.length > 0 && (
|
||||
<SessionMenu align="center" onOpenFile={onOpenFile}>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-1.5 hover:text-foreground"
|
||||
>
|
||||
<button type="button" className={startButtonClass}>
|
||||
<History className="size-4" />
|
||||
{t.recent}
|
||||
</button>
|
||||
</SessionMenu>
|
||||
)}
|
||||
{compact && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenFile}
|
||||
className="inline-flex items-center gap-1.5 hover:text-foreground"
|
||||
>
|
||||
<FileUp className="size-4" />
|
||||
{dict.workspace.openFile}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenFile}
|
||||
className={startButtonClass}
|
||||
data-testid="open-file"
|
||||
>
|
||||
<FileUp className="size-4" />
|
||||
{dict.workspace.openFile}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onDrawYourself}
|
||||
className="inline-flex items-center gap-1.5 hover:text-foreground"
|
||||
className={startButtonClass}
|
||||
data-testid="draw-yourself"
|
||||
>
|
||||
<Pencil className="size-4" />
|
||||
|
||||
@@ -2,7 +2,6 @@ import {
|
||||
AlertCircle,
|
||||
Check,
|
||||
ChevronDown,
|
||||
Code2,
|
||||
Copy,
|
||||
Library,
|
||||
PenTool,
|
||||
@@ -180,17 +179,23 @@ function VersionCard({
|
||||
</button>
|
||||
)
|
||||
|
||||
// What the AI wrote, on every card (main showed it on every tool call)
|
||||
const codeButton = (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowCode((v) => !v)}
|
||||
aria-label={showCode ? t.hideCode : t.showCode}
|
||||
title={showCode ? t.hideCode : t.showCode}
|
||||
className="inline-flex size-7 shrink-0 items-center justify-center rounded-lg text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
<Code2 className="size-4" />
|
||||
</button>
|
||||
// What the AI wrote: a text link in the summary line, so the card's
|
||||
// only button is the action (undo or restore)
|
||||
const summaryLine = (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
{summary}
|
||||
{/* The link wraps as one unit with its separator */}
|
||||
<span className="whitespace-nowrap">
|
||||
<span aria-hidden> · </span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowCode((v) => !v)}
|
||||
className="underline decoration-foreground/30 underline-offset-2 hover:text-foreground hover:decoration-foreground"
|
||||
>
|
||||
{showCode ? t.hideCode : t.showCode}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
const codePanel = showCode && (
|
||||
<div className="relative border-t border-border bg-surface-1 px-3 py-2.5">
|
||||
@@ -231,15 +236,12 @@ function VersionCard({
|
||||
/>
|
||||
</button>
|
||||
{badge}
|
||||
<div className="min-w-0 flex-1" title={summary}>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="truncate text-[13px] text-foreground">
|
||||
{title}
|
||||
</div>
|
||||
<div className="truncate text-xs text-muted-foreground">
|
||||
{summary}
|
||||
</div>
|
||||
{summaryLine}
|
||||
</div>
|
||||
{codeButton}
|
||||
{restoreButton}
|
||||
</div>
|
||||
{codePanel}
|
||||
@@ -271,17 +273,12 @@ function VersionCard({
|
||||
{t.compare}
|
||||
</span>
|
||||
</button>
|
||||
<div className="flex items-center gap-2.5 px-3 py-2.5">
|
||||
{/* Title row with the action; the summary runs under both */}
|
||||
<div className="grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-x-2.5 px-3 py-2.5">
|
||||
{badge}
|
||||
<div className="min-w-0 flex-1" title={summary}>
|
||||
<div className="truncate text-[13px] font-medium text-foreground">
|
||||
{title}
|
||||
</div>
|
||||
<div className="line-clamp-2 text-xs text-muted-foreground">
|
||||
{summary}
|
||||
</div>
|
||||
<div className="truncate text-[13px] font-medium text-foreground">
|
||||
{title}
|
||||
</div>
|
||||
{codeButton}
|
||||
{canUndo ? (
|
||||
<button
|
||||
type="button"
|
||||
@@ -300,6 +297,9 @@ function VersionCard({
|
||||
) : (
|
||||
restoreButton
|
||||
)}
|
||||
<div className="col-span-2 col-start-2 mt-0.5">
|
||||
{summaryLine}
|
||||
</div>
|
||||
</div>
|
||||
{codePanel}
|
||||
</div>
|
||||
|
||||
@@ -220,14 +220,14 @@ export function ModelSelector({
|
||||
<span className="min-w-0 truncate text-xs">
|
||||
{selectedModel
|
||||
? shortModelName(selectedModel.modelId)
|
||||
: dict.modelConfig.default}
|
||||
: dict.modelConfig.serverDefault}
|
||||
</span>
|
||||
) : (
|
||||
// Keep an sr-only label for screen readers when hidden
|
||||
<span className="sr-only">
|
||||
{selectedModel
|
||||
? selectedModel.modelId
|
||||
: dict.modelConfig.default}
|
||||
: dict.modelConfig.serverDefault}
|
||||
</span>
|
||||
)}
|
||||
<ChevronDown className="h-3 w-3 flex-shrink-0 text-muted-foreground" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { MessageSquare, PanelRightOpen, Settings2, Shapes } from "lucide-react"
|
||||
import { MessageSquare, PanelRightOpen, Settings, Shapes } from "lucide-react"
|
||||
import { usePathname, useRouter } from "next/navigation"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { CanvasStage } from "@/components/canvas/canvas-stage"
|
||||
@@ -100,7 +100,7 @@ function StartBar({
|
||||
onClick={() => openSettings()}
|
||||
data-testid="settings-button"
|
||||
>
|
||||
<Settings2 />
|
||||
<Settings />
|
||||
</IconButton>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
"replicateDescription": "Upload and replicate an existing flowchart",
|
||||
"creativeDrawing": "Creative drawing",
|
||||
"creativeDescription": "Draw something fun and creative",
|
||||
"cachedNote": "Examples open instantly and don't use your model.",
|
||||
"cachedNote": "Examples use saved answers: they appear instantly and don't call the AI.",
|
||||
"mcpServer": "MCP Server",
|
||||
"mcpDescription": "Use in Claude Desktop, VS Code & Cursor"
|
||||
},
|
||||
@@ -96,7 +96,7 @@
|
||||
"language": "Language",
|
||||
"languageDescription": "Choose your interface language.",
|
||||
"theme": "Theme",
|
||||
"themeDescription": "Light or dark interface. The diagram always stays on a white sheet, the way it exports.",
|
||||
"themeDescription": "Light or dark interface. The canvas follows the same theme.",
|
||||
"diagramStyle": "Diagram style",
|
||||
"diagramStyleDescription": "How the AI draws new diagrams: Styled uses colors and icons, Minimal keeps shapes plain.",
|
||||
"sendShortcut": "Send shortcut",
|
||||
@@ -399,7 +399,7 @@
|
||||
"searchModels": "Search models...",
|
||||
"noModelsFound": "No models found.",
|
||||
"default": "Default",
|
||||
"serverDefault": "Server Default",
|
||||
"serverDefault": "Server model",
|
||||
"serverModels": "Server Models",
|
||||
"userModels": "User Models",
|
||||
"configureModels": "Configure Models...",
|
||||
@@ -694,7 +694,7 @@
|
||||
},
|
||||
"lobby": {
|
||||
"title": "What would you like to draw?",
|
||||
"lede": "Describe a diagram, or upload a screenshot or PDF. You get a regular draw.io diagram that you can keep editing and export.",
|
||||
"lede": "Describe a diagram or upload a screenshot or PDF. You get a draw.io diagram you can keep editing and export.",
|
||||
"placeholder": "For example: a login sequence diagram with SMS codes and retries",
|
||||
"recent": "Recent diagrams",
|
||||
"drawYourself": "Start with a blank canvas",
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
"replicateDescription": "既存のフローチャートをアップロードして複製",
|
||||
"creativeDrawing": "自由なイラスト",
|
||||
"creativeDescription": "楽しくてクリエイティブなものを描く",
|
||||
"cachedNote": "例はすぐに開き、モデルは使いません。",
|
||||
"cachedNote": "例は保存済みの回答を使うので、すぐに表示され、AI を呼び出しません。",
|
||||
"mcpServer": "MCP サーバー",
|
||||
"mcpDescription": "Claude Desktop、VS Code、Cursor で使用"
|
||||
},
|
||||
@@ -96,7 +96,7 @@
|
||||
"language": "言語",
|
||||
"languageDescription": "インターフェース言語を選択します。",
|
||||
"theme": "テーマ",
|
||||
"themeDescription": "画面をライトにするかダークにするか。図はエクスポートしたときと同じく、常に白い用紙の上に表示されます。",
|
||||
"themeDescription": "画面をライトにするかダークにするか。キャンバスも同じテーマになります。",
|
||||
"diagramStyle": "図のスタイル",
|
||||
"diagramStyleDescription": "AI が新しい図を描くときのスタイル。スタイル付きは色やアイコンを使い、ミニマルは素朴な図形だけにします。",
|
||||
"sendShortcut": "送信のショートカット",
|
||||
@@ -354,7 +354,7 @@
|
||||
"searchModels": "モデルを検索...",
|
||||
"noModelsFound": "モデルが見つかりません。",
|
||||
"default": "デフォルト",
|
||||
"serverDefault": "サーバーデフォルト",
|
||||
"serverDefault": "サーバーのモデル",
|
||||
"serverModels": "サーバーモデル",
|
||||
"userModels": "ユーザーモデル",
|
||||
"configureModels": "モデルを設定...",
|
||||
@@ -694,7 +694,7 @@
|
||||
},
|
||||
"lobby": {
|
||||
"title": "どんな図を描きますか?",
|
||||
"lede": "図の内容を説明するか、スクリーンショットや PDF をアップロードしてください。できあがるのは通常の draw.io の図なので、続けて編集もエクスポートもできます。",
|
||||
"lede": "図を説明するか、スクリーンショットや PDF をアップロードしてください。できあがるのは編集もエクスポートもできる draw.io の図です。",
|
||||
"placeholder": "例:SMS 認証とリトライを含むログインのシーケンス図",
|
||||
"recent": "最近の図",
|
||||
"drawYourself": "白紙のキャンバスから始める",
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
"replicateDescription": "上傳並複製現有流程圖",
|
||||
"creativeDrawing": "創意繪畫",
|
||||
"creativeDescription": "繪製有趣且富有創意的內容",
|
||||
"cachedNote": "範例會立即開啟,不呼叫模型。",
|
||||
"cachedNote": "範例使用保存好的答案,立即顯示,不呼叫 AI。",
|
||||
"mcpServer": "MCP 伺服器",
|
||||
"mcpDescription": "在 Claude Desktop、VS Code 和 Cursor 中使用"
|
||||
},
|
||||
@@ -96,7 +96,7 @@
|
||||
"language": "語言",
|
||||
"languageDescription": "選擇介面語言。",
|
||||
"theme": "主題",
|
||||
"themeDescription": "介面用淺色還是深色。圖紙始終是白底,和匯出後的樣子一致。",
|
||||
"themeDescription": "介面用淺色還是深色,畫布跟隨同一主題。",
|
||||
"diagramStyle": "圖形風格",
|
||||
"diagramStyleDescription": "AI 畫新圖時的風格:精緻會用顏色和圖示,簡約只用樸素的圖形。",
|
||||
"sendShortcut": "傳送快速鍵",
|
||||
@@ -399,7 +399,7 @@
|
||||
"searchModels": "搜尋模型...",
|
||||
"noModelsFound": "未找到模型。",
|
||||
"default": "預設",
|
||||
"serverDefault": "伺服器預設",
|
||||
"serverDefault": "伺服器模型",
|
||||
"serverModels": "伺服器模型",
|
||||
"userModels": "使用者模型",
|
||||
"configureModels": "配置模型...",
|
||||
@@ -694,7 +694,7 @@
|
||||
},
|
||||
"lobby": {
|
||||
"title": "說說你要畫什麼",
|
||||
"lede": "描述一張圖,或上傳截圖、PDF。畫出來的是標準的 draw.io 圖表,可以接著改,也可以匯出。",
|
||||
"lede": "描述一張圖,或上傳截圖、PDF。得到的是可以繼續編輯和匯出的 draw.io 圖。",
|
||||
"placeholder": "例如:使用者登入的時序圖,包含簡訊驗證碼和失敗重試",
|
||||
"recent": "最近的圖紙",
|
||||
"drawYourself": "從空白畫布開始",
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
"replicateDescription": "上传并复制现有流程图",
|
||||
"creativeDrawing": "创意绘画",
|
||||
"creativeDescription": "绘制有趣且富有创意的内容",
|
||||
"cachedNote": "示例会立即打开,不调用模型。",
|
||||
"cachedNote": "示例使用保存好的答案,立即显示,不调用 AI。",
|
||||
"mcpServer": "MCP 服务器",
|
||||
"mcpDescription": "在 Claude Desktop、VS Code 和 Cursor 中使用"
|
||||
},
|
||||
@@ -96,7 +96,7 @@
|
||||
"language": "语言",
|
||||
"languageDescription": "选择界面语言。",
|
||||
"theme": "主题",
|
||||
"themeDescription": "界面用浅色还是深色。图纸始终是白底,和导出后的样子一致。",
|
||||
"themeDescription": "界面用浅色还是深色,画布跟随同一主题。",
|
||||
"diagramStyle": "图形风格",
|
||||
"diagramStyleDescription": "AI 画新图时的风格:精致会用颜色和图标,简约只用朴素的图形。",
|
||||
"sendShortcut": "发送快捷键",
|
||||
@@ -399,7 +399,7 @@
|
||||
"searchModels": "搜索模型...",
|
||||
"noModelsFound": "未找到模型。",
|
||||
"default": "默认",
|
||||
"serverDefault": "服务器默认",
|
||||
"serverDefault": "服务器模型",
|
||||
"serverModels": "服务器模型",
|
||||
"userModels": "用户模型",
|
||||
"configureModels": "配置模型...",
|
||||
@@ -694,7 +694,7 @@
|
||||
},
|
||||
"lobby": {
|
||||
"title": "说说你要画什么",
|
||||
"lede": "描述一张图,或者上传截图、PDF。画出来的是标准的 draw.io 图表,可以接着改,也可以导出。",
|
||||
"lede": "描述一张图,或上传截图、PDF。得到的是可以继续编辑和导出的 draw.io 图。",
|
||||
"placeholder": "比如:用户登录的时序图,包含短信验证码和失败重试",
|
||||
"recent": "最近的图纸",
|
||||
"drawYourself": "从空白画布开始",
|
||||
|
||||
Generated
+1136
-1686
File diff suppressed because it is too large
Load Diff
+17
-17
@@ -45,11 +45,11 @@
|
||||
"@aihubmix/ai-sdk-provider": "^2.2.1",
|
||||
"@aws-sdk/client-dynamodb": "^3.957.0",
|
||||
"@aws-sdk/credential-providers": "^3.943.0",
|
||||
"@extractus/article-extractor": "^8.0.18",
|
||||
"@extractus/article-extractor": "^9.0.0",
|
||||
"@formatjs/intl-localematcher": "^0.9.0",
|
||||
"@langfuse/client": "^4.4.9",
|
||||
"@langfuse/otel": "^4.4.4",
|
||||
"@langfuse/tracing": "^4.4.9",
|
||||
"@langfuse/client": "^5.0.0",
|
||||
"@langfuse/otel": "^5.0.0",
|
||||
"@langfuse/tracing": "^5.0.0",
|
||||
"@next/third-parties": "^16.0.6",
|
||||
"@opennextjs/cloudflare": "^1.17.1",
|
||||
"@openrouter/ai-sdk-provider": "^2.10.0",
|
||||
@@ -74,13 +74,13 @@
|
||||
"cmdk": "^1.1.1",
|
||||
"idb": "^8.0.3",
|
||||
"jsonrepair": "^3.13.1",
|
||||
"lucide-react": "^0.577.0",
|
||||
"motion": "^12.23.25",
|
||||
"nanoid": "^5.0.0",
|
||||
"lucide-react": "^1.0.0",
|
||||
"motion": "^14.0.0",
|
||||
"nanoid": "^6.0.0",
|
||||
"negotiator": "^1.0.0",
|
||||
"next": "^16.0.7",
|
||||
"ollama-ai-provider-v2": "^3.6.0",
|
||||
"pako": "^2.1.0",
|
||||
"pako": "^3.0.0",
|
||||
"prism-react-renderer": "^2.4.1",
|
||||
"react": "^19.1.2",
|
||||
"react-dom": "^19.1.2",
|
||||
@@ -119,27 +119,27 @@
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
"@types/negotiator": "^0.6.4",
|
||||
"@types/node": "^24.0.0",
|
||||
"@types/pako": "^2.0.3",
|
||||
"@types/pako": "^3.0.0",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@types/turndown": "^5.0.6",
|
||||
"@vitejs/plugin-react": "^5.1.2",
|
||||
"@vitest/coverage-v8": "^4.0.16",
|
||||
"concurrently": "^9.2.1",
|
||||
"@vitejs/plugin-react": "^6.0.0",
|
||||
"@vitest/coverage-v8": "^5.0.0",
|
||||
"concurrently": "^10.0.0",
|
||||
"cross-env": "^10.1.0",
|
||||
"electron": "^39.2.7",
|
||||
"electron-builder": "^26.0.12",
|
||||
"esbuild": "^0.28.0",
|
||||
"eslint": "9.39.5",
|
||||
"eslint": "10.12.0",
|
||||
"eslint-config-next": "16.1.6",
|
||||
"husky": "^9.1.7",
|
||||
"jsdom": "^27.4.0",
|
||||
"lint-staged": "^16.2.7",
|
||||
"jsdom": "^30.0.0",
|
||||
"lint-staged": "^17.0.0",
|
||||
"shx": "^0.4.0",
|
||||
"tailwindcss": "^4",
|
||||
"typescript": "^5",
|
||||
"typescript": "^7.0.0",
|
||||
"vite-tsconfig-paths": "^6.0.3",
|
||||
"vitest": "^4.0.16",
|
||||
"vitest": "^5.0.0",
|
||||
"wait-on": "^9.0.3",
|
||||
"wrangler": "^4.60.0"
|
||||
},
|
||||
|
||||
Generated
+527
-217
File diff suppressed because it is too large
Load Diff
@@ -42,16 +42,16 @@
|
||||
"@modelcontextprotocol/sdk": "^1.31.0",
|
||||
"linkedom": "^0.18.0",
|
||||
"open": "^11.0.0",
|
||||
"pako": "^2.2.0",
|
||||
"pako": "^3.0.0",
|
||||
"saxes": "^6.0.0",
|
||||
"zod": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.0.0",
|
||||
"@types/pako": "^2.0.4",
|
||||
"@types/pako": "^3.0.0",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5",
|
||||
"vitest": "^4.1.8"
|
||||
"typescript": "^7.0.0",
|
||||
"vitest": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 67 KiB |
Reference in New Issue
Block a user