mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
42 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0b551c8afe
|
Merge b0c0559198 into 53fb175855
|
||
|
|
53fb175855
|
fix(web): truncate long filenames in file list (no-preview state) (#3370)
Some checks failed
visual-baseline / Capture visual baselines (push) Waiting to run
ci / Detect CI change scopes (push) Successful in 0s
landing-page-ci / Validate landing page (push) Failing after 1s
landing-page-staging / Deploy landing page to staging (push) Has been skipped
nix-check / build (push) Failing after 2s
ci / Validate Nix flake (push) Has been skipped
ci / Preflight (push) Failing after 2s
ci / Workspace unit tests (push) Failing after 2s
ci / Daemon workspace tests (push) Failing after 2s
ci / Web workspace tests (push) Failing after 2s
ci / Browser tests (push) Failing after 2s
ci / Build workspaces (push) Failing after 2s
ci / Validate workspace (push) Failing after 0s
ci / Runtime trace (push) Has been skipped
When the design files preview pane was closed, a very long filename
would expand its `<td.df-cell-name>` and push the kind / mtime / menu
columns off-screen — the auto-layout `<table>` had no width
constraint on the cell, so the existing `text-overflow: ellipsis`
on `.df-row-name` never engaged.
The `:not(.no-preview)` overrides in `routines.css` already pinned
the row's children to `width: 100%; max-width: 100%` when a preview
pane was open, but the no-preview state — the one shown in the issue
screenshot — had no equivalent guard.
CSS:
- `.df-cell-name`: add `max-width: 0; min-width: 0` so the table
cell collapses to its column allocation in auto-layout.
- `.df-row-name-wrap`: add `max-width: 100%`.
- `.df-row-name`: add `max-width: 100%; min-width: 0` so the flex
child clamps to the wrap and the existing ellipsis engages.
JSX (DesignFilesPanel.tsx):
- Add `title={f.name}` (and the equivalent for directory rows and
live-artifact rows) on `.df-row-name`. The browser surfaces the
full filename on hover even when the visible text is truncated, so
users can read the leading characters without opening the preview
pane. `<DfPreview>` already renders the full name with
`word-break: break-word`.
Closes #3260
Validation:
- pnpm exec vitest run tests/components/DesignFilesPanel.long-name-truncate.test.tsx
→ 3/3 passed (1 was red on main: title attr was absent)
- pnpm --filter @open-design/web test → 2501/2501 passed (260 files)
- pnpm --filter @open-design/web typecheck → green
- pnpm guard → green
Note: jsdom does not measure layout, so the truncation itself can't
be asserted directly. The specs encode the structural contract the
CSS depends on (cell / wrap / name nesting + the `title` attr) so a
JSX shape change won't silently regress the fix.
|
||
|
|
9146dc1c57
|
fix(web): persist design files view state across navigation (#2303)
* fix(web): persist design-files view state across navigation
pageSize, sortKey, sortDir, and kindFilter reset on every navigation
because DesignFilesPanel remounts via key={projectId}. Persist them to
localStorage under od:design-files:view-state:v1:<projectId> so each
project's view prefs survive tab-switching.
- Read persisted state via lazy useState initializers (SSR-safe try/catch)
- Write back in a single useEffect keyed on all four values
- Scoped per-project so proj-a settings never bleed into proj-b
- Schema-guarded: invalid/missing fields fall through to defaults
- Red spec: apps/web/tests/components/DesignFilesPanel.view-state-persist.test.tsx
* fix(web): address review feedback on view-state persistence
- Add typeof window guard in readViewState for explicit SSR safety
- Consolidate 4 separate localStorage reads into a single useRef read at
mount time; each lazy useState initializer now reads from savedViewState.current
instead of re-parsing localStorage independently
* fix(web): harden design-files view-state persistence
- Validate restored kindFilter values against the current ProjectFileKind
union via isProjectFileKind() so stale stored values from a prior schema
are dropped silently instead of being cast unchecked.
- Introduce DEFAULT_SORT_KEY/SORT_DIR/PAGE_SIZE constants so the useState
initialisers and the new validation guard share a single source of truth.
- Add viewStateHasMounted ref to skip the first-render write in the persist
useEffect. Without this guard every project the user visits accumulates a
default-value entry in localStorage on mount, growing stale-key garbage
unboundedly and making future field additions silently inject defaults into
every existing entry.
- Harden kindFilter test: replace the silent early-return-on-missing-trigger
with expect(filterTrigger).not.toBeNull() so a render failure surfaces as
a real test failure rather than a passing no-op.
* test(e2e): design files view state persists across navigation and reload
Adds a Playwright UI smoke test in e2e/ui/ that exercises the three key
guarantees of the view-state persistence fix:
(a) Tab-away / tab-back: navigating to a file tab and returning remounts
DesignFilesPanel (conditionally rendered); all four prefs (sortKey,
sortDir, pageSize, kindFilter) are restored from localStorage.
(b) Hard reload: localStorage survives page.reload(); prefs are intact on
the next mount.
(c) Per-project key isolation: a second project starts with defaults and
does not inherit values from the first project's localStorage entry.
The test uses OD_PORT=18011 / OD_WEB_PORT=18012 to avoid port conflicts with
the default development ports.
Also fixes a race in DesignFilesPanel: the stale-kind cleanup useEffect was
running against an empty availableKinds set before the async file list arrived
on mount, which cleared a kindFilter correctly restored from localStorage.
Guard added: skip the cleanup when availableKinds is empty.
Red on origin/main (no persistence logic exists there); green on this branch.
* fix(e2e): address code-reviewer feedback on view-state-persist test
- Add data-testid='df-page-size-select' to per-page <select> in
DesignFilesPanel (W2: decouple test from i18n string 'Show')
- Add StrictMode comment to viewStateHasMounted guard explaining
the dev-mode double-write behaviour (W1: document the invariant)
- Switch nav-away from dblclick to single-click + Open button,
matching the pattern used in app-design-files.test.ts (W4)
- Raise timeout from 60s to 90s for cold CI runners (W3)
- Unify seedTextFile/seedPngFile into shared seedFile helper (N3)
- Add home-hero-input assertion in gotoEntryHome (N2)
- Switch waitForPageSizeSelect to use data-testid (W2)
* test(e2e): split design-files persist into nav, reload, and per-project scenarios
* fix(web): tighten isPageSize to discrete option set, add invalid-value regression test
* fix(web): isolate DesignFilesPanel.test.tsx from persisted view-state key
|
||
|
|
1a3caf04f8 |
fix(web): merge main to resolve BoardComposerPopover conflict
Generated-By: looper 0.9.2 (runner=fixer, agent=opencode) |
||
|
|
755d84e64c
|
feat(web): merge Draw + Screenshot into one Studio mark tool (#3081) (#3277)
Forward-ports chaoxiaoche's Studio toolbar work from #3081 onto current main. The preview toolbar drops to 4 controls — Comment, Mark (the merged Draw/Screenshot tool with box-select + pen sub-tools), Edit, Comments — matching the latest design. The standalone Screenshot button and its copy-to-clipboard path are removed; capture now flows through the mark overlay. Also carries #3081's comment select-all/clear-selection panel and keeps the Draw send guard added in #3270 (Send disabled mid-run, Queue stays). Reconciled with main work that postdates #3081's base so nothing is lost: - Preserves #2190's preview iframe keep-alive pool and the AnnotationHoverPopover hover card (re-added on top of #3081's BoardComposerPopover, with its own anchor helper so it doesn't clash with the composer popover anchoring). - i18n: keeps every locale key main added; adopts #3081's mark wording. Behavior change: the comment side-panel Clear now deselects instead of batch-deleting selected comments (per #3081); per-comment delete and send-selected remain. Validation: pnpm --filter @open-design/web typecheck (clean), full web vitest (2354 passed), pnpm guard. Co-authored-by: chaoxiaoche <fanzhen910412@gmail.com> |
||
|
|
5b708c31a3 | refactor(web): migrate easy primitives | ||
|
|
77b865e4d1
|
fix(web): handle dropped file read failures (#2858) | ||
|
|
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. |
||
|
|
00b3f3e52d
|
feat(design-files): add directory navigation and localization for folders (#2442)
* feat(design-files): add directory support and localization for folders in design files panel * feat(directory-navigation): implement directory navigation and selection reset in DesignFilesPanel * feat(rename): improve draft handling for file renaming in DesignFilesPanel |
||
|
|
10e2019c59
|
Fix plugin publish and Open Design PR workflow UX (#2564)
* Fix plugin publish and PR workflow UX * Update plugin workflow test expectations * Fix fake gh repo view verification path * Fix plugin publish headless tests and preserve PATH in shell wrappers. The publish-repo flow needs real git commits and fake gh auth output that matches gh auth status parsing. Login shells no longer drop PATH so test fakes and agent wrappers stay visible to nested gh/git calls. Co-authored-by: Cursor <cursoragent@cursor.com> * Restore plugin action card when share-task startup fails. If startGeneratedPluginShareTask rejects before a task is created, clear hiddenAssistantPluginActionPaths so the assistant action card reappears. Co-authored-by: Cursor <cursoragent@cursor.com> * Make daemon vitest self-contained for publish-github CLI shell-outs. Build dist/cli.js in tests/setup.ts when missing and set OD_DAEMON_CLI_PATH before server.ts resolves OD_BIN, so headless plugin tests pass from a clean checkout without a prior manual daemon build. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
204599a7ae
|
feat(analytics): ship PostHog v2 event schema (#2285)
* feat(analytics): ship PostHog v2 event schema
Aligns the PostHog wire format with the product team's v2 tracking
spec (Open Design 埋点文档 2.0). The previous v1 catalogue defined a
flat per-page event name (home_view / studio_click / settings_view…);
v2 collapses everything to four core events identified through the
page_name + area + element triplet so dashboards can group by surface
without owning a separate event per page.
Key changes
- packages/contracts/src/analytics: collapse to page_view / ui_click /
surface_view / *_result event names; bump EVENT_SCHEMA_VERSION to 2;
rename the wire field anonymous_id → device_id (value unchanged);
promote the configure-state triplet (has_available_configure_cli /
configure_type / configure_availability) to a global PostHog register
so every event inherits it without per-helper boilerplate.
- apps/web/src/analytics: rewrite the 43 trackXxx helpers behind the
new typed catalogue; opt out of PostHog's built-in UA bot filter so
legitimate embedded webviews, fingerprinted browsers, and the
Playwright-based e2e runs ingest captures (the Privacy → "Share
usage data" toggle remains the single consent gate).
- apps/web components: wire P0/P1/P2 click + view + result surfaces
end-to-end — left nav, toolbar, home chat composer, recent projects,
new project modal, plugins / design systems / integrations /
automations pages, file manager, artifact toolbar/header/share popup,
feedback panel, settings sidebar / language / appearance /
notifications / pets / privacy / connectors. Fixes the v1 feedback
bug where action=clear_feedback_rating shipped rating=null instead of
the rating being cleared.
- apps/daemon: extend run_created / run_finished with the v2 context
(entry_from / project_kind / target_platforms / fidelity /
connectors / etc.), add explicit error_code classification on
result=failed (run.errorCode → AGENT_SIGNAL_* → AGENT_EXIT_* →
AGENT_TERMINATED_UNKNOWN), and read device_id from the new
x-od-analytics-device-id header. Also moves the run_created /
run_finished emission to the canonical /api/runs handler in
server.ts; the chat-routes copy was shadowed by Express's earlier
registration and never executed, which also meant run.clientType
never made it to Langfuse — fixed in the same move.
Verification
- pnpm guard / pnpm typecheck clean for daemon, web, and contracts.
- pnpm --filter @open-design/web test: 1645/1645 passing.
- End-to-end smoke through Playwright + local PostHog ingest project
420348: every page_view (home/projects/automations/design_systems/
plugins/integrations/chat_panel/file_manager), every nav element,
the new_project_modal surface_view + tab + create flow, the
plugin_replacement_modal surface_view, settings_view across nine
sections, settings_cli_test_result (codex CLI), the
project_create_result success path, and run_created + run_finished
(result=failed, error_code=AGENT_EXIT_1) all reached PostHog with
the v2 schema and the expected device_id / page_name / area /
element / fidelity / target_platforms props. The remaining
*_result events (artifact_export / feedback_submit / file_upload /
plugin_replacement / settings_byok_test / settings_connector_auth)
are wired in code; production traffic will trigger them.
* fix(analytics): preserve style category on design-systems surface chip switch
The merge resolution in DesignSystemsTab incorrectly re-introduced a
`setCategory('All')` call alongside the new `trackDesignSystemsTopClick`
emit. main intentionally keeps the active style category when the surface
filter refines within it; the regression was caught by the existing
"keeps the style category when a surface chip refines within it" test
in tests/components/DesignSystemsTab.test.tsx.
* fix(analytics): address review — senseaudio passthrough + daemon-side configure-state
Two follow-ups from the v2 schema review on #2285:
1. `byokProtocolToTracking()` was still falling through to `null` for
`senseaudio` even though the v2 BYOK provider enum now lists it. Every
`SettingsDialog` BYOK call site guards on `if (byokProviderId)`, so a
user on SenseAudio was silently dropping the provider-option,
field-focus, and test-result captures. Added the missing case so
SenseAudio gets the same analytics coverage as the other providers.
2. The daemon-authoritative `run_created` / `run_finished` events were
missing the configure-state triplet (`has_available_configure_cli` /
`configure_type` / `configure_availability`) that v2 promotes to a
global register on the web side. Daemon captures don't go through the
PostHog global register, so dashboards couldn't segment run lifecycle
by execution setup after the migration.
The fix derives the triplet server-side from `detectAgents()` and the
request's `agentId` before `design.analytics.capture(...)`:
- has_available_configure_cli: any CLI on PATH reports installed
- configure_type: 'local_cli' when the run targets an installed CLI,
otherwise 'unknown' (daemon can't see BYOK keys, which live in
web-client storage)
- configure_availability: 'available' / 'unavailable' / 'unknown'
based on the requested agent's install status, with a fallback to
'available' when any CLI is installed
This keeps the v2 schema consistent across both daemon-side and
web-side captures.
* fix(analytics): wire setConfigureGlobals so browser events carry fresh state
Third follow-up from the v2 schema review on #2285. The previous fix
addressed senseaudio + daemon-side configure-state, but reviewer flagged
that `setConfigureGlobals` was still defined-only — no caller — so every
browser-side capture inherited the boot defaults
(`has_available_configure_cli=false`, `configure_type='unknown'`,
`configure_availability='unknown'`). PostHog dashboards therefore could
not segment the new `page_view` / `ui_click` / `surface_view` events by
execution setup after a user configured their environment.
Changes:
- `packages/contracts/src/analytics/events.ts` — add a pure
`deriveConfigureGlobals(mode, agentId, agents, byokConfigured)` helper
so the web client and the daemon can derive the triplet from the same
source of truth. The helper covers all 5 `configure_type` buckets
(`local_cli` / `byok` / `both` / `none` / `unknown`) and the 3
`configure_availability` buckets (`available` / `unavailable` /
`unknown`).
- `apps/web/src/App.tsx` — add a useEffect that re-derives the triplet
whenever the user changes execution mode, selects a new CLI, saves a
BYOK key, or the detected-agent list refreshes, then pushes it to
PostHog via `analytics.setConfigureGlobals(...)`. The setter goes
through the provider so the analytics module stays the single source
of truth.
- `apps/web/src/analytics/provider.tsx` — expose
`setConfigureGlobals` on the analytics context and the test stub so
consumers route through the provider boundary.
- `apps/daemon/src/server.ts` — switch the daemon-side derive in
`/api/runs` to the shared `deriveConfigureGlobals` helper so the
authoritative run_created/run_finished captures match the web-side
payload. BYOK credentials live in the web client and stay invisible
to the daemon, so the daemon arm passes `byokConfigured: undefined`
and falls back to the installed-CLI signal.
- `apps/web/tests/analytics-configure-globals.test.ts` — new regression
test that pins the derive behavior across all branches and confirms
the setter actually mutates the client-side store. Locks the wire-up
so a future refactor can't silently turn the setter back into a
no-op.
Verification: pnpm guard clean; daemon / web typecheck clean; web tests
1703/1703 passing (up from 1696 — 7 new tests in the configure-globals
suite).
* fix(analytics): emit projects page_view + drop misattributed chat_panel source
Fourth review pass on PR #2285. Two follow-ups from mrcfps:
1. DesignsTab (projects landing) was emitting click events but no
matching page_view. Opening /projects without clicking anything left
the surface invisible in PostHog. Added a once-per-mount
trackPageView({ page_name: 'projects' }) with the same ref-keyed
pattern HomeView / PluginsView use.
2. ChatComposer was hard-coding source: 'recent_project' on every
chat_panel page_view. The web router currently only carries
projectId / conversationId / fileName, so we cannot distinguish a
New-project launch from a template-pick or a Recent-projects click
from this layer. A false constant would over-attribute every chat
launch to 'recent_project' and break the funnel slice this schema
was meant to unlock. Dropped the field for now — better no source
than the wrong source — until the router grows a launch-source
channel; the field is still defined as optional on PageViewProps so
the channel can land in a follow-up PR.
Verification: web typecheck clean; web tests 1703/1703 passing.
* fix(analytics): correct plugin-replacement async result + heterogeneous upload + missing requestId
Three follow-ups from the fifth review pass on PR #2285:
1. **plugin_replacement_result emitted before the apply settled**
(`apps/web/src/components/HomeView.tsx`). The modal's confirm action
was a synchronous wrapper around an async `usePlugin(...)` call, so
the surrounding try/catch never observed real failures and every
attempt was reported as `result=success`. Changed `PendingReplacement.
confirm` to return `Promise<void>`, made the wrapper return the
underlying promise, and moved the analytics emit into an async
IIFE in the click handler so the success/failure branches reflect
the actual outcome.
2. **file_upload_result mis-typed heterogeneous batches**
(`apps/web/src/components/FileWorkspace.tsx`). The earlier
implementation only inspected `picked[0]`, so a mixed batch like
`image.png + demo.mp4` reported `file_type=image`. Per the comment
above the block ("mixed batches collapse to other"), the
implementation now maps every file to a tracking type, collapses to
`other` when more than one distinct type is present, and falls
back to the single type otherwise.
3. **project_create_result lost the click→result correlation id**
(`apps/web/src/components/NewProjectPanel.tsx`). The click event
no longer carried the locally-generated `requestId` that
`project_create_result` keeps, so the two could not be joined.
`trackNewProjectModalElementClick()` now accepts an optional
`{ requestId }`, mirroring the other helpers, and the create-button
click threads the same id used for the result.
Verification: web typecheck clean; web tests 1703/1703 passing.
* fix(analytics): gate configure-state on agents probe + drop unsent run_created fields
Two follow-ups from the sixth review pass on PR #2285:
1. **Cold-start configure-state was stamped before fetchAgents() landed**
(`apps/web/src/App.tsx`). The useEffect that pushes the v2 triplet
into the PostHog global register fired on first paint with
`agents=[]`, so the first home/projects/plugins page_view reported
`has_available_configure_cli=false` / `configure_availability=
unavailable` even on machines that did have an installed CLI. The
effect now waits on `agentsLoading === false` and leaves the boot
defaults ('unknown'/'unknown') in place until the probe resolves.
2. **Daemon read run-context fields the web never sends**
(`apps/daemon/src/server.ts`). The daemon-side run_created /
run_finished baseProps read `projectKind`, `entryFrom`,
`projectSource`, `targetPlatforms`, `companionSurfaces`, `fidelity`,
`connectors`, `useSpeakerNotes`, `includeAnimations`,
`referenceTemplate`, and `aspect` from `req.body`, but
`packages/contracts/src/api/chat.ts` and
`apps/web/src/providers/daemon.ts` don't carry those keys on the
wire. Reading them therefore always produced null/undefined.
Dropped the unsent fields from the daemon capture; a follow-up can
extend the create payload to thread the real context through. The
`design_system_id` field stays because the chat contract does send
it.
Tests: added 3 regression tests in `tests/analytics-configure-globals.
test.ts` covering the boot-time gating contract (empty agents +
daemon mode → unavailable / local_cli; installed agent → available;
undefined agents list → unavailable). Verification: web typecheck
clean; daemon typecheck clean; web tests 1706/1706 passing (up from
1703 — 3 new cold-start tests).
* fix(analytics): pin mode='daemon' so missing-agent run reports unavailable
Eleventh review pass on PR #2285. mrcfps flagged that
`apps/daemon/src/server.ts` was calling `deriveConfigureGlobals(...)`
without `mode`, so the helper fell through to the generic branch.
Result: a run for an uninstalled agent was tagged
`configure_availability: 'available'` whenever any OTHER CLI was on
PATH, because the generic branch only looks at the cohort-wide
"any installed?" signal. That precisely undermines the slice the
daemon emit is trying to power.
The daemon's /api/runs handler is always a daemon-mode capture
(daemon is the local CLI runner — BYOK lives in the web layer), so we
now pin `mode: 'daemon'` on the call site. The helper then judges
`configure_availability` from the REQUESTED agent's install status and
reports `unavailable` when the user picked an agent that is not
installed, even if peers are.
Added a regression case in `tests/analytics-configure-globals.test.ts`:
`{ mode: 'daemon', agentId: 'codex', agents: [{claude,true},{codex,false}] }`
→ `{ has_available_configure_cli: true, configure_type: 'local_cli',
configure_availability: 'unavailable' }`.
Verification: daemon typecheck clean; web tests 1707/1707 passing
(up from 1706 — 1 new regression test).
* fix(analytics): hoist chat_panel page_view + thread requestId
- Move chat_panel page_view emit from ChatComposer to ProjectView so
it survives activeConversationId-driven ChatPane remounts. ProjectView
keys the dedupe ref by project.id; the composer drops its duplicate.
- Thread { requestId } into trackAssistantFeedbackReasonSubmitClick so
the click pairs with the existing feedback_submit_result on the same
request id (mirrors the trackNewProjectModalElementClick pattern).
* fix(analytics): keep v2 super-props alive across reset and stamp design_system_source
- Snapshot the register payload in client.ts on PostHog init and
re-register it from applyConsent(true) and applyIdentity() so a
privacy-toggle or Delete-my-data rotation does not resume capture
without event_schema_version / device_id / session_id / locale /
configure-state globals. setConfigureGlobals() also patches the
cache so a later restore picks up the current configure state.
- Stamp design_system_source on daemon-side run_created / run_finished
(it is required by RunCreatedProps / RunFinishedProps). Daemon
can't tell default vs user_selected vs inherited from the wire, so
it derives 'unknown' when designSystemId is present, 'not_applicable'
otherwise — a follow-up that threads designSystemSource through
CreateRunRequest can replace this with the precise source.
|
||
|
|
210b94069a
|
feat(senseaudio): BYOK chat with image + video generation tools (#2065)
* feat(senseaudio): BYOK chat with image + video generation tools
Adds SenseAudio as a first-class BYOK chat protocol and wires the daemon's
chat proxy with a tool loop so BYOK users can generate images and videos
without dropping to a CLI agent.
- BYOK protocol: new senseaudio tab + /api/proxy/senseaudio/stream route +
connection-test + provider-models discovery (OpenAI-compatible wire)
- Tool loop: generate_image (synchronous /v1/image/sync) and generate_video
(async /v1/video/create + 5s polling /v1/video/status, 10-min ceiling,
periodic progress log every 30s)
- Settings dropdown + chat-composer dropdown for the BYOK image model
default; generate_image's model enum lets the LLM override per call
- Seed-on-success: a successful BYOK chat call idempotently mirrors the
key into media-config (preserves env-resolved + already-stored keys)
- Generated artifacts land in <projectsRoot>/<projectId>/ so FileViewer,
DesignFilesPanel, and project export pick them up automatically;
legacy /api/byok-image/:id route kept for old conversation links
- Markdown renderer learns  image syntax with a scheme
allowlist (http(s) / data:image/ / blob: / relative paths)
- i18n key settings.byokImageModel across all 19 locales
- 3 SenseAudio image models registered (2.0, 1.0, doubao-seedream-5.0);
1 video model (doubao-seedance-2.0)
- Tests: byok-tools (29), media-senseaudio-image (8), media-config seed
(7), proxy-routes (47), markdown image rendering (8)
* fix(senseaudio): unblock image gen + design file preview switching
- SenseAudio /v1/image/sync rejected the previous size mapping with
`参数错误:size` (1664x936, 936x1664, 1280x960, 960x1280 are not in
the gateway's accepted set). Switched to standard HD / SD sizes that
every aspect bucket can hit: 1024×1024, 1280×720, 720×1280,
1024×768, 768×1024. Kept the byok-tools and media.ts tables in sync
so the BYOK chat tool and the CLI agent path both stop failing on
non-square aspects.
- DesignFilesPanel's <DfPreview> was missing a key prop, so React
reused the same iframe DOM node when the user picked a different
file — the src prop changed but the iframe never navigated. Added
key={previewFile.name} so the previous preview unmounts cleanly.
- Updated byok-tools + media-senseaudio-image tests for the new size
expectations.
* docs(senseaudio): clear stale provider hint + update README
- Settings → Media → SenseAudio: clear the auto-promoted
"Image · TTS · 70+ voices · clone" hint; the provider label alone is
enough now that the BYOK chat surface covers image + video tooling.
- README: list the new senseaudio (and missing ollama) proxy routes so
the BYOK section reflects what the daemon actually serves, and
mention the generate_image / generate_video chat tools that ship
with the SenseAudio path.
* fix(senseaudio): address PR #2065 review feedback
Three non-blocking review notes from @PerishCode on PR #2065:
1. Drop the dead /api/byok-image/:id route. The PR description claimed
it was "legacy fallback for old chat history" but that storage
layout never existed on main, so the route can only ever 400 or
404 — never 200. Removed the handler, the isSafeByokImageId
export, the unused createReadStream / stat / path / Request /
Response imports, and the two byok-image regression tests.
2. Add rejectProxyPluginContext guard to the senseaudio proxy
handler so it matches the invariant the other five proxy paths
already enforce (plugin runs must go through /api/runs for
snapshot pinning). Extended the existing "API fallback rejects
plugin runs" describe to also cover /api/proxy/senseaudio/stream
with the 409 PLUGIN_REQUIRES_DAEMON expectation.
3. Wrap the secondary image / video downloads (the URLs the
SenseAudio gateway hands back in /v1/image/sync .url and
/v1/video/status .video_url) in validateBaseUrlResolved so a
malicious gateway can't point us at 169.254.169.254 (AWS / Azure
metadata) or RFC1918 hosts via the response payload. Also passed
`redirect: 'error'` on both fetches to match the SSRF posture
the primary proxy fetch already uses. The new
assertExternalAssetUrl helper lives next to executeGenerateImage
so future tool downloads can reuse it.
Tests: 120/120 daemon tests pass; guard + typecheck green.
* fix(senseaudio): mirror SSRF guard onto renderSenseAudioImage CLI path
Follow-up to
|
||
|
|
b311885bee
|
Support folder drops in Design Files (#1662)
Co-authored-by: mzl2233 <mzl2233@users.noreply.github.com> |
||
|
|
3cecb1c881
|
Polish project workspace UI (#2201) | ||
|
|
fa9f1d37be
|
feat(design-files): add filter-by-kind dropdown to the design files viewer (#1990)
* feat(design-files): add filter-by-kind dropdown
The design files viewer already supports grouping and sorting by kind,
but on projects with many files of mixed kinds you still see everything
in one list. Adds a small dropdown next to the group-by toggle that
filters the visible files to one or more selected kinds.
Behavior:
- Dropdown only appears when the project has at least two distinct
kinds; on a single-kind project the control would be noise.
- Multi-select via checkboxes. Empty set means no filter (show all).
- Each row shows the kind glyph, label, and the per-kind file count.
- Trigger label collapses sensibly: "Filter by kind" when none selected,
the single kind's label when one selected, "{n} kinds" when many.
- Filter applies upstream of sort/group/page, so pagination ranges and
the "1-N of M" counter reflect the filtered total.
- Page resets to 0 on filter change so the user doesn't land on an
empty page.
- Selected kinds that disappear from the file list (after a delete or
refresh) are pruned automatically — a stale filter cannot silently
hide everything.
- Popover closes on outside click and Escape.
i18n keys: designFiles.filterBy, designFiles.filterClear,
designFiles.filterCount. All non-English locales inherit via the
existing `...en` spread pattern; zh-CN is the one fully-explicit
dictionary and gets translated values inline.
No behavior change to the group-by toggle, sort, pagination, selection,
or any other existing control. Filtering is layered alongside.
* fix(design-files): prune selection when filter hides selected rows
Codex review flagged that the filter-by-kind change only reset
pagination, not selection. If a user selected files, then narrowed the
filter to a kind that excludes some of them, the now-hidden rows
remained in `selected`. Bulk delete / download still operated on the
full set, so the user could destructively act on rows they could no
longer see — especially risky for the delete path.
Add a useEffect that prunes `selected` to the filtered set whenever
`filteredFiles` or `kindFilter` changes. The empty-filter branch is a
no-op so clearing the filter doesn't disturb any pre-existing
selection — only narrowing the filter prunes.
|
||
|
|
22a3b99a47 |
Merge origin/main into preview/v0.8.0
Sync 49 commits from main. Conflicts resolved:
- .github/workflows/ci.yml: kept v0.8.0 granular per-area gating, added main's
linux specs + release-stable.yml + release-preview.yml triggers
- .github/workflows/release-preview.yml: kept v0.8.0's full workflow over main's placeholder
- apps/web/src/components/AssistantMessage.tsx: combined v0.8.0 file-ops
summary with main's stripTodoToolGroups + suppressAskUserQuestionFallbackText
- apps/web/src/components/ChatPane.tsx: kept both new imports
- apps/web/src/index.css: kept both .msg-plugin-chip and .user-copy-btn blocks
- e2e/ui/*.test.ts: kept v0.8.0 openEntrySettingsDialog helper over main's
inline dialog navigation (UI was redesigned in v0.8.0)
- nix/package-{daemon,web}.nix: kept v0.8.0 pnpmDepsHash; rerun nix build to refresh
|
||
|
|
01e54700a2
|
fix(web): make file grouping by kind work (#1551)
* 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> |
||
|
|
76defffb93
|
Garnet hemisphere (#1702)
* 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 |
||
|
|
53997990b7 |
Merge origin/main (post-0.7.0) into reconciled garnet branch
Second-pass merge layering 41+ new commits from origin/main on top of the first reconcile commit. Headline upstream additions absorbed: - 0.7.0 release: redesigned chat bubble user-text styling, neutralised palette, lucide icons, ElevenLabs audio voice option discovery in the prompt composer, analytics tracking (PostHog) wired across home / studio / create surfaces, Prometheus `/api/metrics` endpoint, critique-theater drop-in mount with a settings toggle. - Misc upstream fixes (titlebar padding, release header layout, deck preview chrome, feedback form auto-scroll, conversation-created SSE on routine runs, etc.) Conflict resolutions (12 files, ~22 hunks): - contracts barrel + prompts/system: union of both sides; new analytics exports (`./analytics/events`, `./analytics/public-params`) added alongside garnet's plugin/atom/genui exports. Both ElevenLabs voice fields (audioVoiceOptions/audioVoiceOptionsError, main) and pluginBlock/activeStageBlocks (garnet) preserved on ComposeInput. - daemon/server.ts: Prometheus `/api/metrics` route inserted after garnet's `/api/daemon/shutdown`. main's `createAnalyticsService` call added before the chat-run service init alongside the prior reconcile note about the dropped legacy POST /api/projects body. - App.tsx: handleCreateProject now consumes both garnet's plugin fields (pluginId / appliedPluginSnapshotId / pluginInputs / autoSendFirstMessage) and main's analytics requestId. Tracking fires success + failure paths; PluginLoopHome auto-send sessionStorage flag is preserved. - ProjectView.tsx: the garnet auto-send useEffect coexists with main's `useCritiqueTheaterEnabled()` hook. - ChatComposer.tsx: imports merged (drop now-unused fetchSkills, add analytics provider + tracking + buildVisualAnnotationAttachment). - index.css: main's redesigned `.msg.user .user-text` chat bubble styling wins over garnet's plain text rule; garnet's `.msg-plugin-chip*` rules preserved alongside. - EntryView.tsx: accepted HEAD (garnet wrapper) — consistent with reconcile decision #2. main's added PetRail / TopTab / analytics view tracking is intentionally NOT brought into the wrapper; the follow-up to re-integrate PetRail / image-templates / video-templates into EntryShell still stands and now also covers analytics view-tracking hooks. - daemon/package.json + pnpm-lock: merged dep set (tar + posthog-node + prom-client coexist). - Test fixtures (FileWorkspace.test): kept garnet's plugin-folders describe block intact; main's projectKind="prototype" addition is dropped where it conflicted with garnet's plugin-folder fixture files. Verification: `pnpm install` (after lockfile reconciled), `pnpm typecheck` exits 0 across all workspace packages. Follow-up not done in this commit: - PetRail / image-templates / video-templates / 0.7.0 analytics view-tracking hooks need to be added to EntryShell. - Critique-theater settings toggle UX (added on main) lives in the SettingsDialog hierarchy; the reconcile state preserves the SettingsDialog so this should work without changes, but no end-to-end verification yet. |
||
|
|
d3602be666 |
Merge origin/main into garnet-hemisphere (reconcile)
Merge of `origin/main` (`03ed3960`, 2026-05-13 pre-0.7.0) into the 161-commit garnet-hemisphere line, reconciling the product-vibe-coded plugin/marketplace/EntryShell surfaces from garnet with the routines / skills / live-artifacts feature work landed on main since the fork point. Headline decisions (full rationale + side-by-side screenshots in `specs/change/20260513-garnet-skills-automations/reconcile-result-vs-garnet.md`): - #1 SettingsDialog: keep main's Memory / Skills / External MCP / Connectors / Routines / MCP server nav items even though the top-level /integrations + /automations routes also cover them. Two entries coexist for now; revisit once Track A/B fill in the placeholder content. - #2 EntryView: accept garnet's thin wrapper delegating to EntryShell. Main's PetRail sidebar + image-templates/video-templates tabs are intentionally deferred to a follow-up that re-integrates them into the new EntryShell layout. - #3 /integrations + /automations top-level routes: kept (garnet's product intent). Skills tab is still a "Coming soon" placeholder awaiting Track A; Routines/Schedules/Live-artifacts cards on /automations are still mock awaiting Track B. - #5 DesignFilesPanel: hybrid — main's pagination as primary list, garnet's Plugin folders section preserved between the live-artifacts block and the pagination block. (by-kind sections drop in favour of pagination; plugin-folders rendering stays because it is a garnet-specific product addition.) - #7 server.ts (10 hunks, ~5400 conflict lines): manual hunk-by-hunk merge. Both daemon admin routes + plugin/genui routes (garnet) and routines/memory/skills upgrades (main) preserved. Garnet's inline project route block kept alongside main's `registerProjectRoutes` / `registerProjectUploadRoutes` modular wiring — duplicate route audit is a follow-up. Garnet's POST /api/projects plugin-snapshot resolution + default-scenario fallback is intentionally dropped from the inline body (now handled by registerProjectRoutes) and listed for follow-up re-integration into `project-routes.ts`. Verification (worktree at /Users/elian/Documents/open-design-garnet): - `pnpm typecheck` exits 0 across all workspace packages - daemon (`pnpm tools-dev run web --namespace reconcile-shots`) boots, serves `/api/daemon/status` healthy, and survives a Playwright walkthrough of /integrations / /automations / home / projects / design-systems / plugins / settings dialog - `@open-design/plugin-runtime` package built (was missing dist/ on garnet); without it the daemon's plugins/* imports fail at boot Track A (Skills tab → real SkillsSection) and Track B (Automations cards → real routines / live-artifacts backend) are the two remaining follow-ups blocking the placeholder/mock content from going live. See `spec.md` and `track-skills.md` in the same directory. |
||
|
|
9040088f1c
|
fix(web): remove redundant bulk-select button (#1550) | ||
|
|
5f71968f61 |
feat(daemon, web): implement plugin sharing features for GitHub and Open Design contributions
- Added new API endpoints for publishing plugins to GitHub and contributing to Open Design, enhancing the plugin sharing capabilities. - Introduced functions for handling plugin sharing actions, including `publishGeneratedPluginToGitHub` and `contributeGeneratedPluginToOpenDesign`. - Updated the `DesignFilesPanel` and `FileWorkspace` components to support new sharing functionalities, allowing users to publish or contribute plugins directly from the interface. - Enhanced the UI with new buttons for publishing and contributing plugins, improving user interaction and experience. - Added tests to ensure the reliability of the new sharing features and their integration within the existing plugin management system. This update significantly improves the plugin ecosystem by enabling users to share their creations with the community and streamline collaboration. |
||
|
|
6f818d971d |
feat(daemon, web): implement plugin folder installation and enhance atom worker registry
- Added a new API endpoint for installing plugins from specified folder paths, improving the plugin management experience. - Introduced functions for normalizing and validating project plugin folder paths, ensuring robust error handling. - Implemented a registry for built-in atom workers, allowing for dynamic signal aggregation during pipeline execution. - Enhanced the `runStageWithRegistry` function to support multiple atom workers, merging their outputs with pessimistic logic. - Updated the UI components to display plugin folder candidates and facilitate user interactions for plugin installation. - Added tests for the new atom worker registry and plugin folder installation features, ensuring reliability and correctness. This update significantly enhances the plugin installation process and the overall functionality of the atom worker system, providing users with better tools for managing plugins and their interactions. |
||
|
|
0f0d214298
|
fix(web): render static previews for sketch json files (#1060)
* fix(web): render static previews for sketch json files * fix(web): tolerate malformed sketch text items * fix(web): harden sketch preview parsing * fix(web): preserve sketch items on round-trip * fix(web): clear sketch files destructively * fix(web): unblock unsupported sketch saves |
||
|
|
e11e86d468
|
feat(hyperframes): land HTML-in-Canvas across web + skills (#866)
* feat(hyperframes): land HTML-in-Canvas across web + skills Ships HTML-in-Canvas as a first-class HyperFrames video path: - 7 new video prompt templates (liquid glass, iPhone+MacBook, portal, shatter, magnetic, liquid background, text-cursor reveal). - skills/hyperframes/references/html-in-canvas.md, surfaced via SKILL.md description+triggers and the system-prompt pre-flight references list. - ChatPane starter prompts now branch by project kind and video model, so the hyperframes-html surface shows HTML-in-canvas-shaped prompts instead of the generic prototype trio. - NewProjectPanel propagates a picked template's model+aspect onto the project, and defaults videoModel to hyperframes-html when the hyperframes skill resolves for the video tab. Polish bundled in the same branch: - DesignFilesPanel empty state becomes a centered pill with a "New sketch" CTA; designFiles.empty copy simplified across 19 locales. - Topbar project title + meta render on one baseline row separated by a middot. - scripts/seed-test-projects.ts hardens daemon URL discovery against pnpm engine warnings on stdout. * fix(new-project): preserve explicit video model choice across tab revisits Latch a videoModelTouched guard once the user picks a model via the dropdown or via a template that declares one, so the hyperframes-html auto-default no longer silently overwrites the override when the Video tab is re-entered. Generated-By: looper 0.6.1 (runner=fixer, agent=claude-code) * fix(i18n): register hyperframes html-in-canvas templates, category, and tags Adds the seven new prompt-template ids, the "VFX / HTML-in-Canvas" category, and the new tag set to the de/ru/fr i18n bundles so the e2e localized-content coverage test passes. Generated-By: looper 0.6.1 (runner=fixer, agent=claude-code) * fix(daemon): inject html-in-canvas preflight for hyperframes runs The contracts-side derivePreflight() learned about references/html-in-canvas.md when this PR landed, but the daemon copy at apps/daemon/src/prompts/system.ts kept the older five-ref allowlist. server.ts:4138 wires composeSystemPrompt from the daemon copy into live chat runs, so the main HyperFrames flow this PR is meant to improve still wasn't auto-injecting the preflight directive in production. Mirror the html-in-canvas case into the daemon composer and lock it behind a daemon-side test so the two copies cannot drift again on this reference. The broader live-artifact preflight gap (artifact- schema / connector-policy / refresh-contract) is pre-existing drift and is intentionally out of scope here. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(web): restyle designs empty state as centered card on grid backdrop Swap the horizontal pill for a stacked card and add a faint grid backdrop so the empty designs surface reads as an intentional canvas rather than a gap. Title now wraps instead of truncating; container is taller. * fix(new-project): pin skillId to hyperframes when videoModel is hyperframes-html When the Video tab resolves its skill it used to fall back to `list[0]?.id` if no skill declared `default_for: video`. That list is built from an unsorted `readdir()` in apps/daemon/src/skills.ts, so a freshly mounted project could land on `video-shortform` even when the user had explicitly chosen the HyperFrames-HTML model (or one of the new `hyperframes-html-in-canvas-*` templates). The agent then ran without the hyperframes SKILL body or its `references/html-in-canvas.md` preflight — the exact regression PR #866 was meant to land. `skillIdForTab` now pins to `hyperframes` whenever the current video model is `hyperframes-html`, regardless of discovery order. Added a unit test that mounts both `video-shortform` and `hyperframes` (with hyperframes last, simulating the bad readdir order) and asserts the create payload routes through `hyperframes`. --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
976a5900f8
|
fix: clear stale upload failure banner when previewing files (#797)
* fix: clear stale upload failure banner when previewing existing files Closes #786 - Clear uploadError in openFile() so navigating to a file dismisses the banner - Scope banner visibility to the Design Files tab so stale errors do not bleed into preview surfaces - Add test pinning that no banner is rendered when there is no upload error * fix(workspace): move upload banner into DesignFilesPanel + interactive test Per @mrcfps + @lefarcen review on PR #797: - Move the upload-error banner from FileWorkspace into DesignFilesPanel body. Hide it whenever the in-panel preview is active (the missed flow that mrcfps and lefarcen flagged: single-click preview kept activeTab on DESIGN_FILES_TAB, so the old guard left the banner mounted above the preview). - Keep a fallback banner in FileWorkspace that fires only when activeTab is not Design Files. This preserves the partial-upload visibility flagged by chatgpt-codex-connector: a partial upload opens the last successful file (flipping activeTab to a viewer) and the failure note still surfaces. - Wrap uploadProjectFiles in try/catch so thrown errors surface a banner instead of disappearing. - Replace the brittle viewer-empty assertion with two interactive vitest cases: (1) mock-fail upload, banner visible, preview file, banner hidden, close preview, banner back, dismiss, banner gone; (2) partial-upload uploaded+failed, banner appears on the viewer surface with the existing 'Uploaded N file(s), but M failed' text. - Add df-upload-banner class and stable test ids upload-error-banner and upload-error-dismiss so future tests don't rely on the generic viewer-empty class. Closes #786 staleness; addresses follow-up review. --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: mrcfps <mrc@powerformer.com> |
||
|
|
cbb3c0e33a
|
Improve design files grouping (#1082)
Add a modified-date grouping mode to make busy design workspaces easier to scan as generated files accumulate. The new view keeps existing batch actions and pagination available, adds localized labels, and covers date boundaries with component tests. |
||
|
|
724d071c01
|
feat: add design file rename support (#894)
* feat(contracts): add project file rename contract * feat(daemon): add safe project file rename API * feat(web): support renaming design files * fix(daemon): handle case-only file renames * fix(web): prevent rename collisions with pending sketches * fix(daemon): preserve source names during rename * test(daemon): cover rename symlink escapes * fix(daemon): avoid clobbering rename targets * test(web): align rename tests after rebase * test(web): align rename tests with latest main |
||
|
|
6f74ac304d
|
fix(web): expand design file row click target (#1039) | ||
|
|
0b039777b9
|
fix/Bug#772-DesignFilesSortButton-DesignFilesTableNowSortableColumns (#804)
* Disclaimer: Changes made using OpenCode with Big Pickle, an AI code assistant.
1. Removed the ↑ button from DesignFilesPanel.tsx (was a "back" button that
closed the preview pane — confusingly placed in the header as if it were for
sorting).
2. Converted the file list to a single <table> with sortable columns:
- Replaced the section-based grouping (Pages, Sketches, Scripts, Images,
Other) with a flat, sortable table
- Added column headers: Name, Kind, Modified — all clickable to toggle
sort direction
- Default sort is by modified time descending (same as previous behavior)
- Sort indicator arrows (↑/↓) show the active sort column and direction
- Live artifacts remain as a separate section above the table
3. Added i18n keys designFiles.colName, designFiles.colKind, designFiles.
colModified to all 17 locale files and the type definitions.
4. Updated CSS with table layout styles (.df-table, .df-file-row, column
width classes, sortable header styles).
Files modified:
- apps/web/src/components/DesignFilesPanel.tsx
- apps/web/src/index.css
- apps/web/src/i18n/types.ts
- apps/web/src/i18n/locales/en.ts
- apps/web/src/i18n/locales/*.ts (all 16 other locale files)
* Updated to preserve keyboard access to sorting
* Fixed keyboard to focus/activate/launch file from Design Files list. Single space bar will show preview, double spare bar will open the file as a tab
* Top pagination bar (above the table):
- "Show" dropdown with options 15, 30 (default), 45, 60, All
- Page range indicator (1–20 of 45)
- Previous / Next buttons
Bottom pagination bar (below the table):
- Previous / Next buttons
- "Go to page" dropdown listing all page numbers
- Same page range indicator
Implementation details:
- All controls use native <select> and <button> elements — fully keyboard
accessible (Tab, arrow keys, Enter/Space)
- Page resets to 0 when page size changes
- safePage clamps to valid bounds when file count changes (e.g. after delete)
- "All" sets page size to total file count (effectively one page)
- Prev/Next buttons show disabled state at boundaries with reduced opacity
* All 46 test files, all 385 tests pass. Here's what the regression test covers:
┌────────────────────┬──────────────────────────────────────────────────────┐
│Test │What it verifies │
├────────────────────┼──────────────────────────────────────────────────────┤
│default page size │500 files → only 30 .df-file-row elements in DOM │
├────────────────────┼──────────────────────────────────────────────────────┤
│page size All │changing per-page to "All" shows all 500 rows │
├────────────────────┼──────────────────────────────────────────────────────┤
│page size 60 │changing to 60 shows 60 rows │
├────────────────────┼──────────────────────────────────────────────────────┤
│Next navigation │clicking Next advances page and shows file-31 (sorted │
│ │by mtime desc) │
├────────────────────┼──────────────────────────────────────────────────────┤
│Prev/Next disabled │Prev disabled on page 0, Next disabled on last page │
│states │ │
├────────────────────┼──────────────────────────────────────────────────────┤
│jump to page │bottom dropdown jumps to page 3 (shows file-91) │
├────────────────────┼──────────────────────────────────────────────────────┤
│page info text │1–30 of 500 → after Next → 31–60 of 500 │
├────────────────────┼──────────────────────────────────────────────────────┤
│render time │renders 500 files in under 2s │
└────────────────────┴──────────────────────────────────────────────────────┘
* Fixed i18n for DesignFiles, and Fixed DesignFilesPanel Test
* Fixed - P3 — .df-thead rule defined but never applied
* Fixed keyboard use for file navigation, focus and button usage
* Fix i18n for x of y in design files pagination
* Fixed SafePage clamping
* Fixed dupe file total count
* Fixed x of y i18n
* Fixed DeleteSelected i18n and missing from Test
* fix effective pagesize issue, and change duplicate file kind to a filesize
* Readded page/everything selection and i18n
* Fixed i18n issues
* Resolved indonesian i18n issue with cloudflare keys
* Fixed unrelated cloudflare i18n issues as requested in Pull Request by reviewer
* Fix e2e test: click filename button instead of row for preview
The DesignFilesPanel was refactored from <button> rows to a <tr> with
a nested <button> for the filename. The e2e test was still clicking
the <tr> which has no onClick handler, so the preview never appeared.
* Remove duplicate formatSize helper, reuse humanBytes instead
|
||
|
|
e14b8092ea
|
feat: add Orbit activity summaries (#681)
* feat: add Orbit activity summaries * fix(orbit): make runs navigable while agent continues * fix(web): widen minimum chat panel * feat: support Orbit template selection * fix(daemon): avoid bogus skill side-file preflight * fix(web): collapse orbit artifact project cards * fix(web): preserve orbit project card titles * fix: improve Orbit run daily briefing * fix: handle Orbit digest data failures * fix: load Orbit templates and connector tools reliably * fix: keep Orbit summary counts consistent Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: apply Orbit template skill context * fix: cache and curate connector tools for Orbit * fix: align Orbit defaults and connector discovery * fix: simplify Orbit template settings * fix: move connectors into settings * fix: compact connector settings catalog * fix: address Orbit PR feedback Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: address Orbit PR feedback Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: address Orbit PR feedback Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: address Orbit PR feedback Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: address Orbit PR feedback Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: address Orbit PR feedback Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: address Orbit PR feedback Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: address Orbit PR feedback Generated-By: looper 0.6.1 (runner=fixer, agent=opencode) * fix: prevent connector action button from stretching into pill The icon-only connect/disconnect buttons in the embedded connectors catalog inherited min-width: 92px / 106px from the non-embedded pill rules, overriding the 24px square sizing and causing the buttons to overlap the card head text. Reset min-width to 0 in the embedded icon-only rule so the compact square layout holds. * fix(web): align live artifact file rows * fix: clean up Orbit connector settings lifecycle Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix: address Orbit review regressions Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * feat(web): localize Orbit and connector settings * feat(web): gate Orbit runs without connectors * feat(web): refine connector settings UX * feat(web): safeguard Composio key clearing * fix(web): refresh Composio tool badges * feat(web): show connector logos * feat(daemon): localize Orbit prompt window * fix(daemon): clarify blocked connector callback closes * test(daemon): harden flaky async probes * fix(web): align Indonesian connector locale keys * test(web): align connector browser props * fix(web): preserve explicit credential clears Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): time out Composio logo proxy fetches Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): localize Indonesian connector settings copy Translate the new connector settings strings in the Indonesian locale and lock them with a regression test so this surface no longer silently falls back to English. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): preserve discovered connector tools Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): preserve onboarding autosave completion Keep settings autosave from clearing onboarding completion after the close gesture, and expose the desktop main types from source so workspace validation can typecheck packaged imports without a prior desktop build. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): defer Composio catalog cache hydration Load persisted Composio catalog data only after the runtime data directory is configured so startup cannot read another namespace's cache. Add a regression test that exercises the module-load singleton path. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): treat discovery completion independently Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): preserve latest settings draft on close Use the latest persisted settings draft when the dialog closes so onboarding completion does not race a stale daemon sync and overwrite newer Orbit/template selections. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): avoid syncing draft Composio key on Orbit run Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): localize Orbit settings copy Translate the new Indonesian Orbit and autosave strings so the settings UI no longer falls back to English and the locale regression stays covered. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): prefer fresh connector catalog state Keep refetched connector status/auth data authoritative while retaining discovery-only tool metadata so the connectors UI stays consistent after refreshes. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): declare Indonesian locale fallback keys explicitly Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): inline Indonesian fallback strings for CI Replace the Indonesian locale's per-key English lookups with explicit strings so workspace typecheck no longer depends on brittle build-mode resolution in CI. Add a regression test that blocks those per-key English lookups from reappearing in the CI-sensitive fallback sections. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): restrict proxied connector logos to image MIME types Reject non-image upstream logo responses so the daemon never serves third-party HTML from its localhost origin. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * test(e2e): align settings dialog regressions Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): decouple Orbit runs from media sync failures Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): keep SPA catch-all export-compatible Disable dynamic catch-all params for the exported SPA shell so Next.js static builds can emit the root route again. Add a regression test covering the route config against the web export mode. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): preserve Orbit config and workspace routes Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): block SVG in connector logo proxy Reject SVG and other unsafe proxied logo responses so third-party logo content cannot execute under the daemon origin, while keeping raster logo fetches working and making rejected responses non-cacheable. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): fall back to static catalog for empty cache Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): disable Orbit run before connector gate resolves Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(desktop): export shipped desktop types Point the desktop ./main type export at the generated declaration so installed consumers resolve the published file set. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): restore persisted question form selections Render historical submitted answers directly so reloaded question forms keep their locked selections visible. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): retry forced media sync autosave Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): keep Composio logo timeout through body read Keep the Composio logo fetch timeout active until the response body is fully consumed so stalled body reads abort and clear the inflight cache entry. Add a regression test that proves a delayed body read times out and the next request can recover.\n\nGenerated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): refresh Orbit gate after connector auth Re-check connector availability when the settings window regains focus so Orbit unlocks as soon as a connector finishes authenticating in the same settings session. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): keep connector detail tool lists intact Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): ignore malformed Orbit summaries Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(e2e): stabilize design-system multi-select flow Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): cap Composio logo cache growth Bound the Composio logo cache with LRU eviction and expired-entry pruning so repeated untrusted logo requests cannot grow daemon memory without limit. Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(daemon): bound proxied Composio logo payloads Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): align autosave settings tests Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): remove stray CSS conflict marker Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fixer: address PR #681 follow-up items Generated-By: looper 0.6.2 (runner=fixer, agent=opencode) * fix(web): restore restart routes and connector flows * fix(web): keep SPA export route static * fix(web): stabilize chat scroll tests --------- Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
168cb8ab4d
|
feat(web): add batch delete for selected design files (#771)
Adds batch deletion for selected design files. |
||
|
|
6efac8887e
|
Improve Windows beta packaging and installer flow (#768)
* Optimize Windows packaged web output * Fix packaged contracts runtime build * Optimize Windows packaged size pruning * Prune Windows root Next payload * Remove Windows bundled Node runtime * Prune Windows standalone duplicate Next * Add tools-pack cache foundation * Cache Windows packaged build layers * Cache Windows workspace builds * Cache Electron-ready Windows app * Split Windows tools-pack module * Cache Windows dir build outputs * Split Windows pack build modules * Document Windows NSIS smoke namespace limits * Move Windows NSIS smoke note to agents guide * Optimize Windows beta packaging * Bump packaged beta base version * Improve Windows installer namespace UX * Improve Windows tools-pack cache keys * Stabilize Windows beta cache version keys * Cache Windows workspace build outputs * Optimize windows release beta cache layers * Cache windows release dependencies * Trim windows release cache before save * Refresh windows tools-pack cache key * Improve windows installer preflight prompts * Fallback NSIS installer strings to English * Fix Windows installer cleanup and preflight * Improve Windows NSIS state logging * Fix system NSIS Persian language alias * Use long-path removal for Windows uninstall * Fix mac tools-pack tests on Windows * Address Windows packaging review feedback * Fix Windows installer cache namespace isolation * Include web output mode in Windows tarball cache key * Use unique Windows release cache save keys |
||
|
|
832ea7d864
|
fix: batch of small bug fixes (#283, #275, #390) (#530)
* fix(web): add hover tooltips to Design Files action buttons (#283) The batch-download, select-all, and clear-selection buttons in DesignFilesPanel had no title attribute, so users hovering them saw no tooltip. The other action buttons (refresh, new sketch, paste, upload) already had titles. Added titles to the three missing ones using the existing translation keys, so hover behavior is consistent across the panel. Closes #283. * docs: point pi-ai links to pi-mono packages (#275) The pi project moved from a standalone repo to the pi-mono monorepo. The old URL https://github.com/mariozechner/pi-ai now 404s. Replaced both shapes of reference: - The reference-style [piai]: definition now points at https://github.com/badlogic/pi-mono/tree/main/packages/ai (the multi-provider LLM API package). - Inline links whose visible text is the CLI tool 'pi' or 'Pi' now point at https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent (the interactive coding-agent CLI), so a reader clicking 'pi' in the daemon-discovery section lands on the actual binary's docs. Affected: README.md and 10 translated READMEs, plus docs/spec.md, docs/architecture.md, docs/references.md, docs/roadmap.md. Closes #275. * fix(daemon): expand $HOME / ${HOME} in OD_DATA_DIR (#390) Some launchers (systemd unit files, NixOS modules, certain Docker entrypoints) pass OD_DATA_DIR with a literal '$HOME' or '${HOME}' because no shell ever expands them. resolveDataDir previously only handled '~/' shorthand, so '$HOME/.open-design' fell through to path.resolve(PROJECT_ROOT, '$HOME/.open-design') and produced paths like /opt/open-design/$HOME/.open-design. resolveDataDir now expands '~', '~/...', '$HOME', '$HOME/...', '${HOME}', and '${HOME}/...' to os.homedir() before the absolute / relative branch runs. Rebuilds via path.join so the platform separator is correct on Windows even when the input used forward slashes. Tests: 7 unit tests cover empty/undefined, '~', '~/...', '$HOME', '$HOME/...', '${HOME}/...', absolute paths, and relative paths. Closes #390. * fix(daemon): accept backslash separators + hermetic resolve-data-dir tests Round 1 review feedback on PR #530. The previous regex only matched forward-slash separators, so a Windows launcher passing OD_DATA_DIR=$HOME\.open-design or ${HOME}\.open-design fell through to path.resolve(projectRoot, ...) and produced a directory named $HOME or ~ under projectRoot. The regex now accepts both forward and back slashes for the home-prefix separator. The previous tests called the real resolveDataDir against literal ~/od-test, $HOME/od-test, etc., which created and write-checked directories under the developer's or CI runner's actual home. The tests now stub os.homedir() with vi.spyOn to a per-test mkdtemp directory and remove it in afterEach, so no test ever writes outside its own sandbox. Added explicit fixtures for the Windows backslash forms ($HOME\od-test, ${HOME}\od-test, ~\od-test) so launcher coverage stays cross-platform. 12/12 resolve-data-dir tests pass, daemon typecheck clean. * fix(docs,daemon): apply pi-mono links to README.es and await test cleanup Round 2 review feedback on PR #530. README.es.md was added in upstream #552 after my pi-mono link sweep landed, so the daemon-discovery paragraph (line 222), the [piai] reference (line 684), and the Pi table row (line 709) still pointed at the broken https://github.com/mariozechner/pi-ai URL. Applied the same replacements: the [piai] ref now points at packages/ai, and the inline Pi link now points at packages/coding-agent. Spanish readers get the same coverage as the other 11 locales. The absolute-path test in tests/resolve-data-dir.test.ts dropped its fixture via void rm(abs, ...), so a failed async removal could leak rdd-abs-* directories from the suite. The test is now async and awaits the rm in the finally block, matching the awaited cleanup in afterEach. 12/12 resolve-data-dir tests still pass, daemon typecheck clean. * fix(daemon): share $HOME expander between OD_DATA_DIR and OD_MEDIA_CONFIG_DIR Round 3 review feedback on PR #530. resolveDataDir (server.ts) now expands $HOME / ${HOME} / ~, but media-config.ts had its own resolveOverrideDir that only handled ~/. Because configFile() falls back to OD_DATA_DIR when OD_MEDIA_CONFIG_DIR is unset, setting OD_DATA_DIR=$HOME/.open-design split state: SQLite, projects, and artifacts went to the expanded path while media-config.json stayed under <projectRoot>/$HOME/.open-design. Stored provider keys then appeared missing on the next read. Extracted the home-prefix expansion into apps/daemon/src/home-expansion.ts so resolveDataDir and resolveOverrideDir share one resolver. Both now recognize ~ / $HOME / ${HOME} (bare tokens) and ~/, ~\, $HOME/, $HOME\, ${HOME}/, ${HOME}\ (prefix forms with either separator). Three new media-config routing tests cover the OD_DATA_DIR fallback for $HOME/..., ${HOME}/..., and the OD_MEDIA_CONFIG_DIR explicit-override $HOME/... case so the co-location guarantee is locked down by tests. Daemon typecheck clean. Tests pass on Linux CI; the existing pattern in the file uses process.env.HOME which os.homedir() reads on POSIX. Resolve-data-dir tests stay hermetic via vi.spyOn. * docs(daemon): media-config comments reflect full $HOME / ${HOME} expansion Round 3 review feedback on PR #530 (lefarcen, P3 non-blocking). The file-header and resolveOverrideDir() function comment said only ~/ expands. Updated both to mention the shared expandHomePrefix() helper and the full set of forms it handles (~, $HOME, ${HOME} with either separator), so a future reader does not need to chase the implementation to understand what env values are accepted. * test(daemon): stub os.homedir() in media-config routing tests Round 4 review feedback on PR #530. The new $HOME / ${HOME} routing tests relied on process.env.HOME being read by os.homedir(), which works on POSIX but is unreliable on Windows (Node prefers USERPROFILE / profile APIs there). The tests would expand to the real user home while fixtures were written under the per-test homeDir, causing platform-specific failures in the same area this PR is making cross-platform. The inner describe block now stubs os.homedir() via vi.spyOn to return the per-test homeDir, matching the pattern in resolve-data-dir.test.ts. Restored in afterEach. The four $HOME-form routing tests now pass on both POSIX and Windows. Daemon typecheck clean. The two OAuth fallback test failures unrelated to this change (real ChatGPT/Codex tokens in the local env) remain out-of-scope. * fix(i18n): drop duplicate uk.ts promptTemplates keys after rebase Upstream #674 added the same Ukrainian translations my earlier commit added. The rebase landed both copies; tsc rejects duplicate property names. Drop my copies so #674 (which is now upstream) is the single source for these keys. --------- Co-authored-by: Nagendhra <nagendhra405@gmail.com> |
||
|
|
29e1ed5f28
|
fix: 修复设计文件列表行菜单被裁剪的问题 (#561) | ||
|
|
c3d9136a0c
|
Add live artifacts and Composio connector catalog (#381)
* docs: add live artifacts implementation spec * docs: align live artifacts implementation plan * Ralph iteration 1: work in progress * Ralph iteration 2: work in progress * Ralph iteration 3: work in progress * Ralph iteration 4: work in progress * Ralph iteration 5: work in progress * Ralph iteration 6: work in progress * Ralph iteration 7: work in progress * Ralph iteration 8: work in progress * Ralph iteration 9: work in progress * Ralph iteration 10: work in progress * Ralph iteration 11: work in progress * Ralph iteration 12: work in progress * Ralph iteration 13: work in progress * Ralph iteration 14: work in progress * Ralph iteration 15: work in progress * Ralph iteration 16: work in progress * Ralph iteration 17: work in progress * Ralph iteration 18: work in progress * Ralph iteration 19: work in progress * Ralph iteration 20: work in progress * Ralph iteration 21: work in progress * Ralph iteration 22: work in progress * Ralph iteration 23: work in progress * Ralph iteration 24: work in progress * Ralph iteration 25: work in progress * Ralph iteration 26: work in progress * Ralph iteration 27: work in progress * Ralph iteration 28: work in progress * Ralph iteration 29: work in progress * Ralph iteration 30: work in progress * Ralph iteration 31: work in progress * Ralph iteration 32: work in progress * Ralph iteration 33: work in progress * Ralph iteration 34: work in progress * Ralph iteration 35: work in progress * Ralph iteration 36: work in progress * Ralph iteration 37: work in progress * Ralph iteration 38: work in progress * Ralph iteration 39: work in progress * Ralph iteration 40: work in progress * Ralph iteration 41: work in progress * Ralph iteration 42: work in progress * Ralph iteration 43: work in progress * Ralph iteration 44: work in progress * Ralph iteration 45: work in progress * Ralph iteration 46: work in progress * Ralph iteration 47: work in progress * Ralph iteration 48: work in progress * Ralph iteration 49: work in progress * Ralph iteration 50: work in progress * Ralph iteration 51: work in progress * Ralph iteration 52: work in progress * Ralph iteration 53: work in progress * Ralph iteration 54: work in progress * Ralph iteration 55: work in progress * Ralph iteration 56: work in progress * Ralph iteration 57: work in progress * Ralph iteration 58: work in progress * Ralph iteration 59: work in progress * Ralph iteration 60: work in progress * Ralph iteration 61: work in progress * Ralph iteration 62: work in progress * Ralph iteration 63: work in progress * Ralph iteration 64: work in progress * Ralph iteration 65: work in progress * Ralph iteration 1: work in progress * Ralph iteration 2: work in progress * Ralph iteration 3: work in progress * Ralph iteration 4: work in progress * Ralph iteration 5: work in progress * Ralph iteration 6: work in progress * Ralph iteration 8: work in progress * Ralph iteration 9: work in progress * Ralph iteration 17: work in progress * Add Composio-backed connectors * Add Composio-backed connector catalog * Fix connector callback flow * Update live artifact connector refresh * Fix live artifact refresh updates * Improve live artifact viewer toolbar * Refine live artifact source tabs * Expand Composio connector catalog * Improve Composio connector browsing * Fix artifact refresh source safety checks Generated-By: looper 0.4.1 (runner=fixer, agent=opencode) * Fix live artifacts PR feedback Generated-By: looper 0.5.0 (runner=fixer, agent=opencode) * Fix live artifact preview CORS validation Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode) * Fix connector OAuth IPv6 loopback hosts Allow bracketed IPv6 loopback Host headers when deriving connector OAuth callback URLs so IPv6-bound daemons can complete connection flow. Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode) * Preserve live artifact refresh permissions Respect explicit refresh permission choices during live artifact create and update flows so revoked connector sources remain gated. Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode) * Fix live artifact preview cache freshness Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode) * Fix live artifact refresh validation Guard manual refreshes with local daemon checks and reject daemon_tool sources without a toolName before refresh execution. Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode) * Fix Composio credential invalidation Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode) * Fix live artifact CORS methods Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode) * Fix workspace validation Restore media config test isolation under Vitest setup data-dir overrides and add the missing French live artifact display copy so the workspace test suite stays aligned.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode) * Fix connector safety filtering Keep agent-preview connector listings aligned with execution safety policy and prune stale Composio OAuth state records before they accumulate. Generated-By: looper 0.5.2 (runner=fixer, agent=opencode) * Fix agent runtime cleanup Generated-By: looper 0.5.2 (runner=fixer, agent=opencode) * Fix live artifact daemon access Validate local-only live artifact routes against the peer socket address and pass daemon-resolved CLI paths to ACP MCP descriptors.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode) * Fix connector run limit pruning Evict stale connector rate-limit buckets so long-lived daemon processes do not retain per-run entries indefinitely.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode) * Fix connector compact schemas Generated-By: looper 0.5.2 (runner=fixer, agent=opencode) * Improve connector connection feedback * Adjust connector gate positioning * Fix live artifact refresh commits Avoid marking refresh candidates failed after snapshot or state persistence errors by deferring live artifact mutations until the durable refresh metadata is written. Also align connector OAuth callback host validation with daemon loopback handling.\n\nGenerated-By: looper 0.5.4 (runner=fixer, agent=opencode) * Improve connector search relevance * fix(daemon): harden connector connection state Require loopback daemon validation before connector connect side effects and only clear provider-owned connector statuses during credential reset. Generated-By: looper 0.5.4 (runner=fixer, agent=opencode) * fix(daemon): guard connector disconnect route Require local daemon request validation before connector disconnect side effects. Generated-By: looper 0.5.4 (runner=fixer, agent=opencode) * fix(daemon): guard composio config updates Generated-By: looper 0.5.4 (runner=fixer, agent=opencode) * fix(daemon): dispatch live artifacts mcp first Route the live-artifacts MCP server before the generic MCP CLI so od mcp live-artifacts starts the dedicated server instead of failing generic argument parsing.\n\nGenerated-By: looper 0.5.4 (runner=fixer, agent=opencode) * fix(daemon): handle integer connector schemas Allow JSON Schema integer connector inputs while preserving fractional-value validation so generated connector tool schemas accept valid page sizes and limits. Generated-By: looper 0.5.4 (runner=fixer, agent=opencode) * fix: align live artifact refresh error codes Generated-By: looper 0.5.4 (runner=fixer, agent=opencode) * Fix live artifact connector refresh flow * Update live artifact design cards * Add beta badge to live artifact form * Remove live artifact tile model * Fix live artifact refresh sync * Fix live artifact MCP refresh durability Generated-By: looper 0.5.4 (runner=fixer, agent=opencode) * Fix live artifact refresh safety Enforce persisted refresh opt-out and connector auto-read gating before refresh sources execute. Generated-By: looper 0.5.5 (runner=fixer, agent=opencode) |
||
|
|
a4fb90a9f3
|
fix(design-files): clear selection on project switch (#465)
* fix(design-files): clear selection on project switch to prevent cross-project leak
When switching from project A to project B, filenames present in both
projects (e.g. index.html) would survive the intersection-prune and
remain selected, causing handleBatchDownload() to post against the
wrong projectId. Now selection is fully cleared on projectId change.
* fix(design-files): use key-based remount to prevent cross-project selection leak
Replace the useEffect projectId clearing with a key={projectId} on
DesignFilesPanel. useEffect runs after render, leaving a window where
stale selections from project A could be used against project B. The
key tells React to unmount and remount the component synchronously on
project switch — no async gap.
|
||
|
|
bc04d61903
|
feat(design-files): add batch ZIP download with multi-select (#405)
* feat(design-files): add batch ZIP download with multi-select Add checkbox-based multi-select to the Design Files panel and a new POST /api/projects/:id/archive/batch endpoint that zips selected files using the project name as the archive filename. * fix(i18n): add missing batch-download keys to uk locale The upstream main branch has a uk.ts locale that didn't exist in the fork. Without these keys the web typecheck fails against the full locale set. * fix(design-files): harden batch archive and prune stale selections - Use lstat to reject symlinks, dotfiles, and .artifact.json sidecars in buildBatchArchive (mirror listFiles/collectFiles allowlist) - Reject invalid names explicitly instead of silently skipping - Prune stale filenames from selected set on files/projectId change * fix(daemon): tighten batch archive allowlist with segment-level checks - Check every path segment for hidden directories, not just basename - Walk intermediate directories with lstat to reject symlinks at any level - Fail-fast on any ineligible file instead of silently skipping |
||
|
|
0c65a0508e
|
fix(web): keep Design Files view active after deleting a file (#329)
* fix(web): keep Design Files view active after deleting a file (#115) Deleting a file from the Design Files panel was navigating the user into another file's tab (typically the previously-opened file such as `index.html`). Two unrelated symptoms contributed: - `FileWorkspace.handleDelete` always called `setActiveTab(nextActive ?? DESIGN_FILES_TAB)`, which yanked the user out of the Design Files panel whenever `tabsState.active` still pointed at a real file (clicking the Design Files tab only updates local `activeTab`; it does not touch persisted `tabsState.active`). - The row popover had `onMouseDown` propagation guard but no corresponding `onClick` guard on the destructive action path. Fix in `FileWorkspace.handleDelete`: - If the deleted file is the one being viewed (`activeTab === name`), fall back to another open tab (or Design Files if none remain) — the prior behavior, which is correct in this case. - Otherwise (deletion came from the Design Files panel, the typical path), leave `activeTab` alone so the user stays in the list view. Only null out `tabsState.active` when it referenced the deleted file to avoid leaving a dangling pointer for the hydration `useEffect` to resync against. Defensive cleanup in `DesignFilesPanel`: - Add `onClick` propagation guard on the popover wrapper (mirrors the existing `onMouseDown` guard). - Stop propagation on each popover button (Open / Download / Delete) and on the download `<a>` so destructive/menu actions can't bubble into row click handlers under any DOM arrangement. Closes #115 * fix(web): address review feedback + add multi-tab delete regression E2E Review feedback (#329): - Drop the redundant `onClick={(e) => e.stopPropagation()}` on the download `<a>` wrapper; the inner `<button>` is the actual click target and already stops propagation. - Expand the comment in `handleDelete`'s else branch to explicitly state that `activeTab` is preserved because the user is in a different context (Design Files panel or another tab) and shouldn't be navigated away. Regression coverage: - Extend `runDesignFilesDeleteFlow` to upload a sibling file (`keep-me.png`) before `trash-me.png`, so deletion has a fallback tab that the buggy code would have navigated to. After deletion, assert the Design Files tab still has `aria-selected="true"` and the sibling tab is still present (just not auto-activated). |
||
|
|
b06021cd6f
|
[codex] Improve project input performance (#239)
* Improve project input performance * update: improvements to input performance * Fix buffered stream cancellation lifecycle |
||
|
|
3f266103b0
|
feat(media): port generation workflow onto main (#12)
Co-authored-by: Elian <elian@EliandeMacBook-Pro.local> |
||
|
|
cfebff9653
|
Align app directories and isolate e2e tests (#102)
* chore: align app directories * test: consolidate external suites under e2e |
Renamed from src/components/DesignFilesPanel.tsx (Browse further)