mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
142edb4ac727741057e278b09e5ecb77e13eaae4
315
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
068c9ae83f |
fix(daemon): normalize Anthropic-compatible BYOK base URLs (#5807)
* fix(daemon): normalize Anthropic-compatible BYOK base URLs * test(e2e): stabilize home plugin details flow Wait for Home project loading to settle before revealing templates, then target the semantic Details control after verifying actionability so layout shifts cannot collapse the gallery or trigger the wrong card action. Generated-By: looper 0.10.4 (runner=fixer, agent=codex) * fix(daemon): version Anthropic gateway URL paths Append /v1 through the parsed URL pathname so gateway query parameters and fragments remain in their proper URL components. Preserve the prior string-concatenation fallback for invalid URLs. Generated-By: looper 0.10.4 (runner=fixer, agent=codex) |
||
|
|
421ac5ad56 |
fix(web): keep model picker anchored within visible bounds (#5907)
Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com> |
||
|
|
d8b6b797fe |
Simplify chat execution disclosures (#5667)
* Simplify chat execution disclosures * test: cover collapsed file disclosures * refactor(web): consolidate chat task activity * fix(web): show small file outputs inline * fix(web): separate file outputs from reads * fix(web): collapse completed todo cards * refactor(web): compact completed todo lists * fix(web): make completed todos expandable * fix(web): keep four output files visible * refactor(web): clarify chat activity timeline * fix(web): make file output disclosure interactive * feat(web): emphasize chat run states * style(web): simplify chat run status colors * style(web): remove chat run status icons * feat(web): stream one chat activity at a time * style(web): align chat completion row * fix(web): simplify priority chat states * feat(web): simplify secondary chat details * style(web): simplify secondary chat hierarchy * fix(web): keep execution state out of artifacts * fix(web): use icons for artifact operations * style(web): frame todo disclosure header * fix(web): clarify artifact and tool semantics * fix(web): clarify chat disclosure hierarchy * fix(web): keep execution history neutral * fix(web): simplify user action cards * fix(web): align failure card actions * fix(web): refine chat action hierarchy * fix(web): address chat disclosure review feedback * fix(web): restore chat recovery actions * fix(web): make collapsed action details inert --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> |
||
|
|
20c6c0a6ed |
ci(e2e): shard the full UI functional pool into a merge-ready matrix (#5883)
* ci: benchmark deduplicated UI merge sentinel * ci: benchmark restoration-hosted sentinel * ci: benchmark distributed P0 sentinel * ci: benchmark split P0 sentinel * ci: serialize split sentinel benchmark * ci: finalize deduplicated UI merge topology * ci: prototype all-shades UI domain topology * ci: bound full UI runtime by shade * test(e2e): stabilize full UI suite * fix(web): unclip DS picker popover and propagate patched project metadata Two regressions surfaced by re-enabling the full UI pool: - The New Project design-system popover lost its portal and was clipped by short viewports and the modal body. Render it through createPortal with a viewport-aware anchor that flips upward when space below runs out. - After a working-dir pick, onProjectMetadataChange forwarded only the metadata onto a stale project copy, so ProjectView.currentProject's recency comparison let an older useProjectDetail snapshot shadow the accepted PATCH and the picker label never updated. The callback now carries the daemon's authoritative post-patch project (fresh updatedAt included), matching the design-system switch path, and ProjectView hands it straight to onProjectChange. * test(e2e): repair remaining stale full-suite UI contracts Second repair batch for the failures surfaced by full diagnostic run 29480362163, plus one CI-invisible case that was serially skipped behind the BYOK failure in the same file: - Point the working-dir metadata spec at a directory that exists on the runner instead of a hardcoded absolute path, and assert the label from the picked path (this spec is red without the ProjectView patched-project fix). - Navigate back to All project files before asserting the plugin-folder cards, since a finished run auto-opens the produced file tab. - Resolve the create-run response race in real-daemon-run's sendPrompt via a single waitForResponse alongside the click. - Refresh selectors and copy for entry topbar, home hero rail, chat todo autoscroll, project management, workspace keyboard, design files, manual edit, restoration, and DS picker clipping flows to match the current UI contracts while keeping each spec's oracles. * ci: distribute the full UI suite over a generic 8-shard matrix Replace the diagnostic four-domain P0/P1/P2 serial topology with a single all-shades Playwright invocation per shard (--shard=N/8, two fully parallel workers, 20-minute cap) and drop the scheduled trigger; full runs stay manual until the merge-queue wiring lands. Update the workflow topology guard accordingly. * ci: serialize full UI shards and widen the matrix to twelve The eight-shard two-worker experiment left six light shards healthy (260-477s test steps) but both shards holding runtime-heavy files degraded: repeated two-minute timeouts with retry recovery in one, and a consistent create-run response starvation failure in the other. This matches the earlier finding that runtime-heavy scenarios cannot share a runner under two fully parallel workers. Run each shard with a single worker and rebalance to twelve shards; fully-parallel stays on only for test-granularity sharding. * fix(web): preserve prompt-extracted plugin inputs across apply reconcile The active-plugin apply reconcile rebuilt the inputs from the bind-time optimistic snapshot, so edits the user typed during the apply roundtrip (already extracted into active.inputs by handlePromptChange) were silently reverted to defaults — the submitted pluginInputs then disagreed with the visible prompt. Merge the apply result's defaults into the current inputs inside the functional updater instead, mirroring the guard the prompt-text reconcile already had. * test(e2e): stabilize home gallery flows for all-shades execution Generic all-shades sharding executes tests in orders the shade-filtered domain topology never produced, exposing a home-surface remount window: the async projects fetch can mount or remount HomeTemplatesReveal after a test starts interacting, collapsing the gallery (inert) under the test's cursor. Stabilize the shared helpers instead of individual specs: - gotoEntryHome arms a projects-list response waiter before navigating and holds until it settles. - revealHomeTemplates requires the revealed state (or a true pass-through) to survive a settle window, retrying when the wrapper mounts late; a card's isVisible() is true inside the collapsed container, so openHomePluginDetails now always routes through the reveal path. - The browse-registry spec reveals before clicking. - The DS-picker options moved out of the new-project-modal subtree with the portal fix; query the page-level popover per the clipping spec's convention. - real-daemon-run's sendPrompt reports on timeout whether POST /api/runs was ever issued, so the CI-only BYOK failure can be split into swallowed-click vs unanswered-request on the next reproduction. * test(e2e): make BYOK availability hermetic and reveal remaining gallery clicks The BYOK missing-provider spec could only pass on machines with a real `opencode` binary: daemon detection maps byok-opencode's availability through the `opencode` agent's configured cli env, and the web composer refuses to POST /api/runs for an unavailable agent (the sendPrompt diagnostic confirmed "was never issued" on CI). Point the helper's agentCliEnv at the fake opencode runtime — the run still fails pre-spawn on the missing provider config, so the fake binary never executes. Also route the two remaining collapsed-container gallery clicks (the browse-registry starter journey and the detail-use force-click) through revealHomeTemplates; an inert container swallows force-clicks silently. * ci: probe a 24-shard full UI matrix against the four-minute wall target The first green 12-shard run put eleven shards at 141-354s test steps but concentrated the contiguous runtime-heavy chain in one 894s shard, setting a ~16-minute wall tail. With ~3568 total test-seconds and ~90s per-job overhead, 24 shards should land every job near four minutes. * ci: settle the full UI matrix on twelve shards The 24-shard probe stayed green but proved the runtime-heavy chain is a serial group (test.describe.configure serial in real-daemon-run), which Playwright keeps atomic within one shard: the tail stayed ~16 minutes while the extra twelve cold starts raised aggregate runner time from ~76 to ~102 minutes. Twelve shards dominate; lowering the wall below the serial-chain floor is a de-serialization follow-up, not a shard-count knob. * test(e2e): drop serial mode from shard-splittable files Playwright keeps a serial group atomic within one shard, so real-daemon-run's file-level serial made its ~16-minute chain the floor of the full UI matrix wall regardless of shard count. Every test in the three serial files already performs its full setup per test (config reset, route stubs, own project), so serial only added skip-after-failure and shard atomicity. Verified order independence by running each file's two standalone shard halves locally (fully parallel sharding, one worker): 21/21, 57/57, and 12/12 across the halves. * test(e2e): settle the projects fetch in real-daemon-run home navigation With serial mode gone, the plugin-authoring spec runs after arbitrary shard predecessors, so the daemon holds more projects when it navigates home; the late-resolving projects list re-renders the hero and left the shortcuts trigger unstable for the whole click timeout on CI. Port the projects-settle waiter already used by entry-chrome-flows into this file's gotoEntryHome. * test(e2e): name the plugins-load gate in the plugin authoring spec The home shortcuts trigger is disabled while the plugins list loads, and this spec's mid-flow reload re-fires that fetch after gotoEntryHome's settle has already passed — on CI the click then times out opaquely for 120 seconds. Arm a response waiter across the reload and assert the trigger's enabled state explicitly, so a slow or hung /api/plugins fails with the actual cause named. * test(e2e): enter plugin authoring through the plugins page create button The home shortcuts trigger sits disabled on CI runners while a home plugin apply hangs (plugins list resolves, the pending-apply gate never clears); three reproduction attempts confirmed the anomaly is CI-only and independent of this journey. The create button on the Plugins page drives the same queuePluginAuthoring flow, and this spec's oracle is the generated scaffold plus its action cards, so route the entry there and track the disabled-trigger anomaly separately. * ci: let configure-ci-parallelism drive full UI shard workers The single-worker override predates the repairs that explained the two-worker instability (BYOK agent availability and the reveal remount race, both test-side and since fixed), so it was pinning throughput on a stale diagnosis. Drop it and let the repo's nproc/2 convention apply — two workers on the four-core ui_hot profile — halving the per-shard test step if the runtime holds. * ci: probe three full UI workers against Blacksmith's actual vCPU capacity The ui_hot profile resolves to blacksmith-4vcpu runners that reportedly provide six actual vCPUs while nproc's cgroup view says four, so the nproc/2 convention derives two workers and idles capacity. Pin three workers for this probe and print the CPU topology alongside for verification. * Revert "ci: probe three full UI workers against Blacksmith's actual vCPU capacity" This reverts commit 63c8296ae0ead2c3dadfbfda41f6e068d58331ef. * ci: skip the critical fallback for pure packaged-leaf changes Playwright starts tools-dev web (daemon + web runtimes) and never launches the desktop, packaged, or tools-pack entrypoints, so PRs confined to apps/desktop, apps/packaged, or tools/pack were paying the two-job critical fallback (5.4-13.4 minutes of wall each) for coverage their package tests and preflight already provide — seven of the eight fallback PRs in the latest 100-merge sample were such false positives. Add a fail-closed ui_critical_validation_required scope: it clears only when every non-exempt changed file sits under one of those three leaf roots. tools-dev, any transitive package (including the undeclared metatool edge), scripts, runtime resources, unknown roots, and mixed leaf + runtime changes keep the fallback armed; root manifests keep enabling P0 with the existing critical/P0 mutual exclusion; merge-group full mode is unchanged. * test(e2e): align question-form specs with inline Studio discovery Rebasing onto main picked up #5496, which moved clarification forms inline into the chat flow and removed the legacy Questions workspace tab. Re-point the submit-persistence spec at the inline form, and fix the oracles that no other lane had verified since: the answered summary echoes the picked visual-style card title (not the option label), and the submitted answer message carries the card title plus its value id. * test(e2e): absorb post-rebase drift in BYOK gating and zh-CN hero copy Two more contracts only the full pool guards moved under the rebase: - The composer's BYOK gate silently swallows submits until the incremental /api/agents stream has delivered byok-opencode's availability, so a fast submit races the stream (the sendPrompt diagnostic reports the POST was never issued). Retry through that window; runErrorCard reads the last card, so swallowed attempts cannot shadow the provider-validation oracle. The gate erroring instead of waiting while agents are still loading is a product-side follow-up. - The home hero title copy changed in every locale; re-point the zh-CN P2 smoke at the current translation. * test(e2e): align gallery specs with the all-types default slice The Community gallery now defaults to an All category pill (#5759) instead of pre-selecting Deck: assert the new default state in the hero and category-tab specs, and have the facet-filter spec pick Deck explicitly before asserting the deck-only visibility set. * test(e2e): align the first-run reveal spec with the all-types default slice Same #5759 drift family as the entry-chrome-flows gallery specs, missed by the first sweep because it lives in home-hero-rail: the revealed gallery now shows the All pill selected instead of hiding it with live-artifact pre-selected. * docs(e2e): add UI test stability rules distilled from the full-pool work Capture the invariants a UI test must hold to stay green under the generic sharded full pool, learned from stabilizing that suite and two rebases: - order independence (no serial groups; setup is per-file, not universal), and that neither shade-filtered local runs nor merge-path P0 prove it; - retry-only passes are an order-leak/readiness signal, not flake; - settle async surfaces (best-effort waiter + a state-survives-a-window check) before interacting; - an enabled control is not a ready control when a streamed precondition (e.g. BYOK-OpenCode agent availability over the /api/agents SSE stream) gates it; - never force-click into inert/collapsed reveal containers; use actionability, not visibility, as the readiness signal; - hermetic agent availability via route mocks (with the terminal SSE `done` event) or fake CLI runtimes + agentCliEnv, never host binaries; - realign stale oracles against the product and confirm them in the lane that actually executes the case, since a merged PR does not verify P1/P2 or unregistered-file P0 oracles; - name failure causes so a CI-only reproduction carries its own evidence. Cross-linked from the top-of-file coverage-status pointer. * test(e2e): realign BYOK missing-provider spec to the #5745 client-side preflight main #5745 added a client-side BYOK preflight that blocks a missing-provider run before any POST and opens the execution Settings section, instead of letting the run reach the daemon and fail there. Rewrite the spec to the new "blocked before spawn" behavior: submitting opens the execution-mode dialog, no create-run request is issued, and no artifact is produced (persisted across reload). This drops the now-obsolete daemon-failed-run assertions and the SSE-availability retry loop, which the preflight makes unnecessary. * docs(e2e): explain why the functional config ignores visual specs Clarify that visual-*.test.ts are owned by playwright.visual.config.ts and its playwright_visual lane, so excluding them from the functional config is intentional scope (it keeps a bare test:ui or the full-pool shard run from executing visual specs without their visual config), not a disabled lane. * fix(web): portal the New Project brand-preview flyout with the popover The earlier DS-picker unclip portaled the popover list but left its companion brand-preview flyout on the old inline `position: absolute` against the trigger wrapper. Once the popover moved to a body portal, the flyout for a finalized `user:<id>` brand was still clipped by the modal body and no longer anchored to the popover. Portal the flyout too and place it beside the popover with the same viewport-aware logic (right of it when the 320px card fits, else flipped left, then clamped), mirroring the popover's up/down vertical anchor. Red spec: e2e/ui/new-project-ds-picker-clipping.test.ts "finalized-brand preview flyout is not clipped by the modal body" — red with the popover portaled but the flyout inline, green with this change. |
||
|
|
2192a7f6b9 |
fix incomplete BYOK configuration preflight (#5745)
* fix BYOK configuration preflight * fix(web): short-circuit non-BYOK run preflight Local-agent test fixtures omit BYOK-only fields, but provider resolution read model before rejecting non-BYOK protocols. Return before touching those fields and keep the pending-prompt API fixture explicitly valid. Generated-By: looper 0.10.4 (runner=fixer, agent=codex) * fix(web): persist committed BYOK key clears Treat a blank active-provider key as draft-only while it is being edited, then persist the clear once the field is committed. This preserves incomplete replacement drafts while invalidating saved account-scoped model state. Generated-By: looper 0.10.4 (runner=fixer, agent=codex) * test(web): align BYOK draft expectations Keep incomplete model discovery edits in the provider-scoped draft while the active configuration remains unchanged, and expect the current DeepSeek preset default. Generated-By: looper 0.10.4 (runner=fixer, agent=codex) |
||
|
|
3447f60a34 |
fix packaged payload desktop handoff (#5678)
* fix packaged payload desktop handoff * fix beta mac full smoke fixture wiring * fix tools-pack mac payload cold start * test payload desktop update restart * fix Nix daemon launcher protocol build * fix(pack): harden Windows long-jump updates * fix(pack): harden mac long-jump acceptance * fix(handoff): defer armed journal writes until spawn and shutdown succeed Previously executeLegacyPayloadDesktopHandoff wrote the armed handoff journal, attempt, and runtime state before spawning the payload desktop and before the old desktop accepted shutdown. When spawn() threw or the shutdown request failed, the armed journal was stranded on disk, so the next cold start bailed out of prepareLegacyPayloadDesktopHandoff() with reason "already-armed" and the install stayed pinned to the old desktop generation indefinitely. Move the three writes to after both the payload child has spawned and the shutdown has been accepted. The old desktop is still alive while it acks the shutdown, and the payload waits for the old pid to exit before resuming, so the state still lands before the payload reads it. Add regression coverage for both the spawn-failed and shutdown-failed paths, asserting the journal stays "prepared" and a later cold start can retry. Generated-By: looper 0.10.3 (runner=fixer, agent=claude-code) * fix(updater): await payload spawn acceptance * fix(packaged): advance confirmed handoff recovery --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
6b90486c97 |
docs: reconcile stale documentation with current code (#5829)
* fix(docs): align question guidance with form flow * docs: reconcile stale documentation with current code * fix(docs): remove retired template metadata from guides Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(e2e): stabilize visual workspace helper Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(docs): align localized template guide metadata Generated-By: looper 0.10.6 (runner=fixer, agent=codex) |
||
|
|
ded62dd8ab |
fix(web): route history deck keys to preview (#5755)
* fix(web): route history deck keys to preview Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * fix(web): prove history deck keyboard navigation Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) |
||
|
|
1dd813f00a |
fix(byok): preserve provider model order (#5774)
* fix(byok): preserve provider model order * test(e2e): expect current DeepSeek preset model Generated-By: looper 0.10.4 (runner=fixer, agent=codex) * fix(byok): preserve DeepSeek and Ollama defaults Align DeepSeek e2e fixtures with the V4 preset defaults and keep the existing Ollama Cloud gpt-oss:120b default first in the canonical preference list.\n\nGenerated-By: looper 0.10.4 (runner=fixer, agent=codex) |
||
|
|
19de7953c4 |
Fix Open Design example logo loading (#5765)
* Fix Open Design example logo loading Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * Stabilize visual home cold start checks Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) |
||
|
|
cb5fd3baab |
fix(web): auto-fit wide html previews (#5751)
* fix(web): auto-fit wide html previews Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * test(e2e): allow auto-fit preview zoom Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * fix(web): gate preview auto-fit on content width Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * fix: measure preview width through iframe bridge * fix: bridge powered preview sizing |
||
|
|
265aa51630 |
feat(web): make Studio discovery visual and inline (#5496)
* feat(web): make Studio discovery visual and inline Move clarification forms into the chat flow, add artifact-aware visual style choices, and keep follow-up actions hidden until discovery is complete. * feat(web): keep clarification entirely in chat Remove the legacy Questions workspace tab, preserve discovery analytics in the inline form, and keep Skip, Submit, and answered summaries in one conversation flow. * docs: split Studio Chat input and response work Frame visual discovery as the input-side initiative and record response aggregation as a separately reviewed follow-up so the current PR stays bounded. * docs: reorganize Studio Chat experience plans Separate the overall journey, visual discovery, and response architecture so each scope can be reviewed and delivered independently. * docs: define first-artifact satisfaction prompt Limit the feedback prompt to the first successful previewable artifact so it gathers a useful signal without interrupting every iteration. * docs: keep Studio Chat plans independent Preserve the existing discovery proposal as one document and keep response architecture as a separate review surface without an extra master layer. * fix(web): preserve inline discovery behavior Keep visual direction single-select while restoring custom input, optional auto-continue, analytics, and current end-to-end coverage for the inline flow. * fix(web): preserve files when skipping discovery step * fix(web): exclude skipped file answers * fix(web): align inline discovery with slim prompt Preserve the latest discovery contract while keeping inline forms, uploads, drafts, and schema-driven visual selections consistent after the rebase. * feat(web): add style catalog preview images * fix(web): clarify discovery form completion * fix(web): preserve question form context * fix(web): time out unanswered question forms * test(web): cover inline question form next steps * fix(web): roll back partial inline uploads * ci: trigger validation after rebase * fix(web): unlock blocked inline question submits * fix(web): retain previewless visual answers * fix(web): load visual style previews from R2 * fix(web): clean blocked inline uploads * test(web): expect R2 style preview assets * feat(web): show full visual style catalog * fix(web): keep inline question answers consistent --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> |
||
|
|
6e38058dcf |
feat(web): add agent-assisted home headline (#5699)
* feat(web): add time-aware home greeting * feat(web): add contextual greeting emoji * feat(web): use Agent-focused home headline * fix(web): refine agent-focused home copy * fix(web): keep German home copy informal --------- Co-authored-by: elifive555555 <296440099+elifive555555@users.noreply.github.com> |
||
|
|
c67048516c |
fix(web): polish preview status action (#5696)
* fix(web): polish preview status action * fix(web): keep preview failure hint passive --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> |
||
|
|
24c7876b37 | fix(web): preserve delivery for in-place HTML edits (#5689) | ||
|
|
167db9de20 |
feat(web): add preview delivery status feedback (#5557)
* feat(web): add preview delivery status feedback
* fix(web): keep delivery retry in chat
* feat(web): stage preview delivery progress
* refine(web): clarify preview delivery stages
* fix(web): preserve preview delivery feedback
* fix(web): address preview delivery review
* refine(web): keep preview delivery status passive
* Revert "refine(web): keep preview delivery status passive"
This reverts commit
|
||
|
|
925db8d2af |
ci: move nix and docker off the merge validation path (#5682)
* ci: move nix and docker off the merge validation path Core ci.yml / Validate workspace / merge_group no longer schedule or require Nix flake check or Docker image builds. Packaging lives on two standalone workflows: nix.yml (flake check) and docker-image.yml (PR smoke build + tag/release publish). Update scopes, topology tests, and agent docs. * fix(ci): detect Docker publish from release inputs, not workflow_call event Reusable workflow callers keep their own github.event_name (usually workflow_dispatch), so matching event_name == workflow_call never fires and stable GHCR publish would silently smoke-build only. Gate publish on tag push or non-empty release_version / publish_latest inputs instead. * fix(ci): keep smoke-only Docker sha tags off the publish path Gate pr-/manual-sha metadata tags on publish != true so release-stable workflow_dispatch callers do not push extra manual-sha-* tags to GHCR. |
||
|
|
a1cbe0ec57 |
chore(release): bump main to 0.15.1 ahead of stable 0.15.0 (#5661)
Co-authored-by: open-design-release-bot[bot] <open-design-release-bot[bot]@users.noreply.github.com> |
||
|
|
d7463072a8 |
fix(web): Plan 模式生成/重写 HTML 后自动打开生成的文件 (#5602)
* fix(web): re-focus HTML rewritten in place when a turn ends
Plan mode's core loop is plan -> generate -> edit the plan -> regenerate.
On the second generation the deliverable (index.html) already exists, so
the turn-end auto-open — a pure pre/post file-NAME diff — saw no new file
and left the viewer stuck on the markdown plan. Protocols that emit no
Write tool events (codex, gemini, opencode, ACP agents) have no per-write
fallback, so nothing opened at all.
Turn-end selection now also considers pre-existing project files whose
mtime lands inside the turn window (same attribution as AssistantMessage's
inferProducedFilesFromTurn), ranked by the existing HTML > markdown
preview priority. Turns without a start stamp keep the produced-only
behavior.
Red spec: e2e/ui/real-daemon-run.test.ts "Plan mode regeneration re-opens
the existing generated HTML file" (red on main, green here), plus a
first-generation companion spec and unit coverage for the new selector.
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* worker: Plan模式下,不会自动打开生成的HTML文件
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* fix(web): scope the turn-window auto-open to agent-touched files and bound it by turn end
Review follow-ups on the Plan-mode auto-open selector: the mtime
attribution window [turnStartedAt - 1s, +inf) could attribute a file the
USER was editing to the turn - in Plan mode plan.md autosaves from the
split editor during a run, so a text-only turn could yank focus back to
it - and the missing upper bound let post-turn edits fall in-window on
the reload/reattach recovery call sites.
selectAutoOpenTurnArtifact now accepts:
- agentTouchedFileNames: when the protocol emits Write/Edit tool events
(claude stream-json), mtime-window candidates are restricted to files
the agent actually wrote; protocols with no write events (codex,
gemini, opencode, ACP) pass an empty set and keep the pure time
window - the case the window exists for.
- turnEndedAt: bounds the window at endedAt + 60s, matching
AssistantMessage's inferProducedFilesFromTurn on both sides; callers
without an end stamp keep the open-ended window.
All three call sites resolve the agent's raw tool paths to project file
names through the existing findTouchedProjectFile matching (new
resolveAgentTouchedFileNames helper) and pass their terminal timestamp.
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* chore: untrack the looper task-attachment directory
The runner's fallback lifecycle commit (
|
||
|
|
e20ae0bdbe | test(e2e): cover uploaded root-relative image preview (#5621) | ||
|
|
61ee3914d3 |
fix(web): paint the update-ready prompt above the raised home composer (#5608)
The updater prompt lives inside .entry-main__topbar, an isolated sticky stacking context at z-index 10, so its own z-index 80 could not escape. When the composer's agent picker (or another composer popover) is open, .home-hero__input-card:has(...) raises the card to z-index 1700, painting the composer and its popover over the update prompt on scrolled home windows. Mirror the settings-menu precedent and lift the topbar to z-index 1900 while .updater-popup is open. Red spec: e2e/ui/updater-popup-stacking.test.ts reproduces the overlap with elementFromPoint sampling (red on main, green here). Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code) |
||
|
|
d7151b2b60 |
feat(analytics): link downloads and first-party browser opens (#5442)
* feat(analytics): attribute desktop downloads * fix(analytics): initialize attribution routes after HTTP deps * feat(analytics): bridge first-party browser opens * feat(analytics): bridge first-party anchor opens * fix(analytics): make attribution claims idempotent * fix(analytics): record pending attribution results * chore(analytics): bind landing attribution KV * fix(ci): remove landing preview wrangler config override * fix(landing): resolve download attribution function * fix(analytics): harden attribution token consumption * fix(analytics): preserve same-installation claim retries * fix(analytics): merge recovered attribution retries * fix(analytics): preserve attributed browser links * fix(analytics): clear attribution on privacy reset * fix(analytics): bridge stopped AMR console links * fix(ci): deploy attribution schema before Pages * fix(ci): run attribution migrations with Wrangler 4 --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: PerishCode <perishcode@gmail.com> |
||
|
|
da7c4ae051 |
fix(web): rank Community "Newest" by shipped publishedAt, not local install timestamps (#5597)
* fix(web): rank Community "Newest" by shipped publishedAt, not local install timestamps
The Community gallery Newest toggle sorted by the installed-record
updatedAt/installedAt. Those are stamped when a machine seeds its own
database, so a fresh install (or an upgrade that re-stamps the catalog)
writes the whole bundled catalog milliseconds apart in folder-walk
order — Newest showed reverse walk order (roughly reverse-alphabetical),
unrelated to publication recency.
Root-cause fix: bundled templates now ship a real publication date.
- packages/contracts: add optional manifest field publishedAt (ISO 8601).
- apps/web sortByNewest: freshness = publishedAt when parseable, else
updatedAt (right signal for user-installed plugins); tie-breaks and
stability unchanged.
- plugins/_official: backfill publishedAt into all 460 bundled manifests
from each folder's first-appearance commit date in upstream git
history.
- e2e: repository-resource guard requiring every bundled manifest to
declare a parseable publishedAt, so the signal cannot silently erode.
- docs: field reference entries in plugins-spec (en + zh-CN).
Issue: https://plane.powerformer.net/open-design/projects/49832a02-3158-4faf-bf2f-d0e39c40c7e6/issues/ca0778af-97f5-4fc0-bc63-739280904979
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* worker: 模板用最新筛选,筛选出来的不是最新的
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* fix(web): keep shipped appeal order inside same-publishedAt batches
Review follow-up (#5597, nettee): after the freshness tie on an equal
publishedAt, the comparator still consulted local updatedAt/installedAt,
which a fresh install stamps in folder-walk order — so every
same-publication batch (largest: 322 manifests on one catalog date)
re-sorted per machine instead of keeping the shipped visual-appeal
ranking. Same-publishedAt records now preserve their incoming position;
local timestamps break ties only when at least one side has no usable
publishedAt. Adds the requested regression spec pinning
same-publishedAt / different-updatedAt records.
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* fix(web): gate publishedAt freshness to bundled records; untrack oversized looper attachment
Review follow-up (#5597, nettee round 2): publishedAt was overriding
updatedAt for every visible plugin, so a user-installed github/local/
marketplace plugin carrying an old manifest publishedAt would be buried
behind bundled templates despite a newer local install. publishedAtMs
now returns null for non-bundled records — "Newest" means install
recency for user installs, catalog publication for bundled ones. Adds
the requested regression (non-bundled, old publishedAt, newer
updatedAt) and clarifies the field docs (en + zh-CN).
CI repair: commit
|
||
|
|
906d6ff1f9 |
fix(web): keep the sticky home topbar above the popover-elevated composer card (#5596)
Opening any popover inside the home composer card (agent/model switcher, session-mode toggle, plugin picker, template menu) lifted the whole card to z-index 1700, which out-stacked the sticky entry topbar (z-index 10) and the fixed modal family (automation 80, plus-menu 90, plugins-import 100, use-everywhere 920). With the home view scrolled, the card body painted over the topbar chips (GitHub star, Teams, Discord, settings). The lift only needs to beat the static home content below the hero, whose stacking contexts top out at 8, so 9 restores the intended layering: content < elevated card < sticky topbar < fixed modals. Popover z-indexes inside the card are local to its stacking context and keep working unchanged. Source: https://plane.powerformer.net/open-design/projects/49832a02-3158-4faf-bf2f-d0e39c40c7e6/issues/928fae75-d660-426f-be8e-f98ed4eb88e1 Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code) |
||
|
|
d954bee805 | Extract telemetry worker from monorepo (#5565) | ||
|
|
e6bef56e19 |
fix(web): keep the split resize handle hitbox off the chat scrollbar gutter (#5526)
The chat/workspace split handle extends its pointer hitbox with a ::before overhang of left: -2px / right: -10px. The 2px chat-side overhang sits exactly on the outer edge of the chat-log's 8px scrollbar gutter, so clicks aimed at the (~4px visible) scrollbar thumb start a panel resize instead of scrolling, and hovering the gutter flips the cursor to col-resize with the divider highlight. In RTL the physical right: -10px lands on the chat side and covers the entire gutter. Switch the overhang to logical properties with a hard invariant: the hitbox never crosses the handle's inline-start edge (where the scrollbar lives in both directions) and extends 8px on the workspace side only (inset-inline-start: 0; inset-inline-end: -8px). Effective grab width stays 16px; resize JS is untouched. Red spec: e2e/ui/split-resize-scrollbar-hitbox.test.ts probes elementFromPoint on the gutter edge (LTR + RTL), asserts hover does not enter the resize posture, and keeps a drag-the-handle regression guard. Source: https://plane.powerformer.net/open-design/projects/49832a02-3158-4faf-bf2f-d0e39c40c7e6/issues/5c505d35-42e9-40e7-ab07-ba6e3bbfb2ee Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code) |
||
|
|
3e09ebf282 |
feat(release): publish localized changelog metadata (#5520)
* feat(release): publish changelog metadata * fix(release): verify release notes from stored bytes Generated-By: looper 0.10.3 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
8325aa3d21 |
test: expand project context daemon coverage (#5516)
* test: cover project context daemon flows * test: remove private daemon import from e2e Generated-By: looper 0.10.1 (runner=fixer, agent=codex) |
||
|
|
fc5b276f7d |
feat(ci): surface merge-queue needs-validation ejection as a PR comment (#5519)
A PR ejected from the merge queue by the needs-validation gate leaves no trace on the PR itself: the gate fails on the queue's transient ref, the PR's own checks stay green, and mergeQueueEntry silently goes null. The only way to learn why the PR fell out of the queue is to dig through merge_group workflow runs, which nobody watches (observed on #5329). Producer: the merge_group gate in ci.yml now emits a handoff/comment artifact targeting the labeled PR right before it blocks, and uploads it on the failure path. Consumer: comment.atom.yml accepts merge_group workflow_run events; since a merge_group run's head_sha is the queue's synthetic merge commit, artifacts from those runs are bound to their producing run by run_id, and the base-freshness skip is waived (PRs ahead in the queue move the base while the run completes). The live-PR head check still guards staleness. Topology coverage pins the new boundary: comment.atom consumes pull_request + merge_group; autofix/report stay pull_request-only. |
||
|
|
bc5b6f0588 |
fix(daemon): flag runs that end with unfinished work so status never reads "Completed" early (#5470)
A design-generation run that ended its turn with TodoWrite tasks still pending / in_progress / stopped — or was truncated by max_tokens — was stamped `succeeded` and read "Completed" on the Pet task center and the project pill, while the chat footer simultaneously read "Stopped with unfinished work". Users trusted "Completed", assumed the work was done, and re-requested, creating duplicate generations and eroding trust in the run-state UI (#1247 / #1060). Root cause: the daemon equates "the turn/process ended" with "succeeded" and never consults the agent's own declared work; multiple web surfaces then map `succeeded` -> "Completed" without any completeness signal, even though the chat footer already distinguishes unfinished work. Fix — one canonical signal, consumed everywhere so the surfaces cannot drift: - packages/contracts/api/run-completeness.ts defines the canonical "unfinished declared work" predicate (status !== 'completed', so pending / in_progress / stopped all count), matching the web footer's unfinishedTodosFromEvents exactly. - Daemon folds the last TodoWrite snapshot + a max_tokens truncation off the agent event stream (every runtime, via the single emitAgentEvent choke point) and derives run.endedWithUnfinishedWork once at finish(). - The project-status projection derives `incomplete` from the already persisted events_json — no schema migration — so it survives reload/reattach instead of flashing "Completed" once the in-memory run ages out. - Contracts carry endedWithUnfinishedWork on ChatRunStatusResponse and the SSE end payload (backward compatible: absent = finished), plus a new `incomplete` ProjectDisplayStatus. - Web surfaces (Pet task center, project pill, DesignsTab) render `incomplete` as amber needs-attention, never the success color; the footer now sources the same shared predicate. Truncation uses the display-only option (spec Option A): the run stays `succeeded` but is flagged incomplete, avoiding the code===0 / stdin-close hazards of reclassifying a truncated turn to failed. Regression coverage, red on main / green here: an HTTP-boundary e2e (e2e/tests/dialog/task-completeness.test.ts) drives the interactive chat path for unfinished / stopped / truncated / finished runs; daemon + contracts + web unit tests pin the projection and the canonical predicate. Ref: https://plane.powerformer.net/open-design/projects/49832a02-3158-4faf-bf2f-d0e39c40c7e6/issues/011f6f51-7a25-4043-ae94-182e0b8b0931 Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code) |
||
|
|
fb9ae974ab |
chore(release): bump main to 0.14.2 ahead of stable 0.14.1 (#5441)
Co-authored-by: open-design-release-bot[bot] <open-design-release-bot[bot]@users.noreply.github.com> |
||
|
|
bc6a246c65 |
feat(slides): enhance deck project experience (#5083)
* feat(deck): enhance slide deck functionality with speaker notes and navigation improvements - Added a switch for including speaker notes in slide decks, defaulting to true. - Updated keyboard navigation to include 'R' for resetting to the first slide. - Implemented click navigation for half-slide transitions. - Enhanced the deck framework to support hidden programmatic prev/next controls. - Improved handling of file inputs in question forms to support file submissions. This update aims to improve user experience in creating and presenting slide decks, ensuring better accessibility and functionality. * feat(artifacts): enforce semantic naming for user-facing deliverables - Updated guidelines to require semantic filenames derived from user briefs for new artifacts, moving away from defaulting to `index.html`. - Enhanced documentation to clarify naming conventions for HTML files, emphasizing the use of descriptive names like `investor-pitch-deck.html`. - Adjusted prompts and hints across the system to reflect these changes, ensuring consistency in user-facing outputs. - Improved test coverage to validate the new naming conventions and ensure proper implementation in various contexts. This update aims to enhance clarity and usability in project file management, promoting better organization and user experience. * feat(file-viewer): enhance speaker notes display and improve file workspace functionality - Updated the speaker notes section to include a styled placeholder for empty notes, improving user experience. - Changed the icon in the file workspace from "slides" to "panel-left" for better clarity. - Introduced new sub-category filtering options in the file workspace, enhancing organization and navigation. - Improved styling for the page creator search input and added visual feedback for loading states. These changes aim to enhance usability and visual consistency across the file viewer and workspace components. * test(web): align workspace tests with pages switcher * test(e2e): open design files through pages menu * fix(deck): keep source mode reachable * fix(workspace): restore uploaded file tabs * feat(deck-thumbnail): implement virtualized thumbnail rail for improved performance - Introduced a new `DeckThumbnailRail` component to optimize the rendering of deck thumbnails, reducing memory usage and improving load times. - Enhanced the `FileViewer` to integrate the new thumbnail rail, allowing for lazy loading of thumbnails based on viewport visibility. - Added tests for the `DeckThumbnailRail` to ensure correct functionality and caching behavior. - Updated styles for better visual consistency and performance during thumbnail rendering. These changes aim to enhance user experience by providing a smoother and more efficient way to navigate through deck slides. * feat(deck): enhance deck rendering with thumbnail support and keyboard shortcuts - Integrated `DeckSlideThumbnail` for rendering individual slides in a shadow root, improving performance and reducing main-thread load. - Updated `DeckThumbnailRail` to utilize the new thumbnail component, allowing for efficient slide navigation. - Implemented keyboard shortcuts for deck navigation, enhancing user experience during presentations. - Added tests for `buildDeckRenderInput` to ensure proper functionality of the deck stage fallback. - Improved styling for loading states in the viewer, providing a smoother visual experience. These changes aim to optimize the deck viewing experience by reducing resource consumption and enhancing interactivity. * feat(deck): improve thumbnail loading and speaker notes editing experience - Refactored `DeckSlideThumbnail` to enhance loading states with a new shimmer effect, improving visual feedback during thumbnail rendering. - Updated `DeckThumbnailRail` to manage loading states for thumbnails, ensuring a smoother user experience. - Simplified the speaker notes editing interface by removing the toggle switch, allowing direct editing from the notes body. - Enhanced accessibility by adding roles and focus states to speaker notes elements. - Added tests to verify the new loading states and speaker notes functionality. These changes aim to optimize the user experience in deck navigation and speaker notes management, providing a more intuitive and responsive interface. * feat(file-viewer): enhance version export functionality and speaker notes interaction - Introduced new export options for file versions, including PDF and image formats, improving the ability to download and share content. - Implemented a streamlined process for exporting version content, with progress indicators and error handling for a better user experience. - Enhanced speaker notes editing by refining event handling to prevent unintended focus shifts, ensuring a smoother editing experience. - Updated styles for improved visual consistency in the file version download interface. - Added tests to verify the functionality of version exports and speaker notes interactions. These changes aim to optimize the file viewer's usability and enhance the overall experience when managing and exporting project files. * fix(web): polish export menus and creator filters * fix(file-viewer): fall back to preview exports * test(file-viewer): cover version export fallbacks * test(file-viewer): assert loading skeleton by role * fix(file-viewer): restore html source mode affordance * fix(file-viewer): capture full version fallback snapshots * docs: trim slides handoff eof * test(exports): cover full preview snapshot requests * test(file-viewer): account for snapshot options arg * refactor(file-viewer, file-workspace): streamline export functions and enhance page creator dialog visibility * test(file-workspace): enhance slide template creation and mock plugin responses * feat(export): add support for versioned exports and enhance HTML export functionality * feat(export): implement versioned export support across multiple formats and enhance related tests * feat(file-viewer): enhance manual edit functionality with commit sequence tracking and add test for inline text session saving * style(speaker-notes): update filmstrip and thumb-frame styles for improved responsiveness and add corresponding tests * feat(file-viewer): enhance comment composer functionality with portal metrics and improve draw toolbar layout for mobile views * feat(analytics): track slide deck viewing experience Add analytics for the new deck/slides experience introduced in this PR: the deck viewer surface, in-deck slide navigation, thumbnail rail, and speaker-notes authoring. Presentation entry stays on the existing present_popover click to avoid double-counting. - contracts: DeckViewerSurfaceViewProps (surface_view), DeckViewerClickProps (ui_click), SpeakerNotesSaveResultProps (new speaker_notes_save_result event), wired into the event unions. - web: track* wrappers + fire helpers in FileViewer — deck_viewer surface_view on deck mount, slide_prev/next/reset, thumbnail_select, thumbnail_rail_toggle (expand/collapse), speaker_notes_edit, and speaker_notes_save_result (preview + presenter surfaces). - tests: deck analytics suite asserting the emitted (event, props) pairs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(file-viewer, file-workspace): enhance export toast functionality and improve localization for page creation * feat(home-view, plugins-home-section, agent-skill): update default facet preference, enhance category selection handling, and improve localization support - Set `preferDefaultFacet` to true in HomeView component for better user experience. - Introduced `handlePickCategory` function in PluginsHomeSection to manage category selection based on card layout visibility. - Updated PRIMARY_CATEGORIES to reflect the new order and added localization for titles and descriptions in adaptAgentSkill. - Enhanced tests to verify the correct handling of display copy and tags from SKILL frontmatter. * feat(plugins-home, file-workspace): introduce commercial category labels and enhance deck handling - Added a new module for resolving and localizing commercial category labels for plugins. - Updated the FileWorkspace and PluginCard components to display the commercial category label on deck cards. - Enhanced the PageCreatorPresetFrame to adjust frame classes based on deck presets. - Refactored subcategory handling in facets to align with the new commercial category taxonomy. - Improved localization support for new category labels across multiple languages. * feat(deck-preview): implement deck preview scaling and enhance home hero layout - Introduced `useDeckPreviewScale` hook to manage scaling of deck previews within a fixed 1280×720 logical viewport, ensuring proportional rendering across various templates. - Updated `FileWorkspace`, `HomeHero`, and `PluginCard` components to utilize the new scaling functionality for improved visual consistency. - Enhanced the layout of the home hero section to accommodate new subtype chips and descriptions, including a "More" dropdown for overflow handling. - Improved localization support for new UI elements across multiple languages. * fix(PreviewModal): clarify sidebar prop documentation and update test description - Updated the documentation for the `PreviewSidebar` interface to specify that the sidebar's stage-edge handles are not shown when the sidebar prop is absent. - Modified the test suite description for `PreviewModal` to be more concise and relevant. * test(e2e): select prototype visual card --------- Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
cd07d359df |
feat(chat): surface daemon failure_detail to sharpen run-error guidance (#5321)
* feat(chat): surface daemon failure_detail to sharpen run-error guidance The daemon already classifies each run failure into failure_category / failure_detail (run-failure-classification.ts) for retry policy and telemetry, but kept it daemon-internal — so the chat could only key error guidance off the coarse errorCode. That collapses distinct causes that share one code: a hard quota and a transient 429 both arrive as RATE_LIMITED, and a text-detected missing CLI leaks in as the opaque AGENT_EXECUTION_FAILED. Propagate the classification to the client (contract DTO + SSE end frame, mirroring the proven `resumable` path) and let resolveRunFailureUi take `detail` as a first-class input that can override a too-coarse code: - hard_quota / workspace_credits_exhausted -> a distinct "Quota exhausted" card that drops the futile Retry (primaryAction 'none') and steers to the hosted-AMR switch card instead. - cli_not_installed (text-detected) -> the same install-the-CLI card the AGENT_UNAVAILABLE code path already renders. A transient 429 without a hard-quota detail still offers Retry, and the Antigravity terminal switch-model flow still wins over the generic detail override. Stacks on #5308 (the code->guidance mapping this detail layer refines). * chore(i18n): rebrand user-facing "AMR" to "Open Design Cloud" The hosted model service is now Open Design Cloud, but the run-error cards this PR sharpens (switch / auth / balance), plus settings account + wallet labels, avatar console, onboarding gate, and the handoff website link, still showed the old "AMR" (or bare "Open Design") name. Normalize every user-visible brand mention to "Open Design Cloud" across all 19 locales. Value-only: no keys, agent ids, URLs, or raw daemon error strings touched. * fix(chat): persist daemon failure classification onto assistant message The daemon emits the terminal `error` SSE frame from the child-close handler before a run is finalized, so `failureCategory` / `failureDetail` (computed at finalize) weren't known when that frame was first persisted to the assistant message — the stored `status:error` event kept only `{ detail, code }`. A failure persisted without the live web error handler saving the message, or a conversation reloaded before that save landed, therefore fell back to the coarse errorCode UI and lost the specific fix guidance this PR adds. Stamp the finalize-time classification onto the persisted assistant message: enrich the last `status:error` event in place (append one only if a failed run somehow never persisted an error frame). Covered by a daemon regression that reads the stored assistant message via the conversation-messages API after a failed hard-quota run. * fix(chat): keep daemon failure classification on the live web reload/recovery paths Two live-propagation gaps let the sharpened run-error card degrade back to the coarse/raw UI even though the daemon now sends the classification: - appendErrorStatusEvent() no-op'd whenever the message already had a trailing status:error with the same detail. In the reload/reattach race (reload reads the daemon-persisted error frame first, then the run finishes and onError arrives with the finalize-time classification) that dropped the new code / failureCategory / failureDetail. Merge those into the existing event in place instead; no-op only when nothing is added. - The error-frame-then-status recovery probe in providers/daemon.ts broke out on a terminal failed status without copying failureCategory / failureDetail (unlike the post-loop status fallback), so markErrorRunFailure stamped null and the failureDetail mapping fell back to the generic card on the reconnect path. Mirror the two assignments before the break. Covered by chat-events (in-place merge) and daemon-sse-reconnect (error frame + terminal status fetch, no end frame) regressions. * fix(web): update AMR tier-upgrade test for 3-arg resolveRunFailureUi The main merge kept a two-argument call site that passed agentId as detail after the signature gained an explicit detail parameter. Co-authored-by: Cursor <cursoragent@cursor.com> * ci: re-trigger validate workspace on approved head Co-authored-by: Cursor <cursoragent@cursor.com> * test: align AMR rebrand assertions with Open Design Cloud copy Update unit and e2e selectors that still expected pre-rebrand strings for account status, handoff website link, and switch-and-retry CTA. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
9ef4f0daa6 |
[codex] Refine privacy consent choices (#5384)
* Refine privacy consent choices * Add privacy consent value copy * Polish privacy consent copy * Refine privacy banner wording * Fix privacy consent review issues * chore: retrigger privacy consent CI * Fix privacy banner dismissal in AMR onboarding tests * Fix privacy choice telemetry preservation * Preserve settings draft during privacy choice * Preserve pending settings privacy choices * Align privacy policy consent labels --------- Co-authored-by: elifive555555 <296440099+elifive555555@users.noreply.github.com> |
||
|
|
d5aeab77fc |
fix(ci): push the release-cut baked manifest as a ruleset bypass bot (#5358)
* fix(ci): push the release-cut baked manifest as a ruleset bypass bot bake-plugin-previews-release.yml renders every preview on a release/** cut and pushes the authoritative manifest straight onto the release branch. But release/** is guarded by the 'Protected branches (preview/*, release/v*)' ruleset whose pull_request rule rejects direct pushes — and the workflow pushed with PREVIEW_BAKE_TOKEN||github.token, i.e. github-actions[bot], which is NOT a bypass actor. So the writeback failed with 'GH013: Repository rule violations found for refs/heads/release/vX.Y.Z' (observed on release/v0.14.2), and the release branch's bundled data/plugin-previews/manifest.json was never refreshed — the packaged app then falls back to rendering each preview as a live iframe (pathological for the WebGL example templates). Mint an open-design-bot token (app id 3640364 — already a bypass actor on that ruleset, same App the metrics/blog/contributors workflows use) after the render and push with it via an explicit token URL. persist-credentials: false on checkout so the leftover github.token extraheader can't override the inline bot token on push (same failure mode fixed in #5357). No ruleset change required — the bypass actor already exists; the workflow just wasn't using it. * test(ci): lock the release-cut bake's ruleset-bypass push contract Per .github/AGENTS.md, cross-workflow auth changes must update topology coverage in e2e/tests/packaged-smoke-workflow.test.ts rather than rely on YAML review. Add a companion assertion (alongside the existing bake-plugin-previews.yml one) that locks bake-plugin-previews-release.yml's three co-dependent auth invariants: persist-credentials: false on checkout, the open-design-bot token mint (BOT_APP_CLIENT_ID/BOT_APP_PRIVATE_KEY — the App that is a ruleset bypass actor, not RELEASE_BOT_APP_ID), and the explicit x-access-token:${BOT_TOKEN} push. A refactor dropping any one silently reintroduces the GH013 rejection that stranded release/v0.14.2's manifest. |
||
|
|
b3356807b6 |
fix(amr): improve unavailable model gating (#5335)
* fix(amr): honor full model list metadata * fix(amr): classify tier entitlement failures * fix(amr): refine unavailable model upgrade affordance * fix(web): restore stale AMR model fallback Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(web): surface AMR tier upgrade failures Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): mirror chat upgrade attribution Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): skip disabled default models Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): honor catalog default model * chore(pack): bump vela cli to 0.0.20 * fix(amr): align locked catalog fallback state * chore(nix): refresh pnpm deps hash * fix(amr): refresh entitlement-aware model state * fix(amr): refresh models after upgrade return * fix(amr): preserve default model analytics * fix(amr): tighten model gating follow-ups Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): repair default and refresh follow-ups Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): resolve explicit default before spawn Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): concretize default model in smoke paths Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): repair default model gating Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): share connection-test model cache Generated-By: looper 0.10.1 (runner=fixer, agent=codex) --------- Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com> |
||
|
|
39c8eea0c5 |
test: cover recent daemon and e2e follow-ups (#5354)
* test(e2e): cover recent main follow-ups * test: cover recent main automation gaps |
||
|
|
d41cdd9404 |
feat(release): post an immediate "branch cut" Feishu card on both release cuts (#5323)
Cutting a release branch (Tuesday minor via cut-release, Thursday patch via
cut-patch-release) pushes to release/**, which triggers notify-release-feishu to
build a full prerelease before it posts the download card — 20-40 minutes during
which the team has no signal the cut even happened.
Post an eager green "🌿 已切出 release 分支" card the moment the branch exists, from
the cut workflow itself, reusing feishu-notice.ts (node:crypto only, so the
existing setup-node suffices). The card names:
- the branch and whether it is a 大版本 (minor) or 小版本 (patch),
- the exact backport label (`backport release/vX.Y.Z`) so people know which
label to apply for backports,
- a note that the prerelease build is running and a download card will follow.
The download card from notify-release-feishu is unchanged; each cut now yields
an immediate ack card plus the eventual download card. The patch workflow's eager
card only fires on the happy (published) path, alongside the existing skip card.
Topology test asserts both workflows post the eager card after the branch push and
name the backport label.
|
||
|
|
dbc70663aa |
fix(release): let the Thursday patch cut survive an already-matching version (#5320)
The first scheduled cut-patch-release run (2026-07-09) failed at "Create branch + bump version + push" with "nothing to commit, working tree clean". The guard had passed (open-design-v0.14.0 published → happy path) and it computed patch v0.14.1, but main's apps/packaged/package.json was already 0.14.1: in steady state main leads stable by exactly one patch (finalize-release bumps main to X.Y.(Z+1) after X.Y.Z ships), and the Thursday patch equals that same X.Y.(Z+1). So `npm pkg set version=0.14.1` is an idempotent no-op, `git commit -am` finds an empty tree, and under `set -euo pipefail` the step dies before the push — no branch cut, no prerelease, no Feishu card. This collides every Thursday the version already matches, so it is structural, not a one-off. Commit the release marker with `--allow-empty` so the branch is always cut and pushed (which is what triggers notify-release-feishu); a real version bump still commits the change normally. Add a topology assertion that the release commit tolerates an empty tree. Verified locally: with a real `npm pkg set version=<same>` (idempotent, no diff) the old `git commit -am` fails exactly as CI did while `--allow-empty` succeeds with a marker commit; a differing version still commits the bump. |
||
|
|
08da51b3b4 |
test: expand daemon and UI e2e coverage (#5107)
* test: expand daemon and UI e2e coverage * fix: refresh retry assistant metadata Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix: persist inherited run session mode Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix: stabilize AMR inline auth retry Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix: reconcile legacy chat assistant pins Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * test: stabilize fake AMR auth recovery Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * test: restore e2e interaction actionability Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * test: address review feedback for PR 5107 * test: stabilize PR 5107 CI interactions * test: tighten PR 5107 review coverage * fix: inherit run session mode after conversation fallback * test: assert AMR promotion retry renders recovery Generated-By: looper 0.10.1 (runner=fixer, agent=codex) --------- Co-authored-by: Amy <1184569493@qq.com> |
||
|
|
b0e4f83e85 |
ci(release): Thursday patch-release cut, gated on the Tuesday minor shipping (#5294)
* ci(release): add Thursday patch-release cut gated on the Tuesday minor shipping cut-release cuts a minor every Tuesday (from main HEAD) and, via the release/** push, fires notify-release-feishu to build a prerelease and post a Feishu card. Add cut-patch-release: the same flow one weekday later (Thursday 09:00 Asia/Shanghai) with three deltas: - Bumps the PATCH of the highest release/vX.Y.Z branch (X.Y.(Z+1)), still cut from main HEAD like cut-release. - Gates on this week's minor having actually shipped: the line's minor base X.Y.0 must be a PUBLISHED stable GitHub Release (open-design-vX.Y.0, isDraft=false, isPrerelease=false — i.e. release-stable ran `gh release edit --draft=false --latest`, which rolls the tag back on failure). If it is not published, no branch is cut and nothing is built; instead a Feishu notice card announces the skip. - On the happy path it is otherwise identical to cut-release: create the branch, bump apps/packaged, App-token push (which triggers notify-release-feishu), and create the backport label. feishu-notice.ts is a lightweight sibling of feishu.ts for non-build events (here: the skip card). It reuses the same signed-webhook + retry transport and depends only on node:crypto, so it runs under the existing setup-node with no pnpm install. packaged-smoke-workflow.test.ts locks the guard: Thursday cron + patch bump, the published-stable predicate, and that every branch-cutting step is gated so the skip path posts the notice without cutting or building. * fix(release): gate the patch cut on the final version's minor, not the highest branch The guard target MINOR_BASE was derived from the highest release/v* branch before the manual workflow_dispatch `version=` override was applied. On the auto path V comes from that same branch, so it matched — but a manual `version=0.15.1` while the latest branch is release/v0.14.0 would check open-design-v0.14.0 (the wrong minor), letting the workflow cut release/v0.15.1 even when 0.15.0 has not shipped (and the inverse could wrongly block a valid manual patch on another line). Decide V first (validated override wins, else patch-bump the highest branch), then derive MINOR_BASE from V's own major/minor. Add topology assertions that MINOR_BASE comes from V and never from the highest branch, covering the manual dispatch path. |
||
|
|
38c20ef6fa |
chore(release): bump main to 0.14.1 ahead of stable 0.14.0 (#5287)
Co-authored-by: open-design-release-bot[bot] <open-design-release-bot[bot]@users.noreply.github.com> |
||
|
|
8ca68bbfe6 |
feat(web): pre-run Open Design Cloud balance gate with subscription dialog (#5103)
* feat(web): Open Design Cloud pre-run balance gate — two-tier dialogs with auto-resume Gate every AMR chat send before any run spawns. HARD tier (definitive empty wallet <= $0, or signed out) blocks with a subscription-invitation dialog: distinct copy and CTA per cause (console wallet page vs in-app sign-in), benefits card, and auto-resume — a completed sign-in or a recharge observed by a bounded wallet watch resumes the parked task on its own. SOFT tier (<= $4) shows a dismissible reminder with top-up / start-anyway / persisted don't-ask-again (never silences the hard tier). Blocked project sends park in the conversation queue with their full payload and pause auto-drain until a send passes the gate; home submits hold the create open (continuation promise) so drafts and staged context are never lost, and the home decision carries into the project's first auto-send to avoid double-prompting. Fail-open contract: unknown or unparseable wallet answers never block; hard blocks are confirmed with refresh=1 before firing. New amr_entry sources cover both surfaces and tiers; nine chat.amrBalanceGate.* / chat.amrLowBalance.* i18n key groups ship in all 19 locales. * fix(web): a stale wallet-refresh echo must not confirm a hard block A failed refresh returns the previous cached snapshot with stale=true and an error; treating it as a fresh definitive $0 (or signed-out) answer violated the gate's fail-open contract and could strand a user who just topped up while the wallet endpoint hiccuped. (Review feedback.) * chore: retrigger ci * test(e2e): align AMR UI checks with balance gate * fix(web): preserve AMR gated sends across conversation switches --------- Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com> Co-authored-by: Amy <1184569493@qq.com> Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> |
||
|
|
8f177cf0f2 |
Expose run workspace provenance (#4264)
* Model orchestrator scratch workspaces * Address scratch workspace contract review * Expose run workspace provenance * Type run workspace provenance responses * fix(daemon): refresh routine run workspace metadata * test(e2e): allow UI P0 cold start margin * fix(daemon): allow realpath opencode cwd aliases |
||
|
|
dde6228121 |
feat(daemon): add OD_ALLOWED_INTERNAL_HOSTS allowlist for internal provider endpoints (#4250)
* feat(daemon): add OD_ALLOWED_INTERNAL_HOSTS allowlist for internal provider endpoints Fixes #3225. The 0.8.0 SSRF hardening blocks provider base URLs that resolve to private/internal ranges, with no way to opt a trusted host out -- breaking internally-hosted LiteLLM/Ollama gateways on VPN-only RFC1918 addresses. Add an operator opt-in: OD_ALLOWED_INTERNAL_HOSTS exempts listed hosts from the internal-IP guard, threaded only into user-configured provider endpoints (connection test, model discovery, BYOK chat). The attacker-controllable asset-download guard stays strict. Malformed and CIDR entries are dropped with a warning rather than silently trusted. The Settings base-URL field no longer rejects internal-IP URLs client-side, deferring the authoritative decision to the daemon. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(e2e): update BYOK base-URL P0 for relaxed internal-IP validation (#3225) The P0 spec used an internal-IP URL as its 'invalid' example to assert the client-side error; that URL is now accepted (the daemon owns the allowlist decision). Switch to a non-http scheme, which is still rejected client-side. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(web): defer internal-IP base URL to the daemon in BYOK draft validation (#3225) isValidApiBaseUrl was relaxed, but the Test and model-fetch actions gate on validateByokDraft -> blockingByokDraftIssues, which still treated any validateBaseUrl error (including a forbidden internal IP) as a blocking base_url_invalid. So the Test button appeared but the action stayed blocked client-side and never reached the daemon allowlist. Treat a syntactically-valid forbidden URL as non-blocking here too; genuinely malformed / non-http URLs still block. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f6fb7c204c |
fix(web): reattach spuriously-failed messages on reload when daemon run succeeded (#4607) (#4651)
* test(e2e): add red regression for #4607 artifact persistence after reload Failing test that captures the user-reported symptom from #4607: when a real daemon run is reloaded mid-flight, the run does not reach 'succeeded' and producedFiles is not populated on the assistant message. Separates the runStatus and producedFiles polls so that the race between reattach and artifact-write finalisation is observable; the existing bundled assertion in the prior test was masking the bug. Refs #4607 * fix(web): reattach spuriously-failed messages on reload when daemon run succeeded (#4607) When the SSE reconnect fallback fires while the daemon run is still in flight (e.g. the client retried up to the reconnect limit before any events arrived), the message's run_status is written as 'failed'. The reconcileAssistantMessageOnRunEnd SQL UPDATE cannot rescue this because its WHERE clause excludes the 'failed' state. After page reload, attachRecoverableRuns skips these messages because neither isActiveRunStatus nor shouldReplayTerminalRunMessage matches a 'failed' entry, so no reattach fires, the artifact is never written, and producedFiles stays empty. Expand needsFullReplay to also cover messages with runStatus='failed' that have a runId but no content and no producedFiles — the signature of a spurious failure rather than a real one. The existing status fetch (fetchChatRunStatus) below the needsFullReplay check returns the daemon's authoritative status; if the run was still active, it updates the message to 'running', which triggers full reattach on the next effect fire; if the run already succeeded, reattachDaemonRun replays the buffered events and onDone writes the artifact. Legitimately failed runs (with content or producedFiles) are not affected, and completedReattachRunsRef prevents duplicate reattach. Confirmed with: e2e/ui/real-daemon-run.test.ts lines 161, 187, 221, 278, 299 — all pass. * review: address PR #4651 feedback - heuristic gate: spuriouslyFailedPending is now a separate predicate from needsFullReplay; the recovery path is gated on the fetched daemon status (queued/running/succeeded) — genuine failed runs are left intact with their persisted error context and resumable flag - register live-stream failures in completedReattachRunsRef via a new currentRunId closure variable so attachRecoverableRuns never races a run the client already knows failed (fixes threads-resumable-flag regression) - error clear: setError(null) is called when spuriously-failed recovery moves back to running/succeeded (on detection and on reattach onDone) so the stale "daemon stream disconnected" banner does not persist after successful reattach - e2e test tighten: capture {projectId,conversationId} BEFORE page.reload() so the post-reload polls assert the same conversation; use expectRestoredDelayedAssistantMessage with requireRunId:true to prove the assistant was reattached in-place rather than recreated * review: address PR #4651 round 2 feedback - apply status.resumable from daemon when daemon-confirmed failed - assert runId equality post-reload to prove in-place reattach * review: address PR #4651 round 3 — keep null-status retryable Only add runId to completedReattachRunsRef when fetchChatRunStatus returns an authoritative status. A null return covers any non-OK response or fetch exception (per providers/daemon.ts:686), not only authoritative not-found, so a transient reload-time hiccup must remain retryable on the next effect tick. * review: address PR #4651 round 4 — bounded retry on transient null status When fetchChatRunStatus returns null for a spuriouslyFailedPending row, schedule up to MAX_TRANSIENT_RETRIES (2) retries via a 3s timer that triggers effect re-entry. After the cap is reached the run is added to completedReattachRunsRef so we never spin indefinitely. Timers are tracked in a ref Set and cleared on effect cleanup. * review: fix unbounded retry — preserve attempt counts across effect re-entry The Map reset at effect entry zeroed retry counts every time the timer-driven recoveryTick bumped, so attempts >= MAX_TRANSIENT_RETRIES never held and the cap promotion to completedReattachRunsRef never fired. Refs persist across renders, so the unconditional reset was both redundant and the source of the unboundedness. Also clear stale Map entries on success and on cap promotion so the Map doesn't grow without bound for long-lived sessions. Caught by local codex review before merge. * review: clear endedAt on spurious-failure recovery (#4651) streamViaDaemon.onError stamps endedAt at SSE-disconnect time. When attachRecoverableRuns later flips the row from 'failed' back to a live daemon status, the stale disconnect timestamp lingered and the replay finalizers (prev.endedAt ?? Date.now()) preserved it, skewing the assistant elapsed-time footer for exactly the runs this PR repairs. Clear endedAt at the recovery-detection site so the existing finalizers naturally stamp Date.now() when replay completes. * review: scope endedAt to spurious-failure + don't seal generic disconnects (#4651) - endedAt: undefined clear is now gated on spuriouslyFailedPending, so already-succeeded rows reaching needsFullReplay via shouldReplayTerminalRunMessage keep their original terminal time. Fixes UI P0 regression where unconditional clear broke workspace mount and drifted persisted run durations forward. - streamViaDaemon.onError now only adds runId to completedReattachRunsRef on authoritative terminal failures. Generic "daemon stream disconnected before run completed" (browser SSE reconnect-budget exhausted while daemon still queued/running) stays eligible for attachRecoverableRuns to re-query daemon authoritative status next tick. Supersedes follow-up issue #4717. * review: mirror generic-disconnect gate to reattach onError (#4651) - Bound generic-disconnect retries by reusing transientFailedRetriesRef / MAX_TRANSIENT_RETRIES so a flapping daemon can't trigger an unbounded reattach loop. Caught by local codex review before push. - Use a separate genericDisconnectRetriesRef so null-status and generic-disconnect transient errors don't share one per-run budget and cause premature sealing. Caught by second codex pass. * review: reset transient retry budgets on recovery (#4651) Round-8 nettee BLOCKING + codex P2. The genericDisconnectRetriesRef counter was only cleared on terminal outcomes, so two intermittent SSE disconnects separated by a clean recovery still hit the cap and sealed an otherwise-live daemon run. Reset both transient retry budgets at three recovery sites: - attachRecoverableRuns: after a successful fetchChatRunStatus for a still-active run (queued/running/succeeded). - reattachDaemonRun onRunStatus: when the live stream reports running/succeeded. - startDaemonRun onRunStatus: same, guarded by currentRunId. Cap behavior now matches reviewer intent — fires only on *consecutive* disconnects without intervening recovery. * review: reset retry budgets on stream progress, not status fetch (#4651) Round-9 nettee BLOCKING + codex P2. The round-8 fix reset genericDisconnectRetriesRef on fetchChatRunStatus recoverable result and on onRunStatus running/succeeded, but neither is real stream progress: status fetch is REST-only, onRunStatus transitions to running before any SSE data. If SSE keeps flapping while daemon REST stays running, every reattach tick reset the counter and the cap never fired — infinite reattach loop. Move resets to actual stream-data callbacks (onDelta and onAgentEvent) in both reattach and live-stream paths. SSE payload arrival is real recovery; a queued→running transition is not. Remove the three round-8 resets; add resets at four stream-data callbacks (reattach onDelta + onAgentEvent, live-stream onDelta + onAgentEvent). Cap now correctly fires on consecutive SSE disconnects without intervening data, and never fires when the daemon is actually delivering events. * fix(web): keep active disconnect recovery retryable * refactor(web): share generic disconnect marker * fix(web): preserve terminal success after disconnect * fix(web): back off active disconnect retries * fix: preserve terminal daemon status after disconnect * fix: preserve recovered daemon terminal state * fix: harden daemon disconnect recovery * fix: clear transient disconnect error pills * fix: use structured daemon disconnect errors * fix: replay truncated reattach terminal success * test: pin generic disconnect code path * fix: preserve canceled reload recovery state * test: align daemon disconnect mocks * fix: replay partial live disconnect success * fix: clear reattach streaming before status probe * fix: preserve replay terminal status * fix: keep live disconnect recovery eligible * fix(web): finalize canceled reattach telemetry * fix(web): defer reattach telemetry finalization * test(web): lock reload recovery from spurious-failed run daemon already succeeded Regression test for the #4607 reload-artifact-recovery path, covering the client/daemon mismatch raised in review on #4651: a persisted assistant row at runStatus=failed with empty producedFiles while the daemon run authoritatively reached succeeded before the client's reload/reattach recovery pass runs. Asserts post-reload recovery: content restored, producedFiles repopulated, run reattached in-place (same runId + conversationId, not recreated), artifact project file present. Distinct timing window from the existing "reload while still running" coverage in real-daemon-run.test.ts. Browser SSE fault-injected via page.route (connectionreset on /api/runs GET + events); daemon process untouched; state seeded through production HTTP only, no source-level backdoor. content:'' is informational only — the daemon persists content via an internal write path the browser network stack (and thus page.route) cannot intercept, so it cannot be held empty reliably at the UI layer; the precondition gate holds on runStatus/producedFiles/runId/daemonStatus, which reproduce the artifact-missing symptom class stably. * fix(web): reconcile endedAt from daemon terminal time on generic-disconnect recovery When a run's live SSE stream or a reattach stream hits the generic daemon-disconnect error, the client stamps endedAt to the disconnect time. After the retry budget is exhausted it probes fetchChatRunStatus; when that probe returns an authoritative terminal status, the reconciliation kept the stale disconnect-time endedAt via `prev.endedAt ?? ...`, leaving persisted duration/finalization wrong after recovery. Adopt the daemon's authoritative terminal timestamp (ChatRunStatusResponse.updatedAt) for endedAt in the generic-disconnect terminal reconciliation branches: - Live onError retry-exhaustion terminal branches -> latestRunStatus.updatedAt. - Reattach onError retry-exhaustion terminal branches -> latestRunStatus.updatedAt. - Reattach effect loop-level probe: onDone finalization now uses status.updatedAt; the canceled short-circuit now sets endedAt (previously left unset, preserving the stale disconnect stamp). Adds regression tests locking endedAt to the daemon terminal time for reattach-succeeded, reattach-canceled, and live-succeeded generic disconnect recovery. Addresses review feedback on #4607. * fix(web): stamp recovered endedAt from daemon terminal time, not stale snapshots (#4607) Reload-during-active-run reattach and generic-disconnect recovery were persisting endedAt from a non-authoritative timestamp -- the pre-reattach `running` snapshot or the disconnect-time stamp -- instead of the daemon's terminal `updatedAt`. This corrupted persisted run duration and reordered conversations after recovery. Introduce resolveTerminalEndedAt(runId, candidate) whose docblock states the invariant: every terminal-recovery branch stamps endedAt from an authoritative terminal updatedAt observed at the end of recovery, threaded to both the assistant message row and updateConversationLatestRun. Route the recovery branches through it; thread the terminal updatedAt into the conversation-level metadata on generic-disconnect recovery; and on the reattach onError recoverable-artifact branch overwrite endedAt only on confirmed-succeeded -- the earlier synchronous disconnect stamp otherwise poisoned a `prev.endedAt` nullish guard, silently keeping the stale time. Adds 4 app-local regressions pinning: reload-active endedAt advances past the running snapshot; conversation latestRun metadata reconciles; generic-disconnect message row + conversation both advance; and reattach-artifact-after-non-generic- error adopts the terminal time. Addresses review threads at ProjectView.tsx:3940, :5313, :5278. * fix(web): recognize legacy no-code generic-disconnect events in reload recovery (#4607) hasGenericDisconnectFailureEvent matched only the new structured DAEMON_STREAM_DISCONNECTED code, so failed messages persisted before this PR started tagging disconnects with a code (legacy status/error events carrying only the detail string, no code) were skipped by attachRecoverableRuns on reload even when the daemon reported the run succeeded. Broaden the predicate to also match the canonical GENERIC_DAEMON_DISCONNECT_MESSAGE detail, mirroring isGenericDaemonDisconnect which already checks code-or-message on live Error objects. Adds a frozen regression seeding a failed row with partial content plus a message-only legacy disconnect event; verified red with the impl stashed (reattach never entered) and green with the fix. |
||
|
|
32011bdfcc |
[codex] Route BYOK API providers through OpenCode (#4876)
* feat(byok): route API providers through OpenCode * test(web): align BYOK OpenCode expectations Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(byok): preserve OpenCode media defaults Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(byok): forward OpenCode media defaults Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * test(e2e): align API empty stream smoke with daemon runs Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(byok): guard OpenCode API reroute Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * test(e2e): expose BYOK OpenCode in API smoke Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(byok): preserve Azure and Ollama provider contracts * fix(byok): preserve media default fallbacks * fix(byok): keep api history for opencode routing * fix(daemon): alias byok-opencode detection env Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix(daemon): isolate BYOK provider config Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix(web): keep Bedrock BYOK unsupported client-side Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix(byok): allow keyless local Ollama OpenCode runs Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix(web): label remaining BYOK OpenCode agents Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix(daemon): reject Azure BYOK without base URL Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix(byok): preserve keyless vLLM OpenCode runs Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix(byok): omit auth for keyless OpenCode providers Generated-By: looper 0.9.11 (runner=fixer, agent=codex) --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
b5b2b2c974 |
fix(web): stop MCP server snippet code from inheriting the inline-code chip (#4516)
In Settings -> MCP server, the generated CLI command (`claude mcp add-json …`) renders inside a dark `<pre><code>` block, but the inner `<code>` had no style of its own and inherited the global inline-`code` chip rule from primitives.css (`background: var(--bg-subtle)` + `padding: 1px 5px` + rounded corners). On the wrapped bash one-liner each wrapped segment painted its own light rounded rectangle, reading as permanent selection highlights (#4509). Reset the inner `<code>` to a transparent, padding-less, inherit-color/font wrapper so it stops inheriting the inline-code chip styling and instead picks up the dark block's own color and monospace font. Applies to every CLI client (Claude / Codex / …) since they share the snippet block. Add a Playwright regression check that the snippet `<code>` computed background is transparent (it was the light `--bg-subtle` chip before this change). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
cd6fb44c4d |
test: expand e2e coverage for main updates (#4998)
* test: expand e2e coverage for main updates * test: remove unrelated landing contract coverage |
||
|
|
ab45324124 |
[codex] Restore Kimi ACP and retire Gemini CLI runtime (#5023)
* fix(runtime): restore kimi acp and retire gemini cli * test(e2e): drop retired gemini fake runtime from p0 sweep * fix(daemon): clear retired Gemini config Generated-By: looper 0.9.11 (runner=fixer, agent=codex) --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> |