Commit Graph
572 Commits
Author SHA1 Message Date
a019bcd5cc fix(web): backport release-only fixes to main ahead of v0.10.0 re-cut (batch 1) (#3711)
* fix(web): avoid duplicate style picker group keys

(cherry picked from commit efbe579df7)

* Fix Design Files and sidebar page layout regressions (#3629)

Fixes two web UI layout regressions:

- Prevent Design Files name cells from collapsing to near-zero width, which caused generated file and folder names to wrap vertically while leaving empty space to the right.
- Hide inactive entry views with display: none so Plugins, Integrations, Design Systems, and Automations no longer reserve hidden Home view height above their page content.

Validated with web typecheck, focused web component tests, pnpm guard, and local visual checks.

(cherry picked from commit 686a0b3702)

* fix(web): preserve failed retry attempts

(cherry picked from commit 0ef1400a6e)

* Auto-open produced HTML previews (#3636)

(cherry picked from commit 1fada1ec6d)

* Fix URL preview image export capture

(cherry picked from commit 4659926be8)

---------

Co-authored-by: yinjialu <2481044901@qq.com>
Co-authored-by: Ray Xi <109605599+Siri-Ray@users.noreply.github.com>
2026-06-05 05:29:32 +00:00
8f6cdaaba1 Harden release-beta-s self-hosted beta lane (#3641)
* Fix Windows smoke launcher payload layout

* Harden release-beta-s runner probe

* Use cmd shell for release-beta-s probe

* Add win beta build script for self-hosted lane

* Keep release-beta-s checkout lightweight

* Use explicit local beta version for release-beta-s

* Install dependencies in beta build script

* Repair Electron dist before Windows beta build

* Add release-beta-s timings and diagnostics

* Polish release-beta-s observability guardrails

* Trace tools-pack cache materialization

* Reuse materialized workspace build cache

* Trace Windows packaging segments

* Trace Windows archive process details

* Reuse installer unpacked materialization

* Preserve reusable Windows unpacked projection

* Add fast smoke telemetry for self-hosted beta

* Cache Windows archive outputs for beta lane

* Tighten fast Windows smoke lane

* Scope Windows beta artifact reporting by target

* Clean stale Windows target artifacts

* Wire Windows Authenticode signing

* Expose self-hosted beta validation modes

* Add core Windows smoke profile

* Decouple core smoke from updater fixture version

* Trace Windows smoke lifecycle steps

* Skip unpacked materialization on NSIS cache hit

* Add Nexu S3 beta publisher

* Harden self-hosted Windows beta lane

* Use Windows PowerShell for publish probe

* Run publish probe via repo script

* Require explicit self-hosted S3 public origin

* Run real installer acceptance for external feeds

* Skip ready-prompt checks for external feeds

* Relax optional self-hosted update inputs

* Tolerate BOM in self-hosted publish probe

* Converge self-hosted beta metadata and signing flow

* Run self-hosted beta metadata prep on the runner lane

* Use Windows PowerShell for self-hosted beta metadata checks

* Bypass execution policy in self-hosted beta metadata checks

* Split self-hosted beta metadata publish

* Suppress mc output in beta publish helpers

* Split Windows NSIS payload cache layers

* Require fresh tool dist metadata

* Preserve Windows overlay payload paths

* Default beta-s gate to core

* Optimize win beta packaging reuse

* simplify windows full smoke lifecycle

* preserve onboarding state after windows upgrade smoke

* fix windows tools-pack test portability

* recover stale tools-pack locks

* Allow auto signing fallback for beta builds

* Add self-hosted beta mac arm64 lane

* Quote self-hosted signing choices

* Run self-hosted beta metadata on mac lane

* Use shallow metadata checkout on self-hosted beta

* Use sparse beta metadata checkout

* Make mac release profile bash-compatible

* Allow file sparse metadata checkout

* Isolate self-hosted metadata checkout

* Clear sparse skip-worktree before mac build

* Isolate self-hosted mac build checkout

* Run self-hosted beta publish without aws cli

* Use unsigned beta prefix for mixed platform publish

* Sparse checkout self-hosted beta publish

* Publish mac beta platform before metadata

* Pass mac publish release profile

* Probe mac signing keychain import

* Expand mac signing preflight variants

* Use sudo keychain helper for self-hosted mac signing

* Route self-hosted mac codesign through sudo wrapper

* Normalize mac signing identity name

* Harden self-hosted mac notarization

* Optimize self-hosted mac release cache

* Fix mac signing helper cleanup

* Retry transient mac notarization uploads

* Keep mac notarization fail-fast

* Reduce mac symlink diagnostics noise

* Normalize self-hosted beta platform inputs

* chore: bump beta base version to 0.9.1

* chore: tune release tools-pack cache retention

* test: add temporary cache validation marker

* chore: key windows nsis base payload by content

* Revert "test: add temporary cache validation marker"

This reverts commit e8487bfd3e.

* chore: probe windows nsis payload cache before materializing

* chore: align self-hosted beta smoke modes

* chore: skip mac smoke report upload when disabled

* chore: default self-hosted beta to publish both platforms

* chore: make beta signing modes explicit

* Add release report artifacts and metatool metadata

* Fix Windows release report zip publishing

* Remove artifact handoff from release beta self-hosted lane

* Fix release beta merge follow-ups

* Fix release beta install regressions

* Restore web build dependencies

* Route Windows beta downloads through mirrors

* Use PowerShell 7 for Windows beta lane

* Fix release beta preflight gates

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Fix Windows beta smoke update reuse

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Fix release beta review follow-ups

* Refresh Nix pnpm dependency hashes

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Fix Windows signtool fallback resolution

* Reject stale beta platform manifests

* Validate beta platform manifest run identity

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Validate beta manifest commit identity

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Allow beta metadata publish reruns

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Build tools-pack fully in beta Windows bootstrap

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Emit r2 metadata for Windows beta publish

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Stabilize beta publish browser test

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Stabilize Windows beta metadata smoke test

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* Restore multi-platform Vela CLI package

* Refresh Nix pnpm dependency hashes

Generated-By: looper 0.9.5 (runner=fixer, agent=codex)

---------

Co-authored-by: Looper <looper@noreply.github.com>
2026-06-05 03:00:55 +00:00
475b9a480b fix(daemon): include user toolchain dirs in agent spawn PATH so shebang interpreters resolve (#3675)
What: `applyAgentLaunchEnv` now appends the user toolchain bin dirs
(Homebrew, ~/.local/bin, ~/.bun/bin, version-manager node dirs, npm
prefixes — the same set binary *resolution* searches) to the end of the
spawn PATH. Exposed via a new `userToolchainBinDirs()` from executables.ts;
injectable param defaults to the real dirs (tests pass []).

Why: agent detection resolved a binary's path using resolvePathDirs()
(PATH + wellKnownUserToolchainBins) but spawned it with a PATH containing
only nodeBinDir + the agent's own dir. An agent whose shebang interpreter
lives in a toolchain dir not on the daemon PATH then failed to execute:
Pi (`/usr/bin/env bun` via @oh-my-pi/pi-coding-agent) resolved fine but its
`--version` probe exited 127 ("env: bun: No such file or directory"), so
detection classified it not-invocable and marked Pi unavailable. claude/codex
only survived because their interpreter (node) happened to be on the spawn
PATH. Resolution and spawn PATH are now symmetric, fixing detection AND the
run/connection-test spawns that share this function.

How: append appendPathDirs into the PATH merge (lowest priority, deduped).
Verified: Pi flips unavailable -> available after the fix (path + version
now populated), alongside claude/codex.

Test: apps/daemon/tests/runtimes/launch.test.ts — "appends toolchain dirs
so shebang interpreters (e.g. bun) resolve at spawn time" (would go red
without the fix). Existing exact-PATH tests pass [] to stay deterministic.

Co-authored-by: ZC Deng <zhic.deng@gmail.com>
2026-06-04 15:51:49 +00:00
netteeandGitHub c6ee16be9d feat(daemon): pass open design trace env to AMR (#3667) 2026-06-04 13:37:17 +00:00
aa782365e0 feat(daemon): pass parentSession in pi RPC new_session for conversational continuity (#3434)
* feat(daemon): pass parentSession in pi RPC new_session for conversational continuity

Add parentSession option to attachPiRpcSession that sends
new_session { parentSession } before prompt on pi's stdin.
pi loads the prior .jsonl session file, forking conversation
history into the new session.

- resolveLastSessionPath(cwd) scans <cwd>/.pi/sessions/ for
  the most recently modified .jsonl
- piParentSessionPaths Map in server.ts persists the last
  session path per effectiveCwd
- Backward compatible — no new_session sent when no prior
  session exists
- 3 new tests covering stdin ordering, backward compat, and
  session path capture after agent_end

Closes #3414

* fix: replace str shorthand with string in parentSession test type annotations

* fix(daemon): scope pi session resume to conversations

* fix(daemon): handle pi parent session failures

* fix(daemon): clear stale pi session on capture miss

* fix(daemon): keep pi resume failure SSE code stable

---------

Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-06-04 13:20:50 +00:00
lefarcenandGitHub aba4b5bff2 fix(home,daemon): keep mode card on-screen and let plugin authoring pause on a question-form (#3640)
* fix(home,daemon): keep mode card on-screen and let plugin authoring pause on a question-form

Two release/v0.10.0 firefight fixes:

- Home Design Agent description card: the mode toggle's popover card is
  only shown on the home hero and anchors upward, so at its default 360px
  it crowds (and on smaller windows clips) the page header. Cap its height
  on the home hero so it always clears the top chrome and scrolls for the
  overflow.

- Plugin authoring 'ended before generating the required generated-plugin
  artifacts' error: the od-plugin-authoring turn-1 flow emits a
  <question-form> to collect the brief, then stops and waits for the user.
  That turn legitimately closes with code 0 and no artifacts yet, but the
  missing-artifacts guard treated it as a failure. Track whether the agent
  emitted a clarifying <question-form> in its streamed text and skip the
  guard in that case.

Red spec: chat-route.test.ts 'does not fail plugin authoring when the
turn-1 reply is a clarifying question-form awaiting the brief' (red on
main, green on branch).

* fix(daemon): recognize <ask-question> alias in plugin-authoring clarification guard

The web form parser (apps/web/src/artifacts/question-form.ts) accepts both
<question-form> and its <ask-question> alias as a valid brief form. The
plugin-authoring missing-artifacts guard only matched the canonical tag, so
a turn-1 reply using the alias still rendered a valid form in the UI but
fell through to the 'ended before generating…' failure. Mirror the parser's
accepted tag set in the daemon guard and add a regression test for the
alias path.

Addresses Looper review feedback on #3640.

* fix(daemon): gate plugin-authoring clarification carve-out on a renderable form body

The previous carve-out matched only the question-form/ask-question opening
tag, so a malformed (non-JSON) body — which the web parser keeps as raw
prose with no rendered form card — would still suppress the missing-artifacts
failure, turning a hard failure into a false success.

Mirror the parser's minimal renderable contract in a daemon-local helper
(emittedRenderableQuestionForm): a closed question-form/ask-question block
whose body parses as JSON to an object with a non-empty questions array.
Buffer the run's visible text and validate at close. Documented as a
deliberate mirror of apps/web/src/artifacts/question-form.ts since the app
boundary forbids importing it; promote to packages/contracts if they drift.

Tests: question-form and ask-question fixtures now use valid JSON bodies,
plus a new regression pinning that a non-renderable (non-JSON) form body
still fails. Addresses Looper review feedback on #3640.

* fix(daemon): keep question-form close-tag scan Unicode-safe in the daemon mirror

The mirrored renderable-form check lowercased the whole buffer before
indexing the close tag. Some code points expand under toLowerCase ('İ' ->
'i̇'), shifting every offset after them, so closeIdx desynced from openEnd
(original-string coordinate) and the JSON body slice was corrupted —
failing a valid form when a casing-expanding char preceded it.

Mirror the web parser's findCloseTag: scan char-by-char and lowercase each
fixed-length candidate slice, returning an index in the original-string
space. Added a daemon regression with an 'İ' preamble before a valid form.

Addresses Looper review feedback on #3640.
2026-06-04 11:43:06 +00:00
d6fe99bcdf Make existing project folders easier to open and iterate (#3529)
* Support opening and iterating existing project folders

* Fix existing folder flow i18n strings

* Stabilize AMR status sync

---------

Co-authored-by: Ben Stadler <ben@thebenstadler.com>
Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-06-04 11:35:49 +00:00
lefarcenandGitHub d0bca92646 fix(conversation-forking): fork from the in-memory snapshot so an unpersisted turn no longer silently fails (#3648)
"Fork from here" creates a new conversation by asking the daemon to copy the
source conversation's messages up to the fork point, looked up in SQLite by
`forkAfterMessageId`. When the fork point is an assistant turn whose run
errored or had its connection reset before the message was written to the
database (common with AMR/ACP "Connection reset by server"), that id is not in
the DB. The daemon returned 404 "fork message not found", `createConversation`
turned the non-OK response into `null`, and `handleForkFromMessage` threw into
a quiet error state — so no new conversation opened and the user never switched
into the fork. The page just flashed and stayed put.

Make fork copy what the user is actually looking at: the chat "Fork" action now
sends the in-memory messages slice (up to and including the fork point) as
`seedMessages`, and the daemon prefers that snapshot over reading the source
conversation from the DB by id. The Side Chat path (no `seedMessages`) is
unchanged and still seeds from `seedFromConversationId`.

Red spec: apps/daemon/tests/projects-routes.test.ts "forks from a
client-supplied snapshot when the fork point was never persisted" — 404 on
main, 200 on this branch.
2026-06-04 11:04:52 +00:00
chenxueandGitHub b1fd529eea Feat/aihubmix byok provider (#3583)
* feat(media): integrate AIHubMix as full-stack BYOK provider

Add AIHubMix (https://aihubmix.com) as a BYOK provider at the same layer as
SenseAudio — both a chat protocol and a media-generation provider — so users
can paste one key and get chat + image + speech, with the same key auto-mirrored
into media-config for the `od media` CLI path.

AIHubMix is an OpenAI-wire-compatible aggregator. Its distinguishing trait is the
fixed APP-Code attribution header (discount), funnelled through a single
aihubmixHeaders() helper so every outbound call point (chat proxy, connection
test, model discovery, media renderers, memory extractor) injects it in one place.

Chat protocol layer:
- Extend ApiProtocol / ConnectionTestProtocol / MemoryExtractionProvider unions.
- New web provider client + dispatch; mirror across apiProtocols, config,
  utils, Settings/ChatComposer/HomeHero UI surfaces.
- Refactor the SenseAudio tool-loop chat proxy into a shared
  registerByokToolChatProxy() factory; register senseaudio + aihubmix through it
  (senseaudio behaviour byte-preserved). connectionTest + providerModels treat
  aihubmix as OpenAI-shaped with APP-Code headers.

Media layer:
- Register provider + image (aihubmix-gpt-image-1 / -dall-e-3) and speech
  (aihubmix-tts-1) models; prefixed ids stay unique and map to wire names.
- OpenAI-compatible renderers (/v1/images/generations, /v1/audio/speech) and
  chat tool executors; ENV_KEYS + media-picker allowlists updated.

Note: AIHUBMIX_APP_CODE in apps/daemon/src/aihubmix.ts is an empty placeholder —
fill it with the code from https://aihubmix.com/appstore to enable the discount
header (the integration works without it).

Tests: media-aihubmix.test.ts (wire-name mapping, APP-Code invariant, image +
speech renderers) and an AIHubMix proxy-route case; verify:media-models, guard,
and typecheck all green.

* feat(media): source AIHubMix model lists from live catalog endpoints

Chat LLM models and media image models now come from AIHubMix's live catalogue
(GET /api/v1/models?type=llm | image_generation, public, returns model_id /
model_name) instead of only the hand-curated static lists.

Chat: the existing /api/provider/models discovery, when protocol=aihubmix, now
hits the type=llm catalogue and parses the AIHubMix envelope (342 models live).
The static SUGGESTED_MODELS remain as the pre-fetch default.

Media image: new GET /api/media/providers/aihubmix/models endpoint proxies the
type=image_generation catalogue (53 models), prefixes ids `aihubmix-` for
uniqueness, and caches for 5 min with stale-on-error fallback. generateMedia
synthesizes a def for any unregistered `aihubmix-*` id (like the fal-ai/* path)
so every catalogue model renders through the OpenAI-compatible image endpoint.

Helpers (aihubmixCatalogUrl / parseAIHubMixCatalog) + tests for url building,
envelope parsing, and rendering a dynamic catalogue id. The web media pickers
still read the static seed list; wiring them to the live endpoint is a
follow-up UI change.

* feat(web): show live AIHubMix image catalog in all media pickers

Wire the AIHubMix image-generation catalogue (53 models, fetched from the new
daemon endpoint) into every image-model picker. A shared hook
(useAIHubMixImageModels) fetches once per session and caches; mergeAihubmixImageModels
replaces the two static aihubmix seeds with the live list (and falls back to the
seeds when the fetch hasn't resolved or fails, so the picker is never empty).

Surfaces:
- NewProjectPanel image picker — merged list passed to supportedModels('image').
- Home media composer — buildHomeMediaComposer / fieldsForSurface /
  normalizeHomeMediaInputs now accept an injected imageModels list; HomeView
  fetches and threads it through all three composer call sites.

Saved/template image-model ids starting with `aihubmix-` are accepted even
though they're absent from the static IMAGE_MODELS, since they render
dynamically daemon-side.

* feat(byok): load AIHubMix chat model list without an API key

The BYOK chat model dropdown already merges live-fetched models with the static
suggestions, but the fetch was gated on a non-empty API key (every provider hits
/v1/models behind its key). AIHubMix's catalogue is public, so its 342-model
list now loads as soon as the AIHubMix tab is selected — no key required.

- Daemon /api/provider/models accepts an empty apiKey when protocol=aihubmix
  (baseUrl still required); providerModelsHeaders sends no Bearer when the key
  is blank.
- Web: missingByokModelFetchFields treats apiKey as optional for aihubmix, and
  the auto-fetch effect skips the commit-on-blur gate for aihubmix (base URL is
  prefilled and there's no key to debounce), so the list populates on tab select.

* feat(byok): default AIHubMix chat model to claude-opus-4-8

* feat(byok): memory model picker uses live searchable model list

The Memory model picker was a plain <select> hard-wired to the 8 static
SUGGESTED_MODELS. Swap it to the same SearchableModelSelect the chat picker
above uses, fed by the parent's merged fetched+suggested model options
(apiModelOptions). For AIHubMix that means the full live 342-model catalogue
shows as a searchable dropdown (keyless), matching the chat picker; other
protocols get their live /v1/models list once the chat key is set. 'Same as
chat' leads the list and 'Custom…' is pinned last.

* feat(byok): BYOK chat image-model picker lists live AIHubMix catalog

The Settings BYOK 'image generation model' dropdown (byokImageModel, used by
the chat-injected generate_image tool) listed only the 2 static aihubmix seeds.
Feed it the live image catalogue (useAIHubMixImageModels) for aihubmix so it
shows all ~53 models; SenseAudio keeps its static registry list. Relax the
daemon's isAIHubMixImageModel to accept any aihubmix-* id (they all render via
the OpenAI-compatible endpoint with prefix-strip), so a dynamically-chosen
default passes validation instead of being dropped back to the seed default.

* refactor(byok): share one hook for BYOK image-model pickers; wire composer

The chat composer's inline 'image generation model' picker still listed only
the static aihubmix seeds. Rather than re-derive the merge+filter a third time,
extract useByokImageModelOptions(provider) into the shared aihubmix-image-models
module (live AIHubMix catalogue for aihubmix, static registry otherwise) and use
it from both the Settings image picker and the composer picker. One cached fetch
feeds all sites.

* feat(byok): route AIHubMix chat by model name to native protocol wire

Per the AIHubMix integration guide §4.3, route the BYOK chat by model name to
each family's native endpoint on the AIHubMix origin instead of forcing every
model through /v1/chat/completions:
  claude*           → Anthropic /v1/messages (x-api-key + anthropic-version)
  gemini*/imagen*   → Gemini :streamGenerateContent (x-goog-api-key)
  everything else   → OpenAI /v1/chat/completions (keeps the tool loop)
All three carry the APP-Code attribution header.

The claude/gemini routes run base chat only (no in-chat generate_image yet) —
each protocol has a pluggable tool slot for a later Anthropic tool_use / Gemini
functionCall adapter. The OpenAI family keeps in-chat image/speech generation.

Reuse: extracted runAnthropicChatStream / runGeminiChatStream (+ payload
builders) from the existing /api/proxy/{anthropic,google}/stream handlers; those
routes now delegate to the same functions (behaviour preserved, 79 proxy tests
green). New helpers classifyAIHubMixModel / aihubmixOriginFromBase /
aihubmixAppCodeHeader in aihubmix.ts. No SDK added.

Default AIHubMix chat model is now gpt-5.5 (an OpenAI-family model) so the
default keeps in-chat generate_image working after routing.

Tests: claude→/v1/messages and gemini→/gemini/.../streamGenerateContent routing
assertions in proxy-routes.test.ts.

* feat(byok): AIHubMix in-chat image/video/audio model selection + media-adapters

Bring the BYOK chat media surface to parity across image, video and audio:

- Composer + Settings dropdowns for image/video/speech models and TTS voice,
  threaded as byokVideoModel / byokSpeechModel / byokSpeechVoice. The user's
  explicit pick is authoritative over the LLM's tool `model` arg (regression
  the LLM kept overriding the composer choice). "Default" resolves to the first
  live-catalogue model (honest label) with the daemon const as final fallback.
- New apps/daemon/src/media-adapters: injection-style capability registry +
  family-aware video request builder (seedance content[] array vs generic
  input_reference), capability shape aligned with OpenRouter /videos/models.
  The chat video executor now builds requests through it.
- Per-family request shaping:
  * video: duration snapped to each family's allowed set (veo 4/6/8, sora
    4/8/12, wan 5/10); i2v reference resolved to a data URL.
  * image: gemini/nano-banana models routed to gemini-native generateContent
    (the /v1/images/generations shape 400s for them); others stay OpenAI-shaped.
  * speech: gemini TTS via generateContent with PCM->WAV wrapping and Gemini
    voice fallback; others use /v1/audio/speech (mp3).
  * download: same-origin AIHubMix asset URLs re-send Bearer + APP-Code.
- Clear, actionable errors for unsupported i2v / "params dropped" models, plus
  per-call submit logging (model + endpoint) for multi-model verification.
- i18n keys across 19 locales for the new pickers and the neutral default label.

Tests: byok-tools + media-adapters specs (85 passing); guard + daemon/web
typecheck green.

* feat(byok): media tool loops on claude/gemini chat + wan i2v wire + seedance resolution fix

Make AIHubMix in-chat media generation work regardless of which chat model is
selected, and fix two image-to-video wire-shape bugs surfaced by live testing.

chat-routes: the aihubmix routeByModel divert sent claude -> Anthropic
/v1/messages and gemini -> Gemini generateContent BEFORE the OpenAI tool loop,
so those chat models had no generate_image/video/speech tools ("没有音频工具").
Add per-protocol tool loops inside registerByokToolChatProxy (reusing the shared
executeOneTool): runAnthropicToolTurn/Chat parse tool_use content blocks +
input_json_delta; runGeminiToolTurn/Chat parse functionCall parts. The shared
single-pass runAnthropicChatStream/runGeminiChatStream and the direct
/api/proxy/{anthropic,google}/stream routes are untouched. Factor the per-kind
tool-result hint into buildToolResultContent (shared by all three protocols) and
add openaiToolsToAnthropic / openaiToolsToGemini schema converters (Gemini schema
sanitized to the OpenAPI subset). Gemini 3.x attaches a thoughtSignature to each
functionCall part that must be echoed back verbatim or the follow-up 400s, so
replay the raw functionCall part instead of reconstructing {name,args}.

media-adapters: seedance accepts resolution only as a token (480p/720p/1080p),
never a WxH pixel string — passing the aspect-derived 1280x720 made it 400
("resolution ... not valid ... in i2v"). Add snapResolutionToken to normalise.
Add a third request family `wan` for wan*/happyhorse*: verified against a working
happyhorse-1.0-i2v call, these are DashScope/wanx-backed and use
{ input:{ prompt, media:[{type:first_frame,url}] }, parameters:{ resolution, duration, prompt_extend, watermark } },
NOT the flat input_reference shape we were sending. Update the i2v failure-advice
message accordingly (the remaining risk is wanx needing a public image URL while
we send an inline data URL; seedance accepts the inline image).

Tests: anthropic+gemini in-chat tool loops (incl. thoughtSignature round-trip),
snapResolutionToken, seedance token resolution, and the wan input.media shape.

* feat(byok): add veo video family + default to seedance-2.0-fast

veo* models go through the gateway's OpenAI→Gemini predictLongRunning shim,
which wants `seconds` as a NUMBER and only honours `size` (no aspect_ratio) —
distinct enough from the generic flat shape to warrant its own `veo` family in
the media-adapters builder. Verified against a working veo-3.1-lite call.

Also default the BYOK chat video model to doubao-seedance-2-0-fast-260128 (the
broadly-available fast i2v/t2v path) and extend the media-adapters tests to
cover the veo family routing + duration snapping (4/6/8).

* feat(byok): hide account-source model labels for AIHubMix

AIHubMix's live model fetch returns its full account catalogue, so every
picker option carried an identical "from your account" badge that added
noise without distinguishing anything. Introduce a reusable
ACCOUNT_MODEL_SOURCE_LABEL_HIDDEN set + hidesAccountModelSourceLabel()
predicate: for listed protocols the per-option source label is dropped and
the loaded-models hint shows a plain count (new settings.modelsLoadedCount
key) instead of the account wording. Other providers are unaffected; add a
protocol to the set to opt it in.

* fix(byok): close AIHubMix catalogue SSRF + share gemini image branch

Two review fixes on the AIHubMix BYOK provider:

- SSRF: the public `/api/media/providers/aihubmix/models` GET took a
  caller-controlled `baseUrl` and fetched it server-side, so
  `?baseUrl=http://169.254.169.254/` could reach a private/metadata host.
  The catalogue lives at one fixed origin, so the route now ignores any
  `baseUrl` query and hard-codes the official AIHubMix origin — no
  attacker-chooseable fetch target remains. A focused route test asserts a
  malicious `baseUrl` is ignored and only aihubmix.com is contacted.

- Gemini image parity: the media renderer always sent AIHubMix image models
  to the OpenAI `/images/generations` endpoint, which 400s for
  gemini/imagen-family models. Extract the chat tool's Gemini-native branch
  into a shared `aihubmixGeminiImageBytes` helper and route those models
  through it from both the chat tool and the Home/New Project/CLI media path,
  so the catalogue the picker exposes is fully renderable. Added a media-path
  test that asserts a gemini-family id hits the generateContent wire.

* feat(byok): hide redundant gateway preset for single-origin AIHubMix

The "gateway preset" dropdown only ever offered AIHubMix itself (plus the
generic custom-endpoint option) because AIHubMix is a fixed-origin gateway
with exactly one preset — redundant UI. Gate it behind a reusable
GATEWAY_PRESET_HIDDEN set + hidesGatewayPreset() predicate (mirroring the
existing ACCOUNT_MODEL_SOURCE_LABEL_HIDDEN pattern) so another single-origin
gateway can opt in by adding its protocol, rather than hardcoding a check.
The Base URL field still shows the resolved origin; multi-preset and
custom-endpoint-reliant protocols (azure/google/senseaudio) are unaffected.

* feat(byok): hide Base URL field too for fixed-origin AIHubMix gateway

AIHubMix resolves its Base URL automatically, so the editable field was as
redundant as the gateway preset. Generalize the just-added GATEWAY_PRESET_HIDDEN
into one semantic concept — FIXED_ORIGIN_GATEWAYS + isFixedOriginGateway() — and
drive BOTH the preset dropdown and the Base URL field off that single predicate.
Adding a fixed-origin gateway protocol now hides both surfaces in one place; the
user only supplies an API key. azure/google/senseaudio are unaffected.

* fix(byok): close AIHubMix asset-download SSRF redirect bypass

The AIHubMix asset downloads validated the literal URL via
assertExternalAssetUrl but then fetched with the default redirect:'follow',
so a validated public URL could 302 the daemon into 169.254.169.254 / RFC1918
space (and leak Bearer/APP-Code to the hop target). Add a shared
assertAndFetchExternalAsset(url, init) helper that validates and pins
redirect:'error', and route every external asset download through it:
chat video/image (byok-tools.ts) and media image/video + SenseAudio image
(media.ts). Also add the missing isLocalSameOrigin guard to the AIHubMix
catalogue route so it matches its sibling media routes.

Regression tests lock the invariant: helper-level (blocks literal metadata
host, forces redirect:'error') plus chat video/image executors asserting the
download fetch carries redirect:'error', and a cross-origin rejection test on
the catalogue route.

Also point the AIHubMix API-key console link at the referral URL.

* feat(byok): carry New Project media-model pick into BYOK conversation

The model chosen in New Project → Media was stored on project.metadata but
dropped for BYOK providers (AIHubMix): media is produced by the generate_*
chat tools whose default comes from the per-request byok*Model field, which
ProjectView only seeded from Settings. Seed those overrides from the project's
creation-time pick instead, gated to the active BYOK provider so a cross-provider
model (e.g. a SenseAudio run whose image project defaulted to gpt-image-2) can't
clobber the user's Settings default. mediaModelProviderId resolves AIHubMix's
`aihubmix-` live ids by prefix so the seed survives before the async catalogue
loads.

* refactor(byok): remove in-chat media model selector pending unified picker

Drop the in-conversation BYOK image/video/speech model dropdowns from the chat
composer. Media model selection now comes from the project's creation-time pick
(seeded into the byok*Model overrides), and a unified selection surface will
replace this later. Also removes the now-dead option hooks/imports so the
composer no longer fires AIHubMix catalogue fetches it doesn't render. The
byok* props/handlers are retained as plumbing for the future unified picker.

* fix(byok): resolve AIHubMix fixed-origin base URL so model lists load

Hiding the Base URL field for the fixed-origin AIHubMix gateway left
config.baseUrl empty, which blocked the live model-list fetch (it gates on a
valid base URL) so the Settings dropdown and the top-bar switcher showed only
the static suggested models. Centralise the fixed-origin concept in
state/apiProtocols (FIXED_ORIGIN_GATEWAYS / isFixedOriginGateway /
resolveFixedOriginBaseUrl) and resolve the canonical origin in loadConfig so
every consumer sees it — including configs already persisted with an empty
baseUrl. SettingsDialog now imports the shared helpers instead of redefining
them.
2026-06-04 09:00:20 +00:00
0e6d3176ab fix(web): prompt injection warning chip + subdirectory files and tab state (#2804)
* fix(web): show subdirectory files in root list and preserve design-files nav state across tabs

Two related bugs in DesignFilesPanel:

1. Since directory navigation was added (#2442), files nested in
   subdirectories were excluded from the root-level flat list, making the
   page-size select appear broken — changing it could not surface files
   the user knew existed. Fix: at the root level (currentDir === ''),
   include all files in filesAtCurrentDir so pagination covers the whole
   project. Subdirectory rows still render as navigation shortcuts.

2. Switching to any other tab unmounted DesignFilesPanel, resetting
   kindFilter, currentDir, page, and pageSize back to defaults on return.
   Fix: FileWorkspace persists the four nav-state fields in a ref and
   passes them as initial values (navState prop) plus a change callback
   (onNavStateChange) to DesignFilesPanel. The ref resets when projectId
   changes, matching the existing key={projectId} remount behaviour.

Adds a regression test for case 1.

* feat(web): add possiblePromptInjection i18n key to all locales

* feat(web): add injection variant CSS for system-reminder chip

* test(web): add failing tests for prompt injection chip

* test(web): fix null safety and strengthen assertions in injection chip tests

* fix(web): render model-echoed system-reminder as prompt injection warning chip

Add alert-triangle to Icon, update SystemReminderBlock to accept a
variant prop (trusted|injection), render injection variant with
amber warning styling and "Possible prompt injection" label, and
fix the expand test to wrap click in act() for React 18 batching.

* chore(web): document SystemReminderBlock variant semantics

* fix(daemon): prepend prompt injection resistance block to every agent system prompt

* fix(web): preserve page number across tab switches in DesignFilesPanel

Three useEffect hooks that reset page to 0 (on pageSize, kindFilter, and
currentDir changes) also fired on initial mount, overwriting the page
restored from navState. Added a skipPageResetOnMount ref — true during
the first render, set to false by an effect declared after the reset
effects — so user-initiated changes still reset the page while navState
is honoured on remount.

Adds a regression test: navigate to page 2, unmount, remount with the
captured navState, assert page 2 is restored.

* fix(web): translate possiblePromptInjection key into all 17 non-English locales

Replaces the English placeholder 'Possible prompt injection' with
localized strings so the warning chip label is readable for non-English
users.

* fix(web): reset design files nav before project switch render

* fix(web): restore prompt injection warning styling

---------

Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-06-04 08:16:51 +00:00
Ray XiandGitHub 2e23bafb2b Implement Langfuse phase 2 telemetry (#3616) 2026-06-04 08:01:26 +00:00
7403dc681e refactor: move daemon routes into routes dir (#3568)
* refactor: move daemon routes into routes dir

* fix: restore components typecheck dependencies

* fix: update host tools route test import

Generated-By: looper 0.9.4 (runner=fixer, agent=codex)

* fix: restore review follow-up patches

* fix: tighten daemon route typing

---------

Co-authored-by: Looper <looper@noreply.github.com>
2026-06-04 07:39:18 +00:00
e77c739e4e feat(daemon): resume Claude CLI sessions across turns (+ skip unchanged instruction block) (#3448)
* feat(daemon): add agent_sessions store for per-conversation CLI session ids

* refactor(daemon): align getAgentSession row cast with DbRow convention

* feat(daemon): claude adapter emits --resume/--session-id from runtime context

* feat(daemon): add resolveAgentResumeContext resume/create decision helper

* feat(daemon): detect claude --resume missing-session failures

* feat(daemon): resume Claude CLI session across conversation turns

* fix(daemon): persist claude session id after spawn-budget guards

* feat(daemon): store stable instruction hash on agent_sessions

* feat(daemon): carry stored stable-instruction hash in resume context

* feat(daemon): skip unchanged stable instructions on Claude resume turns

* refactor(daemon): extract computeIncludeStable with unit tests; harden agent_sessions ALTER guard

* fix(daemon): persist Claude session after successful turn

---------

Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-06-04 07:27:05 +00:00
ccc165f206 fix(daemon): don't fail a run when a post-completion SessionEnd hook exits non-zero (#3373)
* fix(daemon): don't fail a run when a post-completion SessionEnd hook exits non-zero

A chat run whose model already emitted a clean terminal turn was marked
failed when the spawned agent's SessionEnd hook (e.g. the Honcho memory
plugin) exited non-zero during teardown, dragging the claude child to
exit 1. classifyChatRunCloseStatus mapped any non-zero exit to failed,
so a post-result teardown exit surfaced a red AGENT_EXECUTION_FAILED
banner and halted the flow for work that had already succeeded.

Add a post-completion carve-out: track turnCompletedCleanly at the exact
point the daemon observes a clean terminal turn (turn_end/usage with no
outstanding host answer -- the same condition that closes the child's
stdin), and classify a later non-zero exit or kill signal as succeeded.
Non-zero exits before a clean turn still fail, and the agent-specific
auth/quota/AMR guards still run first.

Fixes #3372

* fix(daemon): record clean turn after host answers

---------

Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-06-04 07:26:33 +00:00
6408937564 feat(web): redesign Design Files panel + pick working directory from Home (#3358)
* feat(web): align Design Files panel with Claude reference UI

Redesign the Design Files panel into a continuous grouped table that
mirrors Claude's own Design Files surface: uppercase gray section bands
(Folders / Stylesheets / Scripts / Documents / Images …), flush
full-width rows with a colored icon block + bold name + type subtitle +
right-aligned timestamp, a clean single-line toolbar (breadcrumbs left,
New sketch / Paste / Upload right), a right preview card with a centered
Open action and `Modified … · size · EXT` stats, and a static
USEFUL INFO footer.

Removes the old table/sort-header/kind-filter/pagination/group-toggle
chrome and the conflicting legacy `.app .df-*` overrides in routines.css
that were trumping the panel's own stylesheet via specificity. Preserves
batch select/download/delete, rename, the row context menu,
live-artifacts, plugin-folders, drag-upload, and the reloading overlay.

Adds the designFiles.* section/kind/useful-info i18n keys across all
locales.

* feat: pick a working directory from Home before the project exists

Let users choose a code folder on the Home screen up front, instead of
only being able to replace it after a project is created. The HomeHero
composer gains a folder pill (pick / clear); the chosen path is threaded
through project creation and applied via the working-dir API once the
project id exists.

On desktop the working-dir POST is gated behind a host-minted token, so
add a `dialog:pick-working-dir` IPC handler that shows the native picker
and mints a single-use token bound to the folder, plus a
`pickHostWorkingDir()` bridge + types/normalizer in `@open-design/host`.
The renderer feature-detects the bridge and falls back to the web folder
dialog (no token) otherwise. Native dialogs now allow creating a new
folder inline (`createDirectory` / `ShowNewFolderButton`), and macOS uses
`choose folder` so the panel reliably takes key focus.

Wire the WorkingDirPill into the project composer footer and surface a
reloading state + breadcrumb root label to the Design Files panel while a
replace reindexes. Drop the WorkingDirPill "recent directories"
localStorage list in favor of a single Replace action.

* fix(web): preserve staged Home attachments when picking a working dir

Move the working-dir handoff ahead of the initial upload so staged
attachments land in the external folder instead of the temporary managed
root, and fall back to the browser folder dialog when the desktop host
build does not expose pickWorkingDir.

* fix(web): surface host pick errors and normalize Windows dir basenames

When the desktop host is present but cannot mint a working-dir token,
surface the error instead of falling back to the browser folder dialog —
the tokenless raw path would be rejected by the desktop auth gate as a
late create-time failure. Only the pure web path (no token gate) keeps
the dialog fallback. Also split the Home pill basename on both path
separators so Windows paths show the folder name, not the full path.

* fix(web,desktop): harden Home working-dir handoff against auth/token failures

Run the desktop-auth handshake before minting the Home working-dir token
so a missed startup registration fails up front instead of as a rejected
deferred POST. Surface a create-time error toast when the working-dir
handoff fails (expired ~60s token or daemon rejection) instead of
silently leaving the project in the managed root while the user believes
their folder was applied.

* fix(web): abort create on failed working-dir handoff and always show root crumb

When the pre-create working-dir handoff fails, short-circuit the rest of the
Home submit path (skip the staged-attachment upload and auto-send) so the first
run cannot proceed against the managed `.od/projects/<id>` tree the user did not
choose, and reword the error toast accordingly. Always render the Design Files
root breadcrumb, falling back to the `designFiles.crumbs` label when no
rootDirName exists, so the toolbar is not blank on the default managed-storage
view. Adds regressions for the short-circuit and default-root crumb cases.

Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)

* fix(web): normalize Windows separators in WorkingDirPill basename

shortPath() split only on '/', so a Windows working dir like C:\work\repo
rendered as the full absolute path in the footer pill instead of the
folder name. Split on both separators to match HomeHero/ProjectView, and
add a regression covering the backslash path.

Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-06-04 05:48:57 +00:00
Harshit KhemaniandGitHub fd8159216a feat(design-systems): import shadcn registry items as design systems (#3525)
* feat(design-systems): import shadcn registry items as design systems

Add a third design-system import source alongside local folders and
public GitHub repos: a shadcn registry item, referenced with the shadcn
CLI shorthand `<owner>/<repo>/<item>` (resolved against the repo's root
registry.json) or a direct https URL to a registry-item document.

The item's cssVars theme is materialized into a temporary project and
run through the existing local importer, so a shadcn theme yields the
same DESIGN.md + tokens.css + manifest.json as every other import.
Classic shadcn bare-HSL cssVars (e.g. "222 47% 11%") are wrapped into
hsl(...) so brand colors survive instead of falling back to neutrals.

Exposed on both surfaces, per the capability dual-track rule:
- POST /api/design-systems/import/shadcn, with ImportShadcn* DTOs in
  packages/contracts and a "shadcn" source in the design-system manifest
  schema.
- `od design-systems import-shadcn <reference> [--name --import-mode
  --craft --json]`.
- Settings -> Design systems: a new "shadcn" import source (placeholder
  shadcn/ui/theme-zinc), with i18n keys added across all locales.

http:// references are accepted only for loopback hosts so a self-hosted
local registry can be imported and tests stay deterministic.

* fix(design-systems): harden shadcn importer per review

- Fail fast in writeShadcnFiles: a declared registry file that 404s,
  exceeds the size cap, exceeds the file-count cap, or has no safe
  destination now throws a path-named LocalDesignSystemImportError
  instead of silently producing a partially-materialized design system.
- Resolve the shadcn `include` registry layout recursively; an item's
  relative file paths now resolve against the registry.json that declared
  it (so `owner/repo/item` works for registries that use include).
- Keep the fetch abort timer armed across response-body consumption so a
  server that stalls the body cannot hang the import.
- Block SSRF: redirect:'error' on the default fetch, plus per-fetch host
  re-validation (https, or http only for loopback) on every URL we
  contact - entry point, raw GitHub URLs, include targets, and raw files.

Adds regression tests for include resolution, a 404 declared file, an
oversized inline file, and a non-loopback http include target.

* fix(design-systems): close two shadcn importer review gaps

- parseShadcnReference: wrap decodeURIComponent of the URL fragment so
  malformed percent-encoding (e.g. "#%E0%A4%A") surfaces as a 400
  BAD_REQUEST instead of an uncaught 500 from the import route.
- writeShadcnFiles: two declared files that collapse to the same sanitized
  destination (e.g. "@/button.tsx" + "button.tsx") now fail as a
  BAD_REQUEST naming both sources, instead of silently dropping the later
  file - the same partial-materialization failure mode this PR avoids.

Adds parser + importer regression tests for both.

* fix(design-systems): harden shadcn importer (SSRF, resource bounds, fidelity)

A deeper hardening pass from an adversarial self-review of the importer.

SSRF egress policy (assertFetchableUrl): loopback is allowed over http or
https (self-hosted/local registries); private (10/8, 172.16/12, 192.168/16,
100.64/10), link-local (169.254/16, fe80::/10), ULA (fc00::/7), unspecified
(0.0.0.0, ::), and IPv4-mapped/integer-encoded internal addresses are refused
for BOTH schemes; any other host must be https. Enforced at parse time and on
every fetch - entry point, include targets, and raw files - so a direct
https://169.254.169.254, or an include/redirect pivot to an internal address,
is blocked rather than only the http downgrade.

Resource bounds: bodies are read with a running byte cap (no unbounded
buffering) plus a Content-Length pre-check; the whole import shares one
wall-clock deadline and a max-total-requests budget; include breadth and file
count are capped. A stalled/huge body or a large include fan-out can no longer
hang or OOM the import.

Fidelity / fail-fast: a files[] entry with no usable destination is now a 400
(was silently skipped); registry files are materialized under a subdirectory so
a crafted target cannot overwrite the importer's theme.css/package.json/
README.md; cssVars keys/values are validated so a hostile entry cannot inject
extra declarations or be silently dropped; slashed git refs are encoded per
segment; direct-URL items resolve path-only files relative to the item URL;
fetch timeouts surface as a clean BAD_REQUEST.

Adds tests for each: https-internal SSRF (entry + include), a no-destination
file, a reserved-file overwrite attempt, a slashed ref, a direct-URL path-only
file, cssVars injection, and a streaming over-cap body.
2026-06-04 05:47:42 +00:00
Ahmed RehanGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
33d59ebb3a Clarify OpenCode reasoning support and avoid unsupported reasoning argv (#3346)
* Clarify OpenCode reasoning support

* Address PR review suggestions

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-04 03:58:39 +00:00
yinjialuandGitHub 836d734455 [codex] Add same-run retry runtime (#3576)
* Add same-run retry runtime

* fix(daemon): route retried-start and watchdog stall through retry finalizer

Two retryable failure paths bypassed the same-run retry finalizer, so they
emitted no run_retry_attempted/run_retry_finished telemetry and could report
the fallback retry_final_result: 'not_attempted'.

- restartSameRunAfterRetry's catch now routes a failed retried start through
  finishWithRetryDecision instead of design.runs.finish, so it emits terminal
  retry telemetry and sets run.retryFinalResult. retryAttemptCount is already
  1 there, so decideSafeRunRetry suppresses with attempt_limit_reached and
  cannot loop.
- failForInactivity's no-output stall now routes through the finalizer after
  surfacing stallPayload. A silent first-token hang classifies as a retryable
  timeout at first_token_wait, so the same-run retry now recovers it. A new
  watchdogRetryRestarted guard makes the SIGTERM'd stalled child's close bail
  early (revoking only its own tool token) so it cannot re-finalize the run or
  delete the new attempt's event sink (both keyed by the shared runId).
- finishWithRetryDecision returns whether it restarted so the watchdog can set
  the guard.

Adds a run-retry-runtime test with a low OD_CHAT_RUN_INACTIVITY_TIMEOUT_MS
proving the same-run retry fires for a silent first attempt.
2026-06-04 03:55:16 +00:00
dbc74a397c feat(agents): CLI detection self-rescue with actionable diagnostics (#3560)
* feat(agents): surface actionable CLI diagnostics

Detect unavailable CLI agents with structured diagnostics, stream agent discovery results to the settings UI, and render actionable fix controls for common setup failures.

Also harden the streamed agents client so server error events and dropped streams surface as failures instead of replacing state with a truncated agent list.

* fix(agents): gate streamed rescan loading

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(agents): distinguish non-executable CLI diagnostics

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(agents): defer OAuth diagnostics without producer

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Looper <looper@noreply.github.com>
Co-authored-by: Looper Fixer <looper-fixer@noreply.github.com>
Co-authored-by: looper-fixer <looper-fixer@users.noreply.github.com>
2026-06-04 03:18:37 +00:00
f3ec4968af feat(web): revamp chat UI styling + live streaming code card (#3382)
* feat(web): revamp chat UI styling + live streaming code card

Restyle the chat pane (chat/tokens/code/tools/routines/composio CSS) and
add a live code-component card that streams Write/Edit tool input and
<artifact type="text/html"> bodies character-by-character via a new
ephemeral tool_input_delta SSE event, flipping to the completed
FileWriteCard/FileEditCard view on close. Includes shiki highlighting,
markdown/artifact strip handling, tool-status cleanup, and i18n keys.

* chore(nix): refresh pnpm deps hash for merged lock

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-06-03 16:39:20 +00:00
90aab29695 feat(analytics): attribute AMR entry conversions (#3579)
* feat(analytics): attribute AMR entry conversions

* test(web): cover AMR attribution entry points

* fix(daemon): gate AMR entry mirror on analytics consent

The /api/integrations/vela/analytics-entry route forwarded every AMR
entry click to the external AMR ingest endpoint regardless of consent:
mirrorAmrEntryAnalytics fired whenever globalThis.fetch existed, so an
opted-out user's click was still shipped to a third-party service.

Gate the mirror the same way the analytics-capture path does:
- null readAnalyticsContext (no x-od-analytics-* headers => Privacy
  metrics off) short-circuits to { mirrored: false }.
- defense-in-depth re-read of telemetry.metrics from app-config drops
  the mirror even if a stale header leak slips through after opt-out.

Adds two daemon route red specs asserting that a no-headers request and
a metrics-off request never hit the capture server.

---------

Co-authored-by: lefarcen <935902669@qq.com>
2026-06-03 15:55:53 +00:00
Tom HuangGitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>qiongyu1999Siri-Ray
c6722d2671 feat: Lexical composer, interactive terminals, comment attachments & browser reference board (#3516)
* feat(daemon): add interactive terminal support with node-pty

- Introduced a new terminal service to manage interactive terminal sessions.
- Added routes for creating, streaming, and managing terminal sessions in the daemon.
- Integrated terminal functionality into the CLI, allowing users to open interactive shells.
- Updated project routes to support conversation seeding for side chats.
- Enhanced the web application to include terminal tab functionality and UI components.

This feature enables users to interact with a terminal directly within the application, enhancing the overall user experience and providing a more integrated development environment.

* feat(web): implement embedded browser module in Design Files workspace

- Added a `+` icon to the Design Files tab for opening a new Browser module.
- The Browser module supports navigation features including back, forward, refresh, and address input.
- Integrated a curated list of design reference URLs for user convenience.
- Implemented browser data clearing functionality via IPC.
- Enhanced desktop runtime to support embedded browser with appropriate security measures.
- Added tests for browser functionality and URL handling.

This commit establishes a new workspace for browsing and referencing design resources directly within the application, improving user experience and accessibility to design tools.

* refactor(web): enhance add tab menu functionality in FileWorkspace

- Updated the add tab button to toggle the visibility of the menu with improved accessibility attributes.
- Refactored the add menu to be portaled to the document body for better positioning and visibility.
- Adjusted CSS styles for the add menu to use fixed positioning and increased z-index for proper layering.
- Minor CSS adjustments in entry layout for consistent padding.

These changes improve the user experience when adding new modules in the FileWorkspace, ensuring the add menu is more accessible and visually consistent.

* feat(daemon): introduce session mode for conversations

- Added a new `session_mode` column to the `conversations` table with a default value of 'design'.
- Implemented logic to handle `session_mode` in conversation creation, updates, and retrieval.
- Enhanced the API to support `session_mode` in conversation requests, allowing for 'chat' or 'design' modes.
- Updated the web application to include a session mode toggle, enabling users to switch between chat and design modes seamlessly.
- Adjusted system prompts to reflect the current session mode, providing context-aware responses.

This feature enhances the user experience by allowing for more flexible conversation management, catering to different interaction styles.

* feat(web): enhance navigation and settings functionality in DesignBrowserPanel and EntryShell

- Introduced a navigation stack in DesignBrowserPanel to manage back and forward navigation states.
- Updated the browser navigation logic to handle URL history and improve user experience.
- Added a settings menu in EntryShell for quick access to language and appearance options.
- Implemented CSS styles for the new settings menu, ensuring a consistent and user-friendly interface.
- Enhanced tests for navigation functionality and settings menu interactions.

These changes improve the overall usability of the application by streamlining navigation and providing easy access to settings.

* feat(daemon): enhance conversation session mode handling

- Added a new `mode` flag to CLI commands for project and conversation creation, allowing users to specify 'design' or 'chat' modes.
- Implemented `normalizeChatSessionModeFlag` function to validate and normalize session mode inputs.
- Updated project routes to handle session mode during conversation creation and updates.
- Enhanced web components to support session mode changes, including new props and handlers for managing session modes in conversations.
- Adjusted UI elements to reflect the current session mode, improving user experience and interaction flexibility.

This update provides a more robust framework for managing conversation modes, catering to diverse user needs and enhancing overall functionality.

* feat(web): enhance HandoffButton and DesignBrowserPanel with improved functionality and styling

- Updated HandoffButton to support framework-specific CLI prompts and improved local project path handling.
- Enhanced DesignBrowserPanel to manage browser history with favicon support and improved address display.
- Introduced new utility functions for formatting addresses and extracting hostnames.
- Refactored CSS styles for better layout and responsiveness across components.
- Added tests for new functionalities in HandoffButton and DesignBrowserPanel, ensuring robust behavior.

These changes improve user experience by streamlining the handoff process and enhancing the design browsing capabilities within the application.

* feat(web): enhance HandoffButton and ProjectView with improved instructions handling and UI updates

- Updated HandoffButton to include a tabbed interface for switching between editor and CLI options, enhancing user experience.
- Added support for opening the AMR website directly from the HandoffButton.
- Refactored ProjectView to implement a modal for custom instructions, allowing users to edit and review instructions more intuitively.
- Improved CSS styles for project instructions modal and handoff menu, ensuring better layout and responsiveness.
- Added keyboard accessibility for closing the instructions modal with the Escape key.

These changes streamline the handoff process and improve the usability of custom instructions within the application.

* feat(daemon): add social share functionality and project folder management

- Introduced new `share` command in CLI for building localized social-share targets for Open Design projects.
- Implemented `printShareUsage` and `runShare` functions to handle share requests and display usage instructions.
- Added API routes for social sharing, allowing users to create shareable links for projects.
- Enhanced project routes with new endpoints for listing and creating project folders, improving project organization.
- Updated relevant files and tests to support new functionalities, ensuring robust behavior.

These changes enhance user experience by facilitating social sharing and better project management within the application.

* feat(web): enhance DesignBrowserPanel and DesignFilesPanel with improved address formatting and drag-and-drop functionality

- Refactored `formatAddressDisplay` to utilize a new `formatAddressDisplayParts` function, separating URL and title handling for better clarity.
- Updated `DesignFilesPanel` to improve drag-and-drop interactions, including enhanced directory navigation and file management features.
- Adjusted CSS styles for better visual consistency and responsiveness across components.
- Added tests for new functionalities in `DesignBrowserPanel` and `DesignFilesPanel`, ensuring robust behavior.

These changes improve user experience by streamlining address formatting and enhancing file management capabilities within the application.

* feat(web): enhance DesignBrowserPanel and DesignFilesPanel with new reference categories and improved folder creation

- Added new reference categories in DesignBrowserPanel, including 'Inspiration', 'Real Interfaces', 'Color', 'Typography', and more, each with curated design resources.
- Improved folder creation logic in DesignFilesPanel to suggest names based on existing folders, enhancing user experience.
- Updated CSS styles for better layout and responsiveness across components, particularly in control rows and search functionalities.
- Added tests for new reference categories and folder creation features, ensuring robust functionality.

These changes enrich the design resource catalog and streamline folder management, improving overall usability within the application.

* feat(web): implement reference icon functionality and enhance social share features

- Replaced favicon URL generation with a new `referenceIconUrl` function to provide reliable icons for curated design sites, improving visual consistency in the DesignBrowserPanel.
- Updated the FileViewer component to enhance social share functionality, including clearer messaging for protected deployments and improved UI for sharing links.
- Added CSS styles to support new visual states for social share components, ensuring better user experience.
- Expanded tests for the new `referenceIconUrl` function and social share interactions, ensuring robust functionality.

These changes enhance the design resource presentation and improve the sharing experience within the application.

* feat(web): enhance DesignFilesPanel and FileViewer with improved folder management and social share functionality

- Added optimistic folder path management in DesignFilesPanel to improve user experience during folder creation.
- Updated social share logic in FileViewer to handle protected deployments more effectively, ensuring clearer messaging and UI updates.
- Refactored CSS styles for better layout and responsiveness in both components, enhancing overall usability.
- Expanded tests for new folder management features and social share interactions, ensuring robust functionality.

These changes streamline folder management and enhance the social sharing experience within the application.

* feat(daemon): enhance project tab management with new state handling

- Updated database schema to include a new `state_json` column in the `tabs_state` table for improved project tab state management.
- Implemented functions to normalize and parse project tab states, including handling browser workspace tabs.
- Modified `listTabs` and `setTabs` functions to utilize the new state management features, allowing for better tracking of active tabs and saved states.
- Refactored related types in the contracts and web applications to support the new tab state structure.

These changes improve the functionality and user experience of managing project tabs within the application.

* feat(web): enhance project tab management and browser tab functionality

- Updated project routes and server logic to include `browserTabs` in the request body, improving tab state management.
- Implemented validation for `browserTabs` to ensure it is an array, enhancing error handling.
- Refactored `setTabs` function to accommodate the new structure for managing tabs, including browser-specific tabs.
- Added tests for browser tab state persistence and management in the new `project-tabs-state.test.ts` file, ensuring robust functionality.

These changes improve the user experience by providing better management and persistence of project and browser tabs within the application.

* feat(web): enhance ProjectView with improved chat send management and UI updates

- Added support for queue-only chat sends, allowing for better handling of messages during busy conversations.
- Refactored chat send functions to improve state management and persistence of queued messages.
- Updated CSS styles in the DesignFilesPanel for better layout and responsiveness, including search control enhancements.
- Expanded tests for new chat send functionalities and search interactions, ensuring robust behavior.

These changes improve the user experience by streamlining chat interactions and enhancing the overall design file management interface.

* feat(web): improve project tab state management and caching

- Enhanced the `loadTabs` function to utilize cached tab states, improving performance and user experience during data fetching.
- Implemented `normalizeTabsState` and caching functions to manage tab states effectively, including validation and error handling.
- Updated `writeCachedTabs` to ensure the latest state is stored in local storage, facilitating better persistence of tab information.
- Modified `listTabs` in the daemon to include `updatedAt` in the state retrieval, allowing for more accurate tracking of tab updates.

These changes streamline tab management and enhance the overall responsiveness of the application.

* feat(web): integrate Lexical for enhanced text composition and mention handling

- Added Lexical as a dependency to improve text composition capabilities within the chat interface.
- Implemented mention functionality with the creation of `MentionNode` and related serialization/deserialization logic for inline mentions.
- Enhanced `ChatComposer` and `ChatPane` components to support queue-only message sending and improved state management for queued messages.
- Updated `DesignBrowserPanel` and `PreviewDrawOverlay` to incorporate new features for capturing and annotating browser snapshots.
- Refactored various components to streamline interactions and improve user experience during chat and design tasks.

These changes significantly enhance the text editing experience and provide better management of chat interactions, improving overall usability in the application.

* feat(workspace): integrate terminal viewer and enhance chat functionality

- Added a new terminal viewer component with customizable themes and improved styling for better user experience.
- Integrated terminal functionality into the workspace, allowing users to interact with a terminal directly within the application.
- Updated chat components to support active conversation states, enabling seamless message handling and interaction.
- Refactored chat-related props and state management to enhance performance and maintainability.
- Removed deprecated file tree explorer components to streamline the workspace interface.

This update enhances the overall functionality of the workspace, providing users with a more integrated and responsive environment for both terminal and chat interactions.

* feat(workspace): enhance chat and session mode functionality

- Introduced a new `+` launcher in the workspace for easy access to project files and new tabs, including Side Chat and Terminal.
- Added Side Chat functionality that allows users to create context-aware conversations based on existing chats.
- Implemented a new terminal tab type for interactive terminal sessions using `node-pty`, enabling users to run shell commands directly within the workspace.
- Enhanced chat functionality with a new session mode toggle, allowing users to switch between 'design' and 'chat' modes seamlessly.
- Added a feature to copy chat responses as markdown to the clipboard, improving usability and sharing capabilities.
- Updated various components and styles to support these new features, ensuring a cohesive user experience.

This update significantly improves the workspace's interactivity and usability, providing users with more tools for collaboration and development.

* feat(workspace): enhance session mode toggle and chat functionality

- Improved the SessionModeToggle component to include localized guidance cards that provide context-aware descriptions for each mode.
- Updated the UI to display a popover with mode descriptions when hovering over options, enhancing user understanding of the available modes.
- Added a new copy button in the AssistantMessage footer to allow users to copy responses as raw Markdown, improving usability for external documentation.
- Enhanced localization support by updating i18n keys and translations for various languages, ensuring consistent user experience across different locales.
- Refactored styles for the session mode toggle and associated components to improve layout and responsiveness.

This update significantly enhances the user experience by providing clearer guidance and improved functionality in chat interactions.

* feat(styles): enhance session mode toggle styling for improved visibility

- Added new CSS rules to ensure the session mode toggle popover and hover cards are displayed correctly with increased z-index and visibility.
- Updated styles for various chat components to maintain consistent positioning and overflow behavior when session mode elements are present.
- Improved overall layout responsiveness for chat interactions, enhancing user experience during mode transitions.

This update refines the visual presentation of session mode toggles, ensuring they are more accessible and user-friendly.

* feat(web): finish Lexical composer input with atomic mention pills

* fix(web): make browser reference board scroll with a pinned toolbar

The browser tab's default Reference Board (.db-start) is wrapped by
PreviewDrawOverlay's position:absolute container, which is not a flex
parent — so .db-start's flex:1 1 auto never bounded its height and the
board grew to its content height instead of scrolling (and the sticky
.db-reference-toolbar could not pin). Fill the overlay with height:100%
like the .db-webview/.db-fallback siblings already do, restoring scroll
and the sticky toolbar.

* test(daemon): expect updatedAt in persisted tab state round-trip

listTabs() returns the tabs_state row's updatedAt timestamp on the
saved-state path, but these two toEqual assertions predated that field
and failed strictly. Match the real shape with expect.any(Number).

* feat(chat): enhance ChatComposer with session mode management and UI improvements

- Introduced a new `sessionMode` prop to the ChatComposer, allowing users to switch between different session modes (e.g., 'design').
- Added a SessionModeToggle component for improved user interaction and visibility of session options.
- Updated the ToolsTab type to reflect the removal of the pet option, streamlining the tools available in the composer.
- Refactored styles to enhance the visibility and positioning of session mode elements, ensuring a better user experience during mode transitions.
- Improved the handling of draft state and user interactions within the composer, enhancing overall functionality.

These changes significantly improve the ChatComposer's usability and flexibility, providing users with clearer options and a more responsive interface.

* feat(chat): implement caret floating layer for mention and slash popovers

- Introduced a new `CaretFloatingLayer` component to manage the positioning of mention and slash command popovers relative to the caret.
- Enhanced `ChatComposer` to utilize the caret rectangle for accurate popover placement, improving user experience during text input.
- Updated `LexicalComposerInput` to pass caret position data to the trigger handling logic, allowing for dynamic popover adjustments.
- Refactored styles for popovers to ensure consistent appearance and behavior, including improved animations and responsiveness.
- Added accessibility features to mention and slash popovers, enhancing usability for keyboard navigation.

These changes significantly improve the interaction model for mentions and commands within the chat interface, providing a more intuitive and responsive user experience.

* feat(chat): update mention tab order and improve search functionality

- Reordered the mention tab sections in the ChatComposer to prioritize 'Design files' over other categories, enhancing user experience during mentions.
- Updated the search prompt to reflect the new tab order, ensuring clarity in search functionality.
- Enhanced the mention selection logic to accommodate the new tab structure, allowing for a more intuitive navigation experience.
- Added tests to verify the correct display and functionality of the updated mention tabs and search behavior.

These changes significantly improve the usability of the mention feature within the chat interface, making it easier for users to find and select relevant items.

* feat(chat): enhance context management in ChatComposer and HomeHero

- Added functionality to manage MCP servers and connectors within the ChatComposer, allowing users to remove these contexts seamlessly.
- Updated the HomeHero component to support the selection and removal of MCP servers and connectors, improving context handling in user interactions.
- Enhanced the search prompt to include files, ensuring users can search across all relevant categories.
- Refactored related components and styles for better integration and user experience.
- Added tests to verify the correct functionality of the new context management features.

These changes significantly improve the usability of context features in the chat interface, making it easier for users to manage their interactions effectively.

* feat(chat): enhance message handling with session mode and plugin snapshot support

- Added new columns to the database schema for `session_mode` and `applied_plugin_snapshot_json` to support enhanced message context.
- Updated the `upsertMessage` and `listMessages` functions to handle the new fields, ensuring messages can store and retrieve session mode and plugin snapshot data.
- Enhanced the `ChatComposer` to manage and send the applied plugin snapshot as part of the message context, improving user interaction with plugins.
- Introduced a new `MessageSessionModeChip` component to visually represent the session mode in the chat interface.
- Updated styles for better presentation of session mode and plugin context within messages, enhancing user experience.

These changes significantly improve the context management capabilities in the chat interface, allowing for richer interactions and better tracking of session-specific data.

* feat(chat): add annotation handling and UI improvements in ChatComposer and PreviewDrawOverlay

- Implemented functionality to stage draw annotations into the composer input without sending, enhancing user interaction.
- Added a new button in the PreviewDrawOverlay to allow users to append notes to the input, improving workflow flexibility.
- Updated the ChatComposer tests to verify the correct staging of annotations and their integration into the input.
- Enhanced internationalization support by adding new translation keys for annotation actions across multiple languages.

These changes significantly improve the user experience by providing more intuitive annotation handling and better integration within the chat interface.

* feat(capture): implement page capture functionality and enhance folder management dialogs

- Added new capture functionality to allow users to take snapshots of the current page, improving user interaction with visual content.
- Introduced in-app dialogs for folder creation and moving files, replacing the unsupported window.prompt in the Electron desktop host, enhancing usability across platforms.
- Updated the DesignFilesPanel to support these new dialogs, ensuring a seamless experience for managing project files.
- Enhanced internationalization support by adding new translation keys for folder management actions across multiple languages.

These changes significantly improve the user experience by providing intuitive capture options and streamlined file management within the application.

* feat(projects): implement folder deletion and enhance project file management

- Added a new API endpoint to delete project folders, improving the file management capabilities within the application.
- Introduced utility functions for ensuring project subdirectories and safely deleting folders, enhancing the robustness of folder operations.
- Updated the DesignFilesPanel and FileWorkspace components to support folder deletion actions, providing users with a more intuitive interface for managing project files.
- Enhanced internationalization support by adding new translation keys for folder management actions.

These changes significantly improve the user experience by streamlining folder management and providing clearer options for users to organize their projects effectively.

* feat(composer): enhance BoardComposerPopover with image attachment functionality

- Added support for attaching images to comments, allowing users to upload and preview images directly within the composer.
- Implemented new handlers for image input changes and clipboard pasting, improving the user experience for image uploads.
- Updated the component's props to include image-related callbacks and state management for attached images.
- Enhanced styles for image thumbnails and removal buttons, ensuring a cohesive design with the existing comment popover interface.

These changes significantly improve the functionality of the BoardComposerPopover, providing users with a more interactive and visually rich commenting experience.

* feat(file-viewer): enhance comment attachment functionality with image support

- Updated the `onSendBoardCommentAttachments` prop to accept an additional `images` parameter, allowing for image attachments alongside comments.
- Introduced state management for handling attached images, including functions to add and remove images, and to generate previews.
- Implemented a modal for previewing attached images, improving user interaction when managing comment attachments.
- Updated the `FileWorkspace` component to reflect changes in the props, ensuring consistency across components.

These enhancements significantly improve the commenting experience by enabling users to attach and preview images directly within the file viewer.

* feat(home-hero, project-view, styles): enhance functionality and user experience

- Updated the HomeHero component to prevent unnecessary state changes during programmatic updates, improving user interaction with prompts.
- Enhanced the ProjectView component to support image attachments alongside comments, allowing for a more versatile commenting experience.
- Implemented a new image upload process that queues tasks efficiently, ensuring smooth handling of comment attachments.
- Added CSS to reserve scrollbar space in design files, preventing layout shifts when scrollbars appear, thus enhancing visual stability.

These changes collectively improve the user experience by streamlining interactions and ensuring consistent UI behavior across components.

* feat(preview-comments, chat): enhance comment functionality with attachment support

- Added support for `attachments_json` in the `preview_comments` table, allowing users to attach files to comments.
- Updated relevant functions to handle attachments, including `upsertPreviewComment` and `listPreviewComments`, ensuring attachments are properly managed and displayed.
- Enhanced the `CommentSidePanel` to render attached files, providing users with a visual representation of their attachments.
- Improved the `BoardComposerPopover` and `ChatPane` components to support image attachments, including drag-and-drop functionality for reordering queued sends.

These changes significantly enhance the commenting experience by enabling users to attach and manage files directly within the chat interface, improving overall usability and interaction.

* refactor(comment-attachments): rename attachment normalization functions for clarity

- Updated the `normalizeCommentAttachments` function to `normalizePreviewCommentAttachments` for better context in handling preview comment attachments.
- Adjusted the `upsertPreviewComment` and `normalizePreviewComment` functions to utilize the renamed attachment normalization function.
- Added tests to ensure that image attachments are correctly saved and retrieved, addressing a regression issue with attachment persistence.

These changes enhance code clarity and maintainability while ensuring the functionality for handling comment attachments remains robust.

* feat(comment-attachments): enhance comment submission with image and note validation

- Updated the `upsertPreviewComment` function to require either a text note or at least one image attachment for comment submission, improving validation logic.
- Modified the `BoardComposerPopover` to allow saving comments with only images, enhancing user experience by simplifying the commenting process.
- Adjusted the `FileViewer` to support saving comments with image-only notes, ensuring consistency across components.
- Improved styles in the chat and home hero components for better visual representation of attachments and comments.

These changes collectively enhance the commenting functionality, providing users with more flexibility in how they submit comments while ensuring robust validation.

* feat(project-view): implement auto-start for queued chat sends

- Replaced the `startingQueuedChatSendIdRef` with a state variable `queuedAutoStartBlocked` to manage the auto-start behavior of queued chat sends.
- Updated the `useEffect` to ensure that queued sends are processed one at a time after the active conversation completes, enhancing the chat experience.
- Added a test to verify that queued sends auto-start correctly after the active run finishes, ensuring reliable functionality.

These changes improve the handling of queued chat messages, providing a smoother user experience during conversations.

* feat(project-view): refine auto-start logic for queued chat sends

- Replaced the state variable `queuedAutoStartBlocked` with a reference `startingQueuedChatSendIdRef` to manage the auto-start behavior of queued chat sends more effectively.
- Updated the `useEffect` to ensure that queued sends are processed sequentially, improving the handling of chat messages during active conversations.
- Introduced a new state variable `queuedAutoStartTick` to track the auto-start process, enhancing the responsiveness of the chat interface.

These changes improve the reliability and user experience of the chat functionality by ensuring queued messages are handled smoothly and efficiently.

* feat(comment-attachments): improve attachment handling in preview comments

- Updated the `upsertPreviewComment` function to merge existing and incoming attachments, ensuring that image attachments are preserved when updating comments without new files.
- Introduced a new helper function, `mergePreviewCommentAttachments`, to handle the merging of attachments without duplicates, enhancing the robustness of attachment management.
- Added tests to verify the correct merging of attachments and the preservation of existing attachments during comment updates, improving overall functionality and user experience.

These changes enhance the commenting system by providing better management of image attachments, ensuring users can update comments seamlessly while retaining their attached images.

* feat(BoardComposerPopover): enhance popover positioning and measurement

- Updated the `popoverAnchorStyle` function to incorporate viewport scroll positions, ensuring the popover remains within visible bounds.
- Introduced a new `PopoverSize` type to manage measured dimensions, improving the accuracy of popover placement.
- Implemented a `useLayoutEffect` to dynamically measure the popover size and adjust its position accordingly, enhancing user experience during interactions.
- Added tests to verify that the popover correctly adjusts its position based on target and viewport dimensions, ensuring it remains fully visible.

These changes improve the usability of the BoardComposerPopover by ensuring it is properly positioned within the viewport, enhancing the overall commenting experience.

* feat(comment-attachments): enhance image attachment handling in comments

- Updated the `normalizeCommentAttachments` function to include image attachments in the comment payload, allowing comments to be submitted with only images.
- Introduced a fallback message for comments that consist solely of image attachments, improving user guidance.
- Enhanced the `renderCommentAttachmentHint` function to display image attachment details, ensuring users are informed about attached images.
- Added tests to verify that image attachments are preserved in comment submissions and correctly rendered in hints, improving overall functionality and user experience.

These changes enhance the commenting system by providing better support for image-only comments, ensuring users can effectively utilize image attachments in their interactions.

* feat(comment-attachments): refine comment context handling and enhance drag-and-drop functionality

- Updated the `normalizeCommentAttachments` function to conditionally omit comment text when the context is set to 'query', improving clarity in comment submissions.
- Enhanced the `renderCommentAttachmentHint` function to only display comments when not in 'query' context, ensuring a cleaner output.
- Implemented drag-and-drop functionality in the `CommentSidePanel` for reordering comments, improving user interaction and organization of comments.
- Added tests to verify the correct handling of comment context and the functionality of the drag-and-drop feature, ensuring robust performance.

These changes enhance the commenting system by providing clearer context management and improved usability through drag-and-drop capabilities.

* feat(FileViewer, ProjectView): enhance comment attachment handling and status updates

- Updated the `FileViewer` component to manage the state of sent comment IDs, ensuring that active previews are correctly updated after sending comments.
- Refined the `ProjectView` component to filter out comment attachments from the board-batch source and update their status to 'applying' during processing, improving user feedback on attachment handling.
- Introduced logic to handle the removal of sent comment IDs from the preview, enhancing the overall user experience when managing comments and attachments.

These changes improve the functionality and responsiveness of the commenting system, providing clearer feedback and better management of comment attachments.

* feat(conversation-forking): introduce message-based conversation forking

- Added the ability to fork conversations from a specific message, enhancing the chat experience by allowing users to create new conversations that inherit context up to a chosen point.
- Updated the CLI commands and help documentation to reflect the new `--fork-after` option, which specifies the message ID to stop copying from.
- Enhanced the backend to handle the new forking logic, ensuring that only messages up to the specified ID are included in the new conversation.
- Implemented tests to verify the forking functionality, ensuring robust performance and correct behavior when forking conversations.

These changes improve the flexibility of conversation management, allowing users to create tailored discussions based on previous interactions.

* feat(terminal-service): enhance session output management and memory handling

- Introduced new parameters for managing session output, including `maxBufferBytes`, `exitTailBytes`, `flushIntervalMs`, and `flushThresholdBytes`, to optimize memory usage and performance.
- Implemented a `trimBuffer` function to efficiently evict old events based on byte and count limits, improving memory management during active sessions.
- Added logic to coalesce buffered PTY output into single `data` events, reducing the frequency of event emissions and enhancing performance during high-throughput scenarios.
- Updated session event structure to include `byteLength`, allowing for better tracking of output size and memory usage.

These changes improve the efficiency and responsiveness of terminal sessions, ensuring better resource management and user experience.

* feat(workspace-context): enhance project attachment handling and workspace context management

- Introduced `formatProjectAttachmentHint` function to render project attachments in a user-visible order, improving clarity for users referencing attachments.
- Added `normalizeWorkspaceContextItems` function to standardize workspace context items, ensuring consistent handling of various context types.
- Updated `mergeRunContextSelections` to include workspace items, enhancing the context management during chat interactions.
- Enhanced `renderRunContextPrompt` to display active workspace context, providing users with better visibility of their current workspace state.
- Implemented tests for new functions to ensure robust functionality and correct behavior in handling project attachments and workspace contexts.

These changes improve the user experience by providing clearer context and better management of project attachments within the application.

* feat(database, chat): enhance message and conversation data structure

- Added `run_context_json` to the `messages` table schema to store contextual information for each message.
- Updated migration logic to include the new `run_context_json` field and ensure backward compatibility.
- Enhanced conversation retrieval to include `messageCount`, providing better insights into the number of messages per conversation.
- Improved attachment handling in the `ChatComposer` component by introducing ordering logic for attachments, ensuring a consistent user experience.
- Refactored `SessionModeToggle` to simplify state management and improve tooltip visibility.

These changes enhance data management and user interaction within the chat application, providing clearer context and improved functionality.

* feat(attachment-handling): improve attachment sorting and context management

- Introduced `sortAttachmentsByUserOrder` function to ensure attachments are displayed in a user-defined order, enhancing clarity and usability.
- Updated `historyWithApiAttachmentContext` to utilize the new sorting function, improving the context provided with message histories.
- Refactored `buildAnthropicMessageContent` to apply sorting for image attachments, ensuring consistent handling across different message types.

These changes enhance the user experience by providing better organization and visibility of attachments within the chat application.

* feat(chat): enhance conversation listing and loading states

- Improved the SQL query for listing conversations to include message counts, providing better insights into conversation activity.
- Added loading states to the ChatPane component, enhancing user experience during data fetching.
- Implemented a search feature in the conversation history, allowing users to filter conversations by title for easier navigation.
- Updated styles for loading indicators and conversation list to improve visual feedback during loading states.

These changes enhance the usability and responsiveness of the chat interface, providing users with clearer context and improved interaction capabilities.

* feat(chat): optimize suggestion filtering and enhance design system integration

- Refactored suggestion filtering in the ChatComposer component to utilize `useMemo`, improving performance by memoizing results based on dependencies.
- Added new props in ChatPane for handling plugin and design system details, enhancing the integration of these features within the chat interface.
- Updated the FileWorkspace component to manage tab states for design system and browser tabs, improving user navigation and context management.
- Introduced modals for displaying plugin and design system details in the ProjectView, enhancing user experience by providing contextual information.

These changes improve the efficiency of suggestion handling and enhance the overall user experience in managing plugins and design systems within the chat application.

* fix(chat): adjust styling and layout for improved chat interface

- Reduced the conversation row height in ChatPane for better alignment with design specifications.
- Updated CSS styles across various components to enhance layout consistency, including adjustments to margins, padding, and flex properties.
- Improved visual feedback and responsiveness in chat elements, ensuring a more cohesive user experience.

These changes refine the chat interface, making it more visually appealing and user-friendly.

* feat(comments): implement structural equality checks for comment snapshots

- Added `commentSnapshotOverlayEqual` and `commentSnapshotEqual` functions to compare comment snapshots based on their structural properties, improving performance by avoiding unnecessary state updates in the `FileViewer` component.
- Updated `HtmlViewer` to utilize these equality checks, optimizing the handling of live comment targets during pointer movements and hover events.
- Enhanced the overall responsiveness of the comment system by preventing redundant re-renders when comment snapshots remain unchanged.

These changes enhance the efficiency of comment handling and improve user experience in the commenting interface.

* feat(chat): enhance comment attachment sorting and order management

- Introduced `sortChatCommentAttachmentsByOrder` function to ensure comment attachments are displayed in a user-defined order, improving clarity and usability.
- Updated the `currentCommentAttachments` function to utilize the new sorting logic, enhancing the organization of attachments.
- Adjusted the order assignment for visual attachments to ensure consistent handling based on existing attachment orders.

These changes improve the user experience by providing better organization and visibility of comment attachments within the chat application.

* feat(chat): enhance queued send strip with overflow handling and styling improvements

- Added overflow handling to the queued send strip, allowing for better visibility of additional queued items when the list exceeds the visible limit.
- Updated CSS styles for the chat components, including adjustments to layout, padding, and font sizes to improve overall aesthetics and usability.
- Refactored the structure of the queued send row to utilize a grid layout, enhancing alignment and responsiveness of the elements within the chat interface.

These changes improve the user experience by providing clearer visibility of queued messages and a more polished interface.

* feat(database): add index for created_at and enhance comment retrieval

- Introduced a new index on `preview_comments` for `created_at` to optimize query performance when retrieving comments.
- Updated the `listPreviewComments` function to order results by `created_at` and `rowid`, improving the organization of displayed comments.
- Enhanced the test suite to verify the injection of the new URL preview selection bridge and its functionality in various scenarios.

These changes improve the efficiency of comment retrieval and enhance the user experience in the commenting interface.

* feat(tooltip): implement tooltip system for enhanced user guidance

- Introduced a new `TooltipLayer` component to manage tooltip display across the application, improving user interaction by providing contextual information on hover and focus.
- Updated various components to utilize the tooltip system, including buttons and icons, ensuring consistent tooltip behavior and styling.
- Enhanced CSS styles for tooltips, improving visibility and responsiveness, while maintaining a cohesive design across the application.

These changes enhance the user experience by providing clearer guidance and improving the overall usability of interactive elements.

* feat(tooltip): enhance tooltip integration across components

- Updated various components to include tooltip functionality, improving user guidance with contextual information on hover and focus.
- Added `data-tooltip` and `data-tooltip-placement` attributes to buttons and interactive elements for consistent tooltip behavior.
- Enhanced CSS styles to ensure tooltips are displayed correctly and responsively, maintaining a cohesive design across the application.

These changes improve the overall user experience by providing clearer guidance and enhancing the usability of interactive elements.

* feat(project-view): refactor comment handling and enhance tooltip positioning

- Introduced `mergeSavedPreviewComment` function to streamline the management of preview comments, improving clarity and maintainability.
- Updated `ProjectView` to utilize the new comment merging function, enhancing the efficiency of comment updates.
- Refactored `TooltipLayer` to use x and y coordinates for positioning, improving tooltip display accuracy and responsiveness.
- Enhanced CSS styles for tooltips, ensuring better visibility and layout consistency across the application.

These changes improve the user experience by providing more efficient comment handling and refined tooltip interactions.

* feat(design-files): enhance workspace hint and file handling in project context

- Introduced `formatDesignFilesWorkspaceHint` function to provide a detailed overview of the current Design Files workspace, including folder and file listings.
- Added limits for the number of folders and files displayed to improve clarity and prevent overwhelming users with excessive information.
- Updated the `startServer` function to integrate the new workspace hint, ensuring that the context of existing project files and folders is communicated effectively.
- Enhanced tests for the new workspace hint functionality to ensure accurate representation of project context.

These changes improve user experience by providing clearer insights into the Design Files workspace and facilitating better project management.

* feat(composer): atomic @mention keyboard navigation and deletion

* feat(database): add attachments_json field to comments and enhance migration logic

- Introduced `attachments_json` field in the database schema for comments to support attachment storage.
- Updated migration functions to include the new field, ensuring existing data is properly migrated.
- Refactored related SQL queries to accommodate the new field, improving data handling for comments.

These changes enhance the comment functionality by allowing attachments to be stored and retrieved effectively.

* chore(nix): refresh pnpm deps hash

* feat(chat-composer): implement design toolbox for enhanced design actions

- Added a new design toolbox feature to the ChatComposer, allowing users to access various design actions such as 'auto-match', 'motion', and 'visual-polish'.
- Introduced a state management system for the design toolbox, including hooks for opening and closing the toolbox.
- Enhanced the user interface with new components and styles for the design toolbox, improving accessibility and usability.
- Implemented functionality to apply design actions directly from the toolbox, streamlining the design workflow.
- Added tests to ensure the correct behavior of the design toolbox and its interactions within the ChatComposer.

These changes significantly enhance the design capabilities within the ChatComposer, providing users with a more efficient and intuitive design experience.

* feat(chat-composer): enhance design toolbox resource management

- Expanded the design toolbox functionality in ChatComposer to include a comprehensive resource index, allowing for better organization and retrieval of skills, plugins, MCP servers, templates, connectors, and project files.
- Introduced new types and interfaces to support the expanded resource management, improving type safety and clarity in the codebase.
- Updated the design toolbox action descriptions and search functionality to reflect the new resource capabilities, enhancing user experience.
- Added tests to validate the new resource indexing and search features, ensuring robust functionality.

These enhancements significantly improve the design workflow by providing users with a more organized and efficient way to access various design resources.

* feat(workspace): enhance workspace context management and UI integration

- Introduced a new function `renderWorkspaceContextToolHints` to provide contextual hints based on the type of workspace items (browser, terminal, files, live artifacts).
- Updated `ChatComposer`, `ChatPane`, and `FileWorkspace` components to support and display workspace context items, improving user interaction and accessibility.
- Enhanced the `QuickSwitcher` and `TabLauncherMenu` components to include workspace context items in search results, allowing users to navigate between tabs and files more efficiently.
- Added new translations and updated existing ones to reflect the inclusion of workspace tabs in the user interface.

These enhancements significantly improve the usability and functionality of the workspace, providing users with better context and navigation options.

* test(e2e): assert Lexical composer content with toHaveText, not toHaveValue

The chat composer and home hero input are now Lexical contenteditable
editors, not native form controls, so Playwright's toHaveValue (form-only)
fails with "Not an input element". Switch all chat-composer-input and
home-hero-input content assertions to toHaveText, and assert multi-line
soft-break cases with separate toContainText checks since the editor's
textContent collapses the newline (the newline reaching the sent payload
is already covered by downstream message/payload assertions).

* chore(nix): refresh pnpm deps hash

* chore(nix): refresh pnpm deps hash

* test(e2e): open settings through the entry settings menu

The home settings entry is now a menu (EntrySettingsMenu): clicking the
gear opens a popover whose "Settings" item opens the full execution-mode
dialog. Update the three specs that assumed a single click opened the
dialog directly to go through the menu trigger + open-details item.

* test(web): drive HomeView context picker through the Lexical helper

The home hero input is a Lexical contenteditable, so fireEvent.change /
reading .value throws "element does not have a value setter". Switch the
MCP+connector first-turn-context spec to setHomeHeroPrompt / homeHeroPromptText
like the rest of the file already does.

* Fix PR review blockers

* Update Nix pnpm deps hash

* Enhance project folder routes with error handling and tests

- Added checks for project existence in GET, POST, and DELETE folder routes, returning a 404 error if the project is not found.
- Updated tests to verify 404 responses for unknown project IDs in folder operations.
- Improved folder metadata handling in project routes.
- Refactored the TabLauncherMenu component for better UI structure and scrolling behavior.
- Adjusted styles for the TabLauncherMenu to improve usability and visual consistency.

* Update ProjectView component and enhance design toolbox localization

- Modified the ProjectView component to include workspacePanelTrack in chat panel width adjustments.
- Updated localization files to add new keys and translations for the design toolbox in English, Simplified Chinese, and Traditional Chinese.
- Enhanced user experience by providing comprehensive tooltips and prompts for design toolbox actions.

* Add browser use prompt launcher

* Cover browser use prompt launcher

* Add design toolbox badge translations

* Refactor ChatComposer and DesignBrowserPanel components

- Removed the design system picker from the ChatComposer component and integrated it into the StagedRunContexts for better context handling.
- Updated the DesignBrowserPanel to include a new function for determining viewport icons and modified the browser use categories to reflect changes in action prompts and titles.
- Enhanced the HandoffButton component with a new feature to copy the project path to the clipboard, improving user experience.
- Added new styles for search input and empty states in design files, enhancing the UI consistency across components.

* Enhance ChatPane and DesignBrowserPanel components with new features and styles

- Added scroll handling features to the ChatPane component, including scrollable state management and improved user experience during chat interactions.
- Updated the DesignBrowserPanel to include new localization keys and improved category titles for better clarity in the browser use prompt.
- Enhanced styles for chat log scrolling behavior, providing a more intuitive interface for users.
- Implemented keyboard shortcuts for tab navigation in the WorkspaceTabsBar, improving accessibility and user efficiency.

* Fix web workspace test hang

* Update styles and functionality for workspace tabs and chat components

- Adjusted CSS for the MAC_WINDOW_CHROME to improve spacing and margins for better layout.
- Enhanced the ChatComposer component to ensure proper tab order and mention handling, improving user experience.
- Implemented keyboard shortcuts for navigating workspace tabs, allowing for more efficient tab management.
- Updated localization strings for clarity in search prompts across multiple languages.
- Improved the HandoffButton component's UI for better visibility and interaction when copying project paths.

* Update visual settings flow

* Refresh Nix pnpm deps hashes

---------

Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
Co-authored-by: qiongyu1999 <2694684348@qq.com>
Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-06-03 15:46:22 +00:00
4aea5fdb01 feat: skip discovery questions for unmodified example prompts (#3257)
* feat: skip discovery questions for unmodified example prompts

When a user selects a curated example prompt from the gallery and sends
it without modification, the agent now skips all discovery/clarification
questions and directly generates the artifact at full quality.

Adds an `examplePrompt` metadata flag that injects a dedicated system
prompt override instructing the agent to treat the prompt as a complete
creative brief requiring showcase-quality generation.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

* feat: enrich example prompt override with title and pre-filled brief

- Pass example prompt title and artifact-type-specific discovery brief
  through metadata so the agent receives full context without asking
- Only skip discovery on the user's first example prompt usage
  (localStorage gated), subsequent uses follow normal discovery flow
- Convert EXAMPLE_PROMPT_OVERRIDE from static string to dynamic builder
  that interpolates title and brief key-value pairs

* fix: prevent handlePromptChange from clearing examplePromptInfoRef

The ref is now only cleared by onExamplePromptStatusChange(null) which
HomeHero triggers when the user actually edits the text or clicks clear.
This prevents the race where usePromptExample sets the ref and then
onPromptChange immediately clears it in the same tick.

* fix: honor example-prompt discovery skip in API/BYOK mode

API/BYOK runs compose their system prompt through @open-design/contracts,
whose ProjectMetadata and composeSystemPrompt only knew about
skipDiscoveryBrief. Unmodified gallery example prompts therefore skipped
discovery in daemon-backed runs but still asked discovery questions in
API mode, making the feature mode-dependent. Mirror the daemon's
examplePrompt/examplePromptTitle/examplePromptBrief metadata and
buildExamplePromptOverride into contracts so both composers behave
identically.

Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
2026-06-03 12:56:44 +00:00
Ray XiandGitHub 8f9ec58c26 Implement Langfuse prompt-stack diagnostics (#3557)
* Implement Langfuse prompt-stack diagnostics

Generated-By: looper 0.9.3 (runner=worker, agent=codex)

* Redact private var and root prompt paths

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* Redact dev-container workspace prompt paths

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* Reduce prompt stack metadata noise

* Normalize arbitrary prompt local paths

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* Preserve semantic slash tokens in prompt telemetry

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* Redact media and srv prompt paths

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* Keep default model bucket in Langfuse

* Redact more POSIX prompt roots

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* Redact private var temp prompt paths

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* Avoid duplicate aggregate prompt telemetry content

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* Keep aggregate prompt content in Langfuse diagnostics
2026-06-03 12:19:53 +00:00
yinjialuandGitHub ee2df3bea9 [codex] Add safe retry policy contracts (#3569)
* Add safe retry policy contracts

* Cap default safe run retry at one attempt

Issue #3543 scopes the first implementation to at most one automatic
same-run retry. Set DEFAULT_SAFE_RUN_RETRY_MAX_ATTEMPTS to 1 so a first
failed retry (attemptCount: 1) suppresses with attempt_limit_reached
instead of being eligible for a second retry, and document that the field
counts retry attempts rather than the initial run. Update the policy test
to assert the one-retry-by-default contract.

Generated-By: looper 0.9.3 (runner=fixer, agent=claude-code)
2026-06-03 11:12:40 +00:00
lefarcen cad67922a5 Merge origin/main into release/v0.9.0 — catch up #3564 BYOK + 7 commits
Resolves MemoryModelInline.tsx and SettingsDialog.execution.test.tsx toward
main's newer #3564 BYOK settings rework (this UI surface is newer on main).
2026-06-03 18:45:06 +08:00
lefarcen 3398ca9826 test(daemon): match AMR live-models detection spec to release JSON vela
#3300's detectAgents AMR spec used the legacy text 'vela models' fake; release
#3425 switched AMR model loading to 'vela model list --format json'. Point the
fake vela at the JSON command so the spec validates the shipped (release) AMR
detection path and stops failing 'fallback' != 'live'.
2026-06-03 18:21:54 +08:00
SidandGitHub 11f2b994e5 Keep integrations CLI guidance aligned with run flow (#3465)
The agent guide still described the old one-shot od run shorthand, while daemon startup duplicated lifecycle code and could exit after the top-level dispatcher completed. This aligns the documented headless path with the current project creation and run start flow, and routes daemon start through the shared startup runtime so the process stays alive until termination.

Constraint: Issue #3454 reports the integrations guide no longer matches current CLI behavior
Rejected: Keep documenting the old od run --plugin shorthand | it no longer reflects the project plus conversation flow users must run
Confidence: high
Scope-risk: narrow
Directive: Keep CLI guide snippets backed by regression tests when the od command flow changes
Tested: pnpm exec vitest run -c vitest.config.ts tests/cli-startup.test.ts tests/daemon-lifecycle.test.ts
Tested: pnpm exec vitest run -c vitest.config.ts tests/components/use-everywhere-agent-guide.test.ts
Tested: pnpm --filter @open-design/daemon typecheck
Tested: pnpm --filter @open-design/web typecheck
Tested: git diff --check
Not-tested: lint unavailable because affected packages have no lint script
Related: #3454
2026-06-03 09:23:15 +00:00
lefarcen fa59871428 Merge origin/main into release/v0.9.0 — back-merge to reconcile v0.9.0 with main
Syncs release/v0.9.0 with main so PR #3282 (release/v0.9.0 → main) merges
cleanly. 17 conflicts resolved by commit-time + per-area ownership:

- Comment/edit/preview: keep main (newer). FileViewer combines main's #3438
  (pin manual-edit inspector, no full-height panel) + #3347 deck/queue work
  WITH release's #3401 hover-card anti-flicker grafted on; #2879 Button kept.
- Toolbar: footer layout (reviewer-validated, ca03a7e0f) overrides main #3447 —
  CLI/agent selector in the composer footer, settings gear in the header, no
  settings item in the AvatarMenu dropdown.
- AMR: keep release's client-side model polling (mergeAmrModelsIntoAgents) and
  all release AMR fixes (#3450 sign-out, #3504 console, #3487 acp tool-only
  guard, amrCloudVisible onboarding, #3511 analytics provider id).
- Pet composer button stays removed (release decision); only /pet slash props
  retained.
- Pickers: main's providerModelsCache approach.

Validation: web typecheck + guard + full web suite (2638) + daemon suite green.
2026-06-03 17:21:00 +08:00
YOMXXXandGitHub b0e7a55a6e fix(runtime): handle Gemini stream-json tool events (#3457)
* fix(runtime): handle Gemini stream-json tool events

* fix(daemon): treat terminal Gemini errors as fatal
2026-06-03 03:52:56 +00:00
Denis RedozubovandGitHub b70791b0c6 Harden sandbox-mode media and tools-dev smoke (#3428)
* Harden sandbox media smoke path

* fix(daemon): keep stream-json stdin open after host answer
2026-06-03 03:30:10 +00:00
YOMXXXandGitHub b791c14384 feat(cli): add od templates subcommand for user-saved templates (#2428)
* feat(cli): add od templates subcommand for user-saved templates

Closes the UI/API/CLI triple for user-saved project templates: the
HTTP layer (POST/GET/DELETE /api/templates) and the New Project ->
Templates UI surface already existed, but external agents could not
list, snapshot, or remove templates without rendering the web UI.

Adds `od templates {help,list,save,delete}` plus the standard
--daemon-url / --json options. `save` takes <projectId> + --name
(and optional --description) and POSTs the same body the UI sends;
`list` and `delete` mirror GET / DELETE /api/templates.

New tests/cli-templates.test.ts pins the contract by spinning up a
tiny HTTP stub and exec-ing the real cli.ts entry, so the SUBCOMMAND
dispatch, flag parsing, missing-arg exit codes, and JSON output mode
are all covered end to end.

* fix(cli): surface clean daemon-unreachable error from `od templates` verbs (#2428 review follow-up)

Reviewer P2 from lefarcen on #2428: each `od templates` sub-verb
(`list`, `save`, `delete`) called `fetch()` without a try/catch, so
when the daemon wasn't running Node threw a raw
`TypeError: fetch failed` instead of the
`failed to reach daemon at <url>: <code>` shape every other CLI
surface emits via `surfaceFetchError`.

Wrap each `fetch` in the same pattern `runAutomation` /
`runResearch` / the project verbs already use:

    let resp;
    try {
      resp = await fetch(...);
    } catch (err) {
      surfaceFetchError(err, base);
      process.exit(3);
    }

Adds three regression cases — one per sub-verb — pointing the CLI at
an unreachable port to assert exit code 3 plus the clean error string
and no raw `TypeError` leak.

* fix(cli): make od templates positional id flag-order tolerant + map 404/400 to precise error codes (#2428 review follow-up)

Reviewer (#2428 non-blocking, round 3) found two robustness issues:

1. `od templates save <projectId>` and `od templates delete <id>`
   both required the positional id to be the first token after the
   sub-verb. A headless caller that put shared options first —
   `od templates save --daemon-url http://... proj-1 --name Cards`
   — would hit the missing-id usage path before reaching the daemon.
   Switch to a `positionalArgs(rest)` helper that mirrors
   `runAutomation`, stepping past `--flag value` pairs for every
   templates string flag so the id can appear before or after flags.

2. `structuredHttpFailure(resp)` with the default fallback maps any
   non-OK templates response to `daemon-not-running`, but the
   `/api/templates` route returns 404 for an unknown source project
   and 400 for body validation — reachable user errors while the
   daemon is up. Map 404 → `project-not-found` and 400 →
   `missing-input` on save, and 404 → `template-not-found` on delete
   (new code, exit 74, alongside `project-not-found`/`run-not-found`).
   Agents reading the exit number alone can now branch correctly
   without parsing the envelope.

Five new regression tests pin:
- positional id after `--daemon-url` for save and delete
- save → 404 surfaces `project-not-found` (exit 68)
- save → 400 surfaces `missing-input` (exit 67)
- delete → 404 surfaces `template-not-found` (exit 74)
- the existing 11 cases still pass under the new flag parsing

* test(cli): reserve-and-release a free port for unreachable-daemon checks (#2428 review follow-up)

The unreachable-daemon regressions previously pointed the CLI at stub.baseUrl's port + 1, but the OS only guaranteed the stub's ephemeral port itself was free — port + 1 could already be bound by another local process on a shared CI host. If that happened, the three cases exercised whatever server was on that port instead of the connection-refused path and could fail or pass for the wrong reason.

Switch to a reserve-and-release helper: open a probe HTTP server on port 0, capture the OS-assigned port, close the server, then point the CLI at that exact port. The connection fails ECONNREFUSED on every platform because nothing is listening on it now and the port was deliberately picked from the same ephemeral pool the kernel uses for free-port allocation.

* fix(cli): align `od templates delete` with the daemon's idempotent contract (#2428 review follow-up)

DELETE /api/templates/:id in the real daemon (project-routes.ts:729-731,
server.ts:6064-6066) calls deleteTemplate(...) unconditionally and
returns { ok: true } for unknown ids. The CLI's earlier 404 special
case mapped a status the production route never emits to a
template-not-found exit code that could not fire, and the stub-only
regression test documented behavior the shipped API does not expose —
exactly the CLI/API drift the dual-track exposure rule is meant to
avoid.

Drop the 404 branch, the RECOVERABLE_EXIT_CODES entry for
template-not-found, and the stub-only regression. Any unexpected
non-2xx still falls through to structuredHttpFailure(resp). Delete
stays documented as idempotent success until the daemon contract
itself changes in a follow-up.

Surfaced by Siri-Ray and mrcfps's matching inline reviews on cli.ts:5135.

* fix(cli): preserve daemon flat-string error messages in structuredHttpFailure (#2428 review follow-up)

POST /api/templates returns flat `{ error: '<message>' }` bodies for
400/404 (project-routes.ts:669, :675, :679), but structuredHttpFailure
expected the nested `{ error: { code, message } }` shape. With a flat
body, parsed.error.message was undefined and the structured envelope
collapsed to a `HTTP 400: ` message — losing the only diagnostic the
daemon actually returned to headless callers.

Normalize a string-shaped error.body into `{ message }` before the
recoverable-code lookup, so:
- The exit-code mapping stays the same (still falls through to the
  fallback code at the call site).
- envelope.error.message now carries the daemon's literal text
  (`source project not found`, `name required`) instead of an empty
  HTTP placeholder.

The two save-error regressions are also realigned to stub the flat
payload the route actually emits and now assert on the message body,
so the CLI/daemon contract stays locked across both the structured
and the legacy flat shapes.

Surfaced by mrcfps's inline review on cli-templates.test.ts:480.
2026-06-03 03:25:43 +00:00
a6198e22fd Improve run failure classification and Langfuse correlation (#3412)
* Classify run failures in analytics

* Add Langfuse delivery observability

* Handle normalized cache token aliases

* Fix normalized cache token accounting

* Cover CLI token usage analytics

* Add stderr diagnostics telemetry

* Wire Langfuse reporting through inline message route

* Add run failure telemetry smoke coverage

* Add run observability regression coverage

* Add asked_user_question to run_finished contract test fixture

main introduced asked_user_question as a required RunFinishedProps field.
The branch's run_finished contract test built the props fixture without it,
so the post-merge Preflight typecheck failed. Supply the field in the base
fixture so the contract test compiles against the merged contract.

Generated-By: looper 0.9.2 (runner=fixer, agent=claude-code)

* Expand observability regression matrices

* Add failure detail telemetry classification

* Classify permission request lifecycle failures

* Classify upstream stream closure failures

* Classify socket closed API failures

* Count stderr lines from merged stream in analytics summary

summarizeRunDiagnosticsForAnalytics summed per-chunk line counts, but
stderr chunks are not line-aligned. A logical line split across two
chunks was counted twice, inflating stderr_line_count_bucket. Concatenate
chunks first, then count, matching collectStderrTailSummary.

Generated-By: looper 0.9.2 (runner=fixer, agent=claude-code)

* Fix first-token timing and Langfuse model labeling

Drop tool_use from FIRST_TOKEN_AGENT_EVENT_TYPES so firstTokenAt is only
stamped by token-producing events; tool-first runs no longer under-report
time_to_first_token_ms / spawn_to_first_token_ms.

Thread agent_reported_model out of the usage scan in langfuse-bridge and
use it for turn.model when the request did not pin an explicit model, so
Langfuse traces label the resolved model and agree with PostHog
run_finished instead of keeping the default placeholder.

Generated-By: looper 0.9.2 (runner=fixer, agent=claude-code)

* Stamp antigravity first-token only when buffered stdout is flushed

The antigravity stdout handler stamped firstTokenAt as soon as any
buffered chunk arrived, but on the OAuth-required path agy prints the
login URL to stdout and the close-time auth-prompt guard suppresses that
buffer without ever flushing it. firstTokenAt was still set, making
time_to_first_token_ms / spawn_to_first_token_ms look artificially fast
for that failure mode. Record only the first chunk's arrival time at
buffer time and stamp firstTokenAt from it at flush time, so suppressed
OAuth-prompt runs never report a TTFT for output the user never saw.

Generated-By: looper 0.9.2 (runner=fixer, agent=claude-code)

* Re-derive Langfuse delivery state at run completion time

The PostHog run_finished sink captured langfuseDeliveryForAnalytics once
when POST /api/runs was handled and reused it in the terminal callback,
so a long-running run could publish stale langfuse_expected /
langfuse_delivery_status / langfuse_drop_reason if the user flipped
telemetry consent or relay config mid-flight. The Langfuse sink
(reportRunCompletedFromDaemon) re-reads app config at completion, so the
two paths could disagree. Recompute deriveLangfuseDeliveryState inside the
run-completion callback so both sinks read the same completion-time
eligibility.

Generated-By: looper 0.9.2 (runner=fixer, agent=claude-code)

* Carry total-only token usage and drop default model label in Langfuse bridge

Generated-By: looper 0.9.2 (runner=fixer, agent=claude-code)

---------

Co-authored-by: Amy <1184569493@qq.com>
2026-06-02 12:18:32 +00:00
lefarcenandGitHub 502526c5cc fix(daemon): don't fail AMR runs that do tool work but emit no text (#3487)
An AMR (ACP) run that completes its turn doing real work — tool calls /
file edits — but emits no closing assistant text was failed with
"ACP session completed without producing any assistant text. Refresh the
AMR model list, choose a supported model, and retry this run."

The prompt-complete handler only checked `!emittedTextChunk`, and the
`modelUnavailableErrorCode` guard is set unconditionally for every AMR
run, so the check reduced to "no assistant text". `emittedTextChunk` is
only set by `agent_message_chunk`; `tool_call` / `tool_call_update`
updates were ignored. So a model that edits a file via a tool and ends
without a chatty summary (common with gemini-3-flash-preview) had its
successful work reported as a model-unavailable failure — verified
end-to-end: the tool's file was written, yet the run was marked failed.

Track tool-call activity and only report the no-output failure when the
turn produced neither assistant text nor any tool call. A genuinely empty
turn (the real unsupported-model signal) still fails.

Tests: a tool-only turn with no assistant text no longer errors; an empty
turn with no text and no tool calls still fails with the same message.
2026-06-02 17:37:44 +08:00
Vivaan DhawanandGitHub 6634790fd4 fix(cli): discover tools-dev daemon URL (#2807) 2026-06-02 08:15:03 +00:00
194f26ce8c fix(prompt): tighten Comment scope from soft guide to hard constraint (#2796)
* fix(prompt): tighten Comment scope from soft guide to hard constraint

The <attached-preview-comments> block opened with 'Scope: apply the
user request to the attached preview target by default. ... Preserve
unrelated elements.' That reads as a soft preference, and in practice
agents still refactor sibling sub-pages, parent layout, or global CSS
when the user only intended the attached element.

Replace with a hard scope directive:

  Hard scope: change ONLY the elements identified below by selector /
  position / pod members. Do NOT modify sibling sub-pages, parent
  layout, global CSS, design tokens, or unrelated rules even if you
  notice issues there — surface those as a follow-up note in your
  reply instead of editing them. If the user's request cannot be
  satisfied without touching outside this scope, ask the user before
  proceeding. For visual marks, inspect the screenshot and modify the
  marked region first.

Applied symmetrically to apps/web/src/comments.ts and
apps/daemon/src/server.ts so the web composer and the daemon-side
attachment renderer stay in sync.

* ci: re-trigger checks (transient checkout-auth flake on previous run)

* test(comments): assert hard-scope sentence text in web and daemon renderers

---------

Co-authored-by: nicejames <nicejames@gmail.com>
2026-06-02 08:13:10 +00:00
lefarcenandGitHub a7440af9e5 Revert "Merge pull request #3410 from nexu-io/fix/deck-comment-slide-scope-v0.9.0" (#3481)
This reverts commit dbcb5a0b25, reversing
changes made to b6d1a3b785.
2026-06-02 16:10:51 +08:00
ed5fef88a1 fix(web): preserve bulk edit file paths (#3475)
Generated-By: looper 0.9.3 (runner=worker, agent=codex)

Co-authored-by: Looper <looper@noreply.github.com>
2026-06-02 07:54:30 +00:00
kamiandGitHub adcb655108 fix(connectors): explain Composio custom auth requirement (#3464)
* fix(connectors): explain Composio custom auth requirement

* fix(connectors): rediscover custom Composio auth configs
2026-06-02 07:54:15 +00:00
PerishFireandGitHub dbcb5a0b25 Merge pull request #3410 from nexu-io/fix/deck-comment-slide-scope-v0.9.0
Fix deck comment slide scoping
2026-06-02 15:36:22 +08:00
f06063baca feat(cli): add MMS redesign workflow (#3311)
* feat(cli): add MMS redesign workflow

Add a CLI-oriented redesign workflow, MMD route env handoff for Claude launches, and bundled style skills for local Open Design redesign jobs.

Agent-Model: gpt-5

Agent-Family: openai

Agent-Session: 019e6ceb-c33d-7cd3-bff0-cbc20c642197

Agent-Step: 0.1.0

* fix(cli): preserve redesign import auth

Agent-Model: gpt-5
Agent-Family: openai
Agent-Session: 019e6ceb-c33d-7cd3-bff0-cbc20c642197
Agent-Step: 0.0.4

---------

Co-authored-by: Codex <gpt-5@openai.com>
2026-06-02 07:34:30 +00:00
Denis RedozubovandGitHub 3da33f92a1 Harden sandbox orchestration daemon chokepoints (#3420)
* Harden sandbox orchestration chokepoints

* Cover web app public copy in neutrality guard
2026-06-02 07:33:12 +00:00
Aria ShishegaranandGitHub 1d48254c4e fix: capture antigravity logs before print mode (#3395) 2026-06-02 06:49:54 +00:00
justasdevandGitHub 66522f0bc5 Fix loading of preview files from DS (#3418) 2026-06-02 03:44:54 +00:00
lefarcen b47b092196 Fix deck comment slide scoping 2026-06-01 22:36:04 +08:00
AmyandGitHub 3083388a1a Add launch review regression coverage (#3300)
* Add main launch review E2E coverage

* Add daemon launch review regression coverage

* Tighten plugin authoring completion regressions

* fix(web): preserve deck slide on preview switches

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* Add project detail regression coverage
2026-06-01 14:19:33 +00:00
d285cb373a feat(daemon): per-agent MCP installer — plugin marketplace + 14-agent planner (#3442)
* feat: add per-agent MCP installer with source-deploy fallback

Wire Open Design's stdio MCP server into 14 coding agents via a single
`curl ... | sh -s <agent>` command. Two paths, chosen automatically:

  Path 1 — a local `od` is found (PATH, packaged app, prior build):
           register the agent via `od mcp install <agent>`.
  Path 2 — no `od`: deploy from source (clone + pnpm install + build +
           link + background daemon), then register.

- od mcp install <agent>: per-agent planner with cli/json/manual
  strategies; resolves the launch spec from the running daemon and
  falls back to a default stdio spec when offline.
- install-agent.sh: POSIX sh bootstrap that locates or source-deploys
  `od` before forwarding; probes past the Unix octal-dump `od`.

* feat(installer): support OD_REF to pin clone branch for source deploy

* fix(installer): fail clearly when OD_HOME is a non-empty non-checkout dir

* fix(installer): place server name before -e flags for claude mcp add

claude's `mcp add` treats `-e/--env` as variadic (`<env...>`), so emitting
`-e KEY=val <name> --` made the CLI swallow the server name as an env value
("Invalid environment variable format: open-design"). Put the name first,
then env flags, then `--`, matching `claude mcp add <name> -e K=v -- <cmd>`.

* feat(plugins): claude/codex one-command install via plugin marketplace; drop install.sh

The install.sh route was load-bearing on a non-existent URL: PR body
advertised `curl -fsSL https://open-design.ai/install.sh | sh -s <agent>`
but Vercel serves the Next.js index page at `/install.sh`, not the
shell script. Bootstrap users got 173KB of HTML piped into sh and
nothing installed.

Re-scoped per maintainer call (lefarcen, 2026-06-01): drop the
self-deploy path entirely, assume the user installs `od` themselves
(brew / npm / DMG), and focus PR #3431 on the one-thing it
genuinely owns — wiring `od mcp` into the user's coding agent.

## Two install paths now

  Agent             User runs
  ───────────────── ──────────────────────────────────────────────────────
  claude            claude plugin marketplace add nexu-io/open-design
                    claude plugin install open-design@nexu-io/open-design

  codex             codex plugin marketplace add \
                       git@github.com:nexu-io/open-design.git
                    codex plugin install open-design@nexu-io/open-design

  cursor / copilot  od mcp install <slug>
  cline / opencode  (writes the agent's own JSON config — see
  openclaw / etc.    apps/daemon/src/mcp-agent-install.ts for the 14
                     supported agents)

Both paths land on the same launch spec: `od mcp --daemon-url <url>`
running as a stdio server, with whatever env the local daemon hands
back from /api/mcp/install-info. The plugin manifest hard-codes
`command: "od"` so it depends on `od` being on PATH — the maintainer's
existing install (brew/npm/DMG) is the source of truth, plugin install
is purely the wiring.

## What this commit does

- Delete deploy/scripts/install-agent.sh (~240 lines) — load-bearing
  but unreachable (Vercel doesn't serve it), and the source-deploy
  path it gated (clone / pnpm install / build daemon / link bin) is
  out of PR scope per the re-scope above.
- Add .claude-plugin/marketplace.json — owner=nexu-io, exposes
  open-design plugin at ./plugins/open-design.
- Add plugins/open-design/.claude-plugin/plugin.json — name +
  displayName + description + mcpServers pointer to .mcp.json.
- Add plugins/open-design/.mcp.json — stdio server `od mcp
  --daemon-url http://127.0.0.1:7456`, same shape /api/mcp/install-info
  hands back.

The TypeScript planner + executor (apps/daemon/src/mcp-agent-install.ts,
runMcpInstall in cli.ts) and its tests are unchanged — they're the
true core for the 10 agents that don't have plugin marketplaces.

## Verified

- JSON validates for all 3 manifests.
- Daemon already serves stdio MCP on `od mcp` (pre-existing,
  /api/mcp/install-info confirms).
- `claude plugin install open-design@nexu-io/open-design` flow: I
  validated the same manifest shape on a sister repo (nexu-xray,
  https://github.com/nexu-io/agent-pr-explore) and it installs cleanly
  on Claude Code + codex from a single marketplace manifest.

## NOT verified yet (worth a smoke on this branch)

- The full `od mcp install <agent>` flow for the 10 non-plugin
  agents (cursor / copilot / cline / opencode / openclaw / antigravity
  / gemini / trae / kimi / hermes-pi-vibe-print-only). The unit tests
  cover plan generation; an end-to-end against a real `claude mcp
  list` / a real cursor.mcp.json would catch shape regressions.

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
Co-authored-by: lefarcen <ontf116@gmail.com>
2026-06-01 22:15:06 +08:00
netteeandGitHub 601183efbb feat(daemon): load AMR model presets before remote catalog (#3425)
* spec

* impl

* fix

* remove default model content

* fix(amr): keep model catalogs fresh across env changes

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(amr): bust logout cache and stop preset polling

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* test(amr): cover logout cache invalidation and bounded polling

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(amr): start preset polling before agent probe

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(amr): clear stale web cache on env rescan

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(amr): restart preset polling after sign-in

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(daemon): remove extra AMR spawn env arg

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)
2026-06-01 20:20:25 +08:00
Denis RedozubovandGitHub fabfddaede feat(daemon): add contained project preview URLs (#3246)
* feat(daemon): add contained project preview URLs

* fix(daemon): tolerate coarse artifact mtimes

* fix(daemon): validate project preview scopes
2026-06-01 07:12:36 +00:00
512e01405f fix(web): queue preview comments while busy and pin deck markers (#3347)
* fix(web): queue preview comments while busy and pin deck markers

While a chat run is in flight, preview comments now queue instead of
showing a stuck Sending state. Deck slide changes no longer collapse
comment markers to 0,0 by filtering hidden targets and persisting slideIndex.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): stop comment overlay jitter from redundant target sync

Skip React updates when live comment target bounds are unchanged, refresh
deck targets only on slide changes, and drop characterData from the
selection-bridge mutation observer to avoid streaming text churn.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): keep comment target metadata fresh

* fix(web): refresh active comment text mutations

* fix(daemon): key preview comments by deck slide

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-01 07:00:50 +00:00