mirror of
https://github.com/nexu-io/open-design.git
synced 2026-09-20 06:15:06 +08:00
codex/design-system-module-only
56 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e654592ba6 |
fix(daemon): point users at the Settings section that actually exists (#6831)
* fix(daemon): point users at the Settings section that actually exists
When image generation failed for a missing credential, the reply told
the user to configure it in "Settings → Media". No such nav item exists —
the section is "Media providers" ("媒体生成提供商" in zh-CN) — so users
following the instruction found nothing.
The cause is that Settings destinations were spelled independently
wherever a producer happened to need one: 29 provider errors in
apps/daemon/src/media/index.ts said a bare unnamed "Settings" (one said
"Settings -> Media Providers"), and the od-media-generation skill said
"Settings → Media". None of them were tied to the Settings dialog, so a
rename could not reach them.
packages/contracts/src/settings-nav.ts is now the single place a Settings
destination is spelled, and every producer reads it: the media provider
errors, the ElevenLabs voice-options prompt (daemon + contracts), and the
external-MCP auth guidance. e2e/tests/settings-nav-copy.test.ts holds the
constants against the labels apps/web actually renders and fails the
build if a producer re-inlines its own guess.
Swept the same drift class while here: both hatch-pet SKILL.md copies
pointed at "Settings → Pets", but #5517 folded the pet picker into
General, so the real path is "Settings → General → Pets".
Verified the gate red on the pre-fix tree (3 failing assertions) and
green after. Adjacent, not fixed: these strings are English and the
agent translates them ad hoc, so a localized client can still render a
section name that does not match its own UI — see the report.
Record: recvre8FrTE2Oa (V0.19.1 acceptance)
* fix(contracts): gate destinations on rendered nav, not the i18n dictionary
Review on #6831 caught that SETTINGS_EXTERNAL_MCP named a place users
cannot navigate to. `mcpClient` kept its Settings render block but lost
its sidebar nav item (SettingsDialog.tsx says so in its own comment), and
reconnecting an external MCP server now lives in the top-level
Integrations view. So the destination is not a Settings section at all.
The stale string predates this branch — it was hardcoded in
prompts/system.ts on main. But promoting it into a named constant made it
worse twice over: the docblock asserted "The Settings nav item where
external MCP servers are added/reconnected" in a canonical location, and
the new gate whitelisted it by construction, so the check built to catch
dead paths became the thing defending one.
The deeper defect was the gate's invariant. Comparing a constant to its
i18n key's value proves only that some dictionary entry matches — not
that anything renders it. `settings.externalMcpTitle` still resolves to
"External MCP" with no nav item behind it, which is exactly how the dead
path passed. The same hole covered SETTINGS_MEDIA_PROVIDERS.
Now the gate parses what the UI actually renders — `settings-nav-item`
buttons and INTEGRATION_TABS — and resolves those keys through the
dictionary, using it as a lookup rather than as the source of truth.
Verified by reintroducing "Settings → External MCP": the old gate passed
it, the new one fails with the rendered destinations listed.
Replaces SETTINGS_EXTERNAL_MCP with INTEGRATIONS_MCP_PATH
(`Integrations → MCP`) and adds a regression test pinning that a
dictionary-only label is rejected.
|
||
|
|
356c8c364f |
feat(workspace-team): team workspaces, shared resources, workspace-scoped billing, and the #5517 redesign (#6142)
* fix(web): scope plugin URL imports to workspace * test(web): cover billing interest remount lifecycle * feat(packaged): enable the workspace-team transport for test-profile builds The vela test backend now serves the workspace-team API, so a packaged build baked with the test AMR profile should drive team projects / collab / resource sharing there instead of leaving them dormant. Replace the single feature-test equality check with a profile -> vela web origin map so adding a backend is one entry, and keep every unlisted profile (prod above all) off. * test(daemon): cover billing catch-up after SSE reconnect * fix(collab): surface and start first materialization when opening a shared project QA P0: a brand-new member on a fresh install joins someone's workspace, opens a project from it, and sees no loading state and no files — content only appears on a SECOND open, much later. Two defects, both on the first `/collab/status` request that opening a shared project makes. 1. No pull is started. The daemon's self-materialization block was gated on `callerIsOwner`, so a non-owner member got the placeholder record registered and nothing else. The web's auto-pull is gated on `publishedVersion` advancing past its cursor, and a fresh daemon's first status response cannot carry a published head: `collab.publishedVersion()` reads an in-process map that has never been written, and the real hub head is fetched fire-and-forget into `headEnrichmentCache` for a LATER poll to consume. Materialization therefore arrived only whenever a proactive lane (hub push / reconnect catch-up / the 30s recovery floor) next fired — the "second open" the report describes. 2. No download state is shown. `useProjectCollab.downloadPending` — which picks DesignFilesPanel's "Syncing files from the team…" over its empty state and create-a-file CTAs — reads only `publishedVersion > cursor`, `contentTransferState`, and an in-flight pull. All three are blank on that first response, so the member was shown an empty project inviting them to start creating over content that was still on its way. The fix makes the placeholder stamp the load-bearing signal on both sides: - `materializePlaceholderOnOpen` (routes/collab-sync.ts) replaces the owner-only block: any viewer opening a shared project whose only local record is an unmaterialized placeholder starts its pull on that same request, through the same coalesced flow. The retracted-share heal in its catch stays owner-only — a member who hits the hub tombstone has merely lost access and must not unshare anyone's project. - `/collab/status` reports `awaitingFirstMaterialization`, a purely local, synchronous fact that needs no hub round-trip and is therefore available on the very first response. `od collab status` prints it too. - `localFilesAreNotTheContentYet` (useProjectCollab.ts) makes it always download-pending, bypassing the member-only `shouldAutoPull` gate: whether the local files are the content is a fact about the record, not about who may pull it, so the owner of an unmaterialized placeholder (the reinstall case, recvqzaDvUU6B3) stops seeing the same empty state too. Red evidence: all six new specs fail on origin/feat/workspace-team @ |
||
|
|
ebcba704ef |
feat(prompts): introduce on-demand discovery in SP v2.0 (#6223)
* feat(prompts): introduce on-demand discovery in SP v2.0 * fix(prompts): prevent nested deck label overlap * fix(plugins): stabilize od-default task routing * fix: address prompt and deck audit regressions * fix(prompts): restore plan mode precedence * fix(daemon): accept all form answer headers --------- Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> |
||
|
|
6b90486c97 |
docs: reconcile stale documentation with current code (#5829)
* fix(docs): align question guidance with form flow * docs: reconcile stale documentation with current code * fix(docs): remove retired template metadata from guides Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(e2e): stabilize visual workspace helper Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(docs): align localized template guide metadata Generated-By: looper 0.10.6 (runner=fixer, agent=codex) |
||
|
|
da7c4ae051 |
fix(web): rank Community "Newest" by shipped publishedAt, not local install timestamps (#5597)
* fix(web): rank Community "Newest" by shipped publishedAt, not local install timestamps
The Community gallery Newest toggle sorted by the installed-record
updatedAt/installedAt. Those are stamped when a machine seeds its own
database, so a fresh install (or an upgrade that re-stamps the catalog)
writes the whole bundled catalog milliseconds apart in folder-walk
order — Newest showed reverse walk order (roughly reverse-alphabetical),
unrelated to publication recency.
Root-cause fix: bundled templates now ship a real publication date.
- packages/contracts: add optional manifest field publishedAt (ISO 8601).
- apps/web sortByNewest: freshness = publishedAt when parseable, else
updatedAt (right signal for user-installed plugins); tie-breaks and
stability unchanged.
- plugins/_official: backfill publishedAt into all 460 bundled manifests
from each folder's first-appearance commit date in upstream git
history.
- e2e: repository-resource guard requiring every bundled manifest to
declare a parseable publishedAt, so the signal cannot silently erode.
- docs: field reference entries in plugins-spec (en + zh-CN).
Issue: https://plane.powerformer.net/open-design/projects/49832a02-3158-4faf-bf2f-d0e39c40c7e6/issues/ca0778af-97f5-4fc0-bc63-739280904979
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* worker: 模板用最新筛选,筛选出来的不是最新的
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* fix(web): keep shipped appeal order inside same-publishedAt batches
Review follow-up (#5597, nettee): after the freshness tie on an equal
publishedAt, the comparator still consulted local updatedAt/installedAt,
which a fresh install stamps in folder-walk order — so every
same-publication batch (largest: 322 manifests on one catalog date)
re-sorted per machine instead of keeping the shipped visual-appeal
ranking. Same-publishedAt records now preserve their incoming position;
local timestamps break ties only when at least one side has no usable
publishedAt. Adds the requested regression spec pinning
same-publishedAt / different-updatedAt records.
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* fix(web): gate publishedAt freshness to bundled records; untrack oversized looper attachment
Review follow-up (#5597, nettee round 2): publishedAt was overriding
updatedAt for every visible plugin, so a user-installed github/local/
marketplace plugin carrying an old manifest publishedAt would be buried
behind bundled templates despite a newer local install. publishedAtMs
now returns null for non-bundled records — "Newest" means install
recency for user installs, catalog publication for bundled ones. Adds
the requested regression (non-bundled, old publishedAt, newer
updatedAt) and clarifies the field docs (en + zh-CN).
CI repair: commit
|
||
|
|
bc6a246c65 |
feat(slides): enhance deck project experience (#5083)
* feat(deck): enhance slide deck functionality with speaker notes and navigation improvements - Added a switch for including speaker notes in slide decks, defaulting to true. - Updated keyboard navigation to include 'R' for resetting to the first slide. - Implemented click navigation for half-slide transitions. - Enhanced the deck framework to support hidden programmatic prev/next controls. - Improved handling of file inputs in question forms to support file submissions. This update aims to improve user experience in creating and presenting slide decks, ensuring better accessibility and functionality. * feat(artifacts): enforce semantic naming for user-facing deliverables - Updated guidelines to require semantic filenames derived from user briefs for new artifacts, moving away from defaulting to `index.html`. - Enhanced documentation to clarify naming conventions for HTML files, emphasizing the use of descriptive names like `investor-pitch-deck.html`. - Adjusted prompts and hints across the system to reflect these changes, ensuring consistency in user-facing outputs. - Improved test coverage to validate the new naming conventions and ensure proper implementation in various contexts. This update aims to enhance clarity and usability in project file management, promoting better organization and user experience. * feat(file-viewer): enhance speaker notes display and improve file workspace functionality - Updated the speaker notes section to include a styled placeholder for empty notes, improving user experience. - Changed the icon in the file workspace from "slides" to "panel-left" for better clarity. - Introduced new sub-category filtering options in the file workspace, enhancing organization and navigation. - Improved styling for the page creator search input and added visual feedback for loading states. These changes aim to enhance usability and visual consistency across the file viewer and workspace components. * test(web): align workspace tests with pages switcher * test(e2e): open design files through pages menu * fix(deck): keep source mode reachable * fix(workspace): restore uploaded file tabs * feat(deck-thumbnail): implement virtualized thumbnail rail for improved performance - Introduced a new `DeckThumbnailRail` component to optimize the rendering of deck thumbnails, reducing memory usage and improving load times. - Enhanced the `FileViewer` to integrate the new thumbnail rail, allowing for lazy loading of thumbnails based on viewport visibility. - Added tests for the `DeckThumbnailRail` to ensure correct functionality and caching behavior. - Updated styles for better visual consistency and performance during thumbnail rendering. These changes aim to enhance user experience by providing a smoother and more efficient way to navigate through deck slides. * feat(deck): enhance deck rendering with thumbnail support and keyboard shortcuts - Integrated `DeckSlideThumbnail` for rendering individual slides in a shadow root, improving performance and reducing main-thread load. - Updated `DeckThumbnailRail` to utilize the new thumbnail component, allowing for efficient slide navigation. - Implemented keyboard shortcuts for deck navigation, enhancing user experience during presentations. - Added tests for `buildDeckRenderInput` to ensure proper functionality of the deck stage fallback. - Improved styling for loading states in the viewer, providing a smoother visual experience. These changes aim to optimize the deck viewing experience by reducing resource consumption and enhancing interactivity. * feat(deck): improve thumbnail loading and speaker notes editing experience - Refactored `DeckSlideThumbnail` to enhance loading states with a new shimmer effect, improving visual feedback during thumbnail rendering. - Updated `DeckThumbnailRail` to manage loading states for thumbnails, ensuring a smoother user experience. - Simplified the speaker notes editing interface by removing the toggle switch, allowing direct editing from the notes body. - Enhanced accessibility by adding roles and focus states to speaker notes elements. - Added tests to verify the new loading states and speaker notes functionality. These changes aim to optimize the user experience in deck navigation and speaker notes management, providing a more intuitive and responsive interface. * feat(file-viewer): enhance version export functionality and speaker notes interaction - Introduced new export options for file versions, including PDF and image formats, improving the ability to download and share content. - Implemented a streamlined process for exporting version content, with progress indicators and error handling for a better user experience. - Enhanced speaker notes editing by refining event handling to prevent unintended focus shifts, ensuring a smoother editing experience. - Updated styles for improved visual consistency in the file version download interface. - Added tests to verify the functionality of version exports and speaker notes interactions. These changes aim to optimize the file viewer's usability and enhance the overall experience when managing and exporting project files. * fix(web): polish export menus and creator filters * fix(file-viewer): fall back to preview exports * test(file-viewer): cover version export fallbacks * test(file-viewer): assert loading skeleton by role * fix(file-viewer): restore html source mode affordance * fix(file-viewer): capture full version fallback snapshots * docs: trim slides handoff eof * test(exports): cover full preview snapshot requests * test(file-viewer): account for snapshot options arg * refactor(file-viewer, file-workspace): streamline export functions and enhance page creator dialog visibility * test(file-workspace): enhance slide template creation and mock plugin responses * feat(export): add support for versioned exports and enhance HTML export functionality * feat(export): implement versioned export support across multiple formats and enhance related tests * feat(file-viewer): enhance manual edit functionality with commit sequence tracking and add test for inline text session saving * style(speaker-notes): update filmstrip and thumb-frame styles for improved responsiveness and add corresponding tests * feat(file-viewer): enhance comment composer functionality with portal metrics and improve draw toolbar layout for mobile views * feat(analytics): track slide deck viewing experience Add analytics for the new deck/slides experience introduced in this PR: the deck viewer surface, in-deck slide navigation, thumbnail rail, and speaker-notes authoring. Presentation entry stays on the existing present_popover click to avoid double-counting. - contracts: DeckViewerSurfaceViewProps (surface_view), DeckViewerClickProps (ui_click), SpeakerNotesSaveResultProps (new speaker_notes_save_result event), wired into the event unions. - web: track* wrappers + fire helpers in FileViewer — deck_viewer surface_view on deck mount, slide_prev/next/reset, thumbnail_select, thumbnail_rail_toggle (expand/collapse), speaker_notes_edit, and speaker_notes_save_result (preview + presenter surfaces). - tests: deck analytics suite asserting the emitted (event, props) pairs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(file-viewer, file-workspace): enhance export toast functionality and improve localization for page creation * feat(home-view, plugins-home-section, agent-skill): update default facet preference, enhance category selection handling, and improve localization support - Set `preferDefaultFacet` to true in HomeView component for better user experience. - Introduced `handlePickCategory` function in PluginsHomeSection to manage category selection based on card layout visibility. - Updated PRIMARY_CATEGORIES to reflect the new order and added localization for titles and descriptions in adaptAgentSkill. - Enhanced tests to verify the correct handling of display copy and tags from SKILL frontmatter. * feat(plugins-home, file-workspace): introduce commercial category labels and enhance deck handling - Added a new module for resolving and localizing commercial category labels for plugins. - Updated the FileWorkspace and PluginCard components to display the commercial category label on deck cards. - Enhanced the PageCreatorPresetFrame to adjust frame classes based on deck presets. - Refactored subcategory handling in facets to align with the new commercial category taxonomy. - Improved localization support for new category labels across multiple languages. * feat(deck-preview): implement deck preview scaling and enhance home hero layout - Introduced `useDeckPreviewScale` hook to manage scaling of deck previews within a fixed 1280×720 logical viewport, ensuring proportional rendering across various templates. - Updated `FileWorkspace`, `HomeHero`, and `PluginCard` components to utilize the new scaling functionality for improved visual consistency. - Enhanced the layout of the home hero section to accommodate new subtype chips and descriptions, including a "More" dropdown for overflow handling. - Improved localization support for new UI elements across multiple languages. * fix(PreviewModal): clarify sidebar prop documentation and update test description - Updated the documentation for the `PreviewSidebar` interface to specify that the sidebar's stage-edge handles are not shown when the sidebar prop is absent. - Modified the test suite description for `PreviewModal` to be more concise and relevant. * test(e2e): select prototype visual card --------- Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
323246a64c |
Website Clone: first-party Home entry, fidelity, real-clone example cards + tracking (#5178)
* Add Website Clone home entry with bundled web-clone skill and root-relative asset preview fix
* Retrigger CI
* Open the site entry after website-clone turns
* Harden web-clone skill asset and color fidelity
Recon now scrolls the full page and captures @font-face rules, real font/image
resource URLs, computed section palette, and resolved root variables. Asset
harvest is rebuilt on the browser network stack so cross-origin CDN images,
fonts, and media (hotlink-protected included) all land locally, with a
self-hosted fonts.css and an originalUrl→localPath manifest. Clone audit gains
--recon --strict fidelity gates (fonts self-hosted, images downloaded, key
section colors exact) that exit 2 on violations, and SKILL.md makes all three
a mandatory delivery gate.
* Default web-clone mode to faithful reproduction when unconfirmed
A real nike.com run showed the agent silently downgrading to visual-homage
mode (placeholder brand, typography blocks instead of photography, approximated
palette) because the user skipped the turn-1 confirmations and the site was a
copyright-heavy commercial SPA. Fidelity is the point of this scenario: default
to faithful reproduction, land real assets first, record trademark/copyright
replacements as a pre-deploy checklist for the user to decide in Step 6, and
never skip script recon just because the target looks bot-sensitive.
* Streamline web-clone runs: skip discovery with URL, exempt brand constraints, actionable playwright setup
Three run-path optimizations for the Website Clone scenario:
1. POST /api/projects derives metadata.skipDiscoveryBrief for web-clone
projects whose pending prompt already carries the target URL — the URL is
the brief, so the turn-1 question form no longer stalls the run (an
explicit client flag still wins). Covered by
project-create-web-clone-discovery.test.ts.
2. Prompt composition skips the design-system authoritative block and craft
rules for intent=web-clone runs: the fidelity target is the original
site, not the project brand; brand application belongs to the skill's
Step 6 replacement phase.
3. The plugin's playwright-loader now also resolves from the process cwd
(so 'npm i -D playwright' in the project root works for scripts staged
under .od-skills/) and fails with exact fix commands; SKILL.md documents
the staged-path resolution and forbids downgrading to eyeballing because
of missing deps.
* Swap the copyright guardrail for faithful reproduction on web-clone runs
The official designer prompt's 'don't recreate copyrighted designs — help
the user build something original instead' bullet made web-clone agents
silently rebrand clones (Nike → placeholder brand, original SVGs instead of
real photography) even after the skill mandated faithful defaults: a system
prompt guardrail outranks skill blocks. For intent=web-clone runs the bullet
is swapped for a faithful-reproduction rule that routes trademark/copyright
caution through a pre-deploy replacement checklist (NOTES.md) the user owns.
Prompt tests guard both directions of the substitution.
Also: recon now captures scroll-feel signals (scroll-behavior, scroll-snap
rule count, sticky/fixed census) and SKILL.md makes matching the original's
scroll behavior (smooth-scroll libs, snap, sticky) a fidelity requirement.
* Extract web-clone into a shared global skill referenced by ref
The Website Clone workflow (SKILL.md + 14 recon/harvest/audit scripts +
references) moves from the example-web-clone plugin into the global skill
registry at skills/web-clone/. example-web-clone now references it via
od.context.skills:[{ref:'web-clone'}] instead of shipping its own copy, so the
upcoming per-site clone example plugins can all share one skill rather than
each duplicating a 16KB SKILL.md and its scripts.
Pinned-plugin skill resolution (server.ts) previously only loaded a plugin's
LOCAL ./SKILL.md; a {ref} skill loaded nothing, so the body never entered the
prompt and the scripts never staged. It now falls back to resolving the ref
against the global registry, loading the body and registering the skill dir for
cwd staging. Verified end-to-end in a live run: skills/web-clone stages to
.od-skills/web-clone-<hash>/ with SKILL.md + all scripts.
guard.ts residual-JS allowlist follows the scripts to their new home; a
structural test locks the manifest<->skill contract.
* Add 7 Website Clone example-prompt cards for the Home clone rail
nexu.io, open-design.ai, anthropic.com, vercel.com, resend.com, linear.app,
raycast.com — each a thin example plugin that references the shared web-clone
global skill (od.context.skills:[{ref:'web-clone'}]) so none duplicate the
workflow. Each seeds the composer with a faithful-clone prompt for its URL and
ships a self-contained example.html preview built from a real recon capture of
the target homepage, so the gallery card shows what the card clones. They
surface under the Website clone chip's example-prompt rail (verified in a live
desktop run) and inherit the chip's intent:'web-clone' metadata, so clicking one
runs through the full fidelity path (skip discovery, brand exemption, faithful
reproduction, script recon/harvest/audit).
* Polish clone example-card previews with a framed hero capture
The first pass inlined a downscaled full-page screenshot cropped mid-content —
it read as a raw screenshot dump. Each preview is now a crisp above-the-fold
hero capture (1440x900 DPR2, 16:10) presented inside a browser-window chrome
(traffic lights + host URL pill) on a brand-tinted gradient, so the gallery
card reads as an intentional site preview. Verified by rendering the previews
headless.
* Cache the plugin list so Home remounts don't grey the create rail
HomeView re-fetched + parsed the large /api/plugins payload on every remount,
leaving the create-rail chips disabled for 1-2s each time. A module-level cache
(listPluginsFresh, 10s TTL) serves warm mounts without the network round trip so
pluginsLoading clears within a frame; the first render stays cheap (empty list)
to keep the click off the critical path. Also hide the base example-web-clone
plugin from the example rail (the per-site clone-* cards are the real examples).
* Ship real self-contained clones as example-card previews + align seed prompt
Each clone-* example.html is now a real, self-contained reproduction of its
target site (inlined CSS/fonts/images via document.styleSheets serialization so
CSS-in-JS/Next.js SPAs like Vercel/Raycast capture correctly, oversized icon
sprites dropped, rasters downscaled to stay under the 5MB preview cap, plus a
scroll-reveal motion layer). Preview renders the real HTML; Remix copies it into
a project as index.html. Manifests reuse the base web-clone useCase.query with a
{{targetUrl}} default per site, so picking a card seeds the same preset prompt
with the URL filled in instead of the marketing description.
* Shrink clone example previews ~33% (dedup + drop EOT + WebP)
Three lossless-to-near-lossless passes on the self-contained clones:
- Dedup repeated data-URIs (same image used in <img> + css url() N times): store
each once as a :root CSS var, point url() at var(), hydrate img[src] from the
var via a tiny script. Resend alone shed 1.8MB.
- Drop leftover EOT/fontobject font data-URIs (IE-only, redundant with woff2).
- Re-encode inlined raster images to WebP (~50% smaller than JPEG at equivalent
quality) via cwebp q72.
Total across the 7 cards: ~23MB → ~15.5MB, every card now under 3MB (was up to
5MB). Image hydration + fidelity verified by headless render.
* Lead create rail with Website clone; seed example cards with just the URL
- Move 'web-clone' to the front of CREATE_RAIL_ORDER so Website clone is the
first create-rail card, ahead of Slides (deck).
- Website-clone example cards (Clone Nexu, Clone Vercel, …) now seed the
composer with the same short 'clone this site: <url>' scaffold the chip uses
(localized webClonePromptSeed prefix + the card's targetUrl), e.g.
'Website URL to clone: https://nexu.io', instead of the multi-paragraph
build spec. Picking the chip with an empty composer already seeds the bare
prefix for the user to paste a URL after.
- Fix a test-only regression from the Home plugin-list cache: the module-level
visible-plugins cache leaked a case's mocked /api/plugins payload into later
cases via listPluginsFresh, greying the rail / stranding scenarios on
'Template None'. Add resetPluginsCache() and clear it in a global afterEach.
* Track web-clone example-card picks (example_prompt / example_open_project)
The Website-clone example cards (Clone Nexu / Vercel / …) had no analytics on
pick or remix, so the site-clone funnel could not be broken down per example.
Wire the two clicks the contracts already type (埋点文档 row 116):
- useExamplePlugin → ui_click area=chat_composer element=example_prompt
- duplicateExamplePlugin (Remix) → element=example_open_project
Both carry chip_id (web-clone) + plugin_id (example-clone-<site>) + plugin_type
for per-site breakdown. The created project's own project_kind=web_clone (already
derived from metadata.intent via projectKindToTracking) still rides
project_create_result / run_created, so 'how many projects are website clones' is
answerable without extra work. No contracts change — the element enum and the
web_clone project_kind already existed. Adds a behavioral test asserting both
events fire with the right triplet + attribution.
* Mirror web-clone copyright-guardrail swap into contracts/BYOK prompt
PR #5178 blocking review (nettee/looper): the daemon prompt special-cases
intent='web-clone' (faithful-reproduction rule) but the contracts prompt stack —
which apps/web uses for API/BYOK runs — imported OFFICIAL_DESIGNER_PROMPT directly
and never routed web-clone, so BYOK website-clone runs kept the original 'build
something original' guardrail. Daemon and BYOK now behave identically:
- contracts/prompts/official-system.ts: add COPYRIGHT_GUARDRAIL_BULLET,
WEB_CLONE_COPYRIGHT_GUARDRAIL_BULLET, renderOfficialDesignerPrompt (mirrors the
daemon renderer; contracts base has no execution placeholders so it only swaps
the bullet).
- contracts/prompts/system.ts: composeSystemPrompt routes the charter through
renderOfficialDesignerPrompt({ webCloneFidelity: metadata.intent==='web-clone' }).
- Add system-prompt-web-clone.test.ts covering both modes + the byte-identical
bullet guard.
* Complete web-clone BYOK prompt parity + rebase relative JS asset refs
Two remaining blocking issues from PR #5178 looper re-review:
1. contracts composeSystemPrompt still appended the active-design-system
'authoritative' block + visual-direction override unconditionally, while the
daemon suppresses both for intent==='web-clone'. A BYOK web-clone run with an
active design system was still told the design system wins, fighting faithful
reproduction. Gate both sections behind !isWebCloneRun; add contracts tests
asserting web-clone BYOK prompts drop the design-system guidance.
2. rewriteInlinedScriptAssetRefs only handled root-relative literals. When
js/app.js is inlined into the HTML entry, a sibling lookup like
fetch('./data.json') / new Worker('./worker.js') / import('./chunk.js')
resolved against the HTML root instead of js/. Take the source script path and
rebase confirmed relative refs against it (mirrors the CSS pass), membership-
confirmed; add unit cases for ./sibling, ../parent, and escaping/missing.
* Website-clone examples: plain text prompt cards, drop embedded HTML + Remix
The 7 site example cards embedded a full self-contained clone of each target site
(anthropic.com, vercel.com, …) as example.html and offered a one-click Remix that
copied that markup into a project. Shipping verbatim copies of other companies'
sites is an IP risk, so replace them with plain text prompt cards:
- Delete plugins/_official/examples/clone-* (7 dirs, incl. the example.html
reproductions and the Remix-enabling preview.entry).
- Add a 'web-clone' entry to HOME_PROMPT_EXAMPLES (en + zh-CN, others fall back to
en): 7 text cards that fill the composer with 'Website URL to clone: <url>'.
With the site plugins gone, the web-clone chip's preset rail is empty so these
static text cards render instead. Clicking one fills the URL prompt and (via
the existing usePromptExample) still fires ui_click element=example_prompt
chip_id=web-clone — no plugin_id / no Remix / no example_open_project.
- Remove the now-dead webCloneCardTargetUrl seed override; refresh stale comments.
- Rewrite HomeView.web-clone-tracking test for the text-card path (asserts text
cards render, no plugin-preset / no remix affordance, and the pick still tracks).
The base example-web-clone skill + web-clone run behavior (intent, fidelity
prompt, discovery skip) are unchanged.
* Give web-clone example cards a site logo + domain, not raw prompt text
The 7 Website-clone examples rendered as near-identical white boxes each showing
'Website URL to clone: https://<site>' — visually flat and hard to scan. Render
them as a logo gallery instead: each card shows the site's own favicon (resolved
at render time via a public favicon service — no third-party brand assets are
bundled) in a rounded tile above the bare domain (nexu.io, vercel.com, …). A
blocked/failed icon fetch falls back to a lettered monogram tile. Click behavior
is unchanged: the full 'Website URL to clone: <url>' prompt is still what fills
the composer and fires ui_click element=example_prompt. Non-URL prompt examples
(other chips) keep the plain text card.
* Web-clone examples: keep only open-design, add kimi
Legal review flagged brand-copy risk in the example rail. Drop the
nexu / anthropic / vercel / resend / linear / raycast site prompts and
keep just open-design.ai plus kimi.com (official Kimi partnership).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
e02a36f51c |
feat(examples): add Open Design homepage — interactive 3D showcase (#5355)
* feat(examples): add Open Design homepage — interactive 3D showcase Adds the live open-design.ai homepage as a first-party, self-contained example: an interactive React Three Fiber / Next.js hero with a real-time 3D "Open Design" wordmark, sticker collage, variable fonts, cursor parallax, and scroll-driven motion. Renders in the sandboxed powered preview. Made repo- and preview-safe without touching the app's runtime: - 3D geometry Draco-compressed (KHR_draco_mesh_compression): hero wordmark 4.4MB -> 300KB, cnt 2.2MB -> 548KB, decoded by the bundled DRACOLoader. Visually identical (verified). - Work/sticker imagery converted to LOSSLESS WebP: pixel-identical to the source PNGs (alpha + visible-pixel diff = 0), 12.2MB -> 7.1MB. - Every file now < 1MB, so the template is fully self-contained in-repo with no external asset host. - Path-portable so it renders from the nested preview subpath, not just the site root: absolute asset paths made relative; font/bgm URLs derived from document.baseURI instead of window.location.origin; App-Router createHrefFromUrl pinned to "/" and history push/replaceState URL neutralized so hydration matches and baseURI stays put (fixes the React #418 + broken relative-asset resolution seen when serving a Next RSC bundle from a subpath). Verified end-to-end from a deep subpath: 3 Draco models + 41 WebP + 3 fonts load, zero 404s, zero console errors, no hydration error, interactive (scroll/cursor). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(examples): list the full asset set in open-design homepage manifest Addresses review: od.context.assets previously listed only the design assets (models, fonts, imagery, bgm) and omitted the Next runtime chunks under assets/_next/. Applying the plugin would stage an incomplete copy of the static export, missing the runtime files example.html needs to render. Now lists every file the entry requires (example.html + all 54 files under assets/, including the _next chunks + css). Also cleaned up the truncated od.useCase.query text into a complete sentence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(examples): complete the open-design homepage asset closure Addresses the review's local-asset-closure blocker (three dangling references the mirror never captured): - Restore the Next polyfills chunk assets/_next/.../a6dad97d9634a72d.js (referenced by the noModule fallback script; modern browsers skip it, so it never 404'd at runtime but left the closure incomplete). - The work grid's passcode-protected /2026 tile pointed at work/tt01|tt02 images that were never in any mirror source (they 404 on the live site too). Add lockscreen placeholder images in the site palette so the reference resolves and — importantly — the client work data still matches the server-rendered HTML (removing the tile instead reintroduced a React #418 text hydration mismatch). - od.context.assets now lists the full closure (58 entries). Also corrected the manifest/SKILL 'zero external dependencies' wording: the Draco decoder is fetched from Google's gstatic CDN on demand (same pattern as the other WebGL examples); everything else is bundled locally. Re-verified from a preview subpath: 3 Draco models + fonts + imagery load, zero local 404s, zero console errors, no #418. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(examples): remove third-party network calls + committed key from homepage bundle Addresses review: the bundled preview shipped two undisclosed external requests, contradicting the manifest/SKILL 'only Draco loads externally'. - useWeather() made a live QWeather request with a hardcoded API key (devapi.qweather.com/...&key=...) to append a live temperature to the clock HUD. Replaced the fetch with static data ({now:{temp:"19"}}) — no network call, key removed from the bundle. The HUD still shows a temperature (static, as befits a mirror showcase). - Removed the Vercel toolbar injection IIFE (vercel.live/_next-live/ feedback/feedback.js + a data-deployment-id). It was cookie-gated to Vercel team members so it never fired in preview, but it left a committed external endpoint in a first-party plugin. Re-verified from a preview subpath: the ONLY external request is now the gstatic Draco decoder (as the manifest states); 3 models + fonts + imagery load, zero local 404s, zero console errors, no #418. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Tuola Ge <gexingli@refly.ai> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
49d64f0e8c |
fix(examples): resize WebGL canvases lazily in the render loop (#5327)
The powered-preview iframe can finish loading while its viewport is still 0x0 (hidden/animating dialog). Every WebGL example sized its canvas once at init plus on window resize, so when no resize event is delivered after the dialog settles, the drawing buffer stays 0x0 and the preview renders black until something (e.g. opening the plugin-info panel) changes the iframe width. Guard each resize handler to no-op when dimensions are unchanged and call it from the render loop, so the canvas self-heals within one frame of the iframe getting its real size — no reliance on resize events. Applies to all 15 webgl-* examples. Reported by QA: preview stays black until fullscreen/plugin-info is toggled. Co-authored-by: Tuola Ge <gexingli@refly.ai> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
7d005a17c3 |
feat(examples): add 10 WebGL example templates (#5312)
* feat(examples): add 10 WebGL example templates Adds 10 first-party powered-preview WebGL examples under plugins/_official/examples, each a self-contained dir (SKILL.md + example.html + open-design.json, self-contained i18n): C-tier — faithful Codrops ports (MIT + credit + LICENSE; original imagery): webgl-depth-gallery, webgl-pixel-reveal-gallery, webgl-horizontal-parallax, webgl-distortion-grain D-tier — original self-contained WebGL2 shader heroes (no third-party assets): webgl-caustic-pool, webgl-halftone-drift, webgl-holographic-foil, webgl-voronoi-cells, webgl-aurora-veil, webgl-liquid-iridescence All changed files are <1MB (pass the blob-size gate). The two large mirror showcases (oryzo, opendesign) are deferred: they exceed the 1MB blob guard and need their heavy assets moved to repository-assets R2 (per the gate's guidance). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(examples): stop shader setup after WebGL2 fallback message Wrap each pure-shader example script in an IIFE and return early when getContext('webgl2') is unavailable, so unsupported environments settle on the fallback message instead of throwing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Tuola Ge <gexingli@refly.ai> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
956b6607f5 |
feat(preview): add powered WebGL previews and examples (#5266)
* feat(powered-preview): implement cross-origin isolation for WebGL and Worker artifacts - Introduced a new powered preview feature that allows rendering HTML artifacts in a cross-origin-isolated iframe, enabling the use of Web Workers, WASM, and SharedArrayBuffer. - Added API endpoint `/api/preview/isolation` to report the daemon's directly-reachable HTTP origin for rendering. - Implemented logic in the file viewer to determine if an artifact requires powered preview based on its content. - Updated the file serving routes to support powered preview, ensuring proper headers are set for cross-origin isolation. - Enhanced the user interface to include new scenarios for WebGL and Worker visualizations in the home hero section, with corresponding translations and descriptions. This feature addresses the limitations of the opaque-origin preview sandbox, allowing for more complex GPU and compute applications to function correctly. * feat(preview): add WebGL templates and lazy HTML previews * test(web): stabilize project back routing assertion * fix(preview): address powered preview review blockers * fix(preview): isolate powered preview origin |
||
|
|
390fcf88f3 |
fix(plugin-previews): keep Community gallery previews in sync with shipped plugins (#5262)
* fix(plugin-previews): validate baked preview metadata against shipped plugins The Home Community gallery renders whatever data/plugin-previews/manifest.json names, and nothing kept that metadata in sync with reality: #4815 deleted 19 example plugins but left all 19 manifest entries behind, #4040 shipped a card showing another plugin's imagery, a failed re-bake silently leaves the old clip serving outdated content, and durationMs recorded the intended walk time rather than the encoded file (23 entries carried holdMs > real duration, so the card's idle loop pointed past the end of the clip). - add scripts/check-plugin-preview-manifest.ts to pnpm guard: every manifest entry must name a shipped plugin, own its clip keys (<id>/<hash>/... or the legacy <id>.<hash>....), carry a coherent fingerprint, and never share a clip with another entry; prune the 19 orphaned entries it caught - bake validation (BAKE_VERSION 5): reject blank clips (whole-clip luma range via ffprobe signalstats), record durationMs from the encoded file, clamp holdMs to it, and write a bake-report.json naming skipped/stale/blank plugins instead of swallowing the failure - strict mode (--strict / PREVIEW_STRICT=1) fails the run when a bake left broken metadata behind; the pre-merge validation workflow now runs strict while the post-merge/nightly publishers stay lenient * fix(plugins): make the hyperframes example self-contained The example loaded cdn.tailwindcss.com (a render-blocking head script the page never used — every style is inline) plus Google Fonts. Inside the sandboxed gallery iframe or on a slow network the stalled script showed a long blank instead of the composition, and the CI bake raced the webfonts. Drop both: the page now renders from local system font stacks with zero external requests, so the live preview, the detail iframe, and the baked clip all show the same content. * fix(plugin-previews): address review — fail fast on probe errors, widen strict trigger paths - probeClipMs/clipLumaRange now throw instead of returning null: ffprobe is required validation infrastructure, and a swallowed probe error silently disabled exactly the checks this PR adds. A thrown error becomes an 'error …' skip, is recorded in bake-report.json under 'errors', and fails strict mode — while the routine skips every sweep has (non-html plugins 404ing the preview route) still never trip strict. - bake-plugin-previews-pr.yml now also triggers on plugins/community/**, .github/actions/bake-previews/**, and itself, so community-plugin preview changes and bake-recipe changes cannot merge without the strict pre-merge validation. * fix(plugin-previews): bake static pages as a held still instead of skipping forever The strict pre-merge bake on this PR caught five manifest entries that could NEVER refresh: example-dating-web, example-html-ppt-zhangzara-8-bit-orbit, example-frame-logo-outro, od-new-generation, example-orbit-notion. All five are (near-)static pages — the CDP screencast only delivers frames when something repaints, so they produce 1-4 frames and the old 'frames < 5' guard skipped them on every bake, nightly included, leaving their committed entries permanently stale (their old clips are the 103-210ms degenerate files in the manifest today). Encode <5-frame captures as a still instead: hold the last frame for the idle-loop span (half before the trailing repeated concat entry, half inherited by it, summing to ~HOLD_MS). Only a zero-frame capture is a real failure now. The blank-luma check still rejects stills of nothing. * fix(plugin-previews): never persist a manifest entry without a fingerprint When the preview fingerprint fetch failed, the loop still rendered and — on an otherwise successful bake — persisted an entry with hash: null and un-fingerprinted keys: metadata the content-hash reuse skip can never match again and the new manifest guard rejects. Treat a missing fingerprint as an infrastructure error instead: skip the plugin, record it under errors in bake-report.json (strict mode exits non-zero), and leave any committed entry untouched for the next sweep. --------- Co-authored-by: Tuola Ge <gexingli@refly.ai> |
||
|
|
54de349c47 |
fix: replace expired Discord invite (#4849)
Co-authored-by: koki yanlai xu <koki@kokideMacBook-Air.local> |
||
|
|
1319bcef2e |
chore: prune curated official example plugins (#4815)
Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com> |
||
|
|
29b138f7a3 |
feat(brands): turn any brand into a reusable design system (#4691)
* Implement brand management routes and CLI support - Added `brand-routes.ts` to handle HTTP endpoints for brand operations: listing, extracting, retrieving details, deleting, and serving logos. - Introduced `brands-cli-help.ts` for CLI commands related to brand management, including usage instructions for listing, creating, retrieving, and deleting brands. - Updated `cli.ts` to integrate brand commands into the existing CLI structure, allowing headless management of brands via the command line. - Created supporting files for brand metadata handling, including `design-md.ts` for rendering brand information in markdown format and `index.ts` for the brand engine API. - Implemented `prefetch.ts` to fetch and process brand material from specified URLs, ensuring a streamlined extraction process. - Enhanced server setup in `server.ts` to register brand routes and manage brand-related data effectively. This commit establishes a comprehensive framework for managing brands within the application, facilitating both HTTP and CLI interactions. * Enhance memory management and onboarding experience - Introduced canonical profile labels to ensure consistent handling of user input in profile forms, preventing duplicate entries. - Updated the `parseProfileBody` and `captureProfileFromForm` functions to utilize the new canonical label matching. - Added a memory callout section in the onboarding view to highlight the benefits of memory usage, including personalized responses and reduced setup questions. - Implemented new UI elements in the onboarding view to improve user engagement with memory features. - Expanded i18n support for new onboarding messages related to memory benefits across multiple languages. * Refactor onboarding flow and enhance design system integration - Updated the onboarding process to include a new brand extraction step, replacing the previous newsletter step. - Adjusted the tracking logic to reflect the new onboarding steps, ensuring accurate analytics for user progress. - Improved the UI for the onboarding view, including new input fields for email collection during the brand extraction phase. - Refined the EntryShell component to remove outdated comments and clarify the onboarding renderer's purpose. - Enhanced CSS styles for the onboarding steps to improve layout and user experience. - Updated internationalization strings across multiple languages to reflect changes in the onboarding flow and brand extraction messaging. * Add brand management features and enhance font handling - Introduced new modules for managing brand assets, including `chrome.ts` for headless Chrome operations and `fonts.ts` for self-hosting web fonts. - Implemented `prefetch.ts` to streamline the brand material extraction process, allowing for efficient harvesting of colors, fonts, and logos. - Enhanced the brand system with new schema definitions in `schema.ts` to support brand color and font management. - Developed the `engine` module to integrate brand building and rendering processes, including token derivation and artifact generation. - Improved the overall structure and organization of brand-related files for better maintainability and scalability. * Enhance brand extraction and project management features - Updated `brand-routes.ts` to include new dependencies for project management, allowing for the registration of brand-related projects. - Modified the `extractBrand` function to support project ID and system files, improving the brand extraction process. - Enhanced the CLI commands in `cli.ts` to handle project IDs during brand creation, enabling better tracking of brand projects. - Updated the server setup in `server.ts` to register new project-related routes. - Improved the UI components to display project information associated with brands, including buttons for opening projects in the `BrandDetailView` and `BrandsTab`. - Added new metadata fields in the contracts to support project tracking and management for brands. This commit establishes a more robust framework for managing brand projects, enhancing both backend and frontend functionalities. * Enhance onboarding profile management and memory persistence - Added new canonical profile labels for 'Organization size', 'Use cases', and 'Discovery source' to improve user input consistency. - Introduced `OnboardingProfileState` type to manage onboarding profile data more effectively. - Implemented functions to build and persist the onboarding profile body to memory, ensuring user selections are saved accurately. - Updated the `OnboardingView` component to handle profile persistence during navigation and submission steps. - Enhanced tests to verify that user selections are correctly persisted to the memory profile. This commit improves the onboarding experience by ensuring that user inputs are consistently captured and stored, enhancing overall user engagement with the application. * Reflow brand extraction into an agent-driven, live flow Replace the deterministic SSE prefetch/preview/system pipeline with an agent-driven extraction: POST /api/brands now reserves the brand and stands up a backing project with the target site open in an in-app browser tab plus a seeded prompt, so the agent measures, synthesizes brand.json incrementally, and the user can clear anti-bot walls by hand. New /preview and /finalize routes let the agent render the kit page live and register the resulting user:<id> design system, so extracted brand facts persist as a structured, reusable brand kit instead of a one-shot deterministic guess. Adds the brand-extract skill (SKILL.md + brand-kit.html template), kit-render engine, brand-extraction-engine tests, brand project covers in the Designs tab, onboarding extract handoff, and the matching od brand extract/preview/ finalize CLI subcommands and contract updates. Co-authored-by: Cursor <cursoragent@cursor.com> * Sediment finalized brands into structured memory Reflow a finalized brand into the memory store (brandToMemoryEntries + reflowBrandToMemory) so future chats can ground vague requests in the brand's palette, type, voice and rules. finalizeBrand now wires through the runtime dataDir and best-effort persists the brand, MemoryChangeEvent gains a 'brand' source, and the brand kit render hardens its inline JSON escaping. Adds brand.previewEmpty / brand.viewDetails across all locales. Co-authored-by: Cursor <cursoragent@cursor.com> * Implement logo fallback and imagery support in brand extraction - Introduced a deterministic logo fallback mechanism to ensure that brand extraction processes can retrieve and save site logos, even when the agent fails to do so. - Enhanced the `startBrandExtraction` and `finalizeBrand` functions to utilize the new logo fallback, allowing for better handling of logo assets. - Added support for imagery samples in brand validation, enabling the inclusion of representative images in the brand kit. - Updated the brand kit rendering to include self-hosted fonts and imagery, improving the overall presentation of brand assets. This commit strengthens the brand extraction workflow by ensuring that logos and imagery are reliably captured and displayed, enhancing the user experience in brand management. * Enhance memory management with rule proposal and verification features - Introduced new functionality for distilling annotations into rule proposals, allowing users to suggest rules based on in-canvas annotations through the `od memory rule suggest` command. - Implemented a verification system that programmatically enforces compliance with active rules during artifact generation, ensuring that all active rules are covered in the self-verify scorecard. - Added endpoints for managing verification outcomes, including listing, removing, and clearing verification records, enhancing the transparency of the verification process. - Updated the memory management system to support the retrieval of active rule entries, ensuring that only linked rules are considered during verification. - Enhanced tests for both rule proposal generation and verification processes to ensure reliability and correctness. This commit strengthens the memory management capabilities by integrating rule proposals and verification, improving the overall user experience in managing design rules and ensuring compliance. * Distill review annotations into memory and enforce self-verify scorecard Add distillAnnotationsToMemory to mine inline preview comments/highlights/ marks into durable feedback + rule memory via a dedicated distiller prompt, threaded through the existing extract pipeline with an 'annotation' change source. Tighten the self-verify prompt (daemon + contracts) to state the daemon programmatically checks the scorecard, so a missing or uncovered scorecard on an artifact turn is an enforcement failure. Cover the rule suggest and verification-history routes with tests. Co-authored-by: Cursor <cursoragent@cursor.com> * Apply brand design system through web config on "Use in new chat" Thread onApplyDesignSystem from the entry shell into BrandsTab so the brand's registered design system is applied via the web config channel instead of a bare daemon PATCH that left the Home composer stale. Add a transient home-intent latch + event so the Brands tab can request the Prototype chip on the already-mounted HomeView, which consumes it once the plugin catalog loads. Co-authored-by: Cursor <cursoragent@cursor.com> * Wire annotation distillation into background memory extraction Add a background distill pass that mines inline review annotations (comments / highlights / drawn marks) from a turn into durable memory alongside the general LLM extraction, surface an `annotation` memory toast source in the web UI, and cover the flow with a unit test. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix brand design system not applying to composer on "Use in new chat" Selecting a brand's "Use in new chat" applies the brand's design system as the default and fires the Prototype chip intent in the same synchronous click handler. HomeView consumed that intent inside the event listener, so `pickChip` ran before React committed the config change and seeded the composer's design-system field from the stale (empty) default — the composer showed "No design system" instead of the brand until a reload. Split the intent handling: the listener now only bumps a tick, and a separate effect consumes the chip after the re-render lands, so the seeded design system reflects the freshly-applied brand. Add the previously-untracked home-intent latch test coverage. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(web): rework Brands into Brand Kit and add Home create entry Co-authored-by: Cursor <cursoragent@cursor.com> * feat(brands): harvest real cover/hero images for the Images module The brand kit's Images gallery only populated when the extraction agent remembered to save imagery — so a forgetful or bot-blocked agent (and the pre-imagery "Open Design" brand) left it empty. Add a deterministic, server-side imagery fallback (imagery-fallback.ts), mirroring the logo fallback: it parses og:image/twitter:image, large <img> (highest-res srcset/<picture>), <link rel=preload as=image>, and CSS background-image hero blocks, fetches candidates with browser-shaped headers, decodes PNG/GIF/JPEG/WebP dimensions to keep only big representative images (dropping icons/sprites/logos/tracking pixels), dedupes by content hash, and saves up to 8 of the largest into imagery/ with labeled samples. finalizeBrand runs it as a timeout-bounded, failure-tolerant safety net (injectable so tests stay offline) when the agent captured too few samples, first adopting any on-disk images. The extraction prompt and brand-extract SKILL now explicitly direct the agent to harvest the site's large/cover/hero images, filtered by rendered size. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(qa): implement deck layout validation and safety checks Add a new QA module for validating the layout of generated brand decks to ensure robustness against clipping and truncation issues. The `analyseDeckLayout` function checks for critical layout invariants, including the presence of `.slide` sections, correct container types, and necessary runtime layers. Introduce `assertDeckLayoutSafe` to enforce these checks during brand system rebuilds, preventing the deployment of decks that fail validation. Additionally, create comprehensive tests to verify the functionality of the new layout validation features. * fix(brands): apply deck shrink-to-fit synchronously so slides never clip The no-clip runtime scheduled its fit pass through requestAnimationFrame, whose callbacks are throttled while the deck is offscreen or occluded. A slide could therefore stay unscaled — and clip its content — until first paint. Fit synchronously on resize/load/fonts-ready with a trailing setTimeout settle pass for late reflow, removing the rAF dependency. Verified at the previously-broken 1024x620 viewport: container-type:size, zero truncations, runtime auto-applies scale (Problem 0.71, ASK 0.87, Product 0.97, Competition 0.97) and frame clip count drops to 0. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(web): let New Brand modal embed scrollable brand reference picker Add a fillHeight mode to BrandReferencePicker so the heading, quick-pick row and controls stay pinned while only the gallery scrolls inside a bounded-height parent. Wire it into NewBrandModal with a stable, spacious dialog and refresh the related newBrand/brandPicker copy across all 18 locales. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(brands): enhance brand extraction with deterministic seed harvesting Introduce a new `seed-fallback` module to provide a server-side deterministic palette and typography seed during brand extraction. This ensures that the brand kit's initial display includes a harvested logo, an approximate color palette, and font families, improving the user experience by reducing the all-skeleton appearance during the first paint. Update the `startBrandExtraction` function to utilize this new module, allowing for a more seamless and visually appealing brand extraction process. Additionally, enhance the `BrandReferencePicker` component to reflect loading states and errors during brand extraction, ensuring users receive immediate feedback on their actions. Update related tests to verify the idempotency of the `finalizeBrand` function, ensuring that re-finalizing a brand correctly reuses the existing design system without duplication. * feat(brand-extract): enhance BrandReferencePicker and localization updates Updated the BrandReferencePicker component to reflect loading states and errors during brand extraction, improving user feedback. Added a new localization key for the brand extraction process and updated existing translations in English, Simplified Chinese, and Traditional Chinese to enhance clarity and user experience. Additionally, introduced new styles for better interaction with brand assets in the brand kit template. * feat(brands): wire in-page lightbox/masonry/asset preview + refine seed Brand-kit preview improvements for the live extraction kit: - brand-kit.html: add in-page overlay system (sandboxed iframe has no top-nav) — clickable image lightbox with prev/next, a "view all" masonry modal, and a full-page asset preview modal that loads system/artifacts/<kind>.html in an iframe. Defer auto-reload while an overlay is open so it never yanks the modal out mid-interaction. - seed-fallback.ts: prefer vivid mid-luminance hues for the seeded accent/accent-secondary, and drop icon/symbol faces (Remix Icon etc.) from the typography seed so specimens never render glyph soup. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(brands): wire in-page lightbox/masonry/asset preview + refine seed Brand-kit preview improvements for the live extraction kit: - brand-kit.html: add in-page overlay system (sandboxed iframe has no top-nav) — clickable image lightbox with prev/next, a "view all" masonry modal, and a full-page asset preview modal that loads system/artifacts/<kind>.html in an iframe. Defer auto-reload while an overlay is open so it never yanks the modal out mid-interaction. - seed-fallback.ts: prefer vivid mid-luminance hues for the seeded accent/accent-secondary, and drop icon/symbol faces (Remix Icon etc.) from the typography seed so specimens never render glyph soup. Co-authored-by: Cursor <cursoragent@cursor.com> * i18n(web): add brandPicker.opening across remaining locales + picker test Completes the brand-reference picker i18n key that was committed only for en/zh-CN/zh-TW, so every locale satisfies the typed Dict, and lands the BrandReferencePicker extraction-feedback test left untracked by the concurrent worker. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(EntryShell): enhance AMR cloud card visibility post-detection Updated the EntryShell component to ensure the AMR cloud card remains visible after detection settles, even when the AMR runtime is unavailable. This change prevents the card from disappearing and allows it to degrade gracefully to fallback content and sign-in flow. Additionally, added tests to verify the new behavior, ensuring a better user experience during onboarding. * feat(library): OD Library asset registry + OD Clipper extension Add a global, cross-project asset registry (OD Library) and a Chrome MV3 capture extension (OD Clipper), wiring the full HTTP + CLI + Web UI three-track loop per specs/od-clipper.md. - contracts: LibraryAsset/Source/Kind, ingest, search, pairing, task DTOs - daemon: 6 additive SQLite tables, content-addressed owned storage, the idempotent registerLibraryAsset hook (hash dedup + append-source), programmatic enrichment (mime/size/image dims/domain/tags), pairing tokens with a persisted extension-origin allowlist, /api/library/* routes, and /api/tools/library/{search,apply} for in-task agent reuse - cli: `od library list|get|rm|search|import|pair` - web: Library tab (grid, source badges, filters, search, live SSE updates, extension pairing affordance) - clipper/: standalone MV3 extension (background SW, content toolbar, popup) - skills/library-curator: utility skill for agent-driven asset reuse Origin middleware now honors paired chrome-extension:// origins (seeded from SQLite on boot) and exempts the pairing-confirm handshake. Enrichment AI stages (caption/OCR/embedding) are recorded as skipped pending a configured model. * feat(brands): programmatic-first design system extraction + rename Make brand extraction two-phase so a usable design system is ready the moment the user enters a URL — the instant "aha" — instead of waiting on the AI agent: 1. PROGRAMMATIC-FIRST (synchronous): startBrandExtraction now harvests the site deterministically (logo, palette, typography, one-line description, cover imagery, source URL) via prefetchBrand, synthesizes a valid design system with brandFromMaterial (no LLM), and finalizes + registers it before returning. finalizeBrand is refactored into a reusable finalizeBrandCore shared by both the programmatic path and the agent path. 2. ASYNC AI ENRICHMENT: the seeded agent prompt is reframed to enrich the already-usable design system and re-finalize in place (same user:<id>), updating every artifact/template. Bounded + best-effort: a blocked/unreachable origin skips phase 1 and stays `extracting` for the agent to drive. Gated on userDesignSystemsRoot so the legacy agent-only path stays intact for tests. Also rename the user-facing "Brand Kit" surface to "Design System" across en + zh-CN strings, project names, and the enrichment prompt. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(library): enhance asset import and management features - Updated the `import` command to allow multiple local files and remote URLs, with restrictions on supported formats. - Added new commands: `apply` for copying assets into project design files, `edit-as-page` for converting HTML assets into editable projects, and `figma` for exporting Figma captures. - Introduced sidecar functionality for storing derived data alongside owned assets, including Figma capture IR and element HTML. - Enhanced server configuration to support larger ingest payloads for asset captures. - Improved error handling and user feedback during asset import and application processes. * feat(asset-management): enhance asset dropzone and introduce chat-to-design feature - Updated the DesignSystemAssetDropzone component to improve file preview handling with new functions for creating and revoking object URLs. - Adjusted CSS for better layout and spacing in the asset dropzone. - Added a new "Chat to design" button in the LibrarySection component, allowing users to send selected assets to the Home chat composer for project creation. - Updated localization strings across multiple languages to reflect changes in asset import terminology. - Enhanced the HomeView component to handle asset staging from the chat composer. * feat(library): enhance asset application with element markup support - Updated the `applyLibraryAsset` function to include an `includeElement` option, allowing the capture of element markup alongside assets. - Modified related components (e.g., `ChatComposer`, `LibrarySection`, `FileWorkspace`) to handle the new element markup feature, ensuring both asset paths and optional element paths are returned and processed. - Introduced a new function, `fetchLibraryAssetElementHtml`, to retrieve the captured HTML for element-pick assets. - Enhanced the UI to display element markup inline within the chat composer, improving user interaction with captured elements. - Updated API contracts to reflect changes in asset application responses, including optional element markup paths. * feat(library): enhance asset filtering and preview handling - Updated the LibraryPicker and LibrarySection components to implement a badge-aware kind filter, allowing for more precise asset filtering based on badge kind. - Introduced a new `matchesKindFilter` function to streamline the filtering logic across components. - Enhanced the DesignSystemAssetDropzone to ensure proper handling of image previews, addressing issues with broken thumbnails under React StrictMode. - Added CSS styles for kind badges to improve asset representation in the UI. - Implemented tests for the DesignSystemAssetDropzone to ensure correct preview lifecycle management. * feat(library): hydrate single asset on SSE ingest Add fetchLibraryAsset(id) so the Library grid can merge just the one asset an `ingest` SSE event references instead of refetching the whole list on every capture. Returns null on miss/error. * feat(clipper): richer in-page image picker Collect CSS background-image url()s in addition to <img> (so hero/section art painted as backgrounds is no longer silently missed), defer thumbnail decode to visible cells via IntersectionObserver, draw downscaled canvas thumbnails instead of second full-res decodes, and add locate-on-page highlighting so a picked image can be traced back to its DOM source. * feat(library): implement lazy loading for thumbnails and enhance asset filtering - Introduced a `LibraryThumb` component to lazily load heavy content (images, videos, iframes) only when they are near the viewport, improving performance. - Added a debounced search feature to optimize asset filtering, reducing unnecessary network requests during rapid input. - Enhanced the asset filtering logic to track active filters using a ref, ensuring efficient updates during live events. - Updated the `snapshotCardRects` and `cardIdsInBand` functions to support improved hit-testing for drag-and-drop interactions. * feat(library): lazy picker thumbnails + debounced search Extend the Library grid's lazy-thumbnail + 250ms debounced-search pattern to the composer LibraryPicker so opening it no longer fires one full-bytes request per asset, and tidy the clipper content-script image collection. * feat(clipper): compress and budget capture inlining Re-encode large raster images to downscaled WebP and inline smallest-first within a fixed budget, dropping only the secondary Figma IR past a safe body size, so an image-heavy page (e.g. a news front page) always saves as an editable HTML capture instead of 413-failing the ingest. * test(library): LibraryPicker debounce + lazy-thumbnail coverage Cover the composer picker's 250ms debounced search and its lazy <img> mount (deferred until the card is in view), matching the grid's perf test. * feat(design-system): enhance asset handling and UI for design systems - Updated the CLI to support additional asset kinds, including 'design-system'. - Enhanced the DesignSystemProvenance type to include source URLs, improving provenance tracking. - Modified the design system generation jobs to correctly summarize source links and GitHub repositories. - Updated UI components to reflect changes in asset handling, including new source link management in the DesignSystemFlow. - Improved tests to cover new functionality for adding source links and ensuring proper handling of design system assets. * refactor(library): rename 'design-system' to 'brand kit' and enhance thumbnail loading - Updated labels and filters in Library components to replace 'design-system' with 'brand kit'. - Introduced a shimmer skeleton for lazy-loaded thumbnails in the LibraryPicker to improve user experience during asset loading. - Enhanced the PickerCard component for better performance by memoizing individual asset cards. - Updated tests to ensure proper handling of brand kit assets and their visibility in the LibraryPicker. * feat(clipper): implement internationalization for toolbar and popup - Added i18n support to the clipper, enabling localization of UI elements and tooltips. - Introduced a new i18n.js file to manage translations for various languages. - Updated content.js and popup.js to utilize the i18n functions for dynamic text rendering. - Enhanced accessibility by ensuring aria-labels and tooltips are also localized. - Improved user experience by providing localized messages for actions and statuses. * feat(clipper): enhance brand kit extraction and localization support - Updated the brand kit extraction process to include improved handling of assets and localization for various UI elements. - Added internationalization support for the brand kit feature, allowing for dynamic text rendering based on user locale. - Enhanced the user experience by ensuring that all relevant messages and tooltips are localized. - Updated tests to cover new localization features and ensure proper functionality of the brand kit extraction process. * feat(clipper): enhance brand color derivation and update localization - Introduced new functions for color manipulation, including linear interpolation and clamping, to improve brand color derivation. - Updated the deriveBrandColors function to better map observed palettes to semantic roles, ensuring consistent brand representation. - Revised localization strings in i18n.js to reflect changes from 'brand kit' to 'design system', enhancing clarity and user experience. - Improved overall code organization and readability by refactoring existing functions and adding new utility methods. * refactor(clipper): update terminology from 'brand kit' to 'design system' - Replaced all instances of 'brand kit' with 'design system' across various components and localization files for consistency. - Updated UI elements, tooltips, and documentation to reflect the new terminology. - Enhanced user experience by ensuring clarity in the design system extraction process and related functionalities. - Adjusted localization strings in multiple languages to align with the updated terminology. * feat(clipper): enhance image fill handling and normalization - Introduced functions to normalize image fills by converting non-PNG/JPEG formats (SVG, WebP, GIF, AVIF) to PNG before import, ensuring all images are properly rendered in Figma. - Updated the UI to report the number of images converted and dropped during the import process, improving user feedback. - Enhanced the overall image processing workflow to prevent silent failures when unsupported formats are encountered. - Revised documentation to reflect the new image handling capabilities and supported formats. * feat(clipper): enhance UI kit and busy state feedback - Updated the UI kit to include new components such as inputs, selection, and overlays, improving the overall design system representation. - Enhanced the busy state feedback during capture processes with localized messages and a step-by-step progress indicator, providing users with clearer status updates. - Revised localization strings to support new UI elements and improve user experience across multiple languages. - Improved documentation to reflect changes in the UI kit and busy state handling. * fix(brands): restore design-systems nav entry + reconcile BrandsTab on re-activation Address review feedback on PR #4260: 1. EntryNavRail dropped the only control that reached view==='design-systems' when Brands replaced it in the rail, leaving the still-rendered/routed design-system manager deep-link only (the entry-nav-design-systems e2e specs assert this). Restore a reachable rail entry (blocks icon, existing navDesignSystems key) alongside Brands. 2. BrandsTab only fetched once on mount, but EntryShell keeps sub-views mounted and toggles visibility, so a brand finishing extraction in its backing project never reconciled until a full reload. Refresh whenever the Brands view becomes active again, and poll while any brand is extracting (torn down once settled / when hidden). Red spec: tests/components/BrandsTab.refresh.test.tsx (fails pre-fix: fetchBrands called once, not twice). * Update clipper/brand-capture.js * fix(clipper): improve busy state handling and UI feedback - Adjusted the spinner CSS to use flex properties for better layout control. - Enhanced the reclampIfMoved function to preserve user position during busy state transitions. - Added loading toast notifications for popup-launched captures to ensure progress visibility even when the on-page bar is hidden. * feat(daemon): add kiwi-schema dependency and enhance Figma API integration - Added kiwi-schema package to the daemon for improved schema handling. - Updated FigmaApiNode interface and related functions to support shared functionality with the offline decoder, ensuring consistency in node processing. - Refactored capture functions in clipper to maintain UI visibility during DOM/IR snapshots, enhancing user experience during capture operations. * fix(web): surface missing backing projects * fix(web): re-enable brand actions after use * fix(daemon): serve brand logos from data roots * fix(brands): reconcile failed extractions * feat(daemon): implement offline Figma import and decoding functionality - Added support for importing `.fig` files directly into the daemon, enabling offline processing without requiring a Figma account. - Introduced a new `fig-decode.ts` module for decoding `.fig` files, handling both ZIP-wrapped and raw formats. - Created `figma-import.ts` to orchestrate the import process, generating a canonical snapshot and associated metadata. - Enhanced the server to handle Figma file uploads and integrate with the new decoding logic. - Updated package dependencies to include `kiwi-schema`, `html2canvas`, and `jspdf` for improved functionality. - Added tests for the new Figma import features to ensure reliability and correctness. * feat(clipper): reload-proof capture progress badge on the extension icon The on-page progress strip dies if a page reloads itself mid-capture (aggressive paywall sites like economist.com do this), leaving no loading signal. Add a per-tab '•••' badge on the extension icon for the lifetime of any capture message — it lives on the action icon, so a page navigation can't take it down. Verified end-to-end via a real loaded extension. * feat(daemon): add export functionality for Figma and enhance PDF export process - Introduced `runFigma` command for importing Figma designs, supporting both local `.fig` files and Figma URLs. - Added detailed usage instructions for the `od figma import` command. - Implemented `runExport` command for programmatic export of HTML/deck artifacts to PDF, PPTX, or image formats. - Enhanced error handling and user feedback during export processes. - Removed obsolete `build-pptx-export-prompt` module and related tests to streamline the codebase. * feat(daemon): enhance library synchronization and export capabilities - Implemented `reconcileLibrary` to mirror design systems and agent-produced project deliverables into the Library as referenced assets. - Added support for programmatic export of artifacts via the `od export` command, including detailed usage instructions. - Introduced new functions for handling Figma imports and exports, improving integration with design workflows. - Enhanced error handling and user feedback during synchronization and export processes. - Added tests for new features to ensure reliability and correctness. * feat(web): PPTX export for any shareable artifact + Library toolbar tooltips * chore(nix): refresh pnpm deps hash * refactor(web): enhance onboarding view and file export progress indicators - Updated the onboarding view layout for improved accessibility and visual hierarchy, including adjustments to spacing, typography, and button styles. - Introduced a loading toast for file export progress, displaying elapsed time and estimated time remaining for slide exports. - Added new translation keys for export progress messages in multiple languages. - Refactored the export progress handling to provide real-time updates during the export process, improving user feedback and experience. * refactor(web): streamline export capture bridge and update connector styles - Removed unused loading logic for html2canvas in the export capture bridge, simplifying the code. - Updated CSS for the onboarding view connector to improve visual clarity and ensure it does not overlap with node numbers. * refactor(web): remove html2canvas dependency and enhance Figma URL handling - Removed the html2canvas package from the project, including its references in the lock file and related components. - Added functionality to manage Figma URLs within the Design System flow, allowing users to add, remove, and validate Figma file links. - Improved drag-and-drop handling to prevent unintended file navigation when dropping files outside designated areas. - Updated UI components to accommodate new Figma URL features, enhancing user experience and accessibility. * refactor(web): unify brand and design system flows - Merged the brand extraction process into the design system creation workflow, allowing users to start from a brand directly within the design system wizard. - Updated routing to redirect legacy brand links to the unified design systems tab. - Enhanced the onboarding experience by removing the separate Brand Kit tab and integrating brand selection into the design system creation process. - Improved UI components to reflect these changes, ensuring a seamless user experience across the application. * feat(web): introduce brand enrichment banner and picker modal - Added a new BrandEnrichmentBanner component to allow users to refine programmatically-extracted design systems with AI by selecting design-system skills. - Implemented a BrandPickerModal for selecting brands from a searchable gallery, enhancing the design system creation flow. - Updated ChatPane to conditionally display the enrichment banner for eligible brand projects, improving user engagement. - Enhanced the design system flow to support the new brand enrichment features, ensuring a seamless experience for users. * feat(web): enhance BrandPickerModal and DesignSystemAssetDropzone - Updated the BrandPickerModal to allow scrolling of the entire picker area, improving user experience by creating a unified scrolling surface. - Added new props to the BrandReferencePicker for action labels and scroll root reference, enhancing flexibility in brand selection. - Introduced a new DesignKitView component for rendering design kits consistently across different surfaces. - Enhanced the DesignSystemAssetDropzone to support a wider variety of file types with appropriate previews, improving asset management during design system creation. - Updated styles for better visual clarity and responsiveness across components. * feat(web): update Design Systems tab actions and enhance localization - Changed the button label in the DesignSystemsTab from "Edit" to "Open" for better clarity in user actions. - Added a new translation key for 'dsManager.openSystem' across multiple languages to support the updated button label. - Enhanced the FileWorkspace component to ensure the Design Files tab aligns correctly with the Design System tab, improving UI consistency. - Implemented a new design system editing feature that allows users to fetch and save design system content from DESIGN.md, enhancing the design workflow. * fix(merge): repair post-merge regressions after origin/main integration Follow-up fixes on top of the origin/main merge ( |
||
|
|
0bf1b6d6b8 |
[codex] converge release workflows and stable dry-runs (#4390)
* fix(tools-pack): use junctions for Windows standalone peer deps * fix(desktop): expose IPC during startup * fix(tools-pack): preserve Windows inspect diagnostics * fix(tools-pack): report Windows inspect status errors * fix(packaged): use Electron net fetch for app protocol * fix(packaged): load Windows renderer from web sidecar * fix(desktop): show Windows packaged window during startup * fix(packaged): disable Windows GPU startup * fix(tools-pack): keep Windows core smoke observable * fix(packaged): remove Windows startup probes * fix(tools-pack): trace Windows desktop IPC status * fix(tools-pack): add Windows IPC diagnose loop * fix(release): default beta-s Windows updater feed * chore: clean merged test eof * refactor(release): unify prerelease channel model * chore(release): close prerelease doc escape hatches * refactor(release): converge release channel workflows * fix(release): install toolchain in metadata jobs * fix(release): build release package before contracts * chore(release): bump development version to 0.10.1 * fix(e2e): seed windows packaged smoke runtime config * fix(release): install toolchain for metadata publish * fix(release): materialize betas metadata checkout * chore(release): bump development version to 0.10.2 * fix(release): allow betas metadata cold start from s3 * fix(e2e): support betas packaged update scenarios * fix(release): pass betas channel into packaged smoke * fix(release): set betas channel during self-hosted builds * fix(release): verify counted channel reservations * fix(release): use pnpm cmd for betas windows publish * fix(release): add betas manifest artifact fallback * fix(release): skip beta-s public metadata fetch * fix(release): read beta-s manifests from storage * fix(release): cache beta windows tools-pack builds * fix(release): inline beta mac tools-pack builds * fix(pack): deep sign unsigned mac bundles * docs(pack): document payload-first beta updater validation * fix(release): align preview tools-pack cache flow * fix(release): align prerelease tools-pack cache flow * fix(release): pass github token to prerelease metadata * fix(release): setup pnpm before feishu notify * fix(release): add stable dry-run prepublish flow * fix(release): accept completed prerelease metadata gate * fix(release): require stable release branches * fix(release): converge r2 access checks * fix(updater): use release channel parser for defaults * fix(updater): harden windows payload relaunch * fix(release): converge updater smoke fixture contract * test(e2e): require silent updater fixture output * fix(release): align stable windows smoke build path * fix(ci): include release workspace in validation * fix(ci): repair release validation lanes Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(ci): restore zero-install Feishu notification Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
b02d20e6b9 |
fix: unify Discord invite links (#4452)
Co-authored-by: koki yanlai xu <koki@kokideMacBook-Air.local> |
||
|
|
915548b4bd |
[codex] Fix social template English metadata (#4427)
* Fix social media template English metadata * Remove social template description hard wraps Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
f6cceb303d |
fix(plugins): unwrap cosmetic hard wraps in bundled manifest descriptions (#4406)
Picking a Home example-prompt card (or "Replicate this content" in the plugin detail modal) seeds the composer with the plugin manifest's `description`. Many descriptions were authored with cosmetic hard wraps (a single newline mid-paragraph, ~75 cols, as if formatted for a terminal/markdown source). The composer renders the seed with `white-space: pre-wrap`, so those newlines survived as short ragged lines that never filled the editor width — leaving a large blank gutter on the right of the input box (e.g. the Trading Analysis Dashboard template: 4 hard breaks, ~200px / 29% of the editor blank). Reflow the offending `description` / `description_i18n` strings in the 56 affected bundled manifests into flowing text (wrapped lines joined, real blank-line paragraph breaks preserved; CJK joins carry no space). Surgical string edits only — manifest formatting/key order untouched (146 lines changed across 56 files). The full build spec still reaches the agent as plugin context (SKILL.md + example.html); only the human-facing seed copy changed. Add an e2e guard (plugin-description-hardwrap.test.ts) that fails if any bundled manifest description carries an intra-paragraph hard wrap, so the cleanup can't silently regress when new examples are added. |
||
|
|
eb749841b4 |
fix(home): surface community slide decks on Home with letterbox-free 16:9 previews (#4350)
* fix(plugins): surface slides decks on Home instead of marketplace sources The 23 community slides/deck plugins from #4127 were registered as a restricted community marketplace source, so they showed up as installable "available sources" cards (受限 + Install) instead of on Home. Relocate them to plugins/_official/examples so they ship bundled — appearing in the Home Community gallery and the deck example-prompt rail, exactly like the existing zhangzara / swiss / guizang decks — and drop their community-registry entries. - Move 23 plugins/community/<slug> → plugins/_official/examples/<slug> (upstream LICENSE / author / homepage / "Based on" attribution preserved) - Rename manifest name community-<slug> → example-<slug> (bundled convention) - Remove the 23 entries from plugins/registry/community/open-design-marketplace.json (the 3 pre-existing community entries stay) - HomeHero: uncap the deck example-prompt rail (other chips keep the curated 18) so every bundled slide template is reachable straight from "All" - curatedPriority: pin the 23 slides to the front of both the deck example rail and the Community Slides shelf Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(home): drop provenance tail from deck seeds & fix deck preview letterbox Two polish fixes for the slide/deck plugins now surfaced on Home: 1. Example-prompt seed: strip a trailing source-attribution sentence ("…。移植自 foo/bar 的 baz 模板。" / "Based on …") from the composer seed so the prompt doesn't end on provenance boilerplate. Conservative — only fires when the final sentence opens with an attribution marker and real text precedes it; attribution woven mid-description (followed by a use-case sentence) and the gallery/detail descriptions are left intact. Latin '.' only ends a sentence at whitespace/EOL so "STYLE_PRESETS.md" / "github.com/…" don't mis-split. 2. Deck gallery preview: decks ship a fixed 16:9 stage that scales to its viewport, so the tall scroll-preview frame letterboxed it and showed a dark --stage-bg band above/below the slide. Tag deck cards with data-od-mode and give them a 16:9 frame the iframe fills natively (no transform, no pan), so the stage sits edge-to-edge with no band. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(home): deck preview frame to 16:9 so no white strip below the slide The deck preview override targeted the inner html-frame while the gallery frame kept its fixed 300px height, leaving a white strip under the 16:9 slide. Make the gallery frame itself 16:9 for deck cards so the stage fills it exactly — title bar + slide, nothing left over. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(decks): hide the page-counter chrome on all 23 community slide decks The five upstream deck families each render a different page-counter ("1 / 10") — a center pill (.deck-controls), an id="counter" badge, a fixed .deck-counter, or a .count span inside a Shadow-DOM rail — so the home gallery thumbnails showed it inconsistently. Per maintainer request, drop it everywhere rather than unify: inject a display:none rule for the light-DOM counters and inline- hide the Shadow-DOM .count span. Keyboard/touch navigation is untouched; only the visual counter is removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(home): fix deck letterbox band in the example-prompt rail tiles too The earlier 16:9 deck-preview fix only covered the Community gallery cards; the hero example-prompt rail tiles render the deck in a 4:3 (1440×1080) preview and still showed a dark --stage-bg band on top. Tag deck preset tiles with data-od-mode and give them a 16:9 preview the iframe fills natively, matching the gallery treatment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(home): remove the ↗ open-external button from community gallery cards The ↗ only rendered when a tile's preview was an HTML source, so it appeared on some cards (most decks, a few prototypes) and not others (images, srcless tiles) — inconsistent chrome across the shelf. Drop it and the whole onOpenExternal pass-through (PluginCard → PluginsHomeSection → HomeView) plus the now-dead .plugins-home__gallery-open styles. * fix(home): make the community search clear (×) button visible The clear button uses the shared <Button> component, whose CSS-module class set padding 6/12 and crushed the 12px × glyph to zero width inside the 26px button (a blank grey square). The .plugins-home__search-clear reset only out-specified the global `button {}` element rule, not the component class — scope it under .plugins-home__search so the padding:0 / 20x20 sizing actually wins. * fix(home): align deck example-prompt tile title row with other tiles Deck preset tiles used a 16:9 `auto` preview row, so their card was shorter than the fixed-150px sibling tiles; the flex rail stretched them back up and the slack leaked into the title row, making deck titles ~6px taller. Keep deck tiles on the standard 150px preview cell and center the native 16:9 stage inside it (neutral margin, no dark band), so card and title-row heights match prototype/HyperFrames/image tiles. * fix(deck-bridge): mirror the visible class so reveal animations fire on navigation Reveal-animation decks (the frontend-slides family) gate staggered entrances on a separate `.slide.visible` class that the deck's own show() adds alongside `.active`. The host bridge's setActive() flipped only the active class, so bridge-driven page turns showed slide chrome but left every .reveal child at opacity:0 — the body rendered blank. Mirror `.visible` in lock-step with the active slide (only for decks that use it, a no-op elsewhere). Adds a red→green regression test. * fix(home): unpin the bare Frontend Slides template from the slides shelf example-frontend-slides is the family-root template with a generic cover; pinned first it read as filler leading the Slides shelf and deck chip. Drop it from PINNED_SLIDE_PLUGIN_IDS so it falls to the uncurated tail while the styled variants (Creative Voltage, Electric Studio, …) keep the lead. --------- Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c7e422d7a2 |
feat(plugins): unify all 56 official deck seeds with the Open Design product narrative (#4357)
* feat(plugins): unify all 56 official deck seeds with the Open Design product narrative Apply the same canonical 10-section story used for the community slides batch (sourced from the homepage structure doc + README) to every official deck plugin seed that ships an example.html: cover, why, three claims, numbers board (60K+ stars / 300+ contributors / 217+ plugins / 129 design systems / 21 agents), 5-step workflow, multimodal outputs, capabilities, agent ecosystem, testimonial, and CTA with GitHub/Discord/X links. Scenario decks keep their framing with Open Design as the subject: weekly-report/weekly-update become OD growth reports, course-module a getting-started tutorial, testing-safety-alert the local-data-security story, xhs-* decks OD-themed xiaohongshu notes, ib-pitch-book an investor narrative, presenter-mode-reveal keeps its presenter-mode demo. open-design-landing-deck only gets its numbers aligned to the canonical figures. Skipped (no example.html seed): guizang-ppt, html-ppt, replit-deck. Content-only edits: CSS tokens, layouts, decorations, animations, keyboard nav, hash routing and functional JS untouched. zh 13 decks / en 43 decks per existing typography. All 56 verified: script syntax, cover screenshot, no fictional brand residue. * fix(decks): wire dead Download/closing CTAs to real destinations Review follow-up for #4145: primary Download CTAs now point to https://open-design.ai/ (the canonical download landing), and the remaining href="#" closing links (Star on GitHub / Discord / X / See All Agents) point to the repo, Discord invite, and X profile. Also split the landing-deck primary CTA off the repo-root URL so the primary and secondary actions no longer share a destination. * style(official-decks): anti-slop visual pass across the official deck seeds Restyle/polish sweep over all 55 official example decks (taste-skill + impeccable + gsap-skills guidelines): - A-class seeds (AI-slop look: default Inter, purple-blue gradients, uniform rounded shadow cards) fully restyled with distinct typographic systems, locked single accents, and off-white/off-black grounds. - B-class seeds (clear style family, e.g. the zhangzara-* craft set) kept their family signature and received polish only: spacing rhythm, contrast to WCAG AA, hairline discipline, reduced-motion guards. - Motion limited to transform/opacity with prefers-reduced-motion guards; signature ease cubic-bezier(.16,1,.3,1). - Content is unchanged: all copy, numbers (60K+ stars, 217+ plugins, 129 design systems, 21 agents, -80% cost), links, slide counts and the deck engine scripts are byte-identical to the previous seeds. - html-ppt-zhangzara-pin-and-paper already met every rule (craft fonts, single ink accent, static content) and is intentionally untouched. * i18n(official-decks): translate all Chinese deck seeds to English All official slide seeds are now English-only per template policy. 15 decks translated (~12,000 CJK chars): presenter-mode-reveal, testing-safety-alert, xhs-pastel-card, tech-sharing, obsidian-claude-gradient, knowledge-arch-blueprint, xhs-white-editorial, hermes-cyber-terminal, xhs-post, dir-key-nav-minimal, graphify-dark-graph, ppt-keynote, guizang-editorial, swiss-international, open-slide-canvas. - Layout, engine scripts, slide counts, stats (60K+/300+/217+/129/21/ -80%) and links unchanged; only content language changed. - CJK-specific Google Fonts (Noto Sans/Serif SC, ZCOOL KuaiLe, Songti) replaced with Latin families matching each deck's voice (Inter, IBM Plex Sans, Nunito, Patrick Hand, Georgia, Noto Serif). - The xhs-* social decks keep their Xiaohongshu aesthetic with native English social copy. - Overflow from longer English copy fixed with minor per-element type sizing; every deck screenshot-verified; zero CJK characters remain across all 56 official deck seeds. * fix(xhs-pastel-card): restore absolute positioning of topbar/footer chrome The content-layer rule '.slide > *:not(.xp-blob){position:relative}' (specificity 0,3,0) overrode the absolutely-positioned .xp-topbar and .xp-footer (0,2,0), dropping both into the flex flow: the chip overlapped the headline, left:90px turned into a 90px rightward shift that pushed the page number off-canvas, and bottom:40px lifted the footer into the body copy on every slide. Excluding the two chrome elements from the content-layer rule restores the intended layout; verified per-slide screenshots across all 8 slides. * feat(deck-seeds): expand the three sampler decks to full 10-page examples deck-guizang-editorial, deck-swiss-international, and deck-open-slide-canvas shipped as 1-2 page style samplers while every other official seed carries a full 8-11 page example. Each is now a 10-page deck built from its own SKILL.md layout vocabulary: - guizang-editorial: one page per L01-L10 layout, single Ink/Monocle palette per the 5-pick-1 rule, ink/paper reversal for rhythm. - swiss-international: 10 of the 22 locked layouts (statement, cards, six-cell grid, timeline, duo compare, loop diagram, why-now, closing manifesto), Klein Blue as the single accent; SKILL.md example_desc updated from the stale two-page wording. - open-slide-canvas: ten free-composition 1920x1080 canvases (asymmetric split, oversized numerals, positioned-block flow, editorial quote, comparison spread) with keyboard + hash navigation per its own convention. Content follows the English-only OD narrative with canonical stats and links; every page screenshot-verified; zero CJK; single-file with Google Fonts as the only external resource. * fix(decks): wire the two remaining dead closing-slide CTAs Review follow-up for #4145 (nettee, looper reviewer): - 8-bit-orbit: the closing 'Download Open Design' / 'Star on GitHub' pixel buttons were plain <button> elements with no click handling; converted to anchors targeting https://open-design.ai/ and the GitHub repo, keeping the .pixel-btn skin. - retro-windows: the closing copy promised download/star actions but the action row was the old unwired Restart / Contact / End Session set; replaced with Download Open Design / Star on GitHub / Join Discord anchors in the same .btn-retro skin. * fix(decks): wire remaining button-skinned dead CTAs across deck seeds Review follow-up for #4145 (looper reviewer round 3). Converts every remaining action-copy control that carried button/chip skin but no href into a real anchor with the canonical targets, keeping each deck's skin: - zhangzara-long-table: closing .pill chips (GitHub / Download) and the cover 'Star on GitHub' pill - zhangzara-raw-grid: closing .label arrow Download + the two .s10-rb-block tiles (macOS-Windows / Star on GitHub) - zhangzara-peoples-platform: GET STARTED slide DOWNLOAD block - obsidian-claude-gradient: all four .oc-pill chips on the CTA slide - zhangzara-biennale-yellow / sakura-chroma / cobalt-grid colophon ftag labels, zhangzara-pink-script 'Star on GitHub' tile, and ib-pitch-book 'Download Open Design' stamp (same pattern, found by a repo-wide sweep for the regression class) * fix(decks): wire zhangzara-coral closing-slide social icons to anchors * feat(plugins): unify guizang-ppt (magazine-web-ppt) deck default with the Open Design product narrative in English The deck-mode default seed (magazine-web-ppt, dir guizang-ppt) was the one official deck the narrative+i18n pass missed, because its content lives in assets/example-slides.html + assets/template.html rather than example.html. - Rewrite the 9-slide example deck to the English Open Design product narrative (60K+ stars / 300+ contributors / 217+ plugins / 129 design systems / 21 agents / -80% cost), preserving the magazine editorial layout vocabulary and hitting all 8 layout categories. English titles use the Playfair .h-hero-en family; copy follows anti-slop craft (no decorative em-dashes, real labelled metrics, tight hierarchy). - Translate template.html (title, hint, all CSS/JS comments), SKILL.md, references/*.md, open-design.json, and the design-templates README to English. - Keep magazine-web-ppt name, mode=deck, default_for=deck intact. - Both synced copies (plugins/_official + design-templates) updated identically. --------- Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com> |
||
|
|
a0afc584bb |
[codex] centralize daemon data directory docs (#4222)
* docs: centralize daemon data directory contract * fix(e2e): allow slower artifact consistency navigation Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * docs: localize daemon data directory pointers Generated-By: looper 0.9.5 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
ec524986b5 |
chore(plugins): remove html-ppt-dir-key-nav-minimal and html-ppt-xhs-post (#4212)
* chore(plugins): remove html-ppt-dir-key-nav-minimal and html-ppt-xhs-post
Final cut list from the maintainer review of the slide-template gallery
(narrowed from the originally proposed nine html-ppt studio seeds to
these two; the other seven stay).
Removed across every surface:
- plugins/_official/examples/<slug>/ (2 plugin dirs)
- design-templates/<slug>/ (2 catalogue entries)
- plugins/registry/official/open-design-marketplace.json entries
- apps/web/src/i18n/content{,.ru,.fr}.ts slug keys
Landing-page solution showcases never referenced these two, so no
landing changes are needed. pnpm guard and pnpm typecheck pass;
repo-wide grep for both slugs returns zero hits.
* fix(registry): sync bundledPreinstallCount after removing two plugins
plugins-marketplaces.test.ts asserts metadata.bundledPreinstallCount
equals the registry plugins array length; update 414 -> 412 to match
the two removed entries.
---------
Co-authored-by: qiongyu1999 <2694684348@qq.com>
|
||
|
|
b034609cde |
chore(plugins): remove the shamoni example plugin (duplicate preview imagery) (#4040)
* chore(plugins): remove the shamoni example plugin The Shamoni scroll-driven gallery example ships a baked preview that duplicates luxury-botanical's hero imagery, so the Community shelf shows the same perfume tile twice. Curator call: drop the example entirely — plugin folder, baked-preview manifest entry, and its slot in the pinned curated ordering. * fix(daemon): prune persisted bundled rows when their folder leaves the image The bundled boot walker only upserted folders that still exist, so a plugin removed from the daemon image (like the Shamoni example this PR deletes) survived in upgraded installs' installed_plugins table — and /api/plugins kept serving a record whose backing files were gone. Make bundled rows mirror the bundled tree: after a successful walk, delete source_kind='bundled' rows whose folder was not seen this boot. Folders that still ship but fail to parse stay registered (warned, not pruned), the ENOENT early-return never prunes (a missing bundledRoot is a packaging bug, not a removal), and user-installed rows are untouched. --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> |
||
|
|
ec47346e94 |
feat(web): composer 插件菜单 & 设计百宝箱 hover 预览 (#4000)
* feat(web): hover-preview column in the composer plugins menu
Hovering (or arrow-defaulting to) a plugin in the composer "+" → Plugins
flyout now opens a second-level preview column: a live preview hero
(reusing the plugins-home PreviewSurface — media poster or sandboxed
example iframe) plus the localized title, trust badge, description, and
tags. The previewed row stays highlighted so the panel's subject is
clear before the cursor lands.
The Plugins flyout widens to fit the side column and reserves that width
in the placement math; on narrow (contained) surfaces the preview drops
below the list instead. Other submenus are unchanged.
* feat(web): design-toolbox hover preview + styled detail panel
Extends the plugin hover-preview to the project composer's design
toolbox. Hovering a plugin entry now renders the same rich preview
(ComposerPluginPreview — poster / sandboxed example iframe + title,
trust badge, description, tags); every other kind (skill, MCP,
connector, file, follow-up action) keeps a compact text card.
The shared hover-detail panel (.plus-menu__detail) previously shipped
with no CSS at all — it had no position/background/border, so the
inline left/top never applied. This adds the panel styling (fixed,
panelled, shadowed, viewport-clamped) plus the section-label and
detail text styles, and clamps the panel's top so the taller plugin
preview stays on screen. ComposerPluginPreview's column divider was
de-scoped to the plugins-flyout context so it renders cleanly inside
the toolbox panel too.
* fix(web): drop redundant divider above design-toolbox search
The toolbox head carried a border-bottom while the search box below it
has its own full border, so with the flyout gap the two hairlines read
as a doubled line. Drop the head border; the search box already bounds
the section.
* fix(web): localize plugin titles in the composer plugins list
The list rendered the raw `plugin.title` (often English) while the
hover preview used the localized `title_i18n`, so the same plugin showed
two different-language names side by side. Render the localized title in
the list too, and fold it into the search haystack so a localized-name
query still matches.
* feat(web): show plugin kind tag in the hover preview
Adds a localized kind pill (Prototype / Slides / Image / Video / Audio /
HyperFrames / Live artifact) to the plugin preview title row, reusing
extractCategories — the same taxonomy that powers the home Community
filter chips — so the preview names the plugin's type at a glance. Shows
in both the composer plugins menu and the design-toolbox preview.
* fix(web): localize the applied-plugin chip title
The composer's applied-plugin chip showed the raw `record.title` (English,
e.g. "Audio Jingle") while the same plugin's preset card / hover preview
used the localized `title_i18n` (e.g. "音频铃声"), so the two read in
different languages. Localize the chip in both surfaces:
- HomeView: activeBadgeTitle now uses localizePluginTitle(locale, record).
- PluginsSection: the ContextItem label (project ChatComposer chip) too.
Mirrors the already-correct PluginPromptPresetCard pattern.
* fix(web): localize trust badge, drop raw tag chips from preview
- TrustBadge now resolves its label via i18n (pluginsView.trust.*) so
Official / Trusted / Restricted follow the active locale everywhere it
renders; an explicit `label` prop still overrides.
- Drop the raw manifest tag chips from the plugin hover preview. Tags are
author-defined English slugs with no controlled vocabulary, so they
can't be reliably localized; the localized kind pill already conveys
the category, so the card stays single-language.
* feat(web): tag design-system plugins in the hover preview
Design-system plugins aren't one of the home Community facets, so
extractCategories returns nothing and they had no kind pill. Detect them
by mode/tag (same heuristic as the preview classifier) and show the
localized 'Design systems' label (entry.navDesignSystems).
* i18n(plugins): backfill title/description translations for 22 example plugins
These 22 official example manifests shipped title_i18n / description_i18n
with only zh-CN + en, so in every other UI language (Korean, Japanese,
…) the plugin name and description fell back to English — visible now
that the composer surfaces them in the hover preview.
Fill all to the full 18-locale set (zh-CN, zh-TW, ja, ko, de, fr, ru,
es, pt-BR, it, vi, pl, id, nl, ar, tr, uk, en), matching the locale set
used by the already-complete manifests. Brand/product/proper names and
technical terms are kept verbatim; useCase.query stays English-authoritative.
* fix(web): clamp design-toolbox detail panel into the viewport
The left-side fallback (when the right side overflows) used
rect.left - gap - detailWidth without clamping, so a row near the left
edge or a pane narrower than detailWidth + gap*2 produced a negative
left and pushed the position:fixed panel off-screen. Clamp the chosen
left into [8, innerWidth - 8 - detailWidth] so it always degrades
gracefully. (review: nettee/looper)
* test(web): extract + unit-test toolbox detail panel positioning
Pull the detail-panel placement out of showToolboxDetail into a pure
computeToolboxDetailPosition helper and pin the narrow-pane clamp with a
focused vitest regression (row near left edge / viewport narrower than
the panel never yields a negative left; top clamps too). Addresses the
nettee/looper review ask for a regression check.
* fix(web): match plugins-flyout placement reserve to rendered width
PLUS_MENU_PLUGIN_FLYOUT_WIDTH was 560 while .plus-menu__flyout--plugins
renders at 466px, so getFlyoutPlacement over-reserved and medium-width
panes (~664-757px side room) wrongly fell back to the contained layout,
silently dropping the side-by-side preview column. Set it to 466 (with a
cross-reference comment to the CSS), extract the boundary arithmetic into
a pure resolveFlyoutSide helper, and pin the 466-vs-560 boundary with a
vitest regression. (review: nettee/looper)
* fix(web): localize trust badge tooltip + aria text
title and aria-label still came from the hard-coded English
meta.description, so on non-English locales the badge read as
mixed-language to tooltips and screen readers. Resolve all of label,
title, and aria-label from the localized tier key. (review: nettee/looper)
* fix(web): update TrustBadge test for localized a11y text
The existing TrustBadge spec asserted the old hard-coded English
descriptions ("Open Design official", aria "…: Action plugin"), which the
localization change replaced — that's why Web workspace tests went red.
Keep a localized tier prefix in the accessible text when a contextual
label is passed ("Official: Action plugin") and update the spec to pin
the localized behavior.
---------
Co-authored-by: qiongyu1999 <2694684348@qq.com>
|
||
|
|
b8489c9874 |
fix(plugins): pin the Motion React UMD loader in motionsites plugins (follow-up to #3973) (#3992)
* fix(plugins): pin Motion React UMD loader in plugins, generalize the system-prompt rule PR #3973 patched the blank-screen crash (Motion React hooks loaded from the vanilla motion.js DOM bundle) at the runtime/write boundary and added a Framer Motion note to the official system prompt. This closes the remaining gaps: - Root cause was in the plugins, not just the runtime: the 25-plugin motionsites batch (#3873) prescribes Framer Motion hooks in the React port but never locks how to load them, exactly as it locks fonts/colors/asset URLs. Add a "Motion loading (locked)" note to the 8 plugins that genuinely prescribe Framer Motion (3d-creator-portfolio, acreage-farming, evergreen-finance, liquid-glass-agency, luxury-botanical, mindloop-landing, portfolio-cosmic, shamoni). Plugins that map useScroll *down* to a passive listener, or use GSAP only (cinematic-landing-page), are intentionally left untouched. - Generalize the system-prompt note to lead with the principle (two UMD builds: vanilla DOM vs React, hooks live only on the React build's window.Motion) while keeping one pinned example version. - Add port-path regression coverage for the reported luxury-botanical plugin: full Motion hook set (useScroll/useTransform/useAnimationFrame/useMotionValue), the minified vanilla bundle, and the wrong-bundle + FramerMotion-global combo. Validation: pnpm guard, contracts + daemon typecheck, daemon artifact-runtime-compat.test.ts (8/8). * fix(daemon): widen Motion UMD normalizer to jsdelivr + wrong-file shape The runtime normalizer only matched the exact unpkg `motion@VER/dist/motion.js` script shape, so two real agent outputs still slipped through to a blank screen: a vanilla bundle served from jsdelivr, and the right package name pointing at the wrong file (`framer-motion@VER/dist/motion.js`). Widen the matcher to both hosts and both package spellings, preserve the original CDN host on rewrite, and document the `<script src>`-only boundary (ESM imports / importmaps / esm.sh are steered by the prompt + plugin notes, not rewritten). The React-hook usage gate still keeps animate-only vanilla DOM artifacts untouched, and a new test pins that the correct framer-motion.js bundle is never falsely rewritten. --------- Co-authored-by: audit <a@b.c> |
||
|
|
75f1472d53 |
feat(web): align Home composer facet rails with Community + drop 6 low-quality example templates (#3939)
* feat(web): align Home composer facet rails with Community + drop 6 low-quality example templates Home composer sub-category rails now mirror the Community plugin grid exactly — same sub-category set, order, and per-facet plugin slice: - Prototype order: Landing/marketing, Brand/design, Dashboards, Apps, Developer tools, Docs/reports - Slides order: Creative decks, Engineering talks, then Pitch/business, Course/training, Reports/briefings, Product/sales - Sub-chips are derived from the full install set (not the curated example subset), so the rail shows every type Community shows - Selecting a sub-category now lists the same plugins Community lists for it via applyFacetSelection (primary-category + sub-category match), so the example-prompt count matches the Community count badge Also removes six example templates with broken/poor visuals (Art Landing, Prisma Creative Studio, Urban Jungle, Modern Agency, AI Automation, FlowMate) and their pinned-order entries in curatedPriority. * fix(web): separate facet display order from matching precedence Addresses review: reordering SUBCATEGORIES re-bucketed overlapping-tag plugins because extractSubcategories() resolves via SUBCATEGORIES.find() (first match wins). Dashboards/app/launch-deck plugins with secondary design/marketing tags wrongly moved into Brand / design or Creative decks in both Home and Community. - Restore SUBCATEGORIES to its original matching precedence (stable buckets) - Add SUBCATEGORY_DISPLAY_ORDER, applied in buildSubcategoryCatalog, so the rails/catalog render Landing/Brand/... and Creative/Engineering/... first without changing which bucket a plugin lands in - Add regression coverage in plugins-home-facets.test.ts for overlapping-tag fixtures (dashboard+design, mobile+design, landing+brand, launch+marketing, pitch+marketing) and update the display-order expectations --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> |
||
|
|
bad35b45c9 |
fix(daemon): stabilize HyperFrames render handoff (#3882)
* fix(daemon): stabilize hyperframes render handoff * fix: align hyperframes skill handoff guidance --------- Co-authored-by: audit <a@b.c> |
||
|
|
a93869ee09 |
feat(plugins): 25 motionsites example plugins + daemon asset cache (#3873)
* feat(plugins): add 25 motionsites example plugins + daemon asset cache Add 25 first-party example scenario plugins under plugins/_official/examples/ (packaged from motionsites.ai templates via the motionsites-to-open-design-plugin skill): each ships open-design.json, SKILL.md, and a self-contained rendered example.html fidelity seed. All 25 pass PluginManifestSchema. Their cross-border CDN images/videos (cloudinary, higgs.ai, motionsites, cloudfront) are mirrored to Cloudflare R2 (plugin-assets.open-design.ai) and high-fidelity compressed (732MB -> 302MB), so example.html / query / SKILL.md reference the fast public origin instead of slow cross-border hosts. Daemon asset cache (plugin-asset-cache.ts + /api/asset-cache): a same-origin disk-cached proxy for any external preview media that remains. The preview URL rewriter now routes external media (src/poster attrs, CSS url(), and JS string constants) through it, so cross-border assets satisfy the sandbox CSP (img-src 'self') and load from local cache. SSRF-guarded: http(s) only, no credentials, and every resolved address must be public. * fix(asset-cache): tie SSRF validation to the actual outbound connection The previous guard resolved DNS in assertSafePublicUrl and then let fetch() resolve again independently, so a DNS-rebinding host could pass the validation lookup with a public address and steer the real connection to a private one (e.g. 169.254.169.254). Move the authoritative check to a connection-time undici Agent lookup (createValidatingLookup): the address that is validated is the exact address the socket connects to, closing the TOCTOU gap. assertSafePublicUrl is now a cheap up-front reject (scheme / credentials / localhost / literal private IP) only. Adds createValidatingLookup unit tests (public pass, rebinding-to-private reject, all:true any-private reject). * fix(asset-cache): reject IPv4-mapped IPv6 literals in the private-IP guard Node's URL parser normalizes a bracketed mapped literal like `http://[::ffff:127.0.0.1]/` to the hex form `::ffff:7f00:1`, which the old dotted-decimal regex missed — so a literal mapped host slipped past assertSafePublicUrl (and literal IPs skip the DNS lookup hook), letting `/api/asset-cache` target loopback/private IPv4 via its mapped representation. Canonicalize IPv6 now: expandIpv6() folds `::` compression and any embedded dotted IPv4 into eight 16-bit groups, and isPrivateAddress() detects the full `::ffff:0:0/96` mapped range (hex or dotted), feeding the embedded IPv4 back through the v4 private-range checks. Group-based classification also replaces the prefix string-matching for ::, ::1, fe80::/10, fc00::/7, ff00::/8. Regression coverage added for ::ffff:7f00:1 / ::ffff:127.0.0.1 and http://[::ffff:127.0.0.1]/x.png. * fix(asset-cache): full link-local range + stream-cap the upstream body Two SSRF/DoS hardening fixes on the cache path: - Link-local was matched as the single fe80:: prefix, leaking the rest of fe80::/10 (fe90::, febf::, …) through as "public". Classify with a mask ((groups[0] & 0xffc0) === 0xfe80); ULA/multicast use masks too now. - maxBytes was not a hard ceiling for responses without a trustworthy Content-Length: arrayBuffer() buffered the whole body before the size check, a memory-exhaustion path for a caller-supplied proxy. Stream the body and abort the moment the accumulated size exceeds maxBytes, before concatenating. Tests: fe80::1 / fe90::1 / febf::1 rejected; a no-Content-Length 800-byte stream against a 16-byte cap rejects with 413 after <10 pulls (proves it stops reading instead of buffering the full body). --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> |
||
|
|
10dfd32a3e |
Revert "feat: add screenshot-based visual validation to critique loop (#3660)" (#3865)
This reverts commit
|
||
|
|
931780c914 |
feat: add screenshot-based visual validation to critique loop (#3660)
* feat(daemon): add visual validation atom Generated-By: looper 0.9.3 (runner=worker, agent=codex) * fix(daemon): fail closed in visual validation Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): narrow visual validation defaults Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): add visual validation to default critique stages Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): harden visual validation review fixes Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): fail closed in visual validation discovery Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * test(daemon): tighten visual validation discovery regression Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): match visual validation reference viewport Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): tighten visual validation capture flow Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): fail closed across visual validation refs Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): honor metadata entry file in visual validation Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): capture visual validation through preview route Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): fail closed without preview context Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): disable pre-start visual validation worker Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): narrow visual validation spec discovery Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): stop advertising visual validation as runnable Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): restore visual validation critique worker Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): delay visual validation until run success Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * test(daemon): cover post-run visual validation scheduling Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): gate post-run visual validation before finish Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * chore(nix): refresh pnpm deps hash * fix(daemon): preserve deferred pipeline ordering Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(packaging): bundle Chromium for visual validation Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(scenarios): keep visual validation out of default critique loop Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(packaging): bundle Playwright headless shell Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(packaging): invalidate Playwright resource cache Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * fix(daemon): include visual-validation in bundled atom roster Generated-By: looper 0.9.3 (runner=fixer, agent=codex) * chore(nix): refresh pnpm deps hash * fix: restore pre-run plugin surfaces and nix hashes Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * fix: preserve pre-run surfaces and tolerate headed-only chromium bundles Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * fix: launch visual validation with bundled chromium Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * fix: avoid Playwright fixture teardown races Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * fix: fail packaged visual validation on shell-only chromium Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * fix: isolate synthetic Playwright test bundles Generated-By: looper 0.9.5 (runner=fixer, agent=codex) --------- Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com> |
||
|
|
df9ec8f40d |
examples: add 3D creator portfolio and Velar luxury real-estate templates (#3817)
* examples: add 3D creator portfolio and Velar luxury real-estate templates Two first-party motionsites.ai template seeds under plugins/_official/examples/, each shipping the manifest + locked SKILL.md spec + a self-contained rendered example.html fidelity anchor. - example-3d-creator-portfolio: dark gradient-text hero with a magnetic 3D portrait, scroll marquee, char-reveal About, and sticky-stacking project cards. - example-velar-luxury-real-estate: typewriter preloader, scroll-driven building that scales up while pinning to a dark stats band, count-up stats, and a hover-expand video gallery. Fixed decoration/portrait images are inlined as compressed WebP data URIs so the card and detail previews never break in the sandbox; large GIFs/videos and stable -CDN backgrounds stay as remote URLs. Both manifests validate against PluginManifestSchema (od.kind=scenario). * examples: use first-party metadata for motionsites templates Align the 3D creator portfolio and Velar manifests with the first-party metadata contract used by the rest of plugins/_official/examples/** (MIT, author Open Design, repo homepage) instead of CC-BY-4.0 / third-party motionsites provenance. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) * examples: point all inlined-asset references in the locked query at example.html The per-section spec in od.useCase.query.en still named the original remote hosts (figma.site portrait/decorations, cloudinary HOUSE_IMG) as the asset source, while only the trailing note said to reuse the inlined data URIs. Since the query is the authoritative generation brief injected on Use, a port could copy the deprecated remote URLs and regress to sandbox-403 / broken images. Rewrote those references to instruct reusing the inlined data:image/webp URIs from example.html. Genuinely-remote assets on stable CDNs (the 21 motionsites marquee GIFs, 9 higgs project images, 5 cloudfront gallery videos, the higgs hero background) are unchanged. * examples: align Velar nav dark-section refs in the locked query with the seed The Fixed Navigation bullet in od.useCase.query.en said the nav-color logic watches "Section 4 and Section 5", but the seed and SKILL.md define the dark sections as Section 5 (dark statement band) and Section 6 (gallery). Since the query is injected as the generation brief, the stale ref could make a port watch the wrong sections and leave the nav dark over the gallery. Updated the string to match the seed/skill wording. * examples: give the 3D portfolio nav links real anchor targets The hero nav shipped #price and #contact links with no matching ids in the seed, so half the navbar did nothing in the preview (and ports would inherit the dead links). Added id="price" to the Services section and a minimal contact footer (id="contact") so all four nav anchors resolve to real targets. The four-link names stay as the prompt specifies; only the seed gains anchors. * examples: document the 3D portfolio contact footer in the locked query and skill The previous fix added a #contact footer to example.html but left the injected query and SKILL.md describing only five sections (no contact target), so a port could still recreate a dead #contact anchor. Added the Contact footer section to the SECTION ORDER, a nav→anchor mapping (every link must resolve), and a Contact Section spec in both od.useCase.query.en and SKILL.md so the prompt, skill, and seed all agree. --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> |
||
|
|
0d84245b98 |
feat(plugins): add Dashboard UI — Liquid Glass first-party prototype preset (#3779)
* feat(plugins): add Dashboard UI — Liquid Glass first-party prototype preset Bundle a premium liquid-glassmorphism conference dashboard as an official example prototype plugin. Picking it routes the plugin as the active driver and reproduces the template: dual theme-swapped fullscreen background videos, a 4x2 glass/solid card grid, animated voice-wave participant indicators, and a floating control bar. - od.kind: scenario with its own generate pipeline (file-write + live-artifact) and the full build spec in od.useCase.query so the agent reproduces the design. - Ships a rendered, self-contained example.html seed as the fidelity anchor and the HTML preview entry; the marketplace card uses the motionsites animated webp poster. - All 30 avatars are inlined as base64 SVG data URIs so the preview never breaks on external avatar-host rate limits inside the sandbox; background videos and screen-share thumbnails stay on stable CDNs. * fix(plugins): make dashboard-ui-glass avatar instructions consistent with the inlined seed The top-of-file "Avatars (critical)" rule says to keep the bundled data: URI avatars, but the Profile button and Meeting alert bullets still named api.dicebear.com remote URLs — conflicting guidance that could lead a React/Vite export to ship broken sandbox avatars. Both bullets now say to reuse the corresponding inlined avatar from example.html. * fix(plugins): drop dashboard-ui-glass zh-CN query override so it falls back to the full English brief resolvePluginQueryFallback picks od.useCase.query['zh-CN'] ahead of the English fallback, so the shortened Chinese string became the entire generation brief for zh-CN users — dropping the locked avatar/network rules, the card-by-card layout, and the interaction details the English brief carries, and producing a materially different dashboard under a Chinese locale. Remove the zh-CN query override so Chinese users fall back to the authoritative, complete English brief. title_i18n / description_i18n (marketplace display strings) are unaffected. --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> |
||
|
|
071db7ca1b |
[codex] Stabilize HTML deck navigation state (#3142)
* fix: stabilize html deck navigation state * fix: avoid misclassifying transform decks as scroll decks * fix: detect default root-scroller decks --------- Co-authored-by: Nongzi <3051966228@qq.com> |
||
|
|
d0921ed335 | fix(skills): avoid orphan web prototype files (#3253) | ||
|
|
f8c860a505 |
feat(landing-page): localize plugins library across 18 locales (#3010)
* feat(landing-page): localize plugins library across 18 locales PR #2926 shipped the new `/plugins/` library hub + four kind sub-routes + detail pages, but the chrome was English-only — visitors landing on `/zh/plugins/` saw the old marketplace registry placeholder rendered by the catch-all instead, and detail pages rendered identical English copy regardless of locale prefix. This PR brings the plugin surface to feature parity with `/zh/skills/`, `/zh/templates/`, `/zh/systems/`, `/zh/craft/`. ## What changes - New `app/_lib/plugins-i18n.ts` — single source for all plugin chrome copy (hub, list pages, chip rails, share dialog, detail-page meta labels). English baseline + 17 locale overrides keyed on `LandingLocaleCode` (the same short-code shape `localeFromPath()` returns). Missing keys per locale fall back to English so a partially-translated locale still renders sensibly. Translations cover hub copy, four tile titles + blurbs, seven artifact-kind labels + descriptions, 23 scene-subcategory labels, 18 detail-page chrome strings, and a six-key share-dialog table with a per-locale `shareTemplate({title, url})` function (translated for every locale where `_lib/i18n.ts` already had one — same voice). - `app/pages/plugins/{,templates/,templates/[kind]/,skills/,systems/, craft/,[slug]/}/index.astro` — every hardcoded English string now reads `getPluginsCopy(locale)` keys. Page logic and routing unchanged. - New short-code wrappers under `app/pages/[locale]/plugins/` — six files (hub + three sub-routes + `[kind]/` and `[slug]/`) following the same pattern `[locale]/skills/index.astro` already uses: each re-exports the canonical page component and adds a per-locale `getStaticPaths()` so the build emits 17 locale prefixes per plugin route. Total plugin-route prerender count goes from ~390 to ~7 000, matching the existing skill/template scaling. - Catch-all (`[locale]/[...path].astro`) — old `getPublicPlugins` / `getRegistryCounts` registry rendering removed (placeholder UI that was never wired to a real marketplace data source). Plugin routes now live exclusively under `[locale]/plugins/...` short-code wrappers, so the catch-all stops claiming `'plugins'` as a route root. The dead-code path also drops a `pluginCounts.all` reference the title row was reading. - `.plugins-tile-grid` styles promoted from a scoped `<style>` in the default-locale hub to global `app/sub-pages.css` so the short-code wrapper renders the same hub markup without re-mounting per-page CSS — `display: contents`-style scoping pitfalls in Astro's per-component CSS scoping made this the cleanest fix. ## Surface area - [ ] **UI** — new page / dialog / panel / menu item / setting / empty state in `apps/web` or `apps/desktop` - [ ] **Keyboard shortcut** — new or changed - [ ] **CLI / env var** — new `od` subcommand or flag, new `tools-dev` flag, or new `OD_*` env var - [ ] **API / contract** — new `/api/*` endpoint, new SSE event, or changed shape in `packages/contracts` - [ ] **Extension point** — new entry under `skills/`, `design-systems/`, `design-templates/`, or `craft/`, or change to the skills protocol - [ ] **i18n keys** — new translation keys (full plugin chrome added across all 18 locales) - [ ] **New top-level dependency** — adding any new entry to the **root** `package.json` - [ ] **Default behavior change** — changes what existing users experience without opting in - [x] **None** — landing-page-only restoration of i18n parity for the plugin surface ## Validation - `pnpm --filter @open-design/landing-page typecheck` → 0 errors - `pnpm --filter @open-design/landing-page build:static` → 16 127 pages built (+6 584 over current main: ~388 plugin detail pages × 17 locale prefixes plus the hub + four sub-routes × 17 locales). - `copy-example-html.ts` reports `266 entry files + 65 referenced files`, identical to before — no regression in the asset-mirroring pipeline. - Local Playwright smoke (`/zh/plugins/...`): - `/zh/plugins/` renders `<title>插件库 · Open Design</title>`, label `插件库`, h1 `407 个可组合的构件。`, four tiles labelled `模板 / 技能 / 设计系统 / 工艺`. - `/zh/plugins/templates/video/` renders h1 `48 视频`, scene chips `全部 / 动效 / 短视频 / 营销 / 产品 / 数据讲解`. - `/zh/plugins/example-article-magazine/` share dialog renders `复制下面的文案、然后跳到你想分享的平台粘贴即可` etc., share template auto-interpolates plugin title + URL into Chinese voice. - All 18 locale prefixes (`/zh`, `/zh-tw`, `/ja`, `/ko`, `/de`, `/fr`, `/ru`, `/es`, `/pt-br`, `/it`, `/vi`, `/pl`, `/id`, `/nl`, `/ar`, `/tr`, `/uk`) → 200 across hub + four sub-routes + sample detail page. - English `/plugins/` unchanged (default-locale path bypasses the `[locale]/...` wrapper). * feat(landing-page): finish plugins i18n chrome across 18 locales The first localization pass shipped a partial fix: hub headings, lead copy, two-level page chrome, detail-page metadata labels, the share dialog, and the chip rail were still falling back to English on every non-English locale because plugins-i18n.ts only filled a chrome slice for `zh` and the file header even claimed "7 artifact-kind labels and 25 scene-subcategory labels are translated" for every locale that did not yet have those blocks. Three changes close the visible gap: 1. plugins-i18n.ts: fills the 27 still-missing chrome fields per locale for zh-tw / ja / ko / de / fr / ru / es / pt-br / it / vi / pl / id / nl / ar / tr / uk. Includes the 7-key category map, the 23-key subcategory map, hubHeading / hubLead, the 4 *Label / *Heading / *Lead triples for the templates / skills / systems / craft hub pages, the 4 tile blurbs, the 4 browse buttons, sceneLabel, allChip, the 12 detail-page metadata labels (mode / scenario / platform / surface / author / manifest id / tags / preview caption / find on GitHub / homepage / open in new tab) and bucket label map, the detail share dialog (title / copy link / jump-to), and the header-side nav.plugins entry. zh receives the same 11 detail-page and share-dialog labels it was also missing. 2. header.tsx + site-footer.astro: routes the hardcoded "Plugins / Templates / Skills / Systems / Craft" labels through `nav.*` from HeaderCopy, so every locale gets its own dropdown trigger and footer column. Adds `nav.plugins` to HeaderCopy and fills it in 18 locales with the local form ("插件" / "プラグイン" / "Plugins" / "Plug-ins" / "Plaginy" / "الإضافات" / etc). 3. plugin-row.astro + content-i18n.ts: chip rail. The bundled-plugin branch now runs raw `mode` / `scenario` slugs through the shared localizeTaxonomyValue, and that helper now also consults the plugins-i18n subcategory map before giving up. localizeTaxonomyValue now returns undefined on a true miss instead of the unknownTag placeholder, so chips drop quietly instead of showing "Category" / "分類" / "Categoría" for taxonomy slugs we have not localized yet. Callers that genuinely want the placeholder (`localizeContentTag`, blog `category`, system noun) still keep the explicit fallback. Out of scope and tracked separately: per-plugin title and description in plugins/_official/* (author-supplied English metadata, ~401 plugins without an i18n schema in the manifest yet — needs RFC + tooling before the manifests can be expanded), and adding the long tail of mode / scenario / category slugs (`code-migration`, `plugin-sharing`, `tune-collab`, `live-artifacts`, `engineering`, ...) to TAXONOMY_TERMS so chips render localized labels for every taxonomy value rather than dropping silently. * feat(landing-page): cover plugins chip rail long-tail taxonomy slugs PR #3010's first round localized the high-frequency mode/scenario chips (prototype, video, image, marketing, design, ...) but left the ~37 mode/scenario and 14 category slugs that show up in real `od.*` metadata — code-migration, plugin-sharing, design-system, planning, scenario, refine, discovery, handoff, token-map, tune-collab, orbit, live-artifacts, engineering, healthcare, hr, sales, support, default-router, downstream-export, figma-migration, media-generation, plugin-authoring, validation, 3d-shaders, animation-motion, audio-music, creative-direction, design-systems, diagrams, documents, image-generation, marketing-creative, screenshots, slides, video-generation, web-artifacts, ... — falling through to undefined and dropping their chip silently on every non-English locale. The data layer is the source of truth here, so this expansion lands in `content-i18n.ts:TAXONOMY_TERMS` / `CATEGORY_LABELS` rather than the plugins-i18n catalog: a single dictionary entry per slug fans out to every chip-rail consumer (catalog rows, detail metadata, the templates/[kind] facets) without each consumer touching its own copy. Translations cover all 17 non-`en` locales. Brand and product nouns (Figma, Open Design, BYOK, plugin) stay literal; technical taxonomy slugs get short equivalents that read as chips rather than full prose. The result on `/ja/plugins/skills/` matches `/plugins/skills/` chip-for-chip (30 chips both sides) instead of dropping 27 of them the way the previous iteration did. * feat(landing-page): read manifest title_i18n / description_i18n on bundled plugins PR #3010's prior rounds localized chrome and chip rails but the catalog's most prominent text — each row's plugin name and blurb — stayed English on every non-English locale. The plugin manifest schema (`packages/contracts/src/plugins/manifest.ts`) has supported `title_i18n` and `description_i18n` (Record<locale, string>) on every manifest from spec v1; ~24 of the 401 first-party manifests already carry one for `zh-CN`. The reader was just never wired to use them. This change does the reader half: bundled-plugins.ts captures the two i18n maps off each `open-design.json`, plugin-row.astro and the detail page resolve them at render time via two new helpers (`resolveBundledTitle`, `resolveBundledDescription`) that mirror the short→long fallback chain documented in the manifest spec (`htmlLang` like `zh-CN` → short `LandingLocaleCode` like `zh` → primary tag → `en` → English baseline). The static-paths pass still runs once for all locales — it has to, since each manifest produces one URL — but the title/description shown on the rendered page now reads the locale off `Astro.url.pathname` and picks the right entry out of the maps. Verified locally: `/zh/plugins/example-card-twitter/` now reads "Twitter 分享卡 / 推特金句 / 数据卡, 适合配推文" from the manifest's existing `zh-CN` block instead of the English baseline. Plugin-data half follows in a separate commit. The 17 non-English locales × 401 manifests need backfilling so the reader has something to resolve to; that's data, not schema, and lands as a sequence of manifest patches rather than tangled with this code change. * feat(plugins): translate scenarios bucket title/description across 17 locales Closes the first chunk of #3028. Eleven scenarios plugins (the default-scenario bundle for each taskKind: code-migration, figma-migration, media-generation, new-generation, tune-collab, plugin-authoring; the default design router; the React / Vue / Next.js downstream-export starters; and the Refine baseline) get title_i18n + description_i18n filled for all 17 non-English locales the landing page serves (zh-CN, zh-TW, ja, ko, de, fr, ru, es, pt-BR, it, vi, pl, id, nl, ar, tr, uk). The reader landed in 7ddfe36; this commit is data-only. taskKind slugs that other docs reference by name (`code-migration`, `figma-migration`, `tune-collab`, etc.) stay literal in the descriptions so cross-references still resolve. Brand nouns — Open Design, Next.js, React, Vue, Figma — also stay literal. `/ja/plugins/od-code-migration/` now reads "コードマイグレーション(デフォルトシナリオ)" instead of the English baseline; `/zh/plugins/skills/` shows "代码迁移(默认场景)" in the catalog row. Remaining buckets (image-templates 45, video-templates 50, examples 140, design-systems 142 = 377 plugins) follow in subsequent commits in this PR. * fix(landing-page): drop CJK template wrap when source name is still English The Chinese / Japanese / Korean fallback templates for craft, skill, template, system, plugin, and blog text splice the source `name` / `title` into a CJK sentence frame: ``${name}工艺规则``, ``Open Design 指南:${topic}``, ``${name} は…のスキルです``. When the underlying SKILL.md / craft markdown / blog frontmatter still ships an English name (true for ~95% of the catalog today), that produces mid-sentence script straddling on `/zh/...`, `/zh-tw/...`, `/ja/...`, `/ko/...` like: H1 : "Editorial typography hierarchy工艺规则" Lead : "这条 Open Design 工艺规则定义 Editorial typography hierarchy 的执行标准…" Plug : "video 插件 · 3D Animated Boy Building Lego" That reads worse than the all-English fallback, because the visitor parses the page in two scripts at once. Adds a `nameNeedsEnglishFallback` guard that fires for the four CJK locales whenever the spliced-in name has no CJK characters of its own, and threads it through every `localizeXxxText` helper: craft, template, system, plugin, skill, blog. When it fires the helper returns the raw English content untouched, so the section renders end-to-end in one language. Chrome (header, footer, breadcrumb, buttons, share dialog) keeps its CJK rendering — only the title-and-lead block falls back. Side benefit: the same guard kicks in on the long tail of plugin manifests still pending `title_i18n` / `description_i18n` backfill (tracked in #3028), so `/zh/plugins/<bundled>/` no longer pairs a "video 插件 · 3D Animated Boy Building Lego" title with a Chinese breadcrumb. The page reads "3D Animated Boy Building Lego" + the English manifest description, while header / footer / breadcrumbs stay localized. Once a manifest ships its i18n maps, the chrome and body re-converge automatically. Non-CJK non-Latin scripts (ar, vi, ...) keep the previous behavior — their templates already read tolerably with English names. If that turns out to be wrong on a real audit, the same guard generalizes by adding the matching Unicode range and locale set. * feat(plugins): translate image-templates bucket title/description across 17 locales 44 of 45 image-templates plugins get title_i18n + description_i18n filled for all 17 non-English locales (zh-CN, zh-TW, ja, ko, de, fr, ru, es, pt-BR, it, vi, pl, id, nl, ar, tr, uk). Generated via Claude Sonnet 4.5 over the OpenRouter gateway, ~$1.38 in API spend, 156s wall-clock. Brand and cultural references stay literal (Open Design, Lego, Hanfu, Showa, Pokémon, Black Myth: Wukong). Long AI generation prompts collapse to a 1-2 sentence summary capturing what the plugin does — the description doubles as catalog blurb on the landing site, not as the actual generation prompt (which lives in example.html / the manifest's preview entry). Skipped: `profile-avatar-realistically-imperfect-ai-selfie` returned malformed JSON on three retries; will rerun with a tighter prompt in a follow-up commit. Catalog rows for that plugin keep falling back to the raw English fields per #3010's reader change, so nothing breaks. Tracking: closes the image-templates row in #3028. * feat(plugins): translate video-templates bucket title/description across 17 locales 49 of 50 video-templates plugins get title_i18n + description_i18n filled for the 17 non-English landing locales. Generated via Claude Sonnet 4.5 over OpenRouter, ~$1.47 in API spend, 177s wall-clock. HyperFrames templates, the Three Kingdoms cinematic series, the Seedance/short-film prompts, and the K-pop / wuxia / anime variants all get a 1-2 sentence catalog blurb in each locale; brand and cultural tokens (Black Myth: Wukong, Hanfu, Showa, Pokémon, Three Kingdoms / 三国志, Lego, Disney, K-pop, HyperFrames) stay literal. Skipped: `live-action-anime-adaptation-water-vs-thunder-breathing-duel` returned malformed JSON on three retries; will rerun in followup. Falls back to the raw English fields per the reader landed in |
||
|
|
ceb636aa1b |
feat(landing-page): plugin detail page interactive preview + share dialog (#2958)
* feat(landing-page): plugin detail page interactive preview + share dialog The new `/plugins/<manifest-id>/` detail page that shipped in #2926 landed without the two affordances PR #2679 added to the legacy `/skills/<slug>/` and `/templates/<slug>/` pages: a click-to-expand iframe of the live artifact, and a share dialog with brand-keyword copy plus four-channel jump buttons (X / LinkedIn / Reddit / Facebook). This restores both, sourced from the bundled-plugin manifest under `plugins/_official/<bucket>/<slug>/open-design.json`. ## Interactive preview Three preview-type behaviours, gated on `od.preview.type`: - `video` (Cloudflare Stream URLs already in the manifest) — inline `<video controls poster=...>` with the playable MP4 as `<source>`. Detail-page row is unchanged from #2926; controls double as the open-full affordance. - `html` (a local `example.html` referenced by `od.preview.entry`, only the `examples/` bucket today) — `<details>` toggle wraps the poster image as the summary; clicking opens a sandboxed `<iframe>` that loads the entry HTML lazily, with an "Open in new tab ↗" pill in the frame's top-right corner so the artifact can be inspected at full screen. - `image` or no entry — static `<img>` (existing behaviour). `copy-example-html.ts` is extended to mirror the local entry and any `./assets/...` siblings to `out/plugins/<manifest-id>/<entry>` so the iframe URL resolves on Cloudflare Pages instead of SPA-falling-back to the homepage. The four examples carrying sibling-asset references (flowai-live-dashboard-template, trading-analysis-dashboard-template, open-design-landing, open-design-landing-deck) all render in-place. ## Share dialog Same `<dialog data-share-dialog>` markup the legacy detail pages use, so the global click handlers in `header-enhancer.astro` (`data-share-open` / `data-share-copy` / `data-copy-link`) wire up the open / copy actions automatically — no extra client bundle. Four platform jumps (X / LinkedIn / Reddit / Facebook) plus a Copy-text / Copy-link pair, with a single English template for now (the new `/plugins/...` routes only generate English pages; localisation can land alongside the i18n catch-all follow-up). ## Bundled in - The `copy-example-html.ts` sibling-assets fix from open PR #2880. Without it the existing `/skills/<slug>/` iframe still 404s on Cloudflare Pages for after-hours-editorial-template and the four others; bundling it here means the same script handles both sources in one pass and sidesteps two PRs touching identical helper code. * fix(plugins): remove dangling preview.entry from example-hyperframes The hyperframes example folder ships a SKILL.md (it's an instruction manual for using the HyperFrames HTML format) but no runnable `example.html`. The manifest still claimed `preview.type: html` / `preview.entry: ./example.html`, which made the marketing site try to iframe a non-existent file and forced the preview pipeline into its `Path 3` fallback card — leaving the catalog row visually inconsistent with the eleven sibling `video-template-hyperframes-*` plugins that have real Cloudflare-Stream poster URLs. Drop the preview block entirely so the manifest stops promising a demo it can't deliver. The landing-page detail row continues to render the typographic fallback card (sourced from title / description / mode), which is now the honest representation: "this is an instruction skill, not a renderable template". * fix(landing-page): address PR #2958 review feedback on plugin preview pipeline Two blocking issues called out in code review: 1) `bundled-plugins.ts` exposed `previewEntryUrl` for every manifest that declared `preview.type: "html"`, even when the entry file wasn't shipped. Several first-party manifests fall in this state (example-design-brief's `./brief-preview.html`, example-x-research, example-pptx-html-fidelity-audit, example-hatch-pet, example-last30days, example-guizang-ppt, example-replit-deck, example-live-artifact, example-html-ppt, example-dcf-valuation). The detail page then rendered a click-to-expand iframe and popout link to a file that copy-example-html.ts had skipped, so the iframe URL SPA-fell-back to the homepage on Cloudflare Pages. `entryRelativeUrl()` now `existsSync()`-checks the resolved local path before returning a URL. When the file's missing the detail page falls through to the static thumbnail branch, exactly like plugins that ship no preview entry at all. 2) `copy-example-html.ts` recognised only `(src|href|poster)="./assets/..."` and then bulk-copied the entry's sibling `assets/` folder, so it missed two real ref shapes: bare-relative (`href="assets/styles.css"`, `src="assets/deck-stage.js"` under example-html-ppt-zhangzara-pin-and-paper) and cross-folder (`src="../open-design-landing/assets/hero.png"` under example-open-design-landing-deck). Replaced the heuristic with a generic walker that: - Parses every relative ref in the entry HTML (`(src|href|poster|srcset|data-src)=` plus `url(...)`), splitting srcset on whitespace/commas so multi-URL attrs are honoured. - Resolves each ref against `dirname(entrypointSrc)` for the source and against `dirname(iframeAbsPath)` for the destination — identical to how a browser resolves the same ref against the iframe URL. Files outside the source root or the iframe root are dropped. - Recurses into copied HTML / CSS / JS / SVG so multi-step chains (entry → assets/template.html → assets/fonts/foo.woff) don't strand intermediate files. - Tracks visited *destinations* rather than sources, so a single source that legitimately needs to land at two different out-paths (same-folder copy at /plugins/example-X/assets/foo.png AND a cross-folder copy at /plugins/open-design-landing/assets/foo.png for sibling decks that use `../open-design-landing/assets/foo.png`) gets both copies. Verified manually: - /plugins/example-html-ppt-zhangzara-pin-and-paper/assets/styles.css and assets/deck-stage.js → 200 (bare-relative) - /plugins/open-design-landing/assets/hero.png and assets/about.png → 200 (cross-folder destination, no manifest-id prefix because iframe URL `..` collapses the prefix) - /plugins/example-design-brief/ renders the static thumbnail only, no click-to-expand iframe (broken entry guard) - /plugins/example-flowai-live-dashboard-template/assets/template.html → 200 (existing same-folder behaviour preserved) Build now reports `copied 266 entry files + 65 referenced files`, where the 65 includes both the same-folder `./assets/...` payloads the previous heuristic captured and the bare-relative + cross-folder shapes it didn't. --------- Co-authored-by: Joey-nexu <joeylee12629@gmail.com> |
||
|
|
587f6de46d |
fix: restore Atelier Zero deck plugin prompt (#2822)
Co-authored-by: icc <iccccccccccccc@users.noreply.github.com> |
||
|
|
c14baf07d3 |
Merge origin/main into release/v0.8.0
PR #2461 sync prep — resolves 14 conflicts merging 84 main-side commits on top of 58 release-side commits accumulated during the 0.8.0 cycle. Resolution summary: Take main (theirs) where main carried deliberate forward progress: - apps/web/src/components/PluginCard.tsx — 7 hunks, i18n migration: hardcoded English aria-labels/titles replaced with t() calls keyed on pluginCard.* (all 8 keys verified present in en.ts). - apps/web/src/components/TasksView.tsx — 1 hunk, source-ingestion feature: sortedRoutines (newest-first), sourceIngestionTemplates, patchSourceForm, submitSourceIngestion. activeCount/pausedCount semantics preserved (now keyed on sortedRoutines, count unchanged). - e2e/ui/app.test.ts — new node:fs/promises + tmpdir + path + @/timeouts imports needed by main-side test helpers. - e2e/ui/settings-local-cli-codex-fallback.test.ts — menu-dismissal helper block added by main. Keep both sides where each added a different field to the same object literal: - apps/web/src/components/ProjectView.tsx (locale + analyticsHints spread). - apps/web/src/components/DesignSystemFlow.tsx (locale + analyticsHints). Take release (ours) where release carried deliberate work that ships 0.8.0: - CHANGELOG.md — release-side 0.8.0 entry + PR link refs; main's Unreleased section was the same body of work, now finalized. - apps/landing-page/public/{apple-touch-icon,favicon}.png + apps/web/public/app-icon.svg — release-side visual refresh assets consistent with 0.8.0 stable ship. - tools/pack/src/linux.ts — packageVersion const required by line 466; taking main's empty line would build-error. - e2e/ui/project-management-flows.test.ts + e2e/ui/settings-api-protocol.test.ts + e2e/ui/settings-memory-routines.test.ts — release-side release-smoke hardening (shangxinyu1 + PerishFire) takes precedence on overlap. Closes-issue / unblocks: PR #2461 sync release/v0.8.0 → main. |
||
|
|
10e11531a1 |
Improve deck home previews and plugin gallery performance (#2698)
Co-authored-by: qiongyu1999 <2694684348@qq.com> |
||
|
|
e6da01e998 | Add i18n metadata for official content (#2692) | ||
|
|
0ba88a064d |
Add Codex interactive capability map example (#2657)
* Add Codex interactive capability map example * Fix Codex map preview entry --------- Co-authored-by: tuolaji <tuola@tuolajideMacBook-Air.local> |
||
|
|
bddec2391d | Fix Simple Deck discovery form contract (#2602) | ||
|
|
ce95266586 |
[codex] Polish home composer working-directory controls (#2468)
* Polish design system home flows * Polish home prompt presets * Polish home working directory controls * test: align home hero chrome smoke * fix: stabilize home composer ci checks --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> |
||
|
|
c80acfefeb |
fix(daemon,web): block pitch-deck placeholder publishes and unbreak framework decks (#2384)
Two preview-time bugs surfaced ahead of 0.8.0: 1. Pitch-deck example (#2215): the official html-ppt-pitch-deck prompt asked the agent to confirm three facts first, but the manifest had no structured `od.inputs`, so the platform's required-input gate had no fields to enforce and the run could publish HTML that still contained unresolved fundraising placeholders (`Name to confirm`, `$X.XM`, `Replace this panel with`, ...). Add structured required inputs to the manifest and a daemon-side publication guard that rejects HTML/deck artifact writes whose body still contains those placeholders. Scope is the file-write boundary only (no assistant-text scanning), so the guard cannot trip on the agent's chat prose mid-clarification. 2. Framework deck preview off-screen: `injectDeckBridge` injected `place-content: center !important` on `.deck-shell` for every deck-mode srcdoc, which forced the framework's `display: grid` shell to re-center its implicit track. The framework's `fit()` already centers a `transform-origin: top left` stage with an explicit `translate(tx, ty)` that assumes the stage's natural layout position is (0, 0); the two centerings stacked and the scaled stage landed ~1000px off-screen, so the preview showed a sliver of slide content in the top-left with the rest black. Skip the override when the framework's `id="deck-stage"` marker is in the doc, and drop the dead `display: grid; place-items: center` from the deck framework template so future drift can't re-introduce the same stack. |
||
|
|
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.
|
||
|
|
9ea33e076b |
feat(context-plugins): add support for context plugins in project metadata and UI
- Introduced a new `contextPlugins` field in the `ProjectMetadata` type to accommodate plugins selected via `@` mentions, allowing for additive context in project creation. - Updated the `HomeHero` and `EntryShell` components to handle and display context plugins, enhancing user interaction with selected plugins. - Implemented rendering logic for context plugins in the metadata block, providing clear visibility of selected plugins and their descriptions. - Enhanced the UI to support the removal of context plugins and display additional details on hover, improving the overall user experience. This update significantly enriches the project creation process by allowing users to incorporate multiple context plugins seamlessly. |
||
|
|
0edbf38171 |
feat(plugins): add specVersion and version fields to plugin and marketplace schemas
- Introduced `specVersion` and `version` fields to the plugin and marketplace schemas, ensuring better versioning and compatibility tracking. - Updated various components and functions to handle the new fields, including database migrations, plugin snapshots, and marketplace management. - Enhanced tests to validate the presence and correctness of the new fields in plugin manifests and marketplace entries. - Improved documentation to reflect the changes in schema requirements and provide guidance on the new versioning system. This update strengthens the plugin ecosystem by providing clear versioning, enhancing the reliability and maintainability of plugins and marketplaces. |
||
|
|
d3d95121f3 |
feat(plugins): enhance visual score sorting and add new example templates
- Updated the `sortByVisualAppeal` function to prioritize featured ranks, ensuring that curated plugins are displayed prominently. - Added tests to verify the new sorting logic, ensuring that plugins with numeric featured ranks are sorted correctly ahead of others. - Introduced new example templates for a magazine article layout, a Twitter share card, and a Xiaohongshu card, expanding the available options for users. - Enhanced the overall plugin preview experience by integrating these new templates, providing users with more visually appealing and functional examples. This update significantly improves the plugin sorting mechanism and enriches the template offerings, enhancing user engagement and experience. |
||
|
|
8b2d48a258 |
feat(daemon, web): enhance plugin preview handling and add new templates
- Introduced logic to assemble example slides with a companion template when the declared entry is missing, improving the user experience for plugin previews. - Updated the server logic to handle special cases for `example-slides.html`, ensuring proper fallback to `template.html` when applicable. - Enhanced tests to verify the new preview assembly functionality and ensure correct rendering of fallback content. - Added new HTML and Markdown examples for various skills, including a magazine article layout and a Twitter share card, expanding the available templates for users. This update significantly improves the plugin preview experience, providing users with more robust and visually appealing fallback options. |