18 Commits
Author SHA1 Message Date
open-design-release-bot[bot]andopen-design-bot e00d0bc56e chore(plugin-previews): refresh baked preview manifest (#7036)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-08-20 18:38:03 +00:00
open-design-release-bot[bot]andopen-design-bot 54154a6675 chore(plugin-previews): refresh baked preview manifest (#7025)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-08-18 07:15:53 +00:00
open-design-bot f62c3425c6 chore(plugin-previews): refresh baked preview manifest (release cut) 2026-08-05 00:49:22 +00:00
open-design-release-bot[bot]andlefarcen 440e663886 [backport release/v0.18.0] feat(workspace-team): team workspaces, shared resources, workspace-scoped billing, and the #5517 redesign (#6430)
* BACKPORT-CONFLICT

* fix(backport): resolve #6142 conflicts for release/v0.18.0

- apps/packaged/package.json: keep release 0.18.0 (release version line)
- NewProjectPanel.tsx: keep release variant (hardcoded copy, size 13) to
  avoid referencing newproj.openFolder/openingFolder i18n keys that the
  backport did not carry over (only used at this one call site)

web typecheck + guard both green.

---------

Co-authored-by: lefarcen <935902669@qq.com>
2026-08-05 08:44:59 +08:00
open-design-release-bot[bot]andopen-design-bot 0c5f98e17b chore(plugin-previews): refresh baked preview manifest (#6293)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-07-31 04:24:33 +00:00
open-design-release-bot[bot]andopen-design-bot a8779679bd chore(plugin-previews): refresh baked preview manifest (#5388)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-07-11 08:39:09 +00:00
open-design-release-bot[bot]andopen-design-bot fb4d48c609 chore(plugin-previews): refresh baked preview manifest (#5285)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-07-09 09:36:35 +00:00
XingliGeandTuola Ge 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>
2026-07-08 03:44:05 +00:00
open-design-release-bot[bot]andopen-design-bot 1d83115fd4 chore(plugin-previews): refresh baked preview manifest (#4905)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-06-30 08:31:57 +00:00
github-actions[bot]andopen-design-bot 52a1cd4375 chore(plugin-previews): refresh baked preview manifest (#4672)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-06-23 11:52:21 +00:00
github-actions[bot]andopen-design-bot 618a07d8db chore(plugin-previews): refresh baked preview manifest (#4490)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-06-21 16:18:40 +00:00
github-actions[bot]andopen-design-bot efc0a85e9d chore(plugin-previews): refresh baked preview manifest (#4442)
Co-authored-by: open-design-bot <bot@open-design.ai>
2026-06-17 15:22:07 +08:00
elihahah666andqiongyu1999 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>
2026-06-10 08:07:12 +00:00
68cb6c2aad chore(plugin-previews): refresh baked preview manifest (#4049)
* chore(plugin-previews): refresh baked preview manifest

* ci: trigger checks on bot-authored manifest refresh

---------

Co-authored-by: open-design-bot <bot@open-design.ai>
Co-authored-by: audit <a@b.c>
2026-06-10 07:04:34 +00:00
c0d26ef999 chore(plugin-previews): refresh baked preview manifest (#4032)
* chore(plugin-previews): refresh baked preview manifest

* ci: trigger checks on bot-authored manifest refresh

---------

Co-authored-by: open-design-bot <bot@open-design.ai>
Co-authored-by: audit <a@b.c>
2026-06-10 02:53:16 +00:00
21a7e0f081 chore(plugin-previews): refresh baked preview manifest (#4022)
* chore(plugin-previews): refresh baked preview manifest

* ci: trigger checks on bot-authored manifest refresh

---------

Co-authored-by: open-design-bot <bot@open-design.ai>
Co-authored-by: audit <a@b.c>
2026-06-09 20:25:04 +00:00
5811eb4c54 chore(plugin-previews): refresh baked preview manifest (#4010)
* chore(plugin-previews): refresh baked preview manifest

* ci(plugin-previews): re-trigger checks on the bot-authored manifest PR

---------

Co-authored-by: open-design-bot <bot@open-design.ai>
Co-authored-by: audit <a@b.c>
2026-06-09 15:16:36 +00:00
lefarcenandaudit d0f350e825 feat(plugins-home): pre-baked hover-pan preview clips for the gallery (#3994)
* feat(plugins-home): pre-baked hover-pan preview clips for the gallery

The Community gallery renders every html plugin as a live, scaled
example.html iframe that animates + auto-pans on hover. That is
GPU-expensive at scale (each tile is its own out-of-process document
re-compositing a tall page) and renders inconsistently for tricky pages
(WebGL noise, video backgrounds, lazy content).

Pre-render each preview to a tiny H.264 clip + first-frame poster:

- scripts/bake-plugin-previews.mjs: headless-Chrome screencast of a
  [hold@top in-place animation][linear pan top->bottom] capture, waiting
  on fonts + <img> + CSS background-images + <video> backgrounds first,
  then ffmpeg -> CFR H.264 mp4 + poster.jpg + manifest.json. Velocity is
  pre-computed from page height so the pan always finishes within ~10s.
  Runtime deps (puppeteer-core / Chrome / ffmpeg) stay out of package.json
  and are provided by the CI environment.
- daemon: serves <out> at /api/plugin-previews and attaches the clip to a
  plugin record under od.bakedPreview (a SEPARATE field — the detail modal
  still reads od.preview and opens the live, interactive page).
- web: inferPluginPreview(record, { preferBaked: true }) lets gallery tiles
  opt into the clip; MediaSurface loops the in-place [0, holdMs] span while
  idle and plays the pan on hover, one always-mounted <video> (no black
  flash), looped frame-accurately via requestVideoFrameCallback, with no
  native controls. Plugins without a bake keep the live-iframe fallback.

CI upload to R2 + the post-merge/nightly bake workflow (with content-hash
skip) and the daemon on-demand path land in follow-ups.

* feat(plugins-home): content-hash skip so unchanged plugins reuse their baked clip

The bake now hashes each plugin's preview HTML + a BAKE_VERSION and stores it
in the manifest. Re-running skips any plugin whose hash is unchanged (no render,
no re-encode, and the CI step re-uploads nothing) — editing the page or bumping
BAKE_VERSION invalidates it. Verified: a second pass over already-baked plugins
reuses all of them in ~1s instead of re-rendering.

* feat(plugins-home): point baked-preview URLs at R2 in production

bakedPreviewBlock now builds its poster/video URLs from
OD_PLUGIN_PREVIEWS_BASE_URL (the R2 public origin) when set, falling back to
the daemon's own /api/plugin-previews static route for local dev. The CI bake
uploads the clips to R2 and the deployed daemon points at them there.

* feat(plugins-home): CI workflow to bake + publish plugin previews

Adds .github/workflows/bake-plugin-previews.yml: post-merge (paths:
plugins/_official) + nightly + manual. Each run starts the daemon, bakes ALL
plugins (the content-hash skip makes that cheap — only changed pages re-render,
PREVIEW_REMOTE trusts the manifest hash since CI clips live on R2 not on disk),
`aws s3 cp`s the new clips to R2 (no --delete, so untouched clips stay), and
commits the refreshed manifest back to main.

- The daemon now reads the checked-in manifest from data/plugin-previews/ by
  default (binaries stay on R2; OD_PLUGIN_PREVIEWS_DIR still overrides locally),
  seeded here with an empty manifest so every plugin starts on the live-iframe
  fallback until the first bake lands.

Verification needs a real CI run (R2 secrets + a daemon in CI); the bake script,
hash skip, daemon injection, and web display are all already verified locally.

* ci(plugin-previews): open a reviewed PR for the manifest instead of pushing to main

Protected main can't take a direct push, and the manifest is version-pinned
(ships with the build), so the bake now opens a PR with the refreshed
data/plugin-previews/manifest.json and requests review from @lefarcen rather
than committing straight to main. Only fires when a plugin actually changed.

* ci(plugin-previews): fix invalid YAML — single-line PR body (@ in body broke the literal block)

* ci(plugin-previews): TEMP branch trigger + debug guards (limit 3, skip publish off-main)

* ci(plugin-previews): install puppeteer-core via pnpm (npm chokes on workspace:*)

* ci(plugin-previews): correct R2 secrets (repository-assets bucket) + TEMP branch publish test

* ci(plugin-previews): revert temp branch-debug toggles (workflow verified in CI)

* fix(plugins-home): gate bakedPreview on a fetchable source + fix workflow shellcheck

Review feedback (nettee):
- bakedPreviewBlock now only attaches a baked preview when a remote origin
  (OD_PLUGIN_PREVIEWS_BASE_URL) is set OR the clip files exist on disk. A
  deployment reading the checked-in manifest without the base URL set would
  otherwise emit /api/plugin-previews URLs that 404 (binaries live on R2),
  breaking tiles instead of falling back to the live iframe.
- workflow: `for _` instead of unused `for i` (SC2034) and split the CHROME
  declare/export (SC2155) so the actionlint gate passes.

* fix(plugins-home): log manifest load failures instead of swallowing them

Review feedback (nettee, non-blocking): loadManifest() caught every read/parse
error and returned {}, so a malformed manifest would silently disable all baked
previews with no trace. Warn so it's diagnosable.

* feat(plugins-home): use baked previews on the example-prompt preset tiles too

The HomeHero '示例提示词' preset tiles render the same plugin previews via
PreviewSurface; pass preferBaked so they get the cheap poster + hover-pan clip
instead of a live iframe, matching the gallery.

* ci(plugin-previews): grant pull-requests: write so the manifest PR step can open its PR

Review feedback (nettee): the permissions block only set contents: write, so
pull-requests defaulted to none and gh pr create would 403 on the first run that
changes the manifest.

---------

Co-authored-by: audit <a@b.c>
2026-06-09 13:14:54 +00:00