Commit Graph
1126 Commits
Author SHA1 Message Date
qiongyu1999 ee8e2f6d1a Add connector memory extraction flow 2026-05-19 20:55:34 +08:00
Abe PenaandGitHub a3a238247e fix(workspace-tabs): keep search popover inside the viewport (#1988)
* fix(workspace-tabs): keep search popover inside the viewport

The search-tabs popover used `position: absolute; right: 0` relative to
`.workspace-tabs-actions`, a narrow inline-flex container that sits next to
the tab strip on the left side of the chrome header — not the right. With
`width: min(380px, calc(100vw - 24px))`, the popover's left edge resolved
well past the left edge of the window, clipping the search input and
result rows against the Electron window frame (top + left).

Switch to `position: fixed` anchored to the top-right of the viewport so
the popover always lands inside the window regardless of where the actions
group ends up on the chrome bar as tabs accumulate. `safe-area-inset-right`
guards against any future inset, and `--workspace-tabs-chrome-height`
(38px fallback) keeps the offset honest if the bar height ever changes.

* fix(workspace-tabs): portal popover out of strip's containment block

Codex review on the previous commit flagged that `position: fixed` does
not actually anchor to the viewport here, because the popover is nested
under `.workspace-tabs-strip`, which sets `contain: layout style`. CSS
containment establishes a new containing block for fixed descendants,
so the popover's `top` / `right` were still being resolved against the
strip — meaning in narrower windows or denser tab layouts the popover
could still drift off-screen.

Portal the popover into `document.body` via `createPortal` so it lives
outside the containment context and the existing fixed positioning
actually targets the viewport. Outside-click detection now checks both
the trigger ref (still inside the strip) and a new ref on the portaled
popover, so clicks inside the popover do not count as "outside" and
close it prematurely.

Guarded with `typeof document !== 'undefined'` to keep the component
safe under any SSR / pre-hydration path that may exist now or later.
2026-05-19 20:01:01 +08:00
kamiandGitHub d1eb8b7bef Fix editorial deck navigation (#2173) 2026-05-19 19:30:30 +08:00
Neha PrasadandGitHub 716f06cb73 fix(web): allow Comment/Inspect picker to select iframe-backed components (#2254) 2026-05-19 19:26:11 +08:00
lefarcenandGitHub 7fc4362ba8 perf(landing): edge-cache HTML and precise-load thumbnails (#2235)
* perf(landing): edge-cache HTML and precise-load thumbnails

Without `public/_headers` Cloudflare Pages serves every HTML with
`cf-cache-status: DYNAMIC` so each request roundtrips to the Pages
origin — observed TTFB 660–900ms from Seattle, worse from Asia.
With `s-maxage=3600, stale-while-revalidate=86400` HTML stays cached
at the edge between deploys (CF Pages auto-purges on every deploy so
freshness is unchanged in practice), and `_astro/` hash bundles flip
to `immutable` so the existing 4h+must-revalidate roundtrips go away.

For thumbnails, native `loading="lazy"` is browser-decided —
Chrome over-prefetches (1250–3000px), Safari fires near in-viewport.
A new `<LazyImg>` Astro component and global IntersectionObserver
(rootMargin 300px for images, 600px for videos) replaces all 10
site-wide `loading="lazy"` usages with precise control. Above-the-fold
slots (first 4 rows, detail-page hero previews) opt into `eager` or
`priority` to skip the IO roundtrip.

Homepage hero LCP gets `<link rel="preload" imagesrcset>`, a 4-step
`srcset` (768/1280/1920/2560) plus `fetchpriority="high"` so retina
devices stop repainting from the 1024-only variant — was the P99 long
tail.

Verified: `pnpm guard` 6/6, `pnpm typecheck` 0 errors, `pnpm build`
865 pages 28s, generated `out/index.html` contains the preload link
and 15 `data-precise-src` thumbnails, `out/plugins/index.html` has
95 precise-loaded thumbnails plus the IO script.

* perf(landing): logo to webp + parallelize Google Fonts load

Two HAR-validated wins on top of the edge-cache / precise-load commit:

logo: 500x500 192KB PNG → 200x200 7.5KB WebP. Footer/header actually
render at 36x36, so the source is 5x larger than necessary at the
display size and ships RGBA PNG bytes for what reads as a flat
graphic. WebP at q=85 keeps the gradient ring crisp at every DPR we
care about.

fonts: globals.css used `@import url(...)` for Google Fonts, which
serialized HTML → CSS → fonts.googleapis.com/css2 → fonts.gstatic.com/
woff2. HAR measured 953ms for the fonts CSS plus 400–800ms per woff2
× 4 — close to 3s before text could render in the intended family,
even with display=swap. Moving to `<link>` + `<link rel=preconnect>`
in each page's <head> lets the fonts CSS fetch race the HTML body
parse, and warms the TLS handshake to gstatic.com so woff2 requests
don't pay DNS+TLS at request time.

A shared `font-stylesheet.astro` keeps the four-family URL canonical
across all five entry points (index, sub-page-layout, plugins/index,
plugins/[slug], blog/index, blog/[slug]). og.astro already had this
treatment.
2026-05-19 19:14:25 +08:00
Neha PrasadandGitHub e6d0f4eeab fix(web): restore scrolling in New project modal for tall tabs (#2032) 2026-05-19 19:09:23 +08:00
PerishFireandGitHub 2c128e0e91 refactor desktop host bridge (#2246) 2026-05-19 18:27:05 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
6a6959ed30 docs(blog): refresh indexing status after deploy (#2250)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-19 18:25:55 +08:00
shangxinyu1andGitHub d5eb6d17d7 test(e2e): harden connectors auth cancel recovery (#2176)
* test(e2e): harden connectors auth cancel recovery

* test(e2e): target connector cancel alert
2026-05-19 18:11:32 +08:00
初晨andGitHub 22b5cbdb25 Fix Cursor Agent model id parsing (#2228) 2026-05-19 18:11:09 +08:00
07659b7272 feat(seo): add Search Console reporting workflows (#2229)
* feat(blog): daily 3-day Search Console traffic digest

Adds `blog-3day-report.yml` (cron 09:00 Asia/Shanghai) and a
companion `report-3day.ts` script that refreshes
`docs/blog-traffic-digest.md` once per day. The digest has two
sections:

- T-3 spotlight: posts published exactly three days ago, with their
  3-day Search Analytics window plus current URL Inspection coverage
  state.
- Rolling 30-day cohort: every post 1–30 days old with its latest
  3-day Search Analytics window, sorted by impressions descending.

The workflow is read-only against Google APIs (no Indexing API,
no "request indexing" automation) and mirrors the secret / config
plumbing already used by `blog-indexing-monitor.yml`. Output lands
in a reviewable `automation/blog-traffic-digest` PR opened by the
open-design bot.

Also widens `querySearchAnalytics` to accept `windowDays: 3 | 7 | 28`
and updates `docs/blog-indexing-automation.md` with the new pipeline.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(seo): post daily Search Console report to Feishu

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(blog): push traffic digest to Feishu

Emit a compact JSON summary from the daily 3-day traffic digest and add a Feishu custom bot sender for the summary card. Wire the workflow to send the card when `FEISHU_BLOG_DIGEST_WEBHOOK` is configured while keeping Markdown PR output as the source of truth.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(landing-page): add Discord routing CTAs

Add a lightweight Discord pill to the landing hero and Discord links in the landing and blog footers so community routing is visible without displacing the primary GitHub and download CTAs.

Add a blog-ending conversion card that points guide and use-case readers to the internal workflows library, while keeping Discord as a secondary support path.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 18:09:44 +08:00
e702a6a49f Fix blog indexing status PR base (#2106)
Set an explicit base branch for generated indexing status PRs so create-pull-request works after SHA-based checkouts.

Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 18:08:01 +08:00
PerishFireandGitHub bb13eee765 chore: optimize CI and beta release runtime (#2231)
* chore(ci): add runtime trace summaries

* chore(ci): tighten measured workspace steps

* chore(release): tighten beta setup steps

* chore(release): slim beta windows smoke

* chore(ci): shard daemon tests

* chore(ci): harden runtime trace lookup

* chore(release): avoid mac pnpm cache in beta

* chore(ci): split critical playwright checks

* chore(release): publish beta platforms from builders

* test(e2e): update beta release workflow expectation

* chore(ci): stop gating PRs on nix check

* fix(release): keep beta latest complete
2026-05-19 18:06:28 +08:00
netteeandGitHub 320bd4c303 docs: document ACP runtime integration (#2232)
* docs: document ACP runtime integration

* docs: link ACP runtime guide from entrypoints

Generated-By: looper 0.7.5 (runner=fixer, agent=opencode, model=openai/gpt-5.4)
2026-05-19 18:03:10 +08:00
Neha PrasadandGitHub c6b7c44424 confirm before clearing memory extraction history (#2241) 2026-05-19 17:56:14 +08:00
16d8562290 Follow up #1617: use official version-manager links (#1996)
* Fix links for nvm and fnm in QUICKSTART.md

Updated links for nvm and fnm in QUICKSTART.md.

* docs: point Quickstart version manager links upstream

---------

Co-authored-by: ayumi <ayuday@163.com>
2026-05-19 17:52:49 +08:00
lefarcenandGitHub 34f1391292 feat(discovery): honor plugin inputs as authoritative Quick-brief answers (#2243)
When a user picks a plugin chip on Home (e.g. "Web prototype") and sets
fidelity / artifactKind / audience / etc. before opening the project,
the daemon already renders those choices into the system prompt as a
`## Active plugin` / `## Plugin inputs` block — see
`docs/plugins-spec.md` §1258. The Quick-brief form, however, still
asked the user the same questions a second time:

> "在输入框当中已经选了高保真和 Web,但在 Chat 生成的实时选择面板里面又要选一次。"

Root cause is a prompt scoping bug: RULE 1's "drop matching default
questions" rule only pointed at the `## Project metadata` section, not
the `## Plugin inputs` block. Plugin-trigger projects ship most of
their brief through `## Plugin inputs`, so the agent kept the defaults
(Target platform, Fidelity, …) even though every answer was right there
in the same prompt one section over.

Fix: extend RULE 1's source-of-truth list to both blocks, with an
explicit "equally authoritative" line and a small mapping table the
agent can apply by name:

* `fidelity`            → Fidelity
* `platform` / `surface` / `platformTargets` / `target` → Target platform
* `artifactKind` / `mode` / `taskKind` → "What are we making?"
* `audience`            → "Who is this for?"
* `designSystem` / `brand` → Brand context

Adjacent carve-out updated too: the "don't re-ask the kind itself"
sentence now triggers when the active plugin's `od.kind` /
`taskKind` already names the kind, not only when `metadata.kind` is
set. Closes the loop for chip-launched flows where metadata.kind is
set by the daemon but the form was still re-asking.

Why prompt-only (not a data-flow fix):

`## Plugin inputs` is already a first-class block the daemon writes
into every chip-launched run (`apps/daemon/src/prompts/system.ts:246`,
plugins-spec.md §1258). Mapping plugin inputs to `project.metadata`
fields at create time was the other option considered, but it would
require a per-plugin mapping convention (which input name maps to
which metadata field) and would have to be rolled out across web,
daemon, schema, and every existing plugin manifest. The agent already
sees the inputs; the prompt just wasn't telling it those inputs count
as answers. Cheapest fix that generalises to every plugin.

Tests:

* `apps/daemon/tests/prompts/discovery-plugin-inputs.test.ts` (new) —
  five contract tests locking the new rule: the dual-source
  instruction, the "equally authoritative" line, the canonical
  input→question mappings (`fidelity` / `platform` / `artifactKind` /
  `audience` / `designSystem`), the semantic-equivalence aside for
  alternate input names, and the kind carve-out extension to the
  active plugin's `od.kind` / `taskKind`.

Validation:

* `pnpm --filter @open-design/daemon exec vitest run tests/prompts/discovery-plugin-inputs.test.ts`
  → 5/5 passed
* `pnpm --filter @open-design/daemon exec vitest run tests/prompts/system.test.ts tests/prompts/api-mode-override.test.ts`
  → 34/34 passed (no regressions)
2026-05-19 17:52:20 +08:00
Zellux WangandGitHub 52b702648e Enable LAN web dev access (#1947) 2026-05-19 17:50:50 +08:00
Nicholas-XiongandGitHub 643cfee8e9 fix: prevent form help text truncation in left panel (#2238)
Fixes #2225

Added word-wrap and overflow-wrap properties to .qf-help to ensure
long helper text wraps properly instead of being truncated in the
narrow left panel.

Changes:
- Added word-wrap: break-word to .qf-help
- Added overflow-wrap: break-word to .qf-help
- Added line-height: 1.4 for better readability of wrapped text

The fix ensures helper text remains fully readable in the question
form without requiring panel width changes or tooltips.
2026-05-19 17:50:17 +08:00
726a9c921a feat(web): improve manual edit UX with focus mode, uploads and remove-element patch (#1516)
* feat(web): improve manual edit UX with focus mode, uploads and remove-element patch

* fix: address review feedback on manual edit UX

- Remove unused panel width persistence (leftPanelRef, rightPanelRef props, constants, useEffects)
- Fix image upload to use project-relative URLs instead of daemon API URLs for deploy/share
- Add i18n keys for new UI strings (deleteElement, uploadImage, focusSlides, etc)
- Improve delete guard to prevent removing last document element
- Use translated strings instead of hardcoded English in all new buttons/labels/dialogs
- Fix upload error message to use i18n

* fix: add onPickImage prop and delete-element UI to ManualEditPanel

- Declare onPickImage?: (file: File) => Promise<string | null> in prop interface
- Destructure onApplyPatch and onPickImage from props
- Add image upload section with file input, uploads via onPickImage,
  applies set-image patch on success, shows uploadingImage state
- Add delete element button with two-step confirmation that emits
  remove-element patch via onApplyPatch
- All new strings routed through t() using existing i18n keys

* fix(web): harden manual edit delete/upload flows

* fix(web): gate image upload to image targets and normalize relative asset refs

---------

Co-authored-by: Jose Herrera <nombreregular@gmail.com>
2026-05-19 17:25:39 +08:00
JiannanyaandGitHub 555bc5e7ed fix(daemon): ensure node binary dir is on PATH for agent sub-processes on Windows (#1989)
* fix(daemon): ensure node binary dir is on PATH for agent sub-processes on Windows

When pnpm tools-dev launches the daemon via a full path to node.exe the
nodejs directory may not appear in process.env.PATH. Agent .cmd shims on
Windows (e.g. the npm copilot shim) call `"node" script.js`, so cmd.exe
fails to find node and the run exits immediately with:

  '"node"' is not recognized as an internal or external command

Fix: in createAgentRuntimeEnv, prepend path.dirname(nodeBin) to PATH
when that directory is not already present. This is a no-op on systems
where the node directory is already in PATH.

Also extend the stdin 'error' swallow to cover the Windows equivalent of
EPIPE: err.code === 'EOF' / err.message === 'write EOF' (libuv UV_EOF).
These fire when the child process exits before reading stdin and were
incorrectly surfaced to the user as AGENT_EXECUTION_FAILED.

Affected file: apps/daemon/src/server.ts

* fix(daemon): anchor PATH-prepend test assertions and add coverage for both branches

- Update the existing 'injects daemon URL and run-scoped tool token' test to
  expect PATH = `/opt/open-design/bin${path.delimiter}/bin` after the prepend,
  matching the behaviour introduced in the Windows PATH fix.

- Add 'prepends node binary directory to PATH when not already present': given
  PATH='/bin' and nodeBin='/opt/node/node', asserts PATH becomes
  `/opt/node${path.delimiter}/bin`.

- Add 'does not duplicate node binary directory when already present in PATH':
  given PATH already contains the bin dir, asserts it is unchanged (idempotent).

- Replace parts.includes(nodeBinDir) with a normalised some() predicate that
  strips trailing path separators and performs a case-insensitive comparison on
  win32, producing true idempotence when PATH contains the same directory with a
  different case or trailing slash.

* case-insensitive key path finding

* fix Case-insensitive key lookup and add test

* fix(daemon): inject Node binary dir into all agent launch/probe envs on Windows

applyAgentLaunchEnv() is the shared terminal step for every agent spawn
path — detectAgents(), connection tests, and chat runs.  Add an optional
`nodeBinDir` parameter (default: path.dirname(process.execPath)) so the
running Node directory is prepended to PATH at every call site without
requiring changes to detection.ts or connectionTest.ts.

Add two regression tests: a cross-platform test covering the Windows-style
'Path' key-casing fix, and a Windows-only test using proper C::\ paths and
';' delimiter verifying the full end-to-end Windows behavior.

* test(daemon): fix applyAgentLaunchEnv tests broken by nodeBinDir default

The 4 tests added in agent-runtime-env.test.ts used the 2-argument form of
applyAgentLaunchEnv, picking up path.dirname(process.execPath) as the new
default and making assertions non-deterministic across CI runners.  Also,
three of the fixtures mixed Windows C:\...;... paths with POSIX path.delimiter
(':'), which silently produced wrong splits on POSIX runners.

Pass '' as nodeBinDir to all 4 tests so the early-return and path-prepend
logic is exercised in isolation.  Replace Windows-style fixtures with
POSIX paths + path.delimiter; the real C:\... end-to-end shape is already
covered by winTest in tests/runtimes/launch.test.ts.
2026-05-19 16:58:15 +08:00
6a08dfe111 Add design system package quality guard (#2224)
* Add design system import manifest schema

* Generate hybrid design system imports

* Read design system usage and cached manifests

* Add design system pull-file tool

* Show design system package evidence

* Wire design system import semantics

* Add design system package quality guard

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
2026-05-19 16:53:29 +08:00
b311885bee Support folder drops in Design Files (#1662)
Co-authored-by: mzl2233 <mzl2233@users.noreply.github.com>
2026-05-19 16:52:19 +08:00
mehmet turacandGitHub db9752f5ae fix(template): make orbit github example static (#1829)
* fix(template): make orbit github example static

* fix(template): preserve static github link targets
2026-05-19 16:51:56 +08:00
Yuhao ChenandGitHub a1e8ce480a fix(ci): include bundled resources in Windows cache key (#2034) 2026-05-19 16:50:39 +08:00
lefarcenandGitHub 18ffeae7cc feat(discovery): collapse freeform-project clarification into a single form (#2226)
When the user enters a project from a free-form prompt (no Home chip
selected, so the active plugin is `od-default`), the agent currently
emits two clarification cards back-to-back:

* turn 1 → `<question-form id="task-type" title="Choose the task type">`
  asking what to build + any constraints
* turn 2 → `<question-form id="discovery" title="Quick brief — 30
  seconds">` asking audience / platform / tone / brand / scale /
  constraints

Two cards in a row reads as "the agent is re-asking" and forces the user
to context-switch twice before anything gets built. The fix is to make
the turn-1 `task-type` form a single-shot brief — it now also asks for
audience, brand (with the three branch values RULE 2 dispatches on),
scale, and constraints in the same card. After `[form answers —
task-type]` the agent skips the Quick brief form entirely and goes
straight to RULE 2 brand handling, then RULE 3 planning.

Mechanics:

* `apps/daemon/src/prompts/discovery.ts` line 44 — RULE 1's
  default-router exception now explicitly says "do NOT emit a second
  `<question-form id="discovery">` / 'Quick brief — 30 seconds' form".
  Earlier wording said "continue with the normal discovery / plan /
  generate / critique flow" which the agent read as "emit the normal
  discovery form next turn".
* `apps/daemon/src/prompts/discovery.ts` line 47-99 — task-type form
  grows from 2 questions (taskType + constraints) to 5: taskType,
  audience, brand, scale, constraints. `platform` and `tone` from the
  old Quick brief are deliberately dropped — platform is
  task-type-specific (only matters for prototype/live), tone is fluffy
  and the agent can usually infer it from brand anyway. The agent can
  still ask one targeted follow-up under the "Ask at most one concise
  follow-up only if a required detail is impossible to infer safely"
  rule already in `system.ts:143`.
* `apps/daemon/src/prompts/discovery.ts` line 132 — RULE 2's first
  sentence now accepts `[form answers — task-type]` alongside `[form
  answers — discovery]`, so the brand-branching logic in Branches A/B
  works the same way for both entry points.

Non-default-router projects (the user did pick a Home chip → the active
plugin is a specific scenario, not od-default) are unchanged. They still
get the single `<question-form id="discovery">` Quick brief on turn 1,
because the chip already supplied the task type.

Tests:

* `apps/daemon/tests/prompts/discovery-form.test.ts` (new) — 5 contract
  tests locking the single-shot shape: task-type form contains all five
  brief fields, preserves the three `brand` branch values RULE 2 keys
  off of, keeps the eight canonical task-type options, embeds the
  explicit "do NOT emit a second form" sentence, and teaches RULE 2 to
  accept the task-type answer marker.

Validation:

* `pnpm --filter @open-design/daemon exec vitest run tests/prompts/discovery-form.test.ts`
  → 5/5 passed
* `pnpm --filter @open-design/daemon exec vitest run tests/prompts/system.test.ts tests/prompts/api-mode-override.test.ts tests/plugins-bundled-scenarios-roster.test.ts tests/plugins-scenario-fallback.test.ts`
  → 55/55 passed (no regressions in adjacent suites)
2026-05-19 16:36:38 +08:00
Tom HuangandGitHub 86ec951fb9 [codex] Add automation templates and proposal workflows (#2193)
* feat(web): introduce Automations tab with dual-track capability for routines

This commit adds a new Automations tab that consolidates routines, schedules, and live artifacts, allowing users to manage automations seamlessly. The tab features a modal for creating and editing automations, which supports various scheduling options (hourly, daily, weekdays, weekly) and project modes (create_each_run, reuse). The CLI is also updated to expose automation commands, ensuring consistency between the web UI and CLI interfaces.

Key changes include:
- New `NewAutomationModal` component for automation creation and editing.
- Updated `TasksView` to integrate the new Automations functionality.
- Enhanced styling for the Automations tab to improve user experience.

This implementation aligns with the dual-track capability exposure policy, ensuring all features are accessible via both the web UI and CLI.

* feat(daemon): enhance automation context handling and CLI commands

This commit introduces several improvements to the automation context management and updates the CLI commands accordingly. Key changes include:

- Added support for new context fields (`plugin`, `mcp`, `connector`) in automation commands.
- Updated the CLI to reflect new target options (`new-project`).
- Enhanced error messages for invalid target inputs.
- Introduced functions to handle context selection and normalization for routines, including the ability to parse and store context data in the database.
- Updated the database schema to include a new `context_json` field for routines.
- Improved the handling of context in routine routes and the web interface, ensuring that selected contexts are properly managed and displayed.

These changes aim to provide a more robust and flexible automation experience, aligning with the recent enhancements in the web UI.

* feat(web): enhance TasksView with automation run history and status indicators

This commit introduces several new features to the TasksView component, including:

- Added functionality to display automation run history for each routine, showing metadata such as status, timestamps, and project details.
- Implemented status indicators for routine runs, providing visual feedback on their current state (succeeded, failed, running, queued).
- Enhanced the UI to allow users to expand and view detailed run history, including the ability to open the corresponding project conversation.
- Updated styles to improve the presentation of automation statuses and history.

These changes aim to provide users with better insights into their automation routines and improve overall usability.

* feat(daemon): implement automation ingestion and proposal management

This commit introduces several new features related to automation ingestion and proposal management within the daemon. Key changes include:

- Added new modules for handling automation source packets and proposals, allowing for the storage, retrieval, and management of automation-related data.
- Implemented functions to list, create, and apply automation proposals, enhancing the automation workflow.
- Introduced new CLI commands for interacting with memory entries and automation sources, providing users with more control over their automation processes.
- Enhanced the server routes to support automation source and proposal APIs, enabling seamless integration with the existing system.

These changes aim to improve the overall automation experience, making it easier for users to manage and utilize automation proposals and ingestions effectively.
2026-05-19 16:35:28 +08:00
Siri-RayandGitHub eb127e0f79 Remove live artifact home chip (#2221) 2026-05-19 16:35:09 +08:00
ee08c8b9ac fix live artifacts mcp electron launch (#1927)
Co-authored-by: Jeshua09090 <jeshuaelpro@outlok.com>
2026-05-19 16:08:46 +08:00
169a29ee2b Preserve HTML preview state across edit and comment modes (#1696)
* Preserve HTML preview state across mode toggles

HTML previews could rebuild their iframe when switching into Edit or Comment, which reset scroll/canvas state and caused visible churn for multi-file artifacts. The viewer now keeps URL-loaded previews mounted when the artifact owns the mode bridge, relays file-refreshes through frame navigation, and restores preview scroll/viewport state across bridge mode changes.

Constraint: Generic srcdoc-only bridges are still required for unbridged artifacts, inspect mode, palette tweaks, decks, draw overlays, and forceInline.

Rejected: Keep all Edit/Comment previews on srcdoc | causes unnecessary iframe replacement for bridge-capable URL-loaded artifacts.

Confidence: high

Scope-risk: moderate

Directive: Do not enable URL-load for bridge-dependent modes unless the artifact has an owned postMessage bridge.

Tested: pnpm guard

Tested: pnpm --filter @open-design/web typecheck

Tested: pnpm --filter @open-design/web test

Tested: Playwright verified Edit and Comment toggles preserve iframe src and DOM node while receiving comment targets.

* Prevent preview wheel gestures from escaping into zoom

Trackpad pinch-like wheel events arrive with ctrl/meta modifiers on some platforms, which can make a normal vertical scroll feel like the preview zoomed. The preview now consumes those modified wheel events inside the host preview shell and in injected srcdoc previews, then maps the delta back to scroll where a scroll target exists.

Constraint: URL-loaded sandbox iframes cannot always be inspected by the host, so srcdoc previews need their own in-frame guard.

Rejected: Add allow-same-origin to preview iframes | weakens the sandbox boundary for generated artifacts.

Confidence: medium

Scope-risk: narrow

Directive: Do not broaden iframe sandbox permissions to fix gesture handling without a security review.

Tested: pnpm guard

Tested: pnpm --filter @open-design/web typecheck

Tested: pnpm --filter @open-design/web exec vitest run tests/components/FileViewer.test.tsx tests/runtime/srcdoc.test.ts

Tested: playwright-cli verified ctrl-wheel in preview keeps app zoom at 100% and prevents default in the iframe context

* Revert "Prevent preview wheel gestures from escaping into zoom"

This reverts commit 976407ab4c.

---------

Co-authored-by: nicejames <nicejames@gmail.com>
2026-05-19 15:39:42 +08:00
EliandGitHub 4376d8a8ec [codex] Add pet task center and desktop pet (#1833)
* feat: add pet task center and desktop pet

* Fix pet task center review regressions
2026-05-19 15:38:39 +08:00
6990291217 fix: escape chat transcript role delimiters (#2156)
Co-authored-by: multica-agent <github@multica.ai>
2026-05-19 15:37:35 +08:00
lefarcenandGitHub 387dc83b27 fix(plugins): wire Open Design "Open Design PR" button end-to-end (#2182)
Two-part fix for the Plugin folder card's "Open Design PR" button. The
flow was broken end-to-end: the CLI emitted a 404 URL, and the agent
prompt under-specified the contribution steps so the agent stalled
mid-turn or fell back to the legacy issue-URL path.

Catalog target — `apps/daemon/src/plugins/publish.ts`:

`buildPublishLink({ catalog: 'open-design' })` hardcoded a submission URL
at `github.com/open-design/plugin-registry`, the dedicated registry repo
proposed in docs/plans/plugin-registry.md §1.2. That repo doesn't exist
yet (P3.1 notes "creating the external GitHub repo is an operational
launch step, not a code blocker"), so every generated URL 404'd. Retarget
the catalog at the live `nexu-io/open-design` monorepo and update the
target-path hint in the PR body to `plugins/community/<plugin-name>/`
(the actual layout under main). Plan §1.2 stays the long-term goal — see
the code comment.

Also updates the matching `od plugin yank` issue URL in cli.ts.

Agent prompt — `apps/web/src/components/design-files/pluginFolderActions.ts`:

The `contribute` action prompt only said "use the supported `od plugin
publish` Open Design registry flow", which produces an issue URL (the
legacy path) and left the agent to invent the remaining steps. The agent
ended up calling `AskUserQuestion` mid-turn waiting for input that the
DesignFilesPanel buttons couldn't satisfy, then stalled for 600s.

Rewrite the `contribute` prompt to drive the full PR flow via raw `gh`
commands:
  1. preflight `gh --version` / `gh auth status` (detect-and-instruct on
     missing CLI, never auto-install anything)
  2. read manifest, resolve author login
  3. `gh repo fork nexu-io/open-design --remote=false`
  4. clone fork, branch, cp plugin into `plugins/community/<name>/`,
     commit/push using author's git identity (not a hardcoded bot)
  5. `gh pr create ... --web` so the author reviews and clicks Create

Hard bans on `AskUserQuestion`, retry-on-failure, and the legacy
`od plugin publish --to open-design` CLI keep the turn fire-and-forget.
The `install` / `publish` action prompts are unchanged.

Tests:

* `apps/daemon/tests/plugins-publish.test.ts` — assert URL host +
  catalogLabel match `nexu-io/open-design`, body contains the new path
  hint.
* `apps/web/tests/components/pluginFolderActions.test.ts` (new) — lock
  the contribute prompt's command surface, the `--web` review window,
  the `AskUserQuestion` ban, the install-tool ban, and folder-path
  interpolation. Nine assertions covering the prompt contract without
  coupling to exact wording.

Validation:

* `pnpm --filter @open-design/daemon exec vitest run tests/plugins-publish.test.ts`
  → 11/11 passed
* `pnpm --filter @open-design/web exec vitest run tests/components/pluginFolderActions.test.ts`
  → 9/9 passed
* `pnpm --filter @open-design/web typecheck` clean
* E2E: button click in DesignFilesPanel under namespace=e2e-pr-test ran
  `gh --version` → fork → clone → branch → commit/push → ended at
  `gh pr create --web` opening the GitHub PR draft in browser. No
  AskUserQuestion stall this time.

Doesn't touch: `5f71968f` server-side endpoints (`/contribute-open-design`
+ `/publish-github` still in main as dead code — separate cleanup),
plan/spec docs (per maintainer call to keep the dedicated-repo as the
long-term goal), or `registry-backends.test.ts` (plan terminal-state
fixture; no production caller).
2026-05-19 15:26:59 +08:00
lefarcenandGitHub 9596a0ccd5 feat(privacy): collapse first-run consent banner to a single "I get it" button (#2202)
* feat(privacy): collapse first-run banner to a single "I get it" button

Replaces the first-run privacy disclosure's two-button decision picker
("Share usage data" / "Don't share") with a single "I get it"
acknowledgement. Clicking it accepts the same default telemetry surface
the previous "Share usage data" path enabled — the banner shifts from
binary consent picker to informed disclosure.

To keep the surface honest, the banner footer is rewritten to spell out
the new default and point at the off switch:

  "Data sharing is on by default. You can turn it off any time in
   Settings → Privacy. We never upload the contents of your generated
   artifact files."

Settings → Privacy (PrivacySection.tsx) is unchanged — that surface still
exposes both Share and Don't share buttons so users who arrive there
later (or come back to flip the choice) keep the explicit picker.

Mechanics:

* `PrivacyConsentModal.tsx`: drop `onDecline` prop and the second button;
  rename `onShare` → `onAccept` to match the new semantic. Footer hint
  now reads from `settings.privacyConsentBannerFooter` (new key) so the
  banner copy can speak in single-button voice without disturbing the
  reused `settings.privacyConsentFooter` that PrivacySection still
  displays.

* `App.tsx`: drop the `onDecline` handler. Single `onAccept` handler
  applies the same opt-in payload as the previous `onShare` branch
  (`telemetry.metrics = true`, `telemetry.content = true`, fresh
  `installationId`), so the wire format daemon-side is unchanged.

* `i18n/types.ts` + `locales/en.ts`: two new keys —
  `settings.privacyConsentAccept` ("I get it") and
  `settings.privacyConsentBannerFooter` (the default-on disclosure copy).

* `i18n/locales/*.ts` (all 18 non-en dictionaries): added the two new
  keys. zh-CN and zh-TW are translated; the remaining 16 locales follow
  the project convention of leaving the EN string as a fallback for
  later contributor passes (same shape used by privacyConsentShare /
  Decline today).

* `tests/components/PrivacyConsentModal.test.tsx`: rewritten. The four
  new tests lock the new contract — single "I get it" button, no
  Share/Decline labels, default-on disclosure text in the footer, the
  external privacy-policy link, and onAccept firing on click. Replaces
  the prior "equal-prominence" tests, which only made sense for the
  two-button shape.

Validation:

* `pnpm --filter @open-design/web exec vitest run tests/components/PrivacyConsentModal.test.tsx`
  → 4/4 passed
* `pnpm --filter @open-design/web exec vitest run tests/i18n/locales.test.ts`
  → 5/5 passed (every locale aligned with English keys + placeholders;
  the new keys ship to all 19 dictionaries)
* `pnpm --filter @open-design/web typecheck` clean

* test(privacy): update App.connectors fixture to match single-button banner

`App.connectors.test.tsx > does not show first-run privacy consent until
daemon config hydration finishes` hardcoded the previous "Share usage
data" affirmative button label. The single-button banner now renders
"I get it", so the assertion was looking for a button that no longer
exists.

CI signal: 26081467446 → Web workspace tests → `× does not show
first-run privacy consent until daemon config hydration finishes`. The
App workspace tests + Validate workspace failures cascaded from this
one — both are aggregator jobs.

Local: vitest run tests/components/App.connectors.test.tsx → 5/5 passed.
2026-05-19 15:26:56 +08:00
EliandGitHub 3cecb1c881 Polish project workspace UI (#2201) 2026-05-19 15:14:16 +08:00
5254559cb1 Add WeRead year-in-review HyperFrames template (#2131)
Co-authored-by: Tuola Ge <gexingli@refly.ai>
2026-05-19 15:11:41 +08:00
a38e09f931 fix(web): demote Plugins and Integrations to nav rail footer (#1806)
* fix(web): demote Plugins and Integrations to nav rail footer

Plugins and Integrations are platform-configuration surfaces, not
daily-use destinations. Moving them to the footer section of the
left nav rail — separated from primary items by a thin divider —
keeps them reachable while giving the primary four items
(Home, Projects, Automations, Design Systems) the visual weight
they deserve.

- EntryNavRail: remove Plugins/Integrations from the main __group
  and place them in the __footer above the help launcher
- entry-layout.css: add __divider rule (1 px separator) to visually
  mark the boundary between primary and secondary nav regions

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): remove settings dropdown, gear opens settings directly

The gear/cog button previously opened a dropdown that mixed three
unrelated concerns: community links (X, Discord), preference quick-
access (Language, Appearance), a feature shortcut (Use everywhere),
and a redundant Settings entry — creating two separate paths to the
same Settings dialog and duplicating Language/Appearance relative to
the Settings sidebar.

Changes:
- Gear button now directly opens the Settings dialog (no intermediate
  dropdown layer)
- Follow @nexudotio on X and Join Discord moved to the Help menu at
  the bottom of the nav rail, where community/external links belong
- Language and Appearance remain exclusively in the Settings dialog
- Use everywhere remains exclusively in the topbar chip
- Remove dead state (avatarMenuOpen, languageExpanded,
  appearanceExpanded), ref, outside-click effect, and module-level
  constants (APPEARANCE_THEMES, APPEARANCE_LABEL, describeModelChip)
  that were introduced solely to support the dropdown

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(web): move output-type chips above chat input as tab bar

The home hero previously had two chip rows below the chat input that
mixed two unrelated dimensions: output type (Prototype, Slide deck,
Image…) and workflow source (Create plugin, From Figma, From folder,
From template). Users had no visual cue that these were different
categories.

This change separates the two dimensions clearly:

- Output type (create group) becomes a tab bar positioned above the
  input card. Tabs share the same chip data and onPickChip dispatch,
  so plugin selection, active state, and pending state are unchanged.
  Active tab shows a colored underline; the bar border visually
  connects to the input card below.

- Workflow source (migrate group) stays as the chip row below the
  input card, now standing alone with unambiguous "how to start"
  semantics.

- Subtitle updated from "Pick a plugin below" to "Pick a type"
  to match the new placement.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): skip replace-prompt confirmation when switching output-type tabs

Output-type tab clicks (create group) are mode-selection gestures;
the user expects the prompt to update immediately without a dialog.
The confirmation is still shown for migrate-group chips (From Figma
etc.) where the replacement carries meaningful user-provided content.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): use brand logo as Home destination, drop redundant brand mentions

The entry nav rail previously rendered the brand logo and a separate
Home icon back-to-back; both invoked `onViewChange('home')`, so the
Home button was pure duplicate affordance. The hero pane also
displayed a third "Open Design" lockup that competed with the rail
logo and the rebranded title.

This collapses those affordances:

* `EntryNavRail` drops the dedicated Home `NavButton`. The brand
  logo button now carries `aria-current="page"` and an `is-active`
  visual state when the home view is showing, and its tooltip reads
  "Open Design · Home" off-home so the navigation behavior stays
  discoverable for new users.
* `entry-layout.css` adds the matching `.entry-nav-rail__logo.is-active`
  accent treatment so the "you are here" cue reads at parity with
  primary rail buttons.
* `HomeHero` removes the inline `home-hero__brand` lockup and the
  associated CSS, then retunes the title/subtitle/type-tab spacing
  so the headline group still pairs tightly with the type tabs and
  input card below.
* `entry-chrome-flows` is updated to assert the logo carries the
  active page treatment and that no `entry-nav-home` test id
  resurfaces by mistake.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): auto-grow home chat input, disable internal scroll and drag-resize

The home hero textarea was capped at a fixed `min-height: 84px` with
`resize: vertical`, so users had to either drag the bottom-right
corner to enlarge it or scroll the textarea internally to read
longer prompts. That hid context (loaded plugin templates routinely
overflow three lines) and exposed a manual grip whose state was easy
to leave in an awkward height.

This change makes the chat box grow with its content:

* `HomeHero` adds a `useLayoutEffect` that, on every prompt change,
  resets the textarea height to `auto` so the browser can measure a
  smaller content, then writes back `scrollHeight` in pixels. The
  effect uses layout phase (not effect phase) to avoid a one-frame
  flash at the previous height when a plugin loads a long example
  prompt.
* `home-hero.css` swaps `resize: vertical` for `resize: none` and
  adds `overflow: hidden`, so the manual drag grip disappears and
  the textarea never scrolls internally. `min-height: 84px` is kept
  so the empty input still reads as a chunky chat box. The outer
  page handles overflow when the prompt is genuinely very long.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): make output-type tabs read as folder-tabs attached to chat box

The previous tab bar used a small icon + label per tab and signaled
the active tab with a 2px accent underline sitting on a horizontal
divider line. That divider visually broke the relationship between
the tabs and the input card below — the active tab looked like a
free-floating header, not a flap of the chat surface, so users had
to do extra work to mentally connect "I picked Prototype" with the
prompt area immediately underneath.

This switches the tab bar to a folder-tab pattern:

* `HomeHero` drops the per-tab `Icon` element. The seven labels
  (Prototype, Live artifact, Slide deck, Image, Video, HyperFrames,
  Audio) already disambiguate at the type sizes used here, and the
  icons were primarily decorative.
* `home-hero.css` rewrites the tab styling:
  - The bar no longer paints its own baseline border; the input
    card's top edge serves as the baseline.
  - Each tab is a rounded-top container with a 1px transparent
    border and a `-1px` bottom margin, so its bottom edge overlaps
    the card's top border by exactly one pixel.
  - The active tab borrows the card's panel background and border
    color, and overrides its bottom border with the panel color
    so it visually erases the card's top border for the tab's
    width. The result reads as one continuous "Prototype is this
    chat box" surface.
  - The card's prior `margin-top: 8px` is removed so the tab bar
    bottom and card top sit at the same y coordinate, which is the
    geometric precondition for the 1px overlap to land cleanly.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): enlarge home chat attach and submit buttons for legibility

The attach (paper-clip) and submit (arrow-up) controls on the home
chat input rendered at 32px diameter with 14px and 18px glyphs
respectively. After stroke antialiasing the icons read at roughly
11–12px on typical displays — small enough that users reported the
glyphs were illegible and had to be discovered by trial-and-error.

This bumps both controls to 38px circles and grows their glyphs
(attach 14 → 18, submit 18 → 22). The primary call-to-action now
has clearly more visual weight than the surrounding muted hint
text, and the paper-clip is recognisable at a glance.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): paint a chevron on inline select slots in the home prompt

Inline select slots in the home prompt overlay (e.g. the
`high-fidelity` / `wireframe` fidelity picker on the Live artifact
template) rendered as plain pill highlights, visually identical to
free-text and read-only text slots. The slot's `appearance: none`
strips the browser's default chevron, so users had no affordance
hinting the value was switchable.

This wraps select-type slots in an `inline-flex` span and overlays
an explicit chevron-down `Icon` against the slot's trailing padding
(bumped from 18px to 22px to make room). The chevron inherits the
accent color via the wrap's `color` property so it themes correctly
in light and dark modes. Click semantics are unchanged because the
chevron is `pointer-events: none`.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): size inline number slots to their value, not the whole row

Number-type inline slots in the home prompt (e.g. the slide-count
spinner on the Slide deck template) inherited the generic slot
`min-width: 8ch` and then stretched to the browser's default
`<input type=number>` width, so a two-digit value like "10" ate
the entire remaining line and pushed the native spinner buttons
to the far right edge — far away from the value they control.

This sizes the number input to its actual content plus four
characters of trailing room for the spinner buttons (clamped to
6–14ch), and adds a `home-hero__prompt-slot-input--number`
modifier that overrides the slot `min-width` to 4ch. The
spinner now sits flush against the value and the slot reads as
a compact inline pill matching the surrounding text/select
slots.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): widen prompt line-height so slot pills do not collide vertically

Each interactive slot and mention in the home prompt paints a 2px
outline ring via `box-shadow`. At the previous `line-height: 1.55`
on a 15px font, two lines were ~23px apart while a single pill
occupied ~20px of vertical space (text box + ring on both sides),
leaving roughly 2px of clear space between rows. When the prompt
wrapped onto multiple lines — common for the Image template's
"Generate a {kind} of {subject}. Style: {style}. Aspect: {ratio}."
example — the rings from line N and line N+1 visually merged into
a single bar, making it ambiguous which pill the user was about to
click or edit.

This bumps the line-height of both the highlight overlay and the
underlying editable textarea to 1.85 (~28px per line), restoring
~8px of clear space between pill rows. The two values must stay
identical so the overlay glyphs continue to track the textarea
caret positions exactly; a brief comment in each rule documents
this coupling for future edits.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): paint dropdown chevron on select element with neutral color

The previous chevron treatment wrapped each select slot in an
inline-flex span and laid an accent-orange `<Icon>` over the
trailing padding. At the prompt's normal display size the orange
chevron blended into the orange pill ring corners, so users
perceived "a bunch of dropdown arrows" across every highlighted
slot, even though only the actual select rendered one.

Move the chevron onto the `<select>` itself as a small neutral-
gray `background-image` SVG. The grey contrasts clearly with the
pill's accent ring and the chevron lives inside the select's own
padding, so it can never visually overlap the value text and can
never appear on non-select slots.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): shrink select-slot dropdown caret so it stops reading as a check-mark

The 8×6 stroked chevron looked like a check-mark in zoomed views
because the stroke width was a large fraction of the glyph. Swap
for a small (9×5) filled triangle drawn as a `background-image`,
with `background-size` pinned so browsers can't scale it to its
intrinsic SVG box. The caret is now unambiguously a dropdown
indicator without crowding the value text.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): make read-only prompt slots visually distinct from editable pills

Multi-word context values are rendered as plain <span>s with
pointer-events: none, but they inherited the same orange pill +
ring treatment as the truly editable <input>/<select> slots.
Users couldn't tell which pills they could click into.

Strip the pill background, the ring, the radius, and the padding
from `.home-hero__prompt-slot-text` and replace them with a
subtle dashed bottom border. The orange foreground keeps the
slot family link, but read-only highlights now clearly read as
"context value spliced into the prompt" rather than as
"interactive control".

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): scale select-slot dropdown caret up to 12px wide for legibility

The 9×5 caret was too quiet at the prompt's font size to read as
a dropdown affordance. Bump to a 12×6 filled triangle and pad the
select's trailing space (24px) so the value text still has clear
breathing room from the caret.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): collapse plugins search and filter strips into one bar

The plugins-home gallery laid out search, count, mode (Featured),
total-in-catalog, clear-filters, the main category row, and the
sub-category row as four floating clusters. Search lived up in
the section header, far from the chips it actually scopes; the
mode strip wedged "Featured + 386 in catalog + Clear filters"
between the header and the category row with no obvious
ownership; and the two clear-filter affordances duplicated each
other (chip strip + empty-state).

Fold the mode strip into the category row: Featured is now the
leading chip on the same line as the category pills, and the
search field, the result count, and a compact Clear link sit as
a right-aligned tools cluster on that same row. The header
shrinks back to just the title, subtitle, and Browse registry
link. The sub-category row stays as the contextual second line
when a category is active.

Tests: keeps the existing data-testids (plugins-home-chip-featured,
plugins-home-row-category, plugins-home-clear, plugins-home-count,
plugins-home-search) so the existing 11-case section spec passes
without modification.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): hide Recent projects rail on first-run home when empty

A brand-new user landing on Home saw an empty dashed box with the
copy "No projects yet — type a prompt to start one." sitting
above the plugin gallery. The hero already prompts the user to
type, so the empty rail just adds vertical noise without telling
them anything new.

Return null from RecentProjectsStrip when the recent list is
empty (loading or not) so the rail appears only when there is
actually something to show. Update the entry-chrome e2e to
assert toHaveCount(0) on first run — codifying the new contract
that the rail is conditional, not always-mounted.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): hide structured inputs form when every field is in the prompt

The PluginInputsForm below the chat textarea surfaced every plugin
input — even the ones the prompt template already substitutes
inline as highlighted slot pills. For a plugin like Prototype
that's five identical labelled inputs duplicating the five slot
pills above them, making the chat box look like it has grown a
second composer.

Compute the set of placeholder keys actually referenced in the
prompt template (via INPUT_PLACEHOLDER_PATTERN) and skip those
when deciding what the structured form needs to render. The form
still appears for plugins that expose inputs not referenced in
the prompt text (e.g. a "Run in background" toggle), but
template-only plugins collapse the redundant second editor.

Update the picker spec accordingly: when every field is in the
template the form is now expected to be absent rather than to
render a duplicate of the inline slot.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): drop redundant filtered-count and Clear link beside the search

The combined plugins filter bar trailed the search field with
"59 / 386" and an inline "Clear" link, but both repeat what the
chip strip already shows: every chip carries its own count
(Slides 59, All 386, …) and clicking the All chip already resets
the filters. Users had no way to know what the bare "59 / 386"
fraction or "Clear" referred to without inference.

Strip the trailing tools cluster down to just the search input.
The empty-results message at the bottom of the gallery still
exposes a contextual "Clear filters" button when a stacked
filter yields no matches, so the affordance isn't lost — just
removed from a position where it didn't read as actionable.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): drop default subtitle copy from the Official starters strip

The Home gallery rendered a two-line explanatory subtitle under
"Official starters" — "Ready-to-use Open Design workflows bundled
with this runtime. Pick one to load a starter prompt, or browse
the registry for more." — every visit. Returning users skip it,
new users get the same message from the section title plus the
Browse registry link plus the visual card grid itself; the prose
read as filler chrome above the chip strip.

Default the subtitle prop to undefined and only render the <p>
when a caller passes an explicit string. Other surfaces that
mount PluginsHomeSection with their own copy keep their
subtitle; the bare Home gallery loses one row of vertical noise.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fade out empty workflow lanes in Plugins home filter

Empty top-level lanes (Deploy 0, Refine 0, etc.) and empty
sub-categories (Vercel 0 under Deploy, Figma 0 under Import, etc.)
used to look identical to populated ones, so users couldn't tell at
a glance which chips were real catalog buckets and which were
"contribute a plugin" invites. The strip kept all lanes visible by
design — the workflow shape (Import / Create / Export / Share /
Deploy / Refine / Extend) is part of what we want users to see —
so we keep them clickable, but tag count-zero chips with
data-empty='true' and give them a faded, dashed-border treatment.
"All" pills stay solid since their count reflects the parent lane,
not their own emptiness.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): update home nav test expectations

* fix(e2e): align critical smoke with entry chrome

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 14:58:15 +08:00
Joey-nexuandGitHub 444e33ea60 feat(daemon): add Grok Build (xAI's first-party CLI) as an agent runtime (#2200)
* feat(daemon): add Grok Build (xAI's first-party CLI) as agent runtime

xAI shipped Grok Build (https://x.ai/cli) on 2026-05-19 — a first-
party CLI agent that boxes their SuperGrok subscription into a
Claude-Code-shaped headless mode (`grok -p <prompt>`, optional
`--output-format streaming-json`, `--max-turns`, native subagent /
plan / mcp subcommands). The OAuth flow it ships uses the same
`auth.x.ai` issuer + `b1a00492-073a-47ea-816f-4c329264a828` client_id
+ `grok-cli:access api:access` scope that the existing OD xAI
Settings panel already speaks, so once a user runs the install
script and `grok login --oauth`, Grok Build is fully authenticated
without OD doing anything.

This runtime def lets OD detect a `grok` binary on PATH and surface
it in the agent picker the same way Hermes / Claude Code / Codex are
surfaced today. Headless invocations get:
- `grok -p` (prompt via stdin to avoid Windows ENAMETOOLONG / Linux
  E2BIG on large composed prompts), with `--model` / `--effort`
  pass-through when the user picks one in the picker.
- `grok models` for live model discovery (parsed line-by-line,
  matching the existing `parseLineSeparatedModels` helper opencode /
  cursor-agent already use). Falls back to a static list of
  grok-build / grok-4.3 / grok-4.20-{reasoning,non-reasoning,
  multi-agent} when probing fails (no Heavy entitlement, network
  blip, etc.).
- `--effort` exposed as the standard reasoning-options dropdown.

streamFormat is intentionally `plain` for this first cut. Grok
Build's `streaming-json` output is a real NDJSON event stream, but
the schema is xAI-specific and OD does not yet have a parser for it
— shipping with `plain` now means the user can chat single-turn,
and a follow-up `grok-stream-json` adapter can light up tool_use /
plan-mode streaming once we've validated the shape against a live
Heavy account.

No test added for the def itself; the existing
`tests/runtimes/registry-and-args.test.ts` and `agent-args.test.ts`
iterate over `AGENT_DEFS` and now cover this entry by construction.
All 126 runtime tests pass; daemon tsc + tsconfig.tests.json clean;
pnpm guard clean.

* feat(web): add grok-build agent icon

Pairs with the new daemon runtime def in 35418fe so the Settings →
Agent Runtime row stops falling back to the "G" initial.

The SVG is a hand-drawn geometric "X" silhouette (Unicode 𝕏 / U+1D54F
shape), painted via AgentIcon's mono mask path so it picks up the
active theme color the way hermes / mimo / pi / kilo / cursor-agent
already do. xAI does not publish a downloadable brand SVG (favicon
paths on x.ai 404), so this is intentionally a placeholder rather
than a copy of any licensed mark — happy to swap for an official
asset if maintainers have one to hand.

Wires the id into both `ICON_EXT` and the `MONO_ICONS` set in
AgentIcon.tsx. No other behaviour changes.
2026-05-19 14:55:28 +08:00
EliandGitHub 18b947c25f [codex] Land design system GitHub intake handoff (#2187)
* Add Claude-style design system workflow

* Merge design system workflow into main

* Restore design system workflow UI styles

* Fix design system setup scrolling

* Fix design system setup connector button

* Preserve connector auth link after popup block

* Simplify connected GitHub setup state

* Open generated design system workspace project

* Summarize design system auto prompt in chat

* Add bounded GitHub connector design intake

* Prefer path-scoped GitHub intake tools

* Restore branch GitHub design context intake

* Restore design system review workspace

* Restore design system manager tab

* Let design system workflow routes own details

* Open editable design systems as projects

* Restore design system workspace coverage

* Fix bounded GitHub connector intake

* Hide design system review while generating

* Suppress design system generation questions

* Constrain GitHub design intake to bounded command

* Tolerate oversized GitHub metadata during intake

* Rebuild daemon CLI when sources change

* Fallback when GitHub connector snapshots are rate limited

* Allow GitHub intake without Composio

* Use native GitHub auth for design intake

* Remove design system review group heading

* Improve design system extraction evidence

* Align design system scaffold with Claude output

* Add evidence inventory for design system intake

* Add local design system evidence intake

* Add design system package audit gate

* Allow auditing Claude Design reference packages

* Audit design system package content quality

* Migrate legacy design system artifacts

* Clean migrated design system artifacts

* Require modular design system UI kits

* Reject thin design system UI kits

* Prioritize core design evidence intake

* Require role-based design system UI kits

* Clean stale design system manifest references

* Require representative preserved design assets

* Warn on generic design system visuals

* Enforce design system quality warnings

* Audit connected design system UI kits

* Require mounted design system UI kits

* Require composed design system app shells

* Require runnable JSX design system kits

* Require browser globals for design system components

* Infer design system names from source URLs

* Require source examples in design system packages

* Bind preserved fonts in design system tokens

* Require skill frontmatter in design system packages

* Preserve build icons in design system packages

* Require real assets in brand previews

* Require substantive source examples

* Require product overview in design system README

* Require reusable UI kit README

* Require reusable design system skill docs

* Seed Claude-style UI kit entry contract

* Preserve runtime build assets in design packages

* Audit design system packages after generation

* Audit design system first-run output

* Audit source-backed preview cards

* Align design system UI kit scaffolds

* Materialize design evidence package artifacts

* Show project chat during design system setup

* Hand off design system setup to project chat

* Auto-repair design system audit failures

* Harden design system evidence preservation

* Tighten design system package guidance

* Add targeted design system repair guidance

* Bound design system audit auto repair

* Use connector statuses in design system setup

* Audit design system preview manifests

* Require README preview manifests for design systems

* Fix design system GitHub intake handoff

* Fix daemon prompt CI assertions
2026-05-19 14:30:17 +08:00
Siri-RayandGitHub 1d59ffacd1 fix(web): localize entry i18n gaps (#2060) 2026-05-19 14:05:45 +08:00
5d28f1c19d Add community and use case blog posts (#2103)
* Add community and use case blog posts

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix plugin workflow example path

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix plugin workflow commands and CTA

Co-authored-by: Cursor <cursoragent@cursor.com>

* Reduce blog topics diff noise

Co-authored-by: Cursor <cursoragent@cursor.com>

* Align plugin publishing docs with CLI

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 14:05:16 +08:00
Marc ChanandGitHub 4f116d9eaf fix(ci): anchor PR inactivity clock to author responses (#2185)
* fix(ci): anchor PR inactivity clock to author responses

* fix(ci): add dry-run mode to PR inactivity workflow

* fix(ci): read workflow dry-run input from event payload

* fix(ci): log PR inactivity dry-run diagnostics

* fix(ci): accept both review association field names

* fix(ci): log PR 642 feedback payload shapes

* fix(ci): trust PR reviewers by repo permission

* fix(ci): remove temporary inactivity debug logs
2026-05-19 13:59:15 +08:00
PerishFireandGitHub bd48c597b0 chore: pin dependency versions and harden CI caches (#2189)
* chore: pin dependency versions

* ci: enforce pinned dependency specs

* ci: fix pnpm executable invocation
2026-05-19 13:58:27 +08:00
Ethan GuoandGitHub 477dd627b1 feat(daemon): parse DESIGN.md YAML frontmatter for presets (#2110)
* feat(daemon): parse DESIGN.md YAML frontmatter for presets

Falls back to frontmatter name/description/category/surface behind
existing Markdown heuristics; frontmatter `colors` wins over Markdown
swatches.

Closes #1857
Contract: runs/2026-05-18T08-09-54_open-design_issue-feat/contract.md

* test(daemon): cover DESIGN.md frontmatter fallback chain

* fix(daemon): keep Markdown swatch row when frontmatter colors miss slots

Material Design 3 token names (`on-surface`, `outline`) in totality-
festival's frontmatter left fg/support unmatched, regressing its picker
swatches; fall back to Markdown when the frontmatter row would use hard-
coded defaults.

Refs: https://github.com/nexu-io/open-design/pull/2110#discussion_r3258871692
2026-05-19 13:52:11 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
226bc57471 Update docs/assets/github-metrics.svg (#2145)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-19 13:50:05 +08:00
kamiandGitHub 68b0e0258d fix(web): scope daemon transcript to active agent (#2157) 2026-05-19 13:49:34 +08:00
kamiandGitHub b838e94b88 fix(web): expand skill mention picker (#2170) 2026-05-19 13:49:15 +08:00
bluto447andGitHub 6e1ebb97dd docs: add Windows native setup notes to AGENTS.md (#324)
* docs: add Windows native setup notes to AGENTS.md

* docs: address review feedback on Windows native setup notes

- Reframe Node 22 FAQ around the actual user question (no orphaned
  citation); ground the answer in package.json#engines only
- Remove fabricated better-sqlite3 engines field claim; the
  lockfile entry has only resolution/integrity, no engines metadata
- Cross-reference historical Windows issues (#10, #96, #100, #203,
  #315) for fresh-installer context
- Remove tools-dev bullet that duplicated the Local lifecycle section
- Specify Visual Studio Build Tools 2022 or newer

* docs: pin Windows Node install to verified Node 24 (Looper follow-up)

`OpenJS.NodeJS.LTS` floats with whichever line is currently LTS — works
today (Node 24.15.0) but will silently advance to Node 26 in October
2026, conflicting with package.json#engines: node: "~24". WinGet has no
`OpenJS.NodeJS.24` package to pin against. Reword the install bullet to
(a) keep the WinGet command, (b) offer nodejs.org as alternative, (c)
require `node --version` verification, and (d) call out the October
2026 drift explicitly.
2026-05-19 13:23:00 +08:00
PerishFireandGitHub 99b42726b8 Simplify CI PR gate (#2183) 2026-05-19 13:18:41 +08:00
428603cf6c Add local custom agent profiles (#378)
Co-authored-by: fuyizheng3120 <fuyizheng3120@users.noreply.github.com>
2026-05-19 13:13:48 +08:00