mirror of
https://github.com/ZSeven-W/openpencil.git
synced 2026-06-01 03:14:29 +07:00
* fix(renderer): skip paragraph image cache when zoomed in * refactor(publish-cli): streamline version publishing process - Removed the check for already published versions to simplify the workflow. - Updated npm publish commands to handle already published versions gracefully, allowing the process to continue without aborting. - Added publishing step for the new pen-ai-skills package, ensuring it is included in the deployment process. * fix(mcp): wire openpencil codex install to config toml (#85) Co-authored-by: Kaiiiiiiiii <182183652+Smile232323@users.noreply.github.com> * refactor(mcp): reorganize codex-cli handling in installation process - Removed the codex-cli configuration from CLI_CONFIGS and adjusted the installation logic to handle codex-cli actions directly. - Improved error handling for unknown CLI tools and streamlined the installation process for codex-cli, ensuring it uses its own commands for adding/removing components. * feat(agent): add built-in agent SDK and web integration Introduces @zseven-w/agent — a domain-agnostic agent SDK with: - Agent loop (plan→act→observe) with dual execution model - Anthropic + OpenAI-compatible provider adapters via Vercel AI SDK - Tool registry with auth levels (read/create/modify/delete/orchestrate) - Agent team orchestration with delegate tool - SSE streaming protocol encoder/decoder - Sliding window context management Web app integration: - Built-in provider config UI with presets (Anthropic, OpenAI, OpenRouter, DeepSeek) - Model search via provider API proxy endpoint - Built-in models appear in the model dropdown alongside CLI agents - Server-side agent SSE endpoint with session management - Client-side tool executor with undo batch support - Inline tool call blocks in chat UI * feat(api): implement keep-alive pings for long-running LLM calls - Added a keep-alive mechanism in the SSE stream for the agent API to prevent timeouts during long-running LLM calls. - Updated the keep-alive interval to 8 seconds to align with Bun.serve's default idle timeout of 10 seconds. - Ensured proper cleanup of the ping timer when the stream is closed. * feat(mcp): enhance live sync diagnostics and port file management - Implemented a mechanism to probe the live sync server's availability, providing clearer diagnostics for connection issues. - Updated the port file structure to include a unique token for better management and cleanup. - Enhanced the `getSyncUrl` and `getLiveSyncState` functions to return detailed status messages based on the server's response. - Added tests for live sync diagnostics to ensure accurate reporting of server states. * feat(mcp): implement sync URL caching for improved performance - Added caching mechanism for sync URLs to reduce repeated reads and health checks, enhancing performance during live document and selection fetches. - Introduced functions to set and clear the cached sync URL, improving connection management. - Updated existing functions to utilize the cached URL when available, streamlining the fetching process. * feat(skia): enhance syncFromDocument error handling and normalize document structure - Wrapped the syncFromDocument method in a try-catch block to log errors during synchronization, improving debugging capabilities. - Introduced normalization of external documents in the document store to ensure consistent structure before processing. - Updated text content resolution to handle both 'content' and 'text' fields, enhancing compatibility with various node formats. - Refactored text measurement functions to streamline text handling and improve layout consistency. * chore: update package versions to 0.6.0 across all modules and enhance code generation pipeline - Bumped version from 0.5.3 to 0.6.0 in package.json files for all modules including core, agent, and various code generation packages. - Refactored code generation functions to utilize a new AI code generation pipeline, marking previous functions as deprecated with plans for removal in v1.0.0. - Introduced new export nodes functionality in the MCP server for raw PenNode data export. * fix(mcp): clear stale sync cache on page load to prevent false dirty state When refreshing the page or opening a new file, the SSE document:init event would echo back the old cached document, causing applyExternalDocument to unconditionally set isDirty=true and trigger a spurious save prompt. * style(panels): improve AI checklist visual design Add progress bar, spinner animation, highlighted active items, and pill-shaped counter badge for a more polished orchestrator progress UI. * feat(ci): add Homebrew Cask update workflow for OpenPencil releases - Implemented a new GitHub Actions job to update the Homebrew Cask for OpenPencil upon new version tags. - The workflow fetches the latest macOS binaries, computes their SHA256 checksums, and updates the cask formula accordingly. - Includes steps for committing and pushing changes to the tap repository. * docs: update installation instructions in README and enhance CI workflow for Scoop bucket updates - Added detailed installation instructions for macOS, Windows, and Linux in the README. - Introduced a new GitHub Actions job to update the Scoop bucket with the latest OpenPencil release, including versioning and SHA256 checksum computation for Windows binaries. * docs: add OpenPencil Skill plugin link to all i18n READMEs Add localized LLM Skill link in CLI section across all 15 README files, pointing to zseven-w/openpencil-skill repository. * docs: add same-name project disclaimer to all i18n READMEs Distinguish from open-pencil/open-pencil (Figma-compatible visual design with real-time collaboration) — this project focuses on AI-native design-to-code workflows. * fix(agent): resolve SSE timeout, routing, and message format issues - Add 5s keep-alive ping to agent SSE stream (prevents Bun 10s idle timeout) - Consolidate tool-result and abort into single agent endpoint (?action=result|abort) - Fix assistant message history: include text alongside tool-call parts - Fix ToolResultPart format: use 'output' field with {type:'text',value} structure - Use openai.chat() instead of openai() for Chat Completions API (OpenRouter compat) - Use proper TOOL_SCHEMAS instead of z.any() for tool parameters * fix(agent): prevent sliding window from splitting assistant+tool groups The sliding window context strategy was naively slicing by message count, which could leave orphaned tool_result messages without their preceding assistant tool_use — causing Claude API to reject the request. Now counts "logical turns" (user/assistant starts) and never cuts inside an assistant→tool group. Also increased default window from 10 to 50 turns. * fix(agent): use correct AI SDK v6 parameter name maxOutputTokens streamText() in AI SDK v6 renamed maxTokens to maxOutputTokens. Default 4096 prevents OpenRouter credit limit errors from requesting the model's full 65536 token capacity. * feat(agent): add API error classification and auto-retry without tools When a model doesn't support function calling (400 errors, missing arguments), the agent loop now classifies the error and automatically retries without tools on the first turn. Also provides user-friendly error messages for common failures: privacy restrictions, credit limits, rate limiting, and incompatible models. * fix(agent): improve system prompt with PenNode schema and workflow guidance - Add PenNode property schema to agent system prompt so models know valid properties (fills, cornerRadius, padding array, etc.) - Explicitly forbid CSS properties (backgroundColor, boxShadow, etc.) - Add workflow steps: plan before creating, avoid create-then-delete - Change max turns reached from error to normal done event * feat(agent): align insert_node with CLI batch_design capability - insert_node now supports nested children arrays (recursive ID generation) - Post-processing pipeline runs after insertion: role resolution, icon resolution, layout sanitization, unique ID enforcement — same as MCP batch_design with postProcess=true - System prompt teaches model to create entire designs in ONE insert_node call with nested children, instead of 20+ individual calls - Includes concrete example of nested PenNode structure in prompt * fix(agent): deep-clone node before post-processing to avoid Zustand mutation Zustand state is immutable — post-processing functions mutate in-place. JSON.parse(JSON.stringify()) creates a mutable copy. Each post-processing step is individually try-caught so partial failures don't break insertion. * fix(agent): return node count in insert_node result to prevent model retries insert_node now returns {id, nodesCreated, message} so the model knows the full tree was created. System prompt reinforces: when insert_node succeeds, do NOT retry. Reduces 5+ duplicate insert calls to exactly 1. * fix(agent): prevent duplicate root-level inserts from weaker models Track the first root-level insert_node ID per session. Subsequent root-level insert_node calls return the existing ID with a message instead of creating duplicates. Fixes M2.5 and similar models that ignore "do not retry" prompt instructions. * feat(agent): support Anthropic API format in custom provider settings Custom provider preset now has an API Format toggle: "OpenAI Compatible" or "Anthropic". This allows users to configure custom Anthropic-compatible endpoints (proxies, mirrors) in addition to OpenAI-compatible ones. Anthropic provider also now accepts optional baseURL for proxy support. * fix(agent): update Custom option label in provider dropdown * fix(agent): match 'invalid function arguments' in error classifier for auto-retry * fix(agent): always auto-retry without tools on first turn errors Many providers (MiniMax, StepFun) have broken tool call implementations. Instead of pattern-matching specific error messages, any streaming error on turn 0 now triggers auto-retry without tools. The model falls back to generating a text-only response instead of failing entirely. * fix(agent): use clean JSON Schema for tool definitions (no $schema field) Replaced Zod schemas with jsonSchema() from AI SDK for tool parameter definitions. Zod's zodToJsonSchema adds "$schema" and "additionalProperties" fields that strict OpenAI-compatible APIs (MiniMax, StepFun) reject with "invalid function arguments". Clean JSON Schema only has type/properties/ required — compatible with all providers. Also added text-mode fallback prompt for when tools are truly unsupported. * fix(agent): ensure tool call args is always {} and fix turn>0 retry Two fixes for MiniMax "invalid function arguments" error: 1. Ensure args is always {} (never undefined/null) when building conversation history — undefined args causes strict APIs to reject 2. Auto-retry without tools now works on ANY turn (not just turn 0) by resetting history to original user messages and restarting * fix(agent): use SDK response.messages for history instead of manual construction Root cause of MiniMax "invalid function arguments" error: we were manually constructing ModelMessage[] for conversation history, which the SDK then failed to convert correctly to OpenAI format (dropping function.arguments). Fix: use response.response.messages from the SDK — it produces correctly formatted messages that the provider knows how to convert. Only manually add tool result messages for client-executed tools (no execute() function). Also keeps a fetch interceptor as safety net to patch any remaining edge cases with missing/malformed arguments. * fix(agent): parse stringified JSON in insert_node data parameter Some models (MiniMax M2.5) send insert_node data as a JSON string instead of an object. Now handleInsertNode detects string data and JSON.parse it before processing. Fixes nodesCreated:1 when model sends nested children as a stringified object. * fix(agent): sanitize node data and catch addNode side-effect errors - Convert model's 'border' property to valid 'strokes' array - Filter null/non-object children before processing - Wrap docStore.addNode in try-catch — canvas sync side-effects (e.g., renderer hitting unknown properties) may throw but the node IS still inserted. Return success regardless. * fix(agent): auto-zoom to fit after insert_node to show new design * fix(agent): align insert_node with batch_design — auto-replace empty root frame When inserting a frame at root level and an empty root frame exists, replace it and inherit its position (x:0, y:0). This matches the MCP batch_design behavior (line 146-161) so the design lands in the visible viewport instead of off-screen at x:1250. * fix(agent): use updateNode for empty frame replacement (no duplicate keys) The remove+add pattern caused React duplicate key errors because two separate Zustand state updates could leave the node in two places. Now uses a single updateNode call to replace the empty frame's properties in-place — atomic operation, no duplicates. * fix(agent): set replaced=true BEFORE updateNode to prevent duplicate on side-effect throw * fix(agent): use atomic tree swap for empty frame replacement updateNode caused canvas sync crash (map on undefined) because the renderer couldn't handle a complete property replacement on an existing node. Now uses removeNodeFromTree + insertNodeInTree in a single setState — same atomic approach as MCP batch_design. The Skia engine sees the new node as a fresh addition, not an update to an existing one. * fix(agent): simplify empty frame replacement to removeNode+addNode via store API * refactor(agent): use applyNodesToCanvas instead of raw addNode The agent's insert_node was bypassing the design pipeline's sanitization and canvas sync code, causing blank canvas rendering. Now delegates to the SAME applyNodesToCanvas function used by the CLI/MCP design pipeline. This handles: - sanitizeNodesForInsert (role defaults, layout fixes, unique IDs) - isCanvasOnlyEmptyFrame → replaceEmptyFrame (empty frame at 0,0) - icon resolution and image scanning - proper Skia canvas sync Removed the custom postProcessNode method — no longer needed since applyNodesToCanvas does the same work correctly. * feat(agent): add generate_design tool using internal CLI design pipeline generate_design delegates to the SAME generateDesign() function the standard chat uses — orchestrator, sub-agents, streaming insertion, post-processing. Finds the first connected CLI provider for LLM calls. Also uses insertStreamingNode with resetGenerationRemapping() for insert_node, matching the CLI streaming pattern exactly. * feat(agent): replace insert_node with generate_design as primary design tool Remove insert_node and find_empty_space from agent tool set — models should use generate_design for creating designs, not raw PenNode JSON. generate_design accepts natural language prompts and delegates to the full internal pipeline. Keeps update_node/delete_node for modifications. * feat(agent): simplify system prompt to direct models to generate_design Clear instruction: when user asks to create/design, MUST call generate_design tool. No JSON output, no manual node construction. * fix(agent): strip <think> tags from model text output in chat UI Models like MiniMax M2.5 and DeepSeek output <think>...</think> as plain text (not via the thinking SSE event). Strip both closed and unclosed <think> tags from the displayed text during streaming. * fix(renderer): skip paragraph image cache when zoomed out below 0.5x Bitmap text cache at fixed DPR resolution produces jagged edges when scaled down significantly. Now only uses cache at 0.5x–1x zoom range. Below 0.5x and above 1x, falls back to vector Paragraph API rendering. * fix(ai): prevent model from using OpenPencil as brand name in generated designs * fix(agent): strip <think> tags from final message, not just during streaming The regex was only applied during text-delta events but the final message (returned by runAgentStream and set in done/error handlers) used the raw accumulated text. Now stripThinkTags() is applied at the return point so the final displayed message is always clean. * fix(ai): reduce keepalive ping interval from 15s to 5s for Bun compatibility Bun.serve has a 10s idle timeout. The previous 15s ping interval meant the first ping arrived AFTER Bun killed the connection, causing "socket connection was closed unexpectedly" errors when waiting for slow LLM responses (extended thinking, TTFT > 10s). Now pings at 5s. * fix(renderer): rasterize paragraph image cache at 2x minimum for crisp text on low-DPR * fix(agent): remove hardcoded TOOL_SCHEMAS and maxOutputTokens - Server uses client-provided JSON schemas (single source of truth) - maxOutputTokens configurable per provider, defaults to model limit - turnTimeout increased to 5min for generate_design pipeline - Session cleanup wrapped in try-catch - Re-export streamText from agent SDK for consumer use * feat(agent): add builtin provider support to /api/ai/chat endpoint streamViaBuiltin() uses Vercel AI SDK to call LLM directly with API key — no CLI tool required. ai-service.ts attaches builtin credentials from agent settings store when provider is 'builtin'. This enables generate_design to work without any CLI provider connected. * fix(agent): align generate_design params with CLI pipeline and handle field name variants - Pass concurrency, variables, themes, designMd to generateDesign() (was missing, causing lower quality output vs CLI mode) - Accept both 'prompt' and 'description' field names from models - Fall back to builtin provider when no CLI provider connected - Enable animated node insertion * feat(agent): dynamic system prompt via pen-ai-skills + misc fixes - Replace hardcoded AGENT_SYSTEM_PROMPT with buildAgentSystemPrompt() that loads design knowledge from pen-ai-skills (same as CLI pipeline) - Validate builtin provider apiKey before agent connection - Client-side tool schema serialization for server (no duplication) - Update tool_call block status locally as fallback for lost SSE events - Pass maxOutputTokens from provider config * refactor(agent): extract builtin provider settings to separate file Split BuiltinProviderForm, BuiltinProviderCard, BuiltinProvidersSection from agent-settings-dialog.tsx (1279→730 lines) into builtin-provider-settings.tsx (394 lines). Both under 800 line limit. * refactor(agent): extract model selector to separate file Split ModelDropdown, ConcurrencyButton, resolveNextModel, PROVIDER_ICON from ai-chat-panel.tsx (915→690 lines) into ai-chat-model-selector.tsx (183 lines). Both under 800 line limit. * fix(renderer): guard against undefined fill entries in resolveFillColor/resolveStrokeColor * feat(ai): extend BuiltinProviderPreset with 9 new providers Add MiniMax, Zhipu, Kimi, Bailian, DouBao, Xiaomi MiMo, ModelScope, StepFun and NVIDIA NIM to the builtin provider preset type union. * feat(ai): add provider presets and region switcher for builtin providers Add preset configs for MiniMax, Zhipu, Kimi, Bailian (DashScope), DouBao Seed, Xiaomi MiMo, ModelScope, StepFun and NVIDIA NIM with correct API base URLs and model placeholders. Providers with separate China/Global endpoints (MiniMax, Zhipu, Kimi, Bailian, StepFun) get a region toggle that auto-switches the base URL. Region inference works both for new providers and when editing existing ones via REGION_URLS reverse-lookup table. * style(ai): increase settings dialog height for more provider entries * feat(ai): add i18n for builtin provider settings (15 locales) Extract all hardcoded strings in builtin-provider-settings.tsx to i18n keys under the builtin.* namespace. Add translations for all 15 supported languages: en, zh, zh-TW, ja, ko, fr, es, de, pt, ru, hi, tr, th, vi, id. * fix(ai): remove remaining hardcoded strings in builtin provider UI - Extract error messages, badge text, tooltip, and placeholder to i18n - Remove unused region label fields from PresetRegion interface - Add 8 new builtin.* keys across all 15 locales - Fix ai-chat-model-selector API Key badge and parallel agents tooltip - Fix ai-chat-panel provider description template - Fix ai-chat-handlers error messages via i18n.t() * fix(agent): clean up pending tool calls on exit and improve error handling P0: Wrap agent loop generator in try-finally to reject all pending tool call promises and clear timeout timers when the loop exits. Prevents timeout leaks when sessions end early. P1: Add HTTP status code matching (429, 402, 403) before regex fallback in classifyAPIError for more reliable error classification. P1: Clone tool registry in createTeam instead of mutating the caller's config.lead.tools. Add doc comment for unused _maxTokens parameter in sliding-window strategy. * fix(ai): add error handling and retry for tool result POST The POST to /api/ai/agent?action=result had no error handling. If it failed, the agent loop would hang forever waiting for the tool result. Now retries once on failure and logs the error. * fix(ai): use lastActivity for session TTL and guard stream init P1: Add lastActivity timestamp to AgentSession, updated on every event and tool result. TTL cleanup now checks lastActivity instead of createdAt, preventing active long-running sessions from being killed. P1: Wrap ReadableStream construction in try-catch to ensure session cleanup if stream initialization fails. * chore: add docs/ to gitignore * fix(ai): update model lists and fix model search for providers - Update Anthropic models to include Claude 4.6 (Opus + Sonnet) - Update model placeholders: OpenAI→gpt-5.4, MiniMax→M2.7, Zhipu→glm-5, Kimi→kimi-k2.5, Xiaomi→mimo-v2-pro - Add hardcoded model lists for MiniMax and DouBao (no /models API) - Generalize ANTHROPIC_MODELS to BUILTIN_MODEL_LISTS lookup table - Fix provider-models proxy to handle { models: [...] } and array response formats in addition to OpenAI's { data: [...] } * docs: update CLAUDE.md and README files for new AI agent SDK and i18n support - Added new sections in CLAUDE.md detailing the AI agent SDK and its multi-provider capabilities. - Updated README files in multiple languages to include information about the built-in AI agent SDK and full interface localization in 15 languages. - Adjusted key technologies and scopes to reflect recent changes in the project structure and features. * docs(agent): add Agent Team web integration design spec Phase 3 design: model routing via Agent Team. Lead agent uses fast model for chat, designer member uses capable model for generation. SDK changes: source tracking on events, member_start/end events, auto team suffix. Web changes: team toggle + design model selector in settings, conditional createTeam in server endpoint. * fix(electron): fix Scoop/Homebrew tap auto-update in CI - Add pre_install to Scoop manifest to rename versioned exe to OpenPencil.exe - Add mkdir -p for Casks/ and bucket/ dirs in tap repos - Use curl -fSL to fail fast on HTTP errors instead of silent mode * docs(agent): add Agent Team web integration implementation plan 9 tasks: SDK event types → SSE tests → team source injection → server team endpoint → settings store → team UI → i18n → chat handler wiring → e2e verification * feat(agent): add source field and team events to AgentEvent type * test(agent): add SSE encoder/decoder tests for source and team events * feat(agent): inject source field and team events in agent-team * feat(ai): extend agent endpoint to support team mode with members * feat(ai): add teamEnabled and teamDesignModel to agent settings store * feat(ai): wire team mode in chat handlers with member events * feat(ai): add i18n keys for team settings (15 locales) * feat(ai): add Team section UI with design model selector * fix(agent): route resolveToolResult to correct agent in team mode Member tool calls (e.g. generate_design) were routed to leadAgent which didn't have them in its pending map. Added toolCallOwners map to track which agent (lead or member) issued each tool call and route resolveToolResult accordingly. * docs(agent): clarify resolveToolResult routing, member tools, and source handling * fix(agent): force delegation in team mode and add turnTimeout support Two fixes for team mode generation failures: 1. Remove generate_design from lead's tool registry in team mode, forcing the lead to delegate design work to the designer member 2. Add turnTimeout to TeamMemberConfig/TeamConfig and pass 5min timeout to member agents (generate_design needs it) * fix(ai): make team mode visually distinct in chat UI - Add source badge on tool call blocks (shows "designer" pill for member-initiated tool calls) - Pass evt.source to ToolCallBlockData - Use blockquote format for member_start/end events so team activity is clearly visible in the chat stream * fix(agent): scope designer tools, streamline delegation, add model hint 1. Designer member only gets generate_design + snapshot_layout (was: all tools, causing 7 wasteful batch_get calls) 2. Team suffix tells lead to delegate immediately without verbose planning text 3. UI shows amber tip when only 2 providers configured, suggesting a more capable model for design * fix(ai): clean up partial nodes on generate_design failure When generate_design fails midway, partial nodes were left on the canvas and rootInsertId was not set, allowing a retry that created a duplicate design. Now: 1. Set rootInsertId='generating' BEFORE calling generateDesign 2. Snapshot node IDs before generation 3. On failure, remove all new nodes and reset rootInsertId to null 4. Remove incorrect same-model warning from Team UI * fix(ai): show Team section with 1 enabled provider * refactor(ai): smart team mode — auto-enable when design model is set Remove manual Team toggle. Selecting a Design Model automatically enables team mode; "None (single agent)" disables it. Simpler UX: one dropdown replaces toggle + dropdown. Updated descriptions and removed obsolete teamTitle/teamSameModelWarning i18n keys. * fix(agent): properly serialize non-Error objects in error messages String(err) on plain objects produces "[object Object]". Changed to err instanceof Error ? err.message : JSON.stringify(err) for readable error messages in tool results and design generation failures. * refactor(ai): auto team mode using current chat model Remove Design Model dropdown from settings. Team mode is now fully automatic: the designer member always uses the same provider/model as the current chat selection. Zero configuration needed — the value is in role separation (different prompts + scoped tools), not model selection. * style(ai): use min/max height for settings dialog instead of fixed height * feat(ai): add Google Gemini to builtin provider presets Base URL: generativelanguage.googleapis.com/v1beta/openai (OpenAI compatible). Hardcoded model list: Gemini 2.5 Pro, 2.5 Flash, 2.0 Flash. API key placeholder: AIza... * feat(ai): update Gemini models to 3.x series --------- Co-authored-by: Fini <fini.yang@gmail.com> Co-authored-by: Kaiiiiiiiii <2761362118@qq.com> Co-authored-by: Kaiiiiiiiii <182183652+Smile232323@users.noreply.github.com>
391 lines
18 KiB
Markdown
391 lines
18 KiB
Markdown
<p align="center">
|
|
<img src="./apps/desktop/build/icon.png" alt="OpenPencil" width="120" />
|
|
</p>
|
|
|
|
<h1 align="center">OpenPencil</h1>
|
|
|
|
<p align="center">
|
|
<strong>La primera herramienta de diseño vectorial de código abierto nativa de IA del mundo.</strong><br />
|
|
<sub>Equipos de Agentes Concurrentes • Diseño como Código • Servidor MCP Integrado • Inteligencia Multimodelo</sub>
|
|
</p>
|
|
|
|
<p align="center">
|
|
<a href="./README.md"><b>English</b></a> · <a href="./README.zh.md">简体中文</a> · <a href="./README.zh-TW.md">繁體中文</a> · <a href="./README.ja.md">日本語</a> · <a href="./README.ko.md">한국어</a> · <a href="./README.fr.md">Français</a> · <a href="./README.es.md">Español</a> · <a href="./README.de.md">Deutsch</a> · <a href="./README.pt.md">Português</a> · <a href="./README.ru.md">Русский</a> · <a href="./README.hi.md">हिन्दी</a> · <a href="./README.tr.md">Türkçe</a> · <a href="./README.th.md">ไทย</a> · <a href="./README.vi.md">Tiếng Việt</a> · <a href="./README.id.md">Bahasa Indonesia</a>
|
|
</p>
|
|
|
|
<p align="center">
|
|
<a href="https://github.com/ZSeven-W/openpencil/stargazers"><img src="https://img.shields.io/github/stars/ZSeven-W/openpencil?style=flat&color=cfb537" alt="Stars" /></a>
|
|
<a href="https://github.com/ZSeven-W/openpencil/blob/main/LICENSE"><img src="https://img.shields.io/github/license/ZSeven-W/openpencil?color=64748b" alt="License" /></a>
|
|
<a href="https://github.com/ZSeven-W/openpencil/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/ZSeven-W/openpencil/ci.yml?branch=main&label=CI" alt="CI" /></a>
|
|
<a href="https://discord.gg/h9Fmyy6pVh"><img src="https://img.shields.io/discord/1476517942949580952?label=Discord&logo=discord&logoColor=white&color=5865F2" alt="Discord" /></a>
|
|
</p>
|
|
|
|
<br />
|
|
|
|
<p align="center">
|
|
<a href="https://oss.ioa.tech/zseven/openpencil/a46e24733239ce24de36702342201033.mp4">
|
|
<img src="./screenshot/op-cover.png" alt="OpenPencil — haz clic para ver la demostración" width="100%" />
|
|
</a>
|
|
</p>
|
|
<p align="center"><sub>Haz clic en la imagen para ver el video de demostración</sub></p>
|
|
|
|
<br />
|
|
|
|
> **Nota:** Existe otro proyecto de código abierto con el mismo nombre — [OpenPencil](https://github.com/open-pencil/open-pencil), enfocado en diseño visual compatible con Figma con colaboración en tiempo real. Este proyecto se enfoca en flujos de trabajo AI-nativos de diseño a código.
|
|
|
|
## Por Qué OpenPencil
|
|
|
|
<table>
|
|
<tr>
|
|
<td width="50%">
|
|
|
|
### 🎨 Prompt → Lienzo
|
|
|
|
Describe cualquier interfaz en lenguaje natural. Obsérvala aparecer en el lienzo infinito en tiempo real con animación de transmisión. Modifica diseños existentes seleccionando elementos y chateando.
|
|
|
|
</td>
|
|
<td width="50%">
|
|
|
|
### 🤖 Equipos de Agentes Concurrentes
|
|
|
|
El orquestador descompone páginas complejas en subtareas espaciales. Múltiples agentes de IA trabajan en diferentes secciones simultáneamente — hero, características, footer — todos transmitiendo en paralelo.
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="50%">
|
|
|
|
### 🧠 Inteligencia Multimodelo
|
|
|
|
Se adapta automáticamente a las capacidades de cada modelo. Claude recibe prompts completos con pensamiento; GPT-4o/Gemini desactivan el pensamiento; modelos más pequeños (MiniMax, Qwen, Llama) reciben prompts simplificados para una salida confiable.
|
|
|
|
</td>
|
|
<td width="50%">
|
|
|
|
### 🔌 Servidor MCP
|
|
|
|
Instalación con un clic en Claude Code, Codex, Gemini, OpenCode, Kiro o Copilot CLIs. Diseña desde tu terminal — lee, crea y modifica archivos `.op` a través de cualquier agente compatible con MCP.
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="50%">
|
|
|
|
### 📦 Diseño como Código
|
|
|
|
Los archivos `.op` son JSON — legibles por humanos, compatibles con Git, comparables. Las variables de diseño generan propiedades personalizadas CSS. Exportación de código a React + Tailwind o HTML + CSS.
|
|
|
|
</td>
|
|
<td width="50%">
|
|
|
|
### 🖥️ Funciona en Todas Partes
|
|
|
|
Aplicación web + escritorio nativo en macOS, Windows y Linux mediante Electron. Actualizaciones automáticas desde GitHub Releases. Asociación de archivos `.op` — doble clic para abrir.
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="50%">
|
|
|
|
### ⌨️ CLI — `op`
|
|
|
|
Controla la herramienta de diseño desde la terminal. `op design`, `op insert`, `op export` — DSL de diseño por lotes, manipulación de nodos, exportación de código. Entrada por pipe desde archivos o stdin. Funciona con la app de escritorio o el servidor web.
|
|
|
|
</td>
|
|
<td width="50%">
|
|
|
|
### 🎯 Exportación de Código Multiplataforma
|
|
|
|
Exporta desde un solo archivo `.op` a React + Tailwind, HTML + CSS, Vue, Svelte, Flutter, SwiftUI, Jetpack Compose, React Native. Las variables de diseño se convierten en propiedades CSS personalizadas.
|
|
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
## Inicio Rápido
|
|
|
|
```bash
|
|
# Instalar dependencias
|
|
bun install
|
|
|
|
# Iniciar el servidor de desarrollo en http://localhost:3000
|
|
bun --bun run dev
|
|
```
|
|
|
|
O ejecutar como aplicación de escritorio:
|
|
|
|
```bash
|
|
bun run electron:dev
|
|
```
|
|
|
|
> **Requisitos previos:** [Bun](https://bun.sh/) >= 1.0 y [Node.js](https://nodejs.org/) >= 18
|
|
|
|
### Docker
|
|
|
|
Hay varias variantes de imagen disponibles — elige la que se ajuste a tus necesidades:
|
|
|
|
| Imagen | Tamaño | Incluye |
|
|
| --- | --- | --- |
|
|
| `openpencil:latest` | ~226 MB | Solo aplicación web |
|
|
| `openpencil-claude:latest` | — | + Claude Code CLI |
|
|
| `openpencil-codex:latest` | — | + Codex CLI |
|
|
| `openpencil-opencode:latest` | — | + OpenCode CLI |
|
|
| `openpencil-copilot:latest` | — | + GitHub Copilot CLI |
|
|
| `openpencil-gemini:latest` | — | + Gemini CLI |
|
|
| `openpencil-full:latest` | ~1 GB | Todas las herramientas CLI |
|
|
|
|
**Ejecutar (solo web):**
|
|
|
|
```bash
|
|
docker run -d -p 3000:3000 ghcr.io/zseven-w/openpencil:latest
|
|
```
|
|
|
|
**Ejecutar con AI CLI (ej. Claude Code):**
|
|
|
|
El chat de IA depende del inicio de sesión OAuth de Claude CLI. Usa un volumen Docker para persistir la sesión de inicio de sesión:
|
|
|
|
```bash
|
|
# Paso 1 — Iniciar sesión (una sola vez)
|
|
docker volume create openpencil-claude-auth
|
|
docker run -it --rm \
|
|
-v openpencil-claude-auth:/root/.claude \
|
|
ghcr.io/zseven-w/openpencil-claude:latest claude login
|
|
|
|
# Paso 2 — Iniciar
|
|
docker run -d -p 3000:3000 \
|
|
-v openpencil-claude-auth:/root/.claude \
|
|
ghcr.io/zseven-w/openpencil-claude:latest
|
|
```
|
|
|
|
**Compilar localmente:**
|
|
|
|
```bash
|
|
# Base (solo web)
|
|
docker build --target base -t openpencil .
|
|
|
|
# Con un CLI específico
|
|
docker build --target with-claude -t openpencil-claude .
|
|
|
|
# Completa (todos los CLIs)
|
|
docker build --target full -t openpencil-full .
|
|
```
|
|
|
|
## Diseño Nativo de IA
|
|
|
|
**De Prompt a Interfaz**
|
|
- **Texto a diseño** — describe una página y se genera en el lienzo en tiempo real con animación de transmisión
|
|
- **Orquestador** — descompone páginas complejas en subtareas espaciales para generación en paralelo
|
|
- **Modificación de diseño** — selecciona elementos y describe los cambios en lenguaje natural
|
|
- **Entrada visual** — adjunta capturas de pantalla o bocetos como referencia para el diseño
|
|
|
|
**Soporte Multiagente**
|
|
|
|
| Agente | Configuración |
|
|
| --- | --- |
|
|
| **Integrado (9+ proveedores)** | Selecciona de preajustes de proveedores con selector de región — Anthropic, OpenAI, Google, DeepSeek y más |
|
|
| **Claude Code** | Sin configuración — usa Claude Agent SDK con OAuth local |
|
|
| **Codex CLI** | Conectar en Configuración de Agente (`Cmd+,`) |
|
|
| **OpenCode** | Conectar en Configuración de Agente (`Cmd+,`) |
|
|
| **GitHub Copilot** | `copilot login` y luego conectar en Configuración de Agente (`Cmd+,`) |
|
|
| **Gemini CLI** | Conectar en Configuración de Agente (`Cmd+,`) |
|
|
|
|
**Perfiles de Capacidad de Modelos** — adapta automáticamente los prompts, el modo de pensamiento y los tiempos de espera según el nivel del modelo. Los modelos de nivel completo (Claude) reciben prompts completos; los de nivel estándar (GPT-4o, Gemini, DeepSeek) desactivan el pensamiento; los de nivel básico (MiniMax, Qwen, Llama, Mistral) reciben prompts simplificados de JSON anidado para máxima fiabilidad.
|
|
|
|
**i18n** — Localización completa de la interfaz en 15 idiomas: English, 简体中文, 繁體中文, 日本語, 한국어, Français, Español, Deutsch, Português, Русский, हिन्दी, Türkçe, ไทย, Tiếng Việt, Bahasa Indonesia.
|
|
|
|
**Servidor MCP**
|
|
- Servidor MCP integrado — instalación con un clic en Claude Code / Codex / Gemini / OpenCode / Kiro / Copilot CLIs
|
|
- Detección automática de Node.js — si no está instalado, recurre automáticamente al transporte HTTP e inicia el servidor MCP HTTP
|
|
- Automatización de diseño desde la terminal: leer, crear y modificar archivos `.op` a través de cualquier agente compatible con MCP
|
|
- **Flujo de diseño por capas** — `design_skeleton` → `design_content` → `design_refine` para diseños multisección de mayor fidelidad
|
|
- **Recuperación segmentada de prompts** — carga solo el conocimiento de diseño que necesitas (schema, layout, roles, icons, planning, etc.)
|
|
- Soporte multipágina — crear, renombrar, reordenar y duplicar páginas mediante herramientas MCP
|
|
|
|
**Generación de Código**
|
|
- React + Tailwind CSS, HTML + CSS, CSS Variables
|
|
- Vue, Svelte, Flutter, SwiftUI, Jetpack Compose, React Native
|
|
|
|
## CLI — `op`
|
|
|
|
Instala globalmente y controla la herramienta de diseño desde tu terminal:
|
|
|
|
```bash
|
|
npm install -g @zseven-w/openpencil
|
|
```
|
|
|
|
```bash
|
|
op start # Iniciar la app de escritorio
|
|
op design @landing.txt # Diseño por lotes desde archivo
|
|
op insert '{"type":"RECT"}' # Insertar un nodo
|
|
op export react --out . # Exportar a React + Tailwind
|
|
op import:figma design.fig # Importar archivo de Figma
|
|
cat design.dsl | op design - # Entrada por pipe desde stdin
|
|
```
|
|
|
|
Soporta tres métodos de entrada: cadena inline, `@filepath` (leer desde archivo), o `-` (leer desde stdin). Funciona con la app de escritorio o el servidor de desarrollo web. Consulta el [README del CLI](./apps/cli/README.md) para la referencia completa de comandos.
|
|
|
|
**Habilidad LLM** — instala el plugin [OpenPencil Skill](https://github.com/ZSeven-W/openpencil-skill) para enseñar a agentes IA (Claude Code, Cursor, Codex, Gemini CLI, etc.) a diseñar con `op`.
|
|
|
|
## Características
|
|
|
|
**Lienzo y Dibujo**
|
|
- Lienzo infinito con panorámica, zoom, guías de alineación inteligentes y ajuste
|
|
- Rectángulo, Elipse, Línea, Polígono, Pluma (Bezier), Frame, Texto
|
|
- Operaciones booleanas — unión, resta, intersección con barra de herramientas contextual
|
|
- Selector de iconos (Iconify) e importación de imágenes (PNG/JPEG/SVG/WebP/GIF)
|
|
- Diseño automático — vertical/horizontal con gap, padding, justify, align
|
|
- Documentos multipágina con navegación por pestañas
|
|
|
|
**Sistema de Diseño**
|
|
- Variables de diseño — tokens de color, número y texto con referencias `$variable`
|
|
- Soporte multitema — múltiples ejes, cada uno con variantes (Claro/Oscuro, Compacto/Cómodo)
|
|
- Sistema de componentes — componentes reutilizables con instancias y sobreescrituras
|
|
- Sincronización CSS — propiedades personalizadas autogeneradas, `var(--name)` en la salida de código
|
|
|
|
**Importación de Figma**
|
|
- Importa archivos `.fig` conservando diseño, rellenos, trazos, efectos, texto, imágenes y vectores
|
|
|
|
**Aplicación de Escritorio**
|
|
- Compatible de forma nativa con macOS, Windows y Linux mediante Electron
|
|
- Asociación de archivos `.op` — doble clic para abrir, bloqueo de instancia única
|
|
- Actualización automática desde GitHub Releases
|
|
- Menú de aplicación nativo y diálogos de archivo
|
|
|
|
## Stack Tecnológico
|
|
|
|
| | |
|
|
| --- | --- |
|
|
| **Frontend** | React 19 · TanStack Start · Tailwind CSS v4 · shadcn/ui · i18next |
|
|
| **Lienzo** | CanvasKit/Skia (WASM, acelerado por GPU) |
|
|
| **Estado** | Zustand v5 |
|
|
| **Servidor** | Nitro |
|
|
| **Escritorio** | Electron 35 |
|
|
| **CLI** | `op` — control desde terminal, DSL de diseño por lotes, exportación de código |
|
|
| **IA** | Vercel AI SDK v6 · Anthropic SDK · Claude Agent SDK · OpenCode SDK · Copilot SDK |
|
|
| **Runtime** | Bun · Vite 7 |
|
|
| **Formato de archivo** | `.op` — basado en JSON, legible por humanos, compatible con Git |
|
|
|
|
## Estructura del Proyecto
|
|
|
|
```text
|
|
openpencil/
|
|
├── apps/
|
|
│ ├── web/ Aplicación web TanStack Start
|
|
│ │ ├── src/
|
|
│ │ │ ├── canvas/ Motor CanvasKit/Skia — dibujo, sincronización, diseño
|
|
│ │ │ ├── components/ Interfaz React — editor, paneles, diálogos compartidos, iconos
|
|
│ │ │ ├── services/ai/ Chat de IA, orquestador, generación de diseño, transmisión
|
|
│ │ │ ├── stores/ Zustand — lienzo, documento, páginas, historial, IA
|
|
│ │ │ ├── mcp/ Herramientas del servidor MCP para integración con CLI externas
|
|
│ │ │ ├── hooks/ Atajos de teclado, soltar archivos, pegado de Figma
|
|
│ │ │ └── uikit/ Sistema de kit de componentes reutilizables
|
|
│ │ └── server/
|
|
│ │ ├── api/ai/ API Nitro — chat en streaming, generación, validación
|
|
│ │ └── utils/ Wrappers de Claude CLI, OpenCode, Codex, Copilot
|
|
│ ├── desktop/ Aplicación de escritorio Electron
|
|
│ │ ├── main.ts Ventana, fork Nitro, menú nativo, actualizador automático
|
|
│ │ ├── ipc-handlers.ts Diálogos de archivos nativos, sincronización de tema, preferencias IPC
|
|
│ │ └── preload.ts Puente IPC
|
|
│ └── cli/ Herramienta CLI — comando `op`
|
|
│ ├── src/commands/ Comandos de diseño, documento, exportación, importación, nodo, página, variable
|
|
│ ├── connection.ts Conexión WebSocket a la app en ejecución
|
|
│ └── launcher.ts Auto-detección e inicio de la app de escritorio o servidor web
|
|
├── packages/
|
|
│ ├── pen-types/ Definiciones de tipos para el modelo PenDocument
|
|
│ ├── pen-core/ Operaciones de árbol del documento, motor de diseño, variables
|
|
│ ├── pen-codegen/ Generadores de código (React, HTML, Vue, Flutter, ...)
|
|
│ ├── pen-figma/ Parser y conversor de archivos .fig de Figma
|
|
│ ├── pen-renderer/ Renderizador independiente CanvasKit/Skia
|
|
│ ├── pen-sdk/ SDK global (reexporta todos los paquetes)
|
|
│ ├── pen-ai-skills/ Motor de habilidades AI (carga de prompts por fases)
|
|
│ └── agent/ SDK de agente AI (Vercel AI SDK, multi-proveedor, equipos de agentes)
|
|
└── .githooks/ Sincronización de versión pre-commit desde nombre de rama
|
|
```
|
|
|
|
## Atajos de Teclado
|
|
|
|
| Tecla | Acción | | Tecla | Acción |
|
|
| --- | --- | --- | --- | --- |
|
|
| `V` | Seleccionar | | `Cmd+S` | Guardar |
|
|
| `R` | Rectángulo | | `Cmd+Z` | Deshacer |
|
|
| `O` | Elipse | | `Cmd+Shift+Z` | Rehacer |
|
|
| `L` | Línea | | `Cmd+C/X/V/D` | Copiar/Cortar/Pegar/Duplicar |
|
|
| `T` | Texto | | `Cmd+G` | Agrupar |
|
|
| `F` | Frame | | `Cmd+Shift+G` | Desagrupar |
|
|
| `P` | Herramienta pluma | | `Cmd+Shift+E` | Exportar |
|
|
| `H` | Mano (panorámica) | | `Cmd+Shift+C` | Panel de código |
|
|
| `Del` | Eliminar | | `Cmd+Shift+V` | Panel de variables |
|
|
| `[ / ]` | Reordenar | | `Cmd+J` | Chat de IA |
|
|
| Flechas | Mover 1px | | `Cmd+,` | Configuración de agente |
|
|
| `Cmd+Alt+U` | Unión booleana | | `Cmd+Alt+S` | Resta booleana |
|
|
| `Cmd+Alt+I` | Intersección booleana | | | |
|
|
|
|
## Scripts
|
|
|
|
```bash
|
|
bun --bun run dev # Servidor de desarrollo (puerto 3000)
|
|
bun --bun run build # Compilación de producción
|
|
bun --bun run test # Ejecutar pruebas (Vitest)
|
|
npx tsc --noEmit # Verificación de tipos
|
|
bun run bump <version> # Sincronizar versión en todos los package.json
|
|
bun run electron:dev # Desarrollo con Electron
|
|
bun run electron:build # Empaquetado de Electron
|
|
bun run cli:dev # Ejecutar CLI desde el código fuente
|
|
bun run cli:compile # Compilar CLI a dist
|
|
```
|
|
|
|
## Contribuir
|
|
|
|
¡Las contribuciones son bienvenidas! Consulta [CLAUDE.md](./CLAUDE.md) para detalles sobre la arquitectura y el estilo de código.
|
|
|
|
1. Haz fork y clona el repositorio
|
|
2. Configura la sincronización de versión: `git config core.hooksPath .githooks`
|
|
3. Crea una rama: `git checkout -b feat/my-feature`
|
|
4. Ejecuta las verificaciones: `npx tsc --noEmit && bun --bun run test`
|
|
5. Haz commit con [Conventional Commits](https://www.conventionalcommits.org/): `feat(canvas): add rotation snapping`
|
|
6. Abre un PR contra `main`
|
|
|
|
## Hoja de Ruta
|
|
|
|
- [x] Variables de diseño y tokens con sincronización CSS
|
|
- [x] Sistema de componentes (instancias y sobreescrituras)
|
|
- [x] Generación de diseño con IA y orquestador
|
|
- [x] Integración con servidor MCP con flujo de diseño por capas
|
|
- [x] Soporte multipágina
|
|
- [x] Importación de Figma `.fig`
|
|
- [x] Operaciones booleanas (unión, sustracción, intersección)
|
|
- [x] Perfiles de capacidad multimodelo
|
|
- [x] Reestructuración en monorepo con paquetes reutilizables
|
|
- [x] Herramienta CLI (`op`) para control desde terminal
|
|
- [x] SDK de agente AI integrado con soporte multi-proveedor
|
|
- [x] i18n — 15 idiomas
|
|
- [ ] Edición colaborativa
|
|
- [ ] Sistema de plugins
|
|
|
|
## Colaboradores
|
|
|
|
<a href="https://github.com/ZSeven-W/openpencil/graphs/contributors">
|
|
<img src="https://contrib.rocks/image?repo=ZSeven-W/openpencil" alt="Contributors" />
|
|
</a>
|
|
|
|
## Comunidad
|
|
|
|
<a href="https://discord.gg/h9Fmyy6pVh">
|
|
<img src="./apps/web/public/logo-discord.svg" alt="Discord" width="16" />
|
|
<strong> Únete a nuestro Discord</strong>
|
|
</a>
|
|
— Haz preguntas, comparte diseños y sugiere funciones.
|
|
|
|
## Star History
|
|
|
|
<a href="https://star-history.com/#ZSeven-W/openpencil&Date">
|
|
<picture>
|
|
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=ZSeven-W/openpencil&type=Date&theme=dark" />
|
|
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=ZSeven-W/openpencil&type=Date" />
|
|
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=ZSeven-W/openpencil&type=Date" width="100%" />
|
|
</picture>
|
|
</a>
|
|
|
|
## Licencia
|
|
|
|
[MIT](./LICENSE) — Copyright (c) 2026 ZSeven-W
|