openpencil/packages/docs/programmable/ai-chat.md
Danila Poyarkov 048a8fbbc1
feat(settings): configure tool access, MCP failures, and step limits
* feat(settings): configure tool access and agent step limits

Built-in AI exposed only a hardcoded subset of the tool registry, and the
maximum agent steps was a constant, so users could neither enable
extended tools such as create_component nor adjust long-running tasks.

Built-in AI and the local MCP server now keep independent, locally saved
tool permissions over one shared catalog, with searchable read-only and
side-effect groups and per-target defaults. Chat settings gain a validated
maximum-steps field whose captured value drives the stop condition,
remaining-step warnings, and limit detection for each message.

Tool access, the local server, browser access, and MCP connections are
grouped under a single Automation settings page.

Closes #573
Closes #584

* refactor(settings): split automation into MCP and Tool access pages

The Automation page mixed a permission matrix with server endpoints behind
a Tools/Connections switch, and the view switch was indistinguishable from
the provider switch. The nested scroll region showed three of 110 tools.

Rename the MCP-facing page to MCP and give tool permissions their own Tool
access page. The page owns a fixed toolbar for the target, count, defaults,
and search, so the list uses the full dialog body and no row is clipped.

* fix(automation): explain MCP startup failures with localized guidance

Every startup failure collapsed into "MCP server did not become healthy":
the spawn layer recorded the real error but the runtime discarded it, and
health probes could not distinguish a rejected token from a missing server.
The message also surfaced raw English text as the alert heading.

Classify failures by reason (not installed, denied command, early exit,
startup timeout, rejected token, unexpected response, unreachable) and
render translated heading and guidance from the catalog, keeping captured
stderr or HTTP status as labeled diagnostic detail.

* refactor(ui): share one collapsible disclosure primitive

Six features each wired Reka's collapsible with their own motion classes and
one settings-only theme token, so the same interaction drifted in spacing,
icon size, and reduced-motion handling.

Add AppCollapsible with a family theme and move the settings disclosure and
the model editor's advanced settings onto it. Chat and frame-preset call
sites keep their distinct visuals for a follow-up.

* fix(automation): explain MCP failures with localized details

The failure alert carried raw English error text as its heading, and the
diagnostic payload sat in a sibling block outside the alert with no
relationship to it.

Classify failures by reason, render translated heading and guidance from
the catalog, and keep the payload in a collapsible inside the alert, which
unmounts while collapsed so the live region announces only the summary.
Add a copy action for issue reports.

Find the executable where a graphical launch can: extend PATH with the
common global bin directories before the lookup and report the searched
directories as diagnostic detail.

* fix(automation): keep MCP failure details out of reasons already explained

An unreachable address and a rejected token already name their cause in the
translated guidance, so repeating it under Details added noise. Details now
carry only output the summary cannot: stderr, HTTP status, or an unknown
error message.

* test(settings): browse every MCP failure reason in Storybook

The failure copy lived inside the settings panel, so reviewing the eight
reasons meant reproducing each failure and the mapping could only be
checked through the panel's dependencies.

Extract MCPFailureAlert, which owns the reason-to-copy mapping, detail
visibility, copy action, and restart action, and add a story covering
every reason plus the collapsed-details behavior.

* fix(ui): order alert details above the recovery actions

The alert rendered its action buttons before the details slot, so the
collapsible explanation of a failure appeared under the controls it
explains. Details now render directly after the description.

* fix(automation): correct MCP failure classification and detail

Review follow-ups on the failure diagnostics.

Only 401 and 403 mean the server refused our token; any other status now
reports an unexpected response instead of telling the user to replace a
token that was never the problem.

The install hint rendered the whole diagnostic detail as its package
argument, so searched directories appeared inside the install command.
The install target is now a domain constant and the searched directories
stay as detail, which not-installed failures surface again since they are
the actionable desktop diagnostic.

Exited failures also record the process exit code and signal so copied
diagnostics stay conclusive when stderr is empty. The bundled PATH test
now covers the append branch instead of only the unchanged path.

* feat(settings): accept custom values for presets and retention

Retention was a closed set of three counts while the AI step limit was a
free number, so two bounded numeric preferences looked and behaved
differently for no product reason.

Add a shared preset-or-custom field: presets stay one click, the escape
hatch reveals a validated numeric field, and the model carries only the
resolved number. Diagnostics retention becomes a bounded number (50 to
20,000) with the presets as shortcuts, and the hardcoded revalidation in
the panel is replaced by one domain resolver.

