Commit Graph
1044 Commits
Author SHA1 Message Date
PerishCode ddd803aa67 Refresh auto-update branch for packaged paths 2026-05-18 14:17:41 +08:00
PerishCode 826c55a39b Serialize desktop updater operations 2026-05-18 14:15:47 +08:00
PerishCode 178d98b5db Refresh desktop auto-update branch for main 2026-05-18 14:15:47 +08:00
PerishCode dc25d25a3e Handle counted beta nightly update versions 2026-05-18 14:15:47 +08:00
PerishCode a4ddef4178 Add packaged desktop auto-update 2026-05-18 14:15:47 +08:00
788ce450fc feat(design-systems): add tokens.css + components.html for 10 AI / devtool brands (#2023)
Brands added (each with full 56-token :root + self-contained fixture):
- Tier A (AI ecosystem): x-ai, perplexity, ollama, runwayml, minimax
- Tier B (AI-adjacent devtools): supabase, posthog, resend, shadcn, raycast

All 10 declare the complete shared schema (26 A1 + 26 A2 + 4 B-slot) with no
C-extensions; pnpm guard reports 27 brand pairs aligned end-to-end.

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 14:03:36 +08:00
9983bb3003 feat(design-systems): add tokens.css + components.html for 10 SaaS / consumer brands (#2028)
Brands added (each with full 56-token :root + self-contained fixture):
- Tier B (AI-adjacent devtools / SaaS): sentry, framer, webflow, warp, arc
- Tier C (productivity / consumer): cal, loom, canva, meta, duolingo

All 10 declare the complete shared schema (26 A1 + 26 A2 + 4 B-slot) with no
C-extensions; pnpm guard reports 36 brand pairs aligned end-to-end.

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 14:03:19 +08:00
b603a4ec54 feat(design-systems): add tokens.css + components.html for 10 devtool / fintech / docs brands (#2029)
Brands added (each with full 56-token :root + self-contained fixture):
- Devtools / data infra: clickhouse, hashicorp, mongodb, mintlify, sentry-adjacent (lovable, superhuman)
- AI-app builder / messaging: intercom, lovable, superhuman
- Fintech / crypto: coinbase, binance, wise

All 10 declare the complete shared schema (26 A1 + 26 A2 + 4 B-slot) with no
C-extensions; pnpm guard reports all 6 contract checks passing.

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 14:03:01 +08:00
asim48-ctrlandGitHub 08d6bc73ac Clarify ui-ux-pro-max catalog scope (#1960) 2026-05-18 14:02:33 +08:00
Yuhao ChenandGitHub 156191d565 fix(web): show unavailable state for missing examples (#1983) 2026-05-18 14:02:22 +08:00
2e97ac9e68 Pin daemon data dir in agent runtime env (#2005)
Co-authored-by: multica-agent <github@multica.ai>
2026-05-18 14:02:11 +08:00
Joey-nexuandGitHub f1870cbf3d chore(featured): curate Featured picks down to top 10 across categories (#1966)
* chore(featured): curate Featured picks down to top 10 across categories

The picker's Featured chip currently surfaces 64 plugins because
`isFeaturedPlugin` (apps/web/src/components/plugins-home/facets.ts)
treats any finite `od.featured` number as featured, and the field
had been adopted incrementally by 51 skills + 13 templates without
a curation step. The result is a "Featured" tab that's effectively
"everything tagged at all" — no editorial signal.

Curate down to 10 picks, allocated to keep the showcase legible:

  0.001  skills/deck-swiss-international
  0.01   skills/deck-guizang-editorial
  0.02   design-templates/magazine-poster              [add]
  0.04   skills/doc-kami-parchment
  0.10   design-templates/web-prototype-taste-brutalist [add od: block]
  0.13   skills/video-hyperframes
  0.14   skills/frame-glitch-title
  0.15   skills/vfx-text-cursor
  0.16   skills/frame-logo-outro
  0.17   skills/deck-open-slide-canvas

Selection mirrors the html-anything `recommended: 1..10` ranking
(html-anything is the upstream content source for these skills, per
the `od.upstream` field on each SKILL.md). Two of those 10 picks
weren't in the prior featured set at all — `magazine-poster` had no
`od.featured` field and `web-prototype-taste-brutalist` had no `od:`
block at all — so they get added rather than just rebalanced.

Removes `od.featured` from the other 56 files. No UI code change;
the existing `isFeaturedPlugin` logic now reads a curated set
instead of an accidental one.

* chore(featured): align baked plugin manifests with curated top 10

The picker reads `od.featured` from each plugin's
`plugins/_official/examples/<id>/open-design.json` manifest, not from
the SKILL.md frontmatter the previous commit edited. Without this
follow-up the curated set of 10 would be invisible to users — the
picker's Featured chip would still surface 27 baked plugins from the
pre-existing manifests.

Mirror the SKILL.md curation into the baked layer:

  removed `od.featured` from 19 manifests:
    article-magazine, card-xiaohongshu, data-report,
    frame-data-chart-nyt, frame-flowchart-sticky,
    frame-light-leak-cinema, frame-liquid-bg-hero,
    frame-macos-notification, guizang-ppt, html-ppt,
    kami-deck, kami-landing, mockup-device-3d,
    open-design-landing-deck, ppt-keynote, resume-modern,
    social-reddit-card, social-spotify-card, social-x-post-card

  added `od.featured` to 2 manifests:
    magazine-poster -> 0.02
    web-prototype-taste-brutalist -> 0.10

Verified locally against `daemon /api/plugins`: featured count is
now exactly 10, matching the SKILL.md source of truth from the
previous commit.
2026-05-18 12:56:26 +08:00
b68e4d3252 feat(design-systems): add tokens.css + components.html for 9 AI product brands (#1841)
* feat(design-systems): add tokens.css + components.html for 9 AI product brands

Compiles DESIGN.md prose into machine-consumable agent artifacts for
claude, cohere, elevenlabs, huggingface, mistral-ai, nvidia, opencode-ai,
replicate, and together-ai.

Each brand adds:
- tokens.css  — :root block of CSS custom properties derived from the brand's
                DESIGN.md; agents paste this directly into generated HTML <style> tags
- components.html — reference fixture embedding the token block inline and
                    demonstrating buttons, inputs, cards, and badges styled
                    with var(--token-name) calls

Key brand decisions encoded:
- claude: warm parchment canvas, terracotta accent, Anthropic Serif display
- cohere: pure white, 22px signature radius, CohereText + Unica77
- elevenlabs: achromatic + warm stone, Waldenburg weight 300, pill-shaped
- huggingface: IBM Plex Mono headings/tags, HF Yellow (#ffd21e), 4-6px radius
- mistral-ai: golden amber palette, Arial weight 400, near-zero radius
- nvidia: true black, NVIDIA Green as border/outline signal only, teal hover
- opencode-ai: Berkeley Mono sole typeface, flat depth (ring-only elevation)
- replicate: pill-shaped everything (9999px), rb-freigeist-neue heavy
- together-ai: "The Future" font, -0.03em tracking, white/midnight dual world

openai tokens.css + components.html were merged to main separately.

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

* fix(design-systems): sync :root token blocks with tokens.css for opencode-ai and together-ai

opencode-ai: add missing "Liberation Mono" to all three font-stack fallbacks.
together-ai: remove --lavender declaration absent from tokens.css (guard requires byte-identical :root blocks).
Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 11:54:50 +08:00
Abe PenaandGitHub fa9f1d37be feat(design-files): add filter-by-kind dropdown to the design files viewer (#1990)
* feat(design-files): add filter-by-kind dropdown

The design files viewer already supports grouping and sorting by kind,
but on projects with many files of mixed kinds you still see everything
in one list. Adds a small dropdown next to the group-by toggle that
filters the visible files to one or more selected kinds.

Behavior:
- Dropdown only appears when the project has at least two distinct
  kinds; on a single-kind project the control would be noise.
- Multi-select via checkboxes. Empty set means no filter (show all).
- Each row shows the kind glyph, label, and the per-kind file count.
- Trigger label collapses sensibly: "Filter by kind" when none selected,
  the single kind's label when one selected, "{n} kinds" when many.
- Filter applies upstream of sort/group/page, so pagination ranges and
  the "1-N of M" counter reflect the filtered total.
- Page resets to 0 on filter change so the user doesn't land on an
  empty page.
- Selected kinds that disappear from the file list (after a delete or
  refresh) are pruned automatically — a stale filter cannot silently
  hide everything.
- Popover closes on outside click and Escape.

i18n keys: designFiles.filterBy, designFiles.filterClear,
designFiles.filterCount. All non-English locales inherit via the
existing `...en` spread pattern; zh-CN is the one fully-explicit
dictionary and gets translated values inline.

No behavior change to the group-by toggle, sort, pagination, selection,
or any other existing control. Filtering is layered alongside.

* fix(design-files): prune selection when filter hides selected rows

Codex review flagged that the filter-by-kind change only reset
pagination, not selection. If a user selected files, then narrowed the
filter to a kind that excludes some of them, the now-hidden rows
remained in `selected`. Bulk delete / download still operated on the
full set, so the user could destructively act on rows they could no
longer see — especially risky for the delete path.

Add a useEffect that prunes `selected` to the filtered set whenever
`filteredFiles` or `kindFilter` changes. The empty-filter branch is a
no-op so clearing the filter doesn't disturb any pre-existing
selection — only narrowing the filter prunes.
2026-05-18 11:34:13 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
4b6ddda052 docs(readme): refresh contributors wall (#2012)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-18 11:05:43 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
281c2273d1 Update docs/assets/github-metrics.svg (#2010)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-18 11:05:26 +08:00
332e982a07 fix(web): stabilize HTML preview URL on tab switch (#1959)
Co-authored-by: GHX5T-SOL <200635707+GHX5T-SOL@users.noreply.github.com>
2026-05-17 23:25:14 +08:00
91be2696dd Persist routine failure reasons (#1963)
Co-authored-by: multica-agent <github@multica.ai>
2026-05-17 23:22:00 +08:00
asim48-ctrlandGitHub 9ce504b933 Improve Claude endpoint connection diagnostics (#1955) 2026-05-17 23:19:01 +08:00
hahaplusandGitHub 89bf313782 fix(web): align Home prompt overlay with textarea so caret lands on click (#1958)
Picking a chip such as Slide deck or Image loaded a default prompt
into the Home textarea and rendered an overlay with `{{key}}`
placeholders as interactive `<input>` / `<select>` controls. The
overlay controls and the underlying textarea text were laid out
independently:

- Inputs declared `min-width: 8ch` and `Math.max(displayValue.length
  + 1, 10)ch` of width.
- Selects added 18px of right-padding for the dropdown arrow.
- The textarea kept the raw substituted string in a proportional
  font.

The two layouts no longer matched column-for-column, so every slot
shifted the textarea text to the left of where it appeared in the
overlay, compounding across the line. Clicking on visible prose to
position the caret hit a different character offset in the textarea
and subsequent typing or deletion landed in the wrong place.

For example, the Slide deck template

  Create a {{slideCount}}-slide {{deckType}} for {{audience}} about
  {{topic}}. ...

renders with slideCount=10 (~2 ch in the textarea) under a slot
input forced to 10 ch in the overlay — clicking right after the
literal `-slide` placed the caret several characters into `pitch
deck`. The Image / Video / Audio chips with their pre-filled
subject, style, aspect values reproduced the same drift.

Render the inline pills as read-only `<span>`s carrying the exact
substring the textarea shows at that position, mark them
`aria-hidden` so the textarea remains the single labelled control,
and surface every plugin input field — including the ones referenced
inline — in `PluginInputsForm` underneath. Editing flows through the
form, the parent's `updateActiveInputs` already re-renders the
prompt, and the pills stay aligned with the textarea on every
keystroke.

Also drop the now-unused inline helpers (updatePluginInput,
getTemplateInputNames, shouldRenderSlotAsText, inlineFieldType,
fileInputLabel, fileMetadata) and the dead
`.home-hero__prompt-slot-control/input/select/toggle/file/text` CSS
rules.

Verified:
- pnpm --filter @open-design/web typecheck
- vitest run on HomeHero.plugin-picker, HomeHero.rail, and
  HomeView.prefill (29/29 pass; tests updated to reflect the new
  read-only span + always-on form contract)
- Manual click-to-edit on Slide deck and Image chips in the
  pnpm tools-dev web runtime — caret now lands where the user
  clicked.
2026-05-17 23:18:28 +08:00
Nicholas-XiongandGitHub 5937a648cb fix: rename Pets settings entry from 'Customize in Settings' to 'Manage Pets' (#1939)
* fix: rename Pets settings entry from 'Customize in Settings' to 'Manage Pets'

- Change pet.composerOpenSettings label to 'Manage Pets'
- Improves clarity and discoverability of Pets management feature
- Label now accurately reflects the destination (Pets settings tab)
- Fixes #1250

* fix: remove pet.composerOpenSettings overrides from non-English locales

All locales now inherit the updated 'Manage Pets' label from en.ts

* fix: add pet.composerOpenSettings to zh-CN locale

zh-CN.ts does not use ...en spread, so it needs explicit key definition

* fix: restore pet.composerOpenSettings translations in all locales with 'Manage Pets' equivalent

Instead of falling back to English, each locale now has the proper translation:
- ar: إدارة الحيوانات الأليفة
- de: Haustiere verwalten
- es-ES: Administrar mascotas
- fa: مدیریت حیوانات خانگی
- fr: Gérer les animaux
- hu: Háziállatok kezelése
- id: Kelola Hewan Peliharaan
- it: Gestisci animali
- ja: ペットを管理
- ko: 펫 관리
- pl: Zarządzaj zwierzętami
- pt-BR: Gerenciar pets
- ru: Управление питомцами
- th: จัดการสัตว์เลี้ยง
- tr: Evcil Hayvanları Yönet
- uk: Керувати вихованцями
- zh-TW: 管理寵物
2026-05-17 23:16:37 +08:00
Ethan GuoandGitHub 0d2c87242f fix(web): snapshot pending before reload so expired-auth cancel actually fires (#1972)
reloadConnectorStatuses commits its prune setState (and runs the connectorAuthorizationPendingRef mirror effect) between the two awaits in onFocus, so cancelStaleAuthorizations was reading a post-prune ref and never identified anyone as stuck. Capture the snapshot inside onFocus before reloadConnectorStatuses runs, and pass it explicitly so the expired-auth daemon cancel actually fires.

Refs #1909 #1354
2026-05-17 23:13:53 +08:00
d36ceacf3a feat(web): surface saved Project instructions for review and retrieval (#1933)
Saved Project instructions had no post-save read-back surface. The
header control was a bare pencil icon that opened an editor and closed
on Save, so after returning to the workspace a user could not confirm
what was stored, revisit it, or tell whether it was still active
(#1822).

Make the saved state discoverable: once instructions exist, the header
affordance becomes a persistent "Project instructions" chip. Opening it
shows a read-only review panel with a preview of the saved text and an
"Active - included in every message" status, plus a reopen-to-edit
action. Saving lands back on the review panel so the stored value is
read back immediately. The empty state keeps the pencil and opens the
editor directly.

Persistence and project-level system-prompt injection are unchanged.

Closes #1822

Co-authored-by: multica-agent <github@multica.ai>
2026-05-17 23:07:25 +08:00
647433ccef Fix Inspect preview transport flash (#1967)
* Fix inspect preview transport flash

Co-authored-by: multica-agent <github@multica.ai>

* Keep inactive srcdoc transport lazy

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: multica-agent <github@multica.ai>
2026-05-17 22:30:37 +08:00
8562de404a fix: horizontal overflow pushes chat panel and toolbar off-screen when iframe preview exceeds viewport width (#1930)
Co-authored-by: 郑惠 <14549727+felicia-study@user.noreply.gitee.com>
2026-05-17 20:56:52 +08:00
mar2181andGitHub 1456cc4c14 feat(community-pets): add dentist mascot (#1924)
A friendly stylized chibi dentist in white scrubs and surgical mask.
8x9 atlas (1536x1872 webp) covering idle, run-left/right, waving,
jumping, failed, waiting, running, review states.
2026-05-17 20:45:53 +08:00
张东明andGitHub e93583c550 fix(web): remove overscroll-behavior:none blocking scroll in New Project panel (#1945)
`overscroll-behavior: none` on `.newproj-body` prevented trackpad and
mouse wheel scrolling on macOS — the panel only scrolled when hovering
directly over the native scrollbar track. Removing the property restores
normal scroll behavior.

Fixes #1942
2026-05-17 20:28:22 +08:00
laihenyiandGitHub 53104466d6 docs(i18n): sync zh-TW README with English version (#1919)
* docs(i18n): sync zh-TW README with English version

- Add missing Docker, Nix, and Stay in the loop sections
- Add Desktop data migration guide (OD_LEGACY_DATA_DIR + manual copy)
- Update badge bar with Latest release and Follow @nexudotio badges
- Update At-a-glance table: BYOK endpoint, design systems 72→129,
  Media generation row, [ads] reference
- Update OD_DATA_DIR row from "not supported" to full instructions
- All translations follow Taiwan Traditional Chinese conventions
  and TRANSLATIONS.md rules

* fix(i18n): link QUICKSTART.zh-TW.md instead of QUICKSTART.md in zh-TW README
2026-05-17 20:25:20 +08:00
cd56b5e576 fix(cli): plugin publish reads manifest version when the stored row reads as the 0.0.0 pre-handshake sentinel (#1903)
Closes #1765

`od plugin publish --to open-design` builds the registry-submission
body from the daemon's `/api/plugins/:id` row. The row carries a
stored `version` plus the full manifest. For project-local plugins —
`generated-plugin/`, snapshots, freshly imported folders — the
stored `version` reads as `'0.0.0'` until the registry handshake
runs and stamps the real version. The manifest's `version`, however,
is the author's real value the whole time.

Before this patch, the publish flow consumed `row.version` directly
and printed `version: 0.0.0` into the registry submission body even
when the plugin's `open-design.json` declared `0.1.0` or any other
non-sentinel version.

Mirror `apps/daemon/src/plugins/marketplaces.ts:298,328` and prefer
the manifest version when the stored row reads as the pre-handshake
sentinel. The fallback chain is now:

  1. row.version, when it exists and isn't '0.0.0'
  2. row.manifest.version, when it exists and is non-empty
  3. row.version (even if '0.0.0'), preserving today's behavior for
     plugins that genuinely have no manifest data
  4. '0.0.0' literal, when nothing else is available

The fallback chain is conservative: it never substitutes a higher
version that the author didn't already declare somewhere — it just
prefers the manifest over the stored sentinel.

Validation:
- `pnpm --filter @open-design/daemon test -- tests/plugins-publish.test.ts` → green
- `pnpm --filter @open-design/daemon typecheck` → green

Co-authored-by: nicejames <nicejames@gmail.com>
2026-05-17 20:24:41 +08:00
kamiandGitHub 30ad8b8ac3 improve privacy consent modal: policy link, clearer CTAs, mobile layout (#1921)
The first-run consent banner had no link to a privacy policy, an
affirmative button ("Help improve") that didn't read as a consent
choice, and a fixed bottom-right card that crowded content on phones.

- Add a "Read the privacy policy" link (external-link icon, accent,
  underlined) above the actions, plus a root PRIVACY.md it points to
  documenting the telemetry behaviour the modal discloses.
- Rename the CTAs to "Share usage data" / "Don't share" so both name
  the action; they stay equal-prominence per the EDPB/GDPR comment.
- Stretch the banner to a bottom-edge bar under 540px with a
  safe-area inset so it clears mobile browser chrome.
- Add PrivacyConsentModal tests; sync the new i18n key to every
  locale and update the consent-label assertion in App.connectors.

Refs #1756
2026-05-17 20:24:15 +08:00
Ethan GuoandGitHub 9cc1fb28f3 fix(web): apply Tweaks palette shift to :root CSS custom properties (#1952)
Walk document.styleSheets so chromatic custom properties on :root/html/body/:host (including @media-nested rules) are hue-shifted via inline setProperty, not just the values returned by getComputedStyle.

Fixes #1393
References: PR #1643 (open, in review) binds the Tweaks toolbar toggle to artifact `.tw-panel` panels via a new `injectTweaksBridge` in `srcdoc.ts` — adjacent surface but different problem. Our fix extends `injectPaletteBridge` to also shift `:root` CSS custom-property colors, which #1643 does not touch.
2026-05-17 20:16:57 +08:00
Ethan GuoandGitHub b7fa1d9286 fix(web): recover stuck Composio connector when auth is cancelled (#1909)
* fix(web): recover stuck Composio connector when auth is cancelled

When a user closes the Composio system-browser auth window without completing the flow, the connector card stayed in its loading state forever because nothing told the daemon the request was abandoned.

The window-focus refresh now awaits the status poll and, for every connector still in connectorAuthorizationPending whose freshly fetched status is not 'connected', issues cancelConnectorAuthorizationRequest and clears the matching local pending/error UI state. The connected guard is read from the just-returned statuses so a postMessage success that lands just before focus is not racy.

Fixes #1354

* fix(web): gate Composio focus auto-cancel on TTL + cancel response

Require expiresAt to have elapsed before auto-cancelling a pending
Composio auth on focus, and preserve the spinner on a failed cancel
(matching the manual Cancel handler) so the UI never disagrees with
the daemon.

Refs https://github.com/nexu-io/open-design/pull/1909#discussion_r3254152045
Refs https://github.com/nexu-io/open-design/pull/1909#discussion_r3254152046
2026-05-17 20:15:38 +08:00
Ethan GuoandGitHub 324eca27ea feat(web): add manual removal for captured Pod components (#1951)
* feat(web): add manual removal for captured Pod components

Adds `removePodMember` helper and a per-chip × in `BoardComposerPopover`; leaves `comments.ts` untouched (avoid-zone from #1127).

Closes #802
Contract: runs/2026-05-16T08-08-52_open-design_issue-feat/contract.md

* style(web): hide Pod chip × until chip hover

Swaps the unicode × for the existing `Icon name="close"` SVG so the
hit target stays centered, and fades the button in only on chip
hover / keyboard focus for a quieter resting state.

* fix(web): auto-close Pod composer when last chip is removed

Removing the last chip leaves a stale anchor; close so Send cannot attach to elements no longer visible.

* refactor(web): extract BoardComposerPopover and Pod-member reducer

Moves the popover to its own module and lifts the chip-removal reducer into a pure `applyPodMemberRemoval` so unit tests exercise the real code path and the popover's export is no longer test-only.

* fix(web): rebuild Pod anchor when a member is removed

Without this, the popover keeps the original union bbox / selector / label after each chip removal, so a subsequent Send to chat anchors the comment to elements no longer in the Pod.

* fix(web): render every captured chip and scroll on overflow

The previous slice(0, 6) cap left chips beyond the sixth invisible and undeletable. Render the full list inside a 132px-tall scrollable strip.
2026-05-17 20:13:56 +08:00
Ethan GuoandGitHub 10c62bf6e4 fix(web): warn before editing a built-in skill creates a shadow (#1850)
Clicking Edit on a built-in skill silently issued PUT /api/skills/:id,
which the daemon stores as a user-owned shadow and then hides the
built-in entry from the Settings list. From the user's perspective the
row they just edited disappears with no explanation.

Arm an inline override-warning banner on Edit for source==='built-in'
skills, mirroring the existing inline delete-confirm pattern. The edit
form only opens after the user explicitly confirms. User skills bypass
the warning and edit directly. No daemon or listSkills contract change.

Fixes #1378
2026-05-17 18:30:45 +08:00
Ethan GuoandGitHub a6288cec3f fix(web): allow editing existing routines from RoutinesSection (#1884)
The Routines list only exposed Run now / Pause / History / Delete, so any
change to a routine required deleting and recreating it. The daemon already
serves PATCH /api/routines/:id; only the web entry point was missing.

Add an Edit button on each routine row that pre-populates the create form
from the stored schedule and target via a new formFromRoutine helper, and
branch the submit handler on editingId so it PATCHes /api/routines/:id
with the updated fields instead of POSTing a new routine.

Fixes #1373
2026-05-17 15:02:54 +08:00
Yuhao ChenandGitHub fb57ef2fc3 Improve DeepSeek TUI diagnostics (#1940) 2026-05-17 15:01:10 +08:00
张东明andGitHub bac56415a2 fix(web): surface daemon error messages for invalid folder imports (#1923)
* fix(web): surface daemon error messages for invalid folder imports

importFolderProject() was swallowing non-2xx responses by returning
null, so the UI could only show a generic "Open folder failed: <path>"
message even though the daemon already returns specific errors like
"cannot import the filesystem root" or "folder not found".

Parse the daemon error body and throw so the panel displays the actual
reason. Also show feedback for empty path input instead of silently
returning.

Fixes #1186

* test(web): update folder import test to match new error propagation

The existing test expected a generic "Open folder failed: <path>"
message from a boolean return. Update to match the new behavior where
the daemon's error message is thrown and displayed directly.
2026-05-17 15:00:49 +08:00
Nicholas-XiongandGitHub 330a93116d fix: prevent horizontal overflow in split layout when iframe content exceeds viewport width (#1935)
Fixes #1929

Problem:
- When viewing HTML artifacts in preview mode, if iframe content width exceeds
  the available workspace width, the entire .split grid container expands
  beyond the viewport
- This pushes the left chat panel and top toolbar buttons outside the visible area
- Users cannot access chat or toolbar when viewing wide preview content

Root Cause:
- .split uses grid-template-columns: 460px 8px minmax(400px, 1fr)
- The third column minmax(400px, 1fr) expands to fit content
- No max-width or overflow constraint on .split container
- When iframe content is wider than viewport, grid expands to accommodate it
- Parent containers don't constrain the grid width

Solution:
- Add max-width: 100% to .split to constrain it to parent width
- Add overflow: hidden to prevent content from pushing layout
- Grid columns now stay within viewport bounds
- Only the iframe/preview area scrolls internally

Changes:
- Modified: apps/web/src/index.css
  - Added max-width: 100% to .split (line 1491)
  - Added overflow: hidden to .split (line 1492)

Impact:
- ✅ Fixes horizontal overflow when iframe content exceeds viewport width
- ✅ Chat panel stays visible and accessible
- ✅ Toolbar buttons remain in their intended positions
- ✅ Layout stays fixed to viewport width
- ✅ Only preview area scrolls internally
- ✅ No breaking changes to existing layouts
- ✅ Works with all viewport sizes

Testing:
1. Open any project and generate an HTML artifact (e.g., todo app)
2. Open the artifact in preview mode (desktop viewport)
3. Verify the layout stays within viewport width
4. Verify chat panel remains visible on the left
5. Verify toolbar buttons remain accessible at the top
6. Verify only the preview iframe scrolls horizontally if content is wide
7. Test with various artifact widths (narrow, normal, extra wide)
8. Test resize handle still works correctly

Before Fix:
- Wide iframe content pushes entire layout beyond viewport
- Chat panel disappears off-screen to the left
- Toolbar buttons disappear off-screen
- Horizontal scrollbar appears on entire page
- Poor user experience with wide content

After Fix:
- Layout stays fixed to viewport width
- Chat panel always visible
- Toolbar always accessible
- Only iframe scrolls internally
- Clean, predictable layout behavior
2026-05-17 14:57:33 +08:00
Nicholas-XiongandGitHub d54d3412d6 fix: wire onRenameProject through EntryShell to DesignsTab (#1882)
Fixes #1790

## Problem

Project rename does not take effect in Open Design 0.8.0. After entering
a new name and clicking OK, the project keeps its old name.

## Root Cause

The onRenameProject callback was broken in the prop chain:

App.tsx ──(handleRenameProject)──▶ EntryView ✅
EntryView ──(onRenameProject missing)──▶ EntryShell ❌
EntryShell ──(onRename not in Props)──▶ DesignsTab ❌
DesignsTab.commitRename() → onRename?.() → silent no-op ❌

EntryView received onRenameProject from App but never forwarded it to
EntryShell. Since EntryShell is what renders DesignsTab, DesignsTab
never received the onRename callback. Because the prop is typed optional
(onRename?:), the confirm handler's onRename?.(id, trimmed) call
silently no-ops — no error, no rename.

This was introduced when EntryShell was added to the 0.8.0 codebase as
an intermediate shell layer and the rename prop was missed during the
handoff.

## Solution

Wire the callback through the missing links:

1. EntryView.tsx: Pass onRenameProject={onRenameProject} to EntryShell
2. EntryShell.tsx:
   - Add onRenameProject to Props interface
   - Destructure it in function params
   - Pass onRename={onRenameProject} to DesignsTab

Now the callback chain is complete and project renames work correctly.

## Testing

Verified that:
- Project rename dialog accepts new name
- Clicking OK successfully renames the project
- Project list reflects the new name immediately
- No console errors or warnings

## Impact

3 lines changed across 2 files. Low risk — only restores the missing
prop forwarding, does not change any rename logic or validation.
2026-05-17 14:57:11 +08:00
7766582f0b chore(ci): scope nix-check workflow permissions to contents:read (#1870)
The other workflows under .github/workflows declare explicit
`permissions:` blocks that scope their GITHUB_TOKEN to the minimum
required (contents: read for build-only flows). `nix-check.yml` was
the lone outlier and inherited the repository's default token
permissions instead.

Add `permissions: { contents: read }` to align with the rest of the
workflow suite and follow GitHub's least-privilege workflow guidance.
No behavior change: the job only reads the repo, runs `nix flake
check`, and uploads a logs artifact on failure (which uses an action
that already declares its own permissions internally).

Co-authored-by: nicejames <nicejames@gmail.com>
2026-05-17 11:28:18 +08:00
e64f1d8497 fix(desktop): export PDF saves to a file instead of the OS print dialog (#1920)
* fix(desktop): export PDF saves to a file instead of the OS print dialog

The `od:print-pdf` IPC handler called `webContents.print()`, which
opens the printer-first macOS system print dialog. That handler is the
destination of the renderer's `window.__odDesktop.printPdf()` bridge,
so on desktop "Export PDF" felt like a print flow rather than a file
export — from both the PreviewModal share menu (which always uses this
path) and the FileViewer share menu (whose daemon-route fallback lands
here too).

Route the handler through a direct Save-as-PDF flow instead: a native
Save dialog, then `webContents.printToPDF()` straight to the chosen
file — the same shape `exportPdfFromHtml` already uses for the
daemon-backed export path. The flow is extracted into
`savePrintReadyDocumentAsPdf` behind a structural `PrintReadyPdfTarget`
surface that has no `print()` method, so the regression cannot be
reintroduced.

Fixes #1774

Co-authored-by: multica-agent <github@multica.ai>

* fix(desktop): preserve PDF page sizing in print bridge

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: multica-agent <github@multica.ai>
2026-05-17 11:26:08 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
5b7a2fdb2f Update docs/assets/github-metrics.svg (#1931)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-17 11:25:46 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
3c621131d2 docs(readme): refresh contributors wall (#1932)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-17 11:24:28 +08:00
Marc ChanandGitHub 6bf865a43b fix(ci): avoid duplicate nix-check runs on PR branches (#1917)
* fix(ci): avoid duplicate nix-check runs on PR branches

* fix(ci): keep nix-check on main pushes

Restore the nix-check push trigger for main-only updates while still avoiding duplicate PR-branch runs.

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
2026-05-16 23:38:50 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
cfd361af3a Update docs/assets/github-metrics.svg (#1915)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-16 22:45:00 +08:00
Marc ChanandGitHub 1f728ac8e3 fix(ci): only run docker image workflow for release tags (#1916) 2026-05-16 22:32:33 +08:00
440de58e10 docs(packaging): clarify Intel Mac ZIP support (#1874)
Co-authored-by: li9292 <li9292@li9292s-MacBook-Air.local>
2026-05-16 22:27:33 +08:00
Marc ChanandGitHub d6515643ef fix(ci): use open-design-bot for metrics PRs (#1910)
* fix(ci): use open-design-bot for metrics PRs

* fix(ci): restore metrics workflow app scopes

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
2026-05-16 21:52:37 +08:00
Yuhao ChenandGitHub 2e1dd497aa fix(landing): expose blog RSS feed alias (#1859) 2026-05-16 21:52:11 +08:00
laihenyiandGitHub 22e02446ef docs(i18n): add RTL_LOCALES UI guidance and fix Spanish es-ES alignment (#1908)
Three follow-up fixes for TRANSLATIONS.md from review of #1333:
- P1: Document RTL_LOCALES registration in index.tsx for UI runtime RTL
  (detailed steps, Arabic section, and FAQ — previously only covered
  Markdown auto-RTL)
- P2: Align Spanish terminology section with the repo's actual es-ES code
  (was recommending neutral/LatAm while dismissing Spain terms)
- Minor: Add "(if that file exists)" caveat to Quick Start link translation
  example, matching the detailed section

Refs: #1333, #195
2026-05-16 21:45:15 +08:00