* fix(web): align Home prompt overlay with textarea so caret lands on click
Picking a chip such as Slide deck or Image loaded a default prompt
into the Home textarea and rendered an overlay with `{{key}}`
placeholders as interactive `<input>` / `<select>` controls. The
overlay controls and the underlying textarea text were laid out
independently:
- Inputs declared `min-width: 8ch` and `Math.max(displayValue.length
+ 1, 10)ch` of width.
- Selects added 18px of right-padding for the dropdown arrow.
- The textarea kept the raw substituted string in a proportional
font.
The two layouts no longer matched column-for-column, so every slot
shifted the textarea text to the left of where it appeared in the
overlay, compounding across the line. Clicking on visible prose to
position the caret hit a different character offset in the textarea
and subsequent typing or deletion landed in the wrong place.
For example, the Slide deck template
Create a {{slideCount}}-slide {{deckType}} for {{audience}} about
{{topic}}. ...
renders with slideCount=10 (~2 ch in the textarea) under a slot
input forced to 10 ch in the overlay — clicking right after the
literal `-slide` placed the caret several characters into `pitch
deck`. The Image / Video / Audio chips with their pre-filled
subject, style, aspect values reproduced the same drift.
Render the inline pills as read-only `<span>`s carrying the exact
substring the textarea shows at that position, mark them
`aria-hidden` so the textarea remains the single labelled control,
and surface every plugin input field — including the ones referenced
inline — in `PluginInputsForm` underneath. Editing flows through the
form, the parent's `updateActiveInputs` already re-renders the
prompt, and the pills stay aligned with the textarea on every
keystroke.
Also drop the now-unused inline helpers (updatePluginInput,
getTemplateInputNames, shouldRenderSlotAsText, inlineFieldType,
fileInputLabel, fileMetadata) and the dead
`.home-hero__prompt-slot-control/input/select/toggle/file/text` CSS
rules.
Verified:
- pnpm --filter @open-design/web typecheck
- vitest run on HomeHero.plugin-picker, HomeHero.rail, and
HomeView.prefill (29/29 pass; tests updated to reflect the new
read-only span + always-on form contract)
- Manual click-to-edit on Slide deck and Image chips in the
pnpm tools-dev web runtime — caret now lands where the user
clicked.
* Implement home audio essential workflow
* Fix Home media composer review issues
* Guard stale Home media apply results
---------
Co-authored-by: hahaplus <zmjdll@gmail.com>
Normalizes plugin trust badge rendering across Home, plugin details, registry entries, sources, and plugin share/install surfaces while mapping bundled and official sources to the user-facing Official tier.
Validation: CI and nix-check were green on PR head 1a68f20571.
Resolves short pointer-only HTML artifacts to the existing project HTML target before persisting preview artifacts, with helper and ProjectView regression coverage for #536. Validation: CI and nix-check were green on PR head 8c7ee5f38d.
Routes Finish Design/finalize requests through the selected BYOK provider, including Gemini, while preserving the Anthropic fallback. Validation: CI and nix-check were green on PR head 6c334e08d1.
* fix(web): keep connector errors out of cards
* fix(web): route panel-alert open-details through openConnectorDetails
The new "open details" action on the panel-alert row called
`setDetailConnectorId(alert.connectorId)` directly, bypassing the
`toolPreviewFailedIds` clear that `openConnectorDetails()` does on
every other entry point.
Concrete regression: user opens a connector's drawer from the card,
the tool-preview hydration fetch fails so `toolPreviewFailedIds[id]`
gets stamped with the current `toolPreviewRetryToken`, user closes
the drawer, and later the same connector throws a connect error and
shows up as a panel alert. Clicking the alert's open-details button
re-sets `detailConnectorId` but never clears the failed-fetch token,
so the hydration effect at the previous bail-out check
(`toolPreviewFailedIds[detailConnector.id] === toolPreviewRetryToken`)
returns immediately and the drawer never retries loading tools.
Routing the click through `openConnectorDetails(alert.connectorId)`
restores the same clear-before-set behavior the card and search
entry points already had, so the reopened drawer always gets a fresh
hydration attempt.
* test(web): cover connector panel alert tool retry
* fix(web): clarify connector panel alert status text
* fix(web): clear stale connector cancel alerts
---------
Co-authored-by: lefarcen <935902669@qq.com>
* feat(web): highlight captured Pod component on chip hover
Wires onPointerEnter/Leave on chip + onFocus/Blur on its × so the matching member overlay gets an outline-focused emphasis on canvas.
* ci: trigger re-run for flaky palette dark-mode test
* fix(web): skip non-mouse pointer events on pod chip hover
Gate onPointerEnter/Leave to pointerType === 'mouse' so a touch tap on a chip no longer flickers the captured-member highlight; also add the CommentTargetOverlay class-wiring test, drop the redundant alpha on the hover outline, and document the non-member fallback path.
Picking a chip such as Slide deck or Image loaded a default prompt
into the Home textarea and rendered an overlay with `{{key}}`
placeholders as interactive `<input>` / `<select>` controls. The
overlay controls and the underlying textarea text were laid out
independently:
- Inputs declared `min-width: 8ch` and `Math.max(displayValue.length
+ 1, 10)ch` of width.
- Selects added 18px of right-padding for the dropdown arrow.
- The textarea kept the raw substituted string in a proportional
font.
The two layouts no longer matched column-for-column, so every slot
shifted the textarea text to the left of where it appeared in the
overlay, compounding across the line. Clicking on visible prose to
position the caret hit a different character offset in the textarea
and subsequent typing or deletion landed in the wrong place.
For example, the Slide deck template
Create a {{slideCount}}-slide {{deckType}} for {{audience}} about
{{topic}}. ...
renders with slideCount=10 (~2 ch in the textarea) under a slot
input forced to 10 ch in the overlay — clicking right after the
literal `-slide` placed the caret several characters into `pitch
deck`. The Image / Video / Audio chips with their pre-filled
subject, style, aspect values reproduced the same drift.
Render the inline pills as read-only `<span>`s carrying the exact
substring the textarea shows at that position, mark them
`aria-hidden` so the textarea remains the single labelled control,
and surface every plugin input field — including the ones referenced
inline — in `PluginInputsForm` underneath. Editing flows through the
form, the parent's `updateActiveInputs` already re-renders the
prompt, and the pills stay aligned with the textarea on every
keystroke.
Also drop the now-unused inline helpers (updatePluginInput,
getTemplateInputNames, shouldRenderSlotAsText, inlineFieldType,
fileInputLabel, fileMetadata) and the dead
`.home-hero__prompt-slot-control/input/select/toggle/file/text` CSS
rules.
Verified:
- pnpm --filter @open-design/web typecheck
- vitest run on HomeHero.plugin-picker, HomeHero.rail, and
HomeView.prefill (29/29 pass; tests updated to reflect the new
read-only span + always-on form contract)
- Manual click-to-edit on Slide deck and Image chips in the
pnpm tools-dev web runtime — caret now lands where the user
clicked.
reloadConnectorStatuses commits its prune setState (and runs the connectorAuthorizationPendingRef mirror effect) between the two awaits in onFocus, so cancelStaleAuthorizations was reading a post-prune ref and never identified anyone as stuck. Capture the snapshot inside onFocus before reloadConnectorStatuses runs, and pass it explicitly so the expired-auth daemon cancel actually fires.
Refs #1909#1354
Saved Project instructions had no post-save read-back surface. The
header control was a bare pencil icon that opened an editor and closed
on Save, so after returning to the workspace a user could not confirm
what was stored, revisit it, or tell whether it was still active
(#1822).
Make the saved state discoverable: once instructions exist, the header
affordance becomes a persistent "Project instructions" chip. Opening it
shows a read-only review panel with a preview of the saved text and an
"Active - included in every message" status, plus a reopen-to-edit
action. Saving lands back on the review panel so the stored value is
read back immediately. The empty state keeps the pencil and opens the
editor directly.
Persistence and project-level system-prompt injection are unchanged.
Closes#1822
Co-authored-by: multica-agent <github@multica.ai>
The first-run consent banner had no link to a privacy policy, an
affirmative button ("Help improve") that didn't read as a consent
choice, and a fixed bottom-right card that crowded content on phones.
- Add a "Read the privacy policy" link (external-link icon, accent,
underlined) above the actions, plus a root PRIVACY.md it points to
documenting the telemetry behaviour the modal discloses.
- Rename the CTAs to "Share usage data" / "Don't share" so both name
the action; they stay equal-prominence per the EDPB/GDPR comment.
- Stretch the banner to a bottom-edge bar under 540px with a
safe-area inset so it clears mobile browser chrome.
- Add PrivacyConsentModal tests; sync the new i18n key to every
locale and update the consent-label assertion in App.connectors.
Refs #1756
Walk document.styleSheets so chromatic custom properties on :root/html/body/:host (including @media-nested rules) are hue-shifted via inline setProperty, not just the values returned by getComputedStyle.
Fixes#1393
References: PR #1643 (open, in review) binds the Tweaks toolbar toggle to artifact `.tw-panel` panels via a new `injectTweaksBridge` in `srcdoc.ts` — adjacent surface but different problem. Our fix extends `injectPaletteBridge` to also shift `:root` CSS custom-property colors, which #1643 does not touch.
* fix(web): recover stuck Composio connector when auth is cancelled
When a user closes the Composio system-browser auth window without completing the flow, the connector card stayed in its loading state forever because nothing told the daemon the request was abandoned.
The window-focus refresh now awaits the status poll and, for every connector still in connectorAuthorizationPending whose freshly fetched status is not 'connected', issues cancelConnectorAuthorizationRequest and clears the matching local pending/error UI state. The connected guard is read from the just-returned statuses so a postMessage success that lands just before focus is not racy.
Fixes#1354
* fix(web): gate Composio focus auto-cancel on TTL + cancel response
Require expiresAt to have elapsed before auto-cancelling a pending
Composio auth on focus, and preserve the spinner on a failed cancel
(matching the manual Cancel handler) so the UI never disagrees with
the daemon.
Refs https://github.com/nexu-io/open-design/pull/1909#discussion_r3254152045
Refs https://github.com/nexu-io/open-design/pull/1909#discussion_r3254152046
* feat(web): add manual removal for captured Pod components
Adds `removePodMember` helper and a per-chip × in `BoardComposerPopover`; leaves `comments.ts` untouched (avoid-zone from #1127).
Closes#802
Contract: runs/2026-05-16T08-08-52_open-design_issue-feat/contract.md
* style(web): hide Pod chip × until chip hover
Swaps the unicode × for the existing `Icon name="close"` SVG so the
hit target stays centered, and fades the button in only on chip
hover / keyboard focus for a quieter resting state.
* fix(web): auto-close Pod composer when last chip is removed
Removing the last chip leaves a stale anchor; close so Send cannot attach to elements no longer visible.
* refactor(web): extract BoardComposerPopover and Pod-member reducer
Moves the popover to its own module and lifts the chip-removal reducer into a pure `applyPodMemberRemoval` so unit tests exercise the real code path and the popover's export is no longer test-only.
* fix(web): rebuild Pod anchor when a member is removed
Without this, the popover keeps the original union bbox / selector / label after each chip removal, so a subsequent Send to chat anchors the comment to elements no longer in the Pod.
* fix(web): render every captured chip and scroll on overflow
The previous slice(0, 6) cap left chips beyond the sixth invisible and undeletable. Render the full list inside a 132px-tall scrollable strip.
Clicking Edit on a built-in skill silently issued PUT /api/skills/:id,
which the daemon stores as a user-owned shadow and then hides the
built-in entry from the Settings list. From the user's perspective the
row they just edited disappears with no explanation.
Arm an inline override-warning banner on Edit for source==='built-in'
skills, mirroring the existing inline delete-confirm pattern. The edit
form only opens after the user explicitly confirms. User skills bypass
the warning and edit directly. No daemon or listSkills contract change.
Fixes#1378
The Routines list only exposed Run now / Pause / History / Delete, so any
change to a routine required deleting and recreating it. The daemon already
serves PATCH /api/routines/:id; only the web entry point was missing.
Add an Edit button on each routine row that pre-populates the create form
from the stored schedule and target via a new formFromRoutine helper, and
branch the submit handler on editingId so it PATCHes /api/routines/:id
with the updated fields instead of POSTing a new routine.
Fixes#1373
* fix(web): surface daemon error messages for invalid folder imports
importFolderProject() was swallowing non-2xx responses by returning
null, so the UI could only show a generic "Open folder failed: <path>"
message even though the daemon already returns specific errors like
"cannot import the filesystem root" or "folder not found".
Parse the daemon error body and throw so the panel displays the actual
reason. Also show feedback for empty path input instead of silently
returning.
Fixes#1186
* test(web): update folder import test to match new error propagation
The existing test expected a generic "Open folder failed: <path>"
message from a boolean return. Update to match the new behavior where
the daemon's error message is thrown and displayed directly.
* fix(desktop): export PDF saves to a file instead of the OS print dialog
The `od:print-pdf` IPC handler called `webContents.print()`, which
opens the printer-first macOS system print dialog. That handler is the
destination of the renderer's `window.__odDesktop.printPdf()` bridge,
so on desktop "Export PDF" felt like a print flow rather than a file
export — from both the PreviewModal share menu (which always uses this
path) and the FileViewer share menu (whose daemon-route fallback lands
here too).
Route the handler through a direct Save-as-PDF flow instead: a native
Save dialog, then `webContents.printToPDF()` straight to the chosen
file — the same shape `exportPdfFromHtml` already uses for the
daemon-backed export path. The flow is extracted into
`savePrintReadyDocumentAsPdf` behind a structural `PrintReadyPdfTarget`
surface that has no `print()` method, so the regression cannot be
reintroduced.
Fixes#1774
Co-authored-by: multica-agent <github@multica.ai>
* fix(desktop): preserve PDF page sizing in print bridge
Co-authored-by: multica-agent <github@multica.ai>
---------
Co-authored-by: multica-agent <github@multica.ai>
* fix(runtime): auto-annotate imported HTML elements for Tweaks selection (#892)
* fix(runtime): always annotate missing od-ids and broaden selector (#892)
- Remove the conditional gate so annotateMissingOdIds runs for every
srcdoc, not just comment/inspect bridges. This fixes the persistence
regression where saved Inspect tweaks reference synthesized data-od-id
selectors that vanish when the bridge is rebuilt without annotations.
- Expand the selector to cover div-based imported HTML (div[class],
div[id]), headings, buttons, and links so Picker/Pods work on
common anonymous wrapper markup.
Addresses review feedback from lefarcen and mrcfps.
* fix(runtime): narrow div selector, skip iframe/object/embed, add tests (#892)
- Replace broad div[class] with direct-child combinators only under
semantic containers, body, and [id] elements to avoid layout noise
- Add iframe, object, embed to the skip list alongside script/style
- Add tests for: direct-child divs, nested div skip, always-on behavior,
skip list with id attributes, div children of [id] elements
- Format selector as array join and skip tags as Set for readability
* fix(runtime): let annotateManualEditSourcePaths coexist with data-od-id (#892)
annotateMissingOdIds now runs unconditionally, so elements like main/h1
get data-od-id before annotateManualEditSourcePaths runs. The old skip
condition (has data-od-id) incorrectly prevented source-path marking on
those elements. Change the guard to skip only when the element already
has data-od-source-path, allowing both attributes to coexist.
* feat: add Italian (it) locale support
- Add complete Italian translation dictionary (apps/web/src/i18n/locales/it.ts)
- Register 'it' locale in types.ts (Locale type, LOCALES array, LOCALE_LABEL)
- Import and register Italian dictionary in index.tsx
- All 1352 translation keys translated to Italian
- Follows the same structure as French locale (PR #326)
Closes#1245
* test: Update locale tests to include Italian (it)
1. Add 'it' to EXPECTED_LOCALES array
2. Add LOCALE_LABEL.it assertion to verify 'Italiano' label
This fixes the CI test failure and completes the Italian locale integration.
---------
Co-authored-by: lefarcen <935902669@qq.com>
* Preserve HTML preview state across mode toggles
HTML previews could rebuild their iframe when switching into Edit or Comment, which reset scroll/canvas state and caused visible churn for multi-file artifacts. The viewer now keeps URL-loaded previews mounted when the artifact owns the mode bridge, relays file-refreshes through frame navigation, and restores preview scroll/viewport state across bridge mode changes.
Constraint: Generic srcdoc-only bridges are still required for unbridged artifacts, inspect mode, palette tweaks, decks, draw overlays, and forceInline.
Rejected: Keep all Edit/Comment previews on srcdoc | causes unnecessary iframe replacement for bridge-capable URL-loaded artifacts.
Confidence: high
Scope-risk: moderate
Directive: Do not enable URL-load for bridge-dependent modes unless the artifact has an owned postMessage bridge.
Tested: pnpm guard
Tested: pnpm --filter @open-design/web typecheck
Tested: pnpm --filter @open-design/web test
Tested: Playwright verified Edit and Comment toggles preserve iframe src and DOM node while receiving comment targets.
* Prevent preview wheel gestures from escaping into zoom
Trackpad pinch-like wheel events arrive with ctrl/meta modifiers on some platforms, which can make a normal vertical scroll feel like the preview zoomed. The preview now consumes those modified wheel events inside the host preview shell and in injected srcdoc previews, then maps the delta back to scroll where a scroll target exists.
Constraint: URL-loaded sandbox iframes cannot always be inspected by the host, so srcdoc previews need their own in-frame guard.
Rejected: Add allow-same-origin to preview iframes | weakens the sandbox boundary for generated artifacts.
Confidence: medium
Scope-risk: narrow
Directive: Do not broaden iframe sandbox permissions to fix gesture handling without a security review.
Tested: pnpm guard
Tested: pnpm --filter @open-design/web typecheck
Tested: pnpm --filter @open-design/web exec vitest run tests/components/FileViewer.test.tsx tests/runtime/srcdoc.test.ts
Tested: playwright-cli verified ctrl-wheel in preview keeps app zoom at 100% and prevents default in the iframe context
* Revert "Prevent preview wheel gestures from escaping into zoom"
This reverts commit 976407ab4c.
* Prevent imported Claude canvases from zooming on scroll
Claude Design exports can classify ordinary macOS two-finger vertical wheel events as mouse-wheel zoom clicks inside design-canvas.jsx. Normalize that imported canvas code so plain wheel input pans, while Cmd+wheel remains the explicit zoom gesture.
Constraint: The offending canvas code lives inside imported user artifacts rather than a tracked runtime component, so the fix belongs in the Claude Design zip import normalization path.\nRejected: Host-side wheel interception | wheel events inside the sandboxed iframe are handled by the artifact before the host can reliably classify them.\nRejected: Disable all wheel zoom | users still need Cmd+wheel as an explicit zoom control.\nConfidence: high\nScope-risk: narrow\nDirective: Keep plain wheel as pan-only for imported design-canvas.jsx unless a future bridge provides an explicit wheel-mode handshake.\nTested: pnpm --filter @open-design/daemon exec vitest run tests/claude-design-import.test.ts\nTested: pnpm --filter @open-design/daemon typecheck\nTested: pnpm guard
---------
Co-authored-by: nicejames <nicejames@gmail.com>
Co-authored-by: lefarcen <935902669@qq.com>
* fix: Add error feedback for manual folder path import
Fixes#1408
When users manually enter a folder path and click 'Open folder' (non-Electron
environment), the app now provides clear error feedback if the import fails.
**Before:**
- No error clearing before import
- No error handling for failed imports
- Silent failures left users confused
**After:**
- Clears previous errors before attempting import
- Catches and displays import errors with clear messages
- Success feedback is implicit (navigation to the opened project)
**Why implicit success feedback:**
The parent handler (Home.tsx) navigates to the newly opened project on success,
which provides clear visual feedback by changing the entire view. An additional
toast would be redundant.
**Error handling:**
- Catches all errors from onImportFolder
- Displays user-friendly error messages
- Preserves error details when available
* fix: surface failed folder imports
---------
Co-authored-by: Siri-Ray <2667192167@qq.com>
BYOK/API-mode chats bypass the daemon run path, so attached project
files were saved as message metadata but their readable contents were
not sent to the provider. This adds a web-side attachment context step
for API-mode requests, reusing raw text reads and existing document
preview extraction.
Constraint: Docker PDF previews require pdftotext in the runtime image
Confidence: high
Scope-risk: moderate
Tested: corepack pnpm --filter @open-design/web test -- tests/api-attachment-context.test.ts tests/components/ProjectView.api-empty-response.test.tsx
Tested: corepack pnpm --filter @open-design/web typecheck
Tested: corepack pnpm --filter @open-design/web build
Tested: corepack pnpm guard
Tested: corepack pnpm typecheck
* feat(chat-composer): enhance mention handling and input overlay
- Introduced a new overlay for inline mentions in the chat composer, improving user experience by visually indicating mentions as users type.
- Updated the `ChatComposer` component to manage mention entities and integrate them into the input field, allowing for better context and interaction.
- Enhanced the `AssistantMessage` component to support the display of plugin action panels based on the current project context, facilitating easier plugin management.
- Refactored related components to ensure consistent handling of project files and mentions across the application.
This update significantly improves the chat interaction model, making it more intuitive for users to engage with mentions and plugins.
* feat(plugin-management): enhance plugin action panels and UI components
- Updated the `AssistantMessage` component to include plugin action panels based on the latest project context, improving user interaction with generated plugins.
- Refactored the `PluginsView` to support detailed views for available marketplace entries, allowing users to access more information and actions for each plugin.
- Introduced new CSS styles for improved visual representation of plugin-related UI elements, enhancing overall user experience.
- Enhanced the `listPlugins` function to include an option for fetching hidden plugins, providing more flexibility in plugin management.
This update significantly improves the usability and functionality of the plugin management system, making it easier for users to interact with and manage their plugins.
* fix(assistant-message): refine plugin folder candidate selection logic
- Updated the `pluginFoldersTouchedThisTurn` function to improve the logic for selecting plugin folder candidates based on touched paths and message content.
- Introduced a new helper function, `pathMatchesFolderFileBasename`, to enhance the matching criteria for folder candidates.
- Added a check for explicit folder matches before falling back to a single candidate, improving accuracy in folder selection.
- Modified the `shouldRenderSlotAsText` function in `HomeHero` to include the name parameter, refining the rendering logic for slot text.
These changes enhance the functionality and reliability of the assistant message component in managing plugin folder candidates.
* feat(plugin-folder-actions): implement agent-routed CLI actions for plugin management
- Introduced a new `PluginFolderAgentAction` type to streamline actions related to plugin folders, including install, publish, and contribute.
- Updated the `DesignFilesPanel`, `FileWorkspace`, and `AssistantMessage` components to utilize the new agent action handling, improving user interaction with generated plugins.
- Refactored the action handling logic to send commands to the agent, enhancing the workflow for managing plugin folders.
- Added corresponding tests to ensure the new functionality works as expected and integrates seamlessly with existing components.
This update significantly enhances the plugin management experience by routing actions through the agent, allowing for a more cohesive and interactive user experience.
* Fix PR 1702 CI blockers
* Fix PR 1702 remaining CI checks
* Prebuild AGUI adapter after install
* Restore plugin project snapshot wiring
* feat(marketplace): refactor marketplace URL handling and enhance fetching logic
- Introduced new functions to normalize marketplace URLs and manage fetching of marketplace manifests, improving the reliability of marketplace integrations.
- Updated the server and plugin logic to utilize the new fetching mechanisms, ensuring consistent handling of marketplace data.
- Enhanced tests to cover new URL normalization and fetching scenarios, ensuring robustness in marketplace management.
This update significantly improves the marketplace experience by streamlining URL handling and enhancing data fetching capabilities.
* Fix project auto-send cleanup spec
* Reconcile run messages on cancel
* Use active design system as visual direction
* Fix active design system prompt wording
* feat(workspace-tabs): implement workspace tabs functionality and file attachment handling
- Introduced a new `WorkspaceTabsBar` component to manage workspace tabs, allowing users to navigate between different views (projects, marketplace, etc.).
- Enhanced file handling capabilities in the `HomeHero` and `EntryShell` components, enabling users to stage and attach files before project creation.
- Updated the `App` component to support auto-sending attachments alongside the first message in a project.
- Improved CSS styles for workspace tabs and attachment UI, ensuring a cohesive design and user experience.
This update significantly enhances the workspace navigation and file management features, providing users with a more intuitive and efficient workflow.
* refactor(workspace-tabs): streamline workspace tabs and UI components
- Removed unused components and actions from the `WorkspaceTabsBar` and `AppChromeHeader`, simplifying the codebase.
- Updated CSS styles for the workspace shell and tabs, enhancing visual consistency and reducing element sizes for a cleaner layout.
- Introduced a new client type detection mechanism to dynamically adjust the workspace shell's class, improving responsiveness.
- Added tests for the `WorkspaceTabsBar` to ensure proper navigation and tab management functionality.
These changes improve the overall performance and user experience of the workspace navigation system.
* Update critical e2e for entry modal flow
* Stabilize entry critical e2e flows
* fix(ui): adjust workspace tabs and header styles for improved layout
- Updated the CSS for workspace tabs and the app header, reducing element sizes and padding for a cleaner appearance.
- Introduced a new button in the `WorkspaceTabsBar` for quick access to the home tab, enhancing navigation.
- Minor adjustments to the layout and styles to ensure consistency across components.
These changes enhance the user interface and improve the overall user experience in the workspace navigation system.
* feat(workspace-tabs): implement pinned home tab functionality
- Added a new pinned home tab feature to the `WorkspaceTabsBar`, allowing the home tab to remain accessible during navigation.
- Updated tab management logic to collapse duplicate home tabs into a single pinned instance when restoring from local storage.
- Enhanced CSS styles for workspace tabs to accommodate the new pinned tab design.
- Updated tests to verify the behavior of the pinned home tab and its interaction with other tabs.
These changes improve navigation consistency and user experience within the workspace.
* refactor(workspace-tabs): enhance tab management and styling
- Updated CSS styles for workspace tabs, adjusting padding and flex properties for improved layout and consistency.
- Refactored tab creation logic to ensure unique IDs for project and marketplace tabs, enhancing navigation clarity.
- Removed deprecated functions related to pinned home tabs, streamlining the codebase.
- Improved test cases to verify independent behavior of home tabs during navigation.
These changes enhance the user experience by providing a more intuitive tab management system and a cleaner UI.
* style(workspace-tabs): update CSS for improved layout and visibility
- Adjusted CSS properties for workspace tabs, including overflow, position, and z-index to enhance layout and stacking context.
- Ensured consistent styling across tab components for better visual hierarchy.
These changes contribute to a more polished and user-friendly interface within the workspace.
* style(entry-layout): update CSS variables for improved layout consistency
- Replaced fixed width values with CSS variables for the entry rail to enhance flexibility.
- Adjusted padding and height properties for better visual alignment and spacing.
- Introduced a new background style for the entry main topbar to improve aesthetics.
These changes contribute to a more responsive and visually appealing layout in the entry view.
---------
Co-authored-by: qiongyu1999 <2694684348@qq.com>
Co-authored-by: Eli <129168833+qiongyu1999@users.noreply.github.com>
* fix(web): fall back to srcDoc preview when HTML needs the sandbox shim
The URL-load HTML preview iframe is sandboxed with `allow-scripts`
only — no `allow-same-origin` — so any artifact that reads
`localStorage`/`sessionStorage` at startup throws SecurityError, its
React tree unmounts, and the preview goes blank. The srcDoc path
already polyfills both via `injectSandboxShim`
(apps/web/src/runtime/srcdoc.ts) before any user script runs, but
URL-load served raw HTML untouched. Agent-emitted React prototypes
that read Web Storage at mount went blank until the user toggled
Tweaks (which forces the srcDoc path).
Detect the two reliable signals — `<script type="text/babel">`
(Babel-standalone XHR-fetches and evals sibling `.jsx` files at
runtime; those routinely read Web Storage from `useState`
initializers) and direct `localStorage` / `sessionStorage` references
in the source — and set `forceInline` automatically so those
artifacts route back through the srcDoc path. Plain static HTML keeps
the URL-load benefits (real source maps, per-asset HTTP caching,
isolated per-script failures).
No new daemon endpoint, no new contract, no sandbox loosening. Pure
content sniff in the existing render-mode helper; reuses the same
`forceInline` seam the `parseForceInline` opt-out already uses. Tests
cover the new helper across positive (Babel-standalone variants with
attribute reordering, quoting, whitespace, case) and negative (plain
script tags, module type, JSON type, substring lookalikes) cases.
* fix(web): address review feedback on sandbox-shim fallback
- Accept unquoted `<script type=text/babel>` per HTML5 attribute syntax
(regex `["']` → `["']?`). Adds a focused test covering bare unquoted,
unquoted with unquoted `src=`, mixed unquoted/quoted, and the negative
case `<script type=text/babelish>` to confirm the trailing word-boundary
still rejects look-alikes.
- Memoize `htmlNeedsSandboxShim(source)` on `source`. HtmlViewer re-renders
on board/inspect/edit/slide state changes; the scan only changes when
the source itself does. Cheap micro-opt, free correctness win.
- Narrow the helper docstring's scope claim and add an explicit known
limitation: external scripts (`<script src="./app.js">`,
`<script type="module" src="./main.js">`) that read Web Storage during
module eval are *not* covered — the helper only sees the document, not
the linked subresource. Workaround documented: `?forceInline=1` or
Tweaks. Catching this case would require fetching every script
reference before deciding load strategy, duplicating browser work; not
worth the cost until a real report surfaces.
* fix(web): correct inline comment on `\b` boundary behavior
The comment claimed `\b` rejects `text/babel-other`, but `\b` matches
between `l` and `-` (hyphen is a non-word char), so the regex actually
does match that input. The test asserts `text/babelish` as the negative
case, which `\b` does correctly reject (`i` is a word char). Comment
now matches the regex's actual behavior, with a note that hyphenated
variants are a harmless false positive (srcDoc fallback is the safe
direction) and a pointer to the `(?=[\s>"'])` lookahead tightening if
a real case ever surfaces.
No behavior change; existing tests still pass.
* fix(web): align test comment with helper docstring on hyphenated variants
Same class of inconsistency the previous commit fixed in the helper:
the test comment claimed `type=text/babel-other` "remains a non-match",
but the assertion actually covers `type=text/babelish`, and the helper
docstring explicitly documents hyphenated variants as a safe
false-positive that does match. Comment now describes both shapes
correctly and explains why the hyphenated variant isn't asserted
(it's the documented safe direction, not a regression).
No behavior change; test count unchanged.
* chore: trigger CI
* refactor(web): rename Execution mode and tighten settings dialog UI
- Rename "Settings → Execution & model" to "Settings → Execution mode"
across the web UI, i18n keys, docs, and e2e selectors.
- Redesign SettingsDialog: kicker + title row in the modal head, a
flatMap-driven agent grid that renders the inline test-result row
beside the selected card, compact unavailable cards with right-aligned
install/docs links, and an install guide that only shows when the
user has no working agent picked.
- Trim verbose subtitle / hint copy across chat model, CLI proxy,
media providers, custom instructions, and memory sections.
- Add an `info` Icon variant for the redesigned settings hints.
- Update e2e selectors and docs that referenced the old menu label.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(web): polish Settings dialog — media providers, skills, MCP
Media providers
- Hide internal Stub fixture provider (settingsVisible: false)
- Split provider list into Available (integrated, editable) and Coming
Soon (collapsed <details> drawer with name/hint/Docs link only)
- Drop right-side Integrated/Configured badges from every row; all rows
in the main list are integrated by definition; inline grey "Saved"
chip next to the provider name is the only status indicator now
- "Saved" badge moves inline to the right of the provider name and uses
a neutral grey treatment (was a standalone green pill below the name)
- "Reload from daemon" button shows a 2s green "✓ Reloaded" flash on
success instead of leaving a permanent paragraph under the header;
errors remain sticky
Skills
- Replace three pill-row filter banks (Source, Type, Category) with a
compact single-row toolbar: search + three inline <select> dropdowns
side by side; active filter highlighted with a stronger border
MCP server
- Shorten section hint to one line
- Move WHAT YOUR AGENT CAN DO capabilities above the client dropdown
(motivate before asking to act)
- Move "Build the daemon first" warning below the code block where it
contextually explains why the command might fail, not as a top-level
error before the user has done anything
- Downgrade "Restart your client" left-border from accent orange to
border-strong grey — it is a next step, not a warning
External MCP
- Shorten section hint to one line
Misc CSS
- Add .sr-only utility for accessible off-screen live regions
- Add button.ghost.is-success-flash for transient success feedback
- Add .library-filter-selects / .library-filter-select for dropdown
filter rows
- Add .media-provider-coming-soon-* for the roadmap drawer
Co-authored-by: Cursor <cursoragent@cursor.com>
* [codex] Add Cursor Agent auth diagnostics (#1538)
* Add Cursor Agent auth diagnostics
* Handle Cursor not logged in auth status
* Address Cursor auth review feedback
* Classify Cursor stdout auth failures
* test: expand Memory and Routines coverage (#1521)
* test: expand settings and packaged coverage
* test: extend memory settings coverage
* test: cover routine settings failure states
* test: cover routine operation failures
* test: fix daemon test typing on CI
* test: decouple packaged smoke from orbit bug
* test: avoid live memory LLM calls in route tests
* test: fix daemon fetch typing in CI
* fix: restore preview comment and inspect toggles
* test: align manual edit flow with current inspector UX
* test: align comment attachment flow with current preview comments UI
* fix: probe resolved Codex launch path during detection
* fix: remove duplicate board activation helper after rebase
* test: update ghost cli detection mock
* test: align FileViewer toolbar expectation
* ci: move full app tests to extended lane
* ci: run app tests by changed scope
* ci: cover shared app inputs in test scopes
* ci: avoid setup-node cache in windows packaged smoke
* test: align extended settings and manual edit flows
* refactor(web): rename Execution mode and tighten settings dialog UI
- Rename "Settings → Execution & model" to "Settings → Execution mode"
across the web UI, i18n keys, docs, and e2e selectors.
- Redesign SettingsDialog: kicker + title row in the modal head, a
flatMap-driven agent grid that renders the inline test-result row
beside the selected card, compact unavailable cards with right-aligned
install/docs links, and an install guide that only shows when the
user has no working agent picked.
- Trim verbose subtitle / hint copy across chat model, CLI proxy,
media providers, custom instructions, and memory sections.
- Add an `info` Icon variant for the redesigned settings hints.
- Update e2e selectors and docs that referenced the old menu label.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(web): settings dialog UX polish — layout, dedup, and interactions
- Remove duplicate section headers from all settings sections
(Notifications, Appearance, Privacy, About, Design Systems, Skills,
MCP server, Connectors, Media providers, Routines)
- Restructure Notifications cards: title + toggle on same row, hint below
- Restructure Skills toolbar: search + New skill button in row 1,
filter dropdowns in row 2 with left-aligned labels
- Restructure Pet section: tabs and Wake button on same row
- MCP server: group capabilities and setup into separate cards,
remove nested double border on client picker
- Connectors: show connect errors as toast instead of inline card text,
position toast inside panel, hide single-provider tab
- Media providers: move Reload button to left-aligned small ghost button
- Memory: info icon shows path on hover, Path copied badge inline;
Extraction history and MEMORY.md as standalone collapsible cards;
group header hidden when only one type visible
- Pet grid cards: Adopt button hidden until hover, icon-only when adopted,
description truncated to 2 lines, text fills full width via abs positioning
- Agent cards: selected state uses accent border only, no background change
- Add sun/moon icons to Appearance theme buttons (Light/Dark)
- Shorten several hint strings for clarity
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(web): resolve i18n review comments from PR #1568
- Update settings.title and settings.envConfigure to localized
"Execution mode" in all 17 non-English locale files
- Add settings.memoryFlashPathCopied to all locales and use t()
in MemorySection instead of hardcoded English "Path copied"
- Add settings.agentModelHead to all locales and use t() in
SettingsDialog for "Model for:" agent model row header
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(web): update tests to match settings dialog redesign
- Add role prop to Toast (alert/status) so error toasts from
ConnectorsBrowser are announced immediately by screen readers
- Clear connectErrorToast on successful connector retry
- Update SettingsDialog.execution tests:
- Remove heading assertions for About and MCP server (headers
were intentionally removed as duplicate nav labels)
- Rewrite CLI env test to use codex-only fields (per-agent
filtering means only selected agent's fields are shown)
- Update Composio key hint text assertion to match shortened copy
- Replace filter button click with select change for Type filter
- Replace Configured/Unsupported/Integrated badge checks with
updated assertions matching the new media provider UI
- Replace disabled BFL row test with coming-soon section check
- Update SettingsDialog.media test: remove Fal.ai input assertions
(non-integrated providers no longer have editable fields)
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(web): unblock CI for #1568
Three small fixes to get Playwright back to green on the settings
dialog redesign:
1. `en.ts`: revert `settings.envConfigure` to "Configure execution mode".
This PR collapsed both `settings.title` (header gear) and
`settings.envConfigure` (entry-side foot pill) to the same string
"Execution mode", so `getByRole('button', { name: 'Execution mode' })`
resolved to two elements and tripped Playwright strict mode in the
three Composio-flow tests (entry-configuration-flows.test.ts:174,
228, 285). Restoring the distinct label also gives screen readers
a clearer hint for the pill, which doubles as a status display.
Non-English locales still alias the two keys; happy to follow up
on those, but they don't gate the (English-only) Playwright suite.
2. entry-configuration-flows.test.ts:167 — `Connectors` heading is now
rendered at `<h2>` in the modal-head (SettingsDialog.tsx:1545), with
the inner `<h3>` removed by design (see comment around line 1448).
Updated the assertion from `level: 3` to `level: 2`.
3. project-management-flows.test.ts:360 — same change for the `Pets`
heading.
Verified locally with `pnpm --filter @open-design/web typecheck` and
`pnpm --filter @open-design/e2e typecheck`. The actual Playwright
specs need the dev server up; I didn't rerun them here, but the
locator changes are mechanical and match the new DOM.
* fix(web): use exact match for Execution mode button locator
Playwright's `getByRole({ name })` defaults to substring matching, so
`{ name: 'Execution mode' }` still resolved to both the header gear
(aria-label "Execution mode") and the entry-side foot pill (aria-label
"Configure execution mode" — substring contains "Execution mode").
Strict mode tripped in the three composio-flow tests at lines 202,
257, and 319.
Adding `exact: true` makes each call resolve to just the header gear,
which opens the same dialog the foot pill does — the test outcomes
are unchanged.
---------
Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Caprika <56862773+alchemistklk@users.noreply.github.com>
Co-authored-by: shangxinyu1 <shangxinyu@refly.ai>
Co-authored-by: lefarcen <935902669@qq.com>
* fix(web): group design files by kind
* fix(web): unblock CI for #1551
- FileViewer test (line 434): add missing `projectKind="prototype"`
to match every other instance; this was the source of the typecheck
failure blocking workspace validation.
- DesignFilesPanel "groups files by kind" test: assert against
`.df-section-label` elements so the section header check is not
ambiguous with the per-row kind cell text.
- DesignFilesPanel batch-delete test: derive the expected file names
from the rendered row testids and use `arrayContaining` so the
assertion no longer depends on the (now kind-default) row order.
* fix(web): satisfy strict-index typecheck in batch-delete test
`onDeleteFiles.mock.calls[0][0]` tripped `noUncheckedIndexedAccess`
("Object is possibly 'undefined'"). Drop the separate length probe and
assert the exact array instead — `selected` is a `Set`, `handleBatchDelete`
spreads it with `[...selected]`, and the test clicks rows[0]/rows[1] in
that order, so insertion order is deterministic and equals
`[firstName, secondName]`.
---------
Co-authored-by: lefarcen <935902669@qq.com>
* fix(web): localize accent controls
* fix(web): localize accent default label
* fix(web): unblock CI for #1565
Add missing `projectKind="prototype"` to the FileViewer deck-render
test (line 434) so workspace typecheck stops failing on the
`Property 'projectKind' is missing` error. This mirrors every other
FileViewer render in the same file and is unrelated to the accent
localization changes in this PR — it's drift from a recent change
on main that made `projectKind` required.
---------
Co-authored-by: lefarcen <935902669@qq.com>