* fix(settings): label the preset and custom fields

Replacing the labeled provider field with the shared control left the AI
step limit as a bare select with a detached hint paragraph, outside the
settings group, so nothing on screen said what the number meant. The
accessibility name came from aria-label, which is why behavior tests
passed while the panel was unreadable.

Move both controls into labeled settings rows with their descriptions, and
give the revealed field its own accessible name so the two controls in one
row differ. The specs now assert the control lives inside the row that
names it, which is the check that would have caught this.

* fix(mcp): allow the desktop app origin by default

A server started manually bound the port and answered curl but the app
webview could not use it: no CORS origin was configured, so the browser
blocked every fetch and the app reported the server as unhealthy. The
workaround required an undocumented environment variable.

Allow the desktop app origins by default, accept a comma-separated
override, and document the default in the CLI help and the security notes.
Authenticated requests still need the bearer token, and browsers set Origin
themselves, so only the app webview can present these origins.

* fix(settings): address review findings on the new controls

Copy details awaited nothing and confirmed the copy before the write
finished. VueUse never rejects and falls back to a legacy write, so the
await is what makes the confirmation honest rather than an error branch.

The preset field only left custom mode when a preset arrived; a non-preset
value assigned from the owner left the select showing a value absent from
its options with the field still hidden. The watcher now follows the model
in both directions.

The story play functions queried the revealed field by the row label, which
Testing Library matches as a whole string, so those interactions could not
find it. The Storybook smoke assertion also assumed a button or tab, which
skipped every story built from other primitives.
2026-09-17 23:55:58 +03:00

103 lines
8.9 KiB
Markdown

---
title: AI Chat
description: Built-in AI assistant with 90+ tools for creating and modifying designs.
---
# AI Chat
Press <kbd>⌘</kbd><kbd>J</kbd> (<kbd>Ctrl</kbd> + <kbd>J</kbd>) to open the AI assistant. Describe what you want — it creates shapes, sets styles, manages layout, works with components, and analyzes your design.
## Setup
1. Open the AI chat panel (<kbd>⌘</kbd><kbd>J</kbd>)
2. Click the settings icon
3. Add a model and configure its provider, model ID, credentials, and capabilities
4. Save the model and assign it to **Design agent**
You can configure multiple reusable models and separately assign models for design work, reviews, fast tasks, and image input. Models using the same provider connection reuse its stored credential.
The chat composer grows with multiline prompts and can pin the current canvas selection as explicit node context. Assistant messages show provider reasoning in collapsible sections and provide a per-response copy action. Image attachments remain available for visual references when a Vision model is configured. Streaming responses use a hardened Markdown renderer with Shiki-highlighted code blocks; unsafe link protocols and embedded data images are blocked.
## Step limit
In **Settings → AI & agents → Chat**, set **Maximum steps per message** to a whole number from 1 to 1,000. The default is 50. Press Enter or leave the field to save a valid value; invalid drafts do not replace the saved preference. Higher limits allow longer tool-driven tasks but can increase latency and provider cost.
The built-in AI captures this limit when each message starts. Stopping, remaining-step warnings, and the **Continue** action use that same budget. Changing it does not interrupt an ongoing request; the next message or continuation uses the new limit. A step is one model iteration and can include multiple tool calls. ACP and Pi agents manage their own limits.
## Tool access
Open **Settings → Tool access** to choose which tools direct AI model connections can use. Search by name or description, expand read-only or side-effect groups, and toggle individual tools or an entire group. Group switches affect all tools in that group, not only search results. **Restore defaults** restores the compact default tool set; extended tools such as `create_component` can be enabled individually.
Preferences are saved locally and apply to the next message, including in an existing conversation. They do not change an already-running request. Enabling many tools increases the schemas sent to the model.
The **Local MCP** segment has independent settings for clients connected to OpenPencil's MCP server, including ACP and Pi agents. Restart the server and reconnect stdio clients after changing those settings. Remote MCP connections, WebMCP access, and Pi's shell/filesystem permissions remain separate.
Tool toggles control which tools are offered, not which operations scripts may perform. An enabled `eval` or other script-capable tool can perform design operations whose dedicated tools are disabled; these switches are not a sandbox.
## Saved Conversations
Use **Conversation history** to return to a saved chat, start a **New chat**, or rename or delete a conversation. History and attachment previews are stored locally; **All chats** lets you browse transcripts from other documents.
A conversation belonging to another document is read-only until you open that document. A saved agent transcript is not a guarantee that its external agent session can resume: when resumption is unavailable, start a new chat. Local history is not cloud synchronization or a backup.
In the Chat settings beside the model overview, choose whether reasoning is **Collapsed by default**, **Expand while thinking**, or **Expanded by default**. Disclosure animations follow the app's reduced-motion preference. Expanding older reasoning does not force the conversation to scroll to the bottom.
## Supported Providers
| Provider | Models | Setup |
| ------------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| **OpenRouter** | Claude, GPT, Gemini, DeepSeek, Qwen, and others | API key from [openrouter.ai](https://openrouter.ai) |
| **Anthropic** | Claude Sonnet 4.6, Claude Opus 4.6 | API key from [console.anthropic.com](https://console.anthropic.com) |
| **OpenAI** | GPT-5.3 Codex, GPT-4.1, o3, o4-mini | API key from [platform.openai.com](https://platform.openai.com) |
| **Google AI** | Gemini 3.1 Pro, Gemini 3 Flash | API key from [aistudio.google.dev](https://aistudio.google.dev) |
| **Z.ai** | GLM-5.1, GLM-5, GLM-4.7, GLM-4.5 family | API key from [docs.z.ai](https://docs.z.ai/devpack/quick-start) |
| **MiniMax** | MiniMax M3, M2.7, M2.7-highspeed, M2.5, M2.1 | API key from [platform.minimax.io](https://platform.minimax.io/user-center/basic-information/interface-key) |
| **OpenAI-compatible** | Any endpoint with OpenAI API format | Custom base URL + key. Supports Completions and Responses API toggle. |
| **Anthropic-compatible** | Any endpoint with Anthropic API format | Custom base URL + key |
No backend, no subscription — your key talks directly to the provider. Browser requests are subject to each provider's CORS policy, and model deployments vary in how reliably they stream tool calls. See [BYOK provider and model compatibility](./byok-provider-compatibility) for measured results and reproduction steps.
## External MCP connections
Desktop ACP agents can also use trusted remote [Model Context Protocol](https://modelcontextprotocol.io/) servers. In **Settings → MCP**, under MCP connections, add a named Streamable HTTP endpoint, optionally save a bearer token, and enable the connection. OpenPencil stores the token in the configured credential backend rather than ordinary settings and resolves it only when starting the ACP session.
Remote servers must use HTTPS. Loopback HTTP endpoints are accepted for local development. Review and trust a server before enabling it: its tools may read external data or perform actions with the credentials you provide. OpenPencil's built-in design MCP server remains attached automatically and does not need to be added here.
## What It Can Do
The configurable tool catalog covers these categories; the tools offered to a model depend on your Tool access settings:
- **Create** — frames, shapes, text, components, pages. Renders JSX for complex layouts.
- **Style** — fills, strokes, effects, opacity, corner radius, blend modes.
- **Layout** — auto-layout, grid, alignment, spacing, sizing.
- **Components** — create components, instances, component sets. Manage overrides.
- **Variables** — create/edit variables, collections, modes. Bind to fills.
- **Query** — find nodes, XPath selectors, read properties, list pages, fonts, selection.
- **Inspect** — `get_jsx` for JSX roundtrip view, `diff_jsx` for structural diffs, `describe` for semantic role and design issue detection.
- **Analyze** — color palette, typography audit, spacing consistency, cluster detection.
- **Export** — PNG, SVG, JSX with Tailwind classes. Vision-based verification via `export_image`.
- **Vector** — boolean operations, path manipulation.
## Visual Verification
The assistant can verify its work visually. When `export_image` is enabled, it can capture a screenshot after creating or modifying designs and checks the result against the original request. This catches layout issues, missing elements, and color mismatches that text-only responses would miss.
## Example Prompts
- "Create a card with a title, description, and a blue button"
- "Make all buttons on this page use the same border radius"
- "What fonts are used in this file?"
- "Change the background of the selected frame to a gradient from blue to purple"
- "Export the selected frame as SVG"
- "Find all text nodes with font size less than 12"
- "Describe the selected component — what role does it look like?"
- "Show me the JSX for this frame"
## Tips
- Select nodes before asking — the assistant knows what's selected.
- Be specific about colors, sizes, and positions for precise results.
- The assistant can modify multiple nodes in one message.
- Use "undo" in the editor if you don't like the result — AI mutations support full undo.
- All layout is recomputed automatically after each tool execution.