mirror of
https://github.com/nexu-io/open-design.git
synced 2026-09-20 06:15:06 +08:00
chore/plugin-previews
64 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1ff25e5b2b |
fix(packaged): preserve MCP runtime integrity and sidecar delivery (#8027)
* fix(daemon): keep packaged MCP discovery out of package managers * fix(packaged): preserve MCP payload identity and require sidecar supervisor * fix(pack): finalize runtime manifests and report entry recovery * ci: allow isolated full Windows smoke on dispatched revisions * test(packaged): derive recovery versions from the release channel * test(win): read portable installer logs and retain rollback diagnostics * test(win): distinguish portable startup reconciliation from installer sync |
||
|
|
4e460eae41 |
fix(updater): coordinate shutdown and observe update handoff (#7982)
* fix(updater): wait for shutdown without false quit failures * feat(updater): observe persisted shutdown and successor stages |
||
|
|
be0887b392 | fix(packaged): wait for updater predecessor before instance discovery (#7970) | ||
|
|
0688faaec3 |
reland(sidecar): converge product clients on package boundary (#7636)
* reland(sidecar): converge product clients after weekly release
Restore the sidecar convergence from #7244 after the release-scheduling revert in #7634. This tree matches the previously reviewed and cross-platform QA-accepted implementation at
|
||
|
|
5a62b0edad |
revert(sidecar): defer convergence until after weekly release (#7634)
Revert
|
||
|
|
d83d4e032f |
refactor(sidecar): converge product clients on package boundary (#7244)
* refactor(sidecar): own client identity and lifecycle atomics * refactor(sidecar): converge product clients on package boundary * fix(sidecar): use TypeScript process fixture Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * fix(e2e): assert opaque sidecar capability Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * fix(sidecar): preserve resilient client handoffs Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * fix(nix): build sidecar dependencies first Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * fix(sidecar): restore historical desktop handoff Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * fix(packaged): canonicalize mac runtime paths * fix(tools-pack): clean mac launcher namespace * fix(sidecar): harden client lifecycle boundaries * fix(sidecar): isolate concurrent lifecycle generations * fix(sidecar): retain spawned process generations * fix(sidecar): preserve resources across restart * fix(tools-dev): retain dynamically bound daemon port * fix(sidecar): fence Windows process generations * test(packaged): use sidecar client in payload fixture * fix(sidecar): enforce generation ownership * fix(sidecar): persist generation ownership * fix(sidecar): quick-fail ambiguous recovery * fix(tools-pack): ship sidecar supervisor * fix(sidecar): fence lifecycle generations * fix(tools-pack): build platform before sidecar * fix(sidecar): preserve nested stamped resources * refactor(sidecar): model generation authority * fix(sidecar): converge packaged build and headless actions * fix(sidecar): isolate Windows generations * fix(sidecar): retire orphaned generation descendants * fix(sidecar): unify fenced process retirement * fix(sidecar): converge contended launch generations * test(sidecar): model slower packaged fixtures * fix(sidecar): make supervisor the generation boundary * fix(web): bound sidecar HTTP shutdown * fix(pack): verify complete mac shutdown * refactor(sidecar): converge packaged lifecycle sets * fix(sidecar): serialize Windows packaged lifecycle * fix(windows): harden packaged cold-start validation --------- Co-authored-by: Looper <looper@noreply.github.com> Co-authored-by: Amy <58060647+AmyShang-alt@users.noreply.github.com> |
||
|
|
18273c01b8 |
fix(packaged): recover from stale web sidecars (#7279)
* fix(packaged): recover from stale web sidecars * fix(packaged): stop stamped web owner before socket takeover Unlinking only the unresponsive web socket left the old Next process alive. Its later JsonIpcServer.close() could delete the replacement pathname. Stop the stamped owner through platform primitives first. Generated-By: looper 0.12.0 (runner=fixer, agent=opencode) * fix(packaged): strip handoff parent pid and skip unsafe web unlink Strip OD_TOOLS_DEV_PARENT_PID from the legacy payload desktop spawn environment so the replacement does not exit after waiting for the outer PID. Skip web socket unlink when a stamped owner is still running after stop. Generated-By: looper 0.12.0 (runner=fixer, agent=opencode) * fix(packaged): skip web unlink when process discovery fails listProcessSnapshots returns [] on enumeration failure, so an empty table is not proof that no stamped owner exists. Leave the live socket in place unless discovery succeeded and every matched owner is gone. Generated-By: looper 0.12.0 (runner=fixer, agent=opencode) * fix(daemon): hold parent monitor until handoff journal commits Packaged daemons now exit when the outer Electron dies. Desktop SHUTDOWN acks before asynchronously exiting, so the parent can disappear while armed handoff, attempt, and runtime writes are still pending. Hold the parent-death exit across that window. Generated-By: looper 0.12.0 (runner=fixer, agent=opencode) * fix(daemon): defer SHUTDOWN until handoff journal commits Packaged beforeShutdown still sends sidecar SHUTDOWN after desktop acks, and that path ignored the parent-monitor hold. Wait for the same release before exiting so handoff.json, attempts.json, and runtime.json can finish. Generated-By: looper 0.12.0 (runner=fixer, agent=opencode) * fix(daemon): defer SIGTERM until handoff journal commits Packaged closeManagedChild waits five seconds then stopProcesses() sends SIGTERM. That handler still exited immediately and could cut off the held journal writes. Route signal shutdown through the same hold as SHUTDOWN. Generated-By: looper 0.12.0 (runner=fixer, agent=opencode) * fix(daemon): hold parent monitor before payload spawn A crash after the replacement emits spawn but before the journal hold lets the parent monitor exit the daemon while handoff.json is still prepared. Acquire the hold before spawn and release it on failure. Generated-By: looper 0.12.0 (runner=fixer, agent=opencode) * fix(packaged): wait for deferred handoff shutdown before SIGKILL Daemon SHUTDOWN now reports deferred:true while the handoff journal hold is active. closeManagedChild then waits a bounded 30s for self-exit before stopProcesses, so SIGKILL cannot cut off the three sequential journal writes. A POSIX regression exercises the real stopProcesses path and checks all three files commit before forcedPids. |
||
|
|
7320f9b8ab |
feat(daemon): make OD Next the default design strategy (#7016)
* refactor(observability): isolate legacy run exporter
* refactor(daemon): extract internal run creation service
Route /api/runs and compatibility /api/chat through one daemon-owned create, claim,
resume, and start seam. Preserve HTTP responses, SSE timing, session bookkeeping,
and durable Run formats.
Validated with daemon tests/build/typecheck, workspace guard, and workspace typecheck.
* test(plugin-runtime): freeze OD Next strategy fixture boundaries
Add exact pre-Build route and stage cases plus deterministic deletion-boundary mutations without shipping an evaluation harness.
Preserve the current official and community fallback pipeline and composed verification/critique prompt sections as golden witnesses.
Validated with plugin-runtime tests and types, focused daemon prompt composition, daemon types, guard, and workspace typecheck.
* fix(daemon): finalize terminal telemetry delivery
Persist a versioned delivery record so normal failures stop after bounded retries
and only an unfinished crash window resumes on restart.
Reuse the persisted identity across Vela and Relay transport, isolate stable
direct Langfuse event ids by delivery purpose, and log only redacted sink data.
Validated with focused daemon and contracts tests, workspace typechecks, and
guard. The full daemon suite had one timeout; its four-test file passed alone.
* feat(plugins): add OD Next strategy scenario and contracts
Ship the V2 strategy package as inactive bundled content and validate its contracts without changing ordinary plugin manifest compatibility.
Keep bundled strategy bytes out of the catalog and generic apply path until a later hash-gated activation owner binds them.
* feat(observability): add normalized agent observation contract
Define a pure versioned contract for identity, Prompt, usage, timing, and status evidence with explicit availability and per-value provenance.
Add a structured main-Run compatibility adapter that preserves unknown facts, separates clocks, and omits provenance-ambiguous derived totals without changing legacy export behavior.
* feat(plugins): bind OD Next strategy content identity
* feat(daemon): persist OD Next strategy task chains
Add the daemon-owned SQLite truth for immutable strategy task identity, ordered physical Run mappings, canonical Plan Contracts, revision-CAS transitions, and terminal reconciliation.
Pin task-owned Snapshots and exclude their durable references from pruning so mixed GC sweeps remain safe.
Validated with 103 focused daemon tests, contracts tests/typecheck, daemon and workspace typechecks, and guard.
* feat(daemon): gate OD Next runtime capabilities by fixtures
Add exact CLI/adapter/fixture tuple resolution, stable capability snapshots, and offline
replay graph invariants for the four initial runtime paths.
Keep production registry empty until sanitized real fixtures exist; synthetic evidence and
version drift remain unknown.
Validated with contracts tests, focused daemon and e2e boundary suites, guard, and
workspace typecheck.
* feat(daemon): add hash-gated OD Next prompt recipe
Compose the bundled strategy from validated content, one Task Skill, and the exact stage policy.
Fail closed on package, profile, pipeline, or atom drift while preserving ordinary quality paths.
Validated with focused tests, package typechecks, workspace typecheck, and guard.
* feat(observability): aggregate OD Next task observations
Build stable task, Run, Child, model, and tool hierarchies from durable StrategyTaskExecution mappings and normalized facts while keeping missing coverage explicit.
Map task aggregates to legacy ingestion behind the consent gate. Preserve owner/exclude hierarchy while accounting usage once, enforce kind-specific Prompt boundaries, and accept absolute time only from one Unix-epoch evidence record.
Validated with 228 focused daemon tests, 353 contracts tests, daemon/contracts and workspace typechecks, guard, and the task harness.
* feat(daemon): collect bounded Codex child evidence
Read declared Codex rollout sessions without scanning arbitrary homes.
Normalize verified child facts while redacting prompts and preserving Run semantics.
* feat(daemon): add OD Next planning coordinator
Add a daemon-owned planning reducer, deterministic Resolver and Preflight facts, and a stream-safe machine protocol boundary backed by the durable task store.
Lock one clarification and one serialization-only repair across restart, preserve the Plan hash, and keep ordinary Run text unchanged.
* feat(daemon): collect native OpenCode child evidence
* feat(observability): add Langfuse OTLP task exporter
Map normalized task observations to complete OTLP/JSON v4 spans with stable parent context, allowlisted metadata, usage accounting, and bounded terminal delivery.
Fail closed on drift across root and operation input, model, timing, type, hierarchy, status, and complete usage provenance while dual remains a local-only OTLP shadow.
Keep legacy rollback, consent gates, and X5 live self-host verification boundaries intact.
* feat(daemon): normalize Claude native child evidence
Collect matched Claude Task sidechain lifecycle facts without changing main stream turn, stdin, or error bookkeeping, and adapt them to provider-neutral observations with unavailable Prompt and usage evidence.
Bind session, Task id, and parent identity immutably; poison rebinding, session drift, and conflicting terminals so ambiguous evidence cannot reach L2. Keep production capability unknown until X1 supplies an exact-version sanitized real fixture.
* feat(daemon): consume versioned Vela child evidence
Negotiate schema v1 only on AMR and enforce run-scoped start-to-terminal graph, status/source coherence, and exact usage source/completeness bindings. Emit allowlisted Normalized child facts without Vela private I/O.
Pin the unpublished producer golden for offline compatibility while keeping production capability unknown until the X1/X3 evidence gates are satisfied.
Validated with 147 focused daemon tests, 353 contract tests, daemon/workspace typechecks, guard, and the task harness.
* feat(daemon): automate OD Next simple production
Connect parsed OD Next terminal output to the durable coordinator, claim clarification, repair, and production Runs atomically, and start continuations only after the source Run ends.
Converge task failure and cancellation before physical end, require daemon-owned execution facts and canonical delivery, and keep ordinary Runs compatible.
Validated with focused daemon route and coordinator tests, contracts tests, daemon and workspace typechecks, guard, and the task harness.
* feat(daemon): enforce verified complex production
* feat(web): follow OD Next task chains across Web and CLI
Persist daemon-issued task handles and visible predecessor-prefix boundaries, then follow projected active Runs through one terminal outcome in Web and od run.
Normalize reloads to daemon activeRunId before subscribing, transfer controller ownership atomically across successors, discard stale cursors, and preserve visible prefixes without replaying predecessor machine payloads.
Validated with focused Web and daemon tests, contracts tests, workspace typecheck, guard, diff checks, and the task harness.
* feat(daemon): roll out OD Next task observability
* feat(daemon): add controlled OD Next rollout
* fix(daemon): align OpenCode and Vela evidence tuples
Pass GPT-5.6 Sol's verified high variant to OpenCode, pin native evidence to 1.18.18, retain locally recorded success and failure seeds as explicitly unattested, and align the Vela consumer golden to the local versioned producer.
Validated with 5 focused daemon files (175 tests), daemon and workspace typechecks, guard, the real local Vela ACP Sol smoke, and a minimal test-relay telemetry write.
* fix(daemon): honor OpenCode model variant capabilities
Parse the live verbose OpenCode catalog per model and forward only variants advertised by the exact detected binary. Keep fallback and one-off OPENCODE_BIN connection tests on the base model when variant support is unknown.
Record machine-checkable OpenCode 1.18.18 root, tool, child, recovery, cancel, timeout, and resume evidence without promoting the unattested seed into the production capability registry.
Validated with focused runtime and connection tests, host process-group and watchdog tests, contracts tests, daemon/workspace typechecks, guard, and an isolated SIGKILL delivery-recovery exercise.
* feat(daemon): add OD Next analytics operations report
Reduce normalized task aggregates into source-aware operations metrics without
copying the Langfuse dashboard or exposing user trace links.
Preserve main/Child accounting, stage-scoped coverage, unavailable facts, and
external-signal-only quality inputs.
Validated with focused and contract tests, the full daemon suite, guard,
workspace typecheck, and exact-trace Langfuse readback.
* feat(observability): complete child prompt and runtime provenance
Export bounded redacted child-injected Prompt content and exact CLI, companion, and
adapter versions through task-level legacy and OTLP mappings.
Register the OpenCode 1.18.18 best-effort replay tuple while keeping unknown versions
and incomplete Codex evidence fail closed.
Validated with 353 contracts tests, 196 focused daemon tests, daemon/workspace
typechecks, and guard.
* fix(daemon): recognize Codex child failure terminals
Parse Codex 0.147.0 Child task_complete.error as the runtime-owned failed terminal, honor session_meta id over its legacy root session_id, and map interrupt_agent aborts to canceled.
Add a redacted seven-path best-effort replay and exact Codex capability tuple. Unknown versions remain fail-closed and ordinary Codex runs are unchanged.
Validated with 92 focused daemon tests, 353 contracts tests, daemon and workspace typechecks, guard, and the 25-unit task harness.
* fix(daemon): report verified child runtime versions
Use versions observed from resolved CLI probes or Vela's ACP handshake when annotating Child observations. Correct Native OpenCode's allowlist key, add Claude and Vela/OpenCode companion provenance, reject Vela probe/handshake disagreement, and ignore the legacy 0.0.0 placeholder.
Validated with 252 focused daemon tests, daemon and workspace typechecks, guard, the task harness, and a real local Vela --version/-v/ACP initialize build smoke.
* test(observability): record Vela child evidence matrix
Add a sanitized provider-backed Terra replay for main, tool, child success, child failure with parent recovery, cancel, timeout, and cross-process resume. Keep the unpublished Vela tuple outside the production registry while pinning its exact candidate and OpenCode companion evidence.
Validated with focused Vela consumer/capability tests, daemon typecheck, workspace typecheck, guard, and the task harness.
* feat(daemon): enable OD Next production profiles
Make prototype, presentation, marketing, and HyperFrames the exact global OD Next production set while preserving explicit off/observe, user plugin authority, and fail-closed runtime capability gates. Feed runtime-owned profile, route, output, input, and capability facts into the planning contract and keep all other artifact kinds on ordinary Open Design.
Use bounded executable-scoped CLI version probes so headless and restarted daemons can resolve exact tuples without a prior agent-list request or cross-binary cache contamination.
Validated with four provider-backed Terra CLI chains, focused daemon/contracts/plugin-runtime suites, daemon and workspace typechecks, guard, and the 25-unit task harness.
* feat(daemon): classify OD Next exact agent inputs
Route prompt contributors through one daemon-owned choke point and version their final-text, semantic-fact, transport, and exclusion ownership for the forthcoming canonical bundle. Send OD Next continuation stages directly through native sessions without rewrapping or re-seeding stable instructions.
Validated with focused daemon and contracts tests, daemon/workspace typechecks, and guard.
* fix(daemon): close OD Next input ownership gaps
Bind semantic request facts to their real daemon-system or request producers, cover the DSH profile exact-text transport, and reject lookalike prompt-bundle root names.
Validated with focused exact-input, production-server and DSH tests, daemon typecheck, task harness, and guard.
* feat(daemon): emit canonical OD Next prompt bundles
Add strict pure TypeScript Bundle and request-Turn serializers, then route OD Next request and continuation text through their versioned XML contracts.
Split Web prior transcript from the current turn without text subtraction, keep mutable Skill and attachment inputs explicitly pending, and preserve ordinary prompt behavior.
Validated with focused contracts, daemon and web tests, the real server fixture, package and workspace typechecks, and guard.
* fix(daemon): align OD Next bundle input ownership
Register the real canonical Bundle contributors and keep current-turn, prior-transcript, pending-fact, and research-query ownership explicit at the production seam.
Reject continuation task_run_index zero and cover Web framing, ordinary compatibility, fail-closed contributor drift, and real server prompt capture.
* feat(daemon): freeze OD Next user skills
Capture explicit Skill bodies and audited side files before task claim, persist verified task-owned bytes, and replay only the frozen package for OD Next runs.
Keep legacy single-Skill CLI requests and ordinary live staging compatible while adding Web/CLI multi-Skill coverage and fail-closed snapshot checks. Validated with focused server, contract, CLI, Web, typecheck, and guard suites.
* fix(daemon): harden OD Next skill snapshots
Require an explicit frozen package for every mapped OD Next task and fail corrupt task state before any live Skill staging.
Use bounded no-follow descriptor reads with race checks, preserve legacy CLI compatibility, and make materialized roots collision-resistant. Validated with focused, real-server, workspace typecheck, and guard suites.
* feat(daemon): freeze OD Next task input snapshots
Freeze OD Next attachments and canonical configuration before the atomic run/task claim, then route runtime access through durable task-scoped snapshots while preserving ordinary attachment behavior.
Validate immutable identities, transport references, continuation propagation, tamper failure, and the four production task types with focused contract and daemon coverage.
* fix(daemon): isolate OD Next runtime input projections
Keep canonical task snapshots daemon-only, rebuild a read-only per-Run projection, and deliver frozen document resources through ACP or OD_TASK_INPUT_DIR.
Harden source and snapshot reads with no-follow same-fd identity checks and bounded caps. Validated with focused runtime tests, contracts, daemon/workspace typechecks, guard, and the task harness.
* fix(daemon): harden OD Next snapshot transport boundaries
Reject intermediate symlinks and realpath escapes while loading canonical snapshot files, including identical-byte replacement targets.
Preserve ordinary ACP duplicate image ordering while suppressing only OD Next resource/image cross-duplicates. Validated with focused tests, daemon typecheck, guard, and the task harness.
* fix(daemon): preserve structured OD Next snapshot failures
Defer frozen Skill package errors from the Task 04 preclaim lookup to the existing post-claim failure boundary so mapped Runs remain durable JSON failures without orphan input snapshots.
Validated with the combined real-server repair, missing-package, and tampered-package regressions.
* fix(daemon): keep OD Next continuation cwd stable
Separate authoritative project cwd resolution from best-effort file inventory and tolerate entries deleted between directory enumeration and stat.
This keeps native-session identity stable while frozen task inputs replace live attachments during continuation.
* feat(daemon): persist exact OD Next prompt inputs
Persist the canonical first-turn Bundle and every deterministic continuation Turn with UTF-8 and SHA-256 identities, then send only those validated texts through runtime transports.
Fail closed on mapped task drift, tamper, legacy NULL identities, missing mappings, and cold continuation while leaving ordinary Runs on the existing live composer.
Validated with the 15-case automatic server acceptance twice, 223 focused daemon tests, daemon typecheck, guard, and the task harness.
* feat(daemon): observe exact OD Next prompt inputs
* feat(daemon): bind and observe Claude native subagents
Register the replay-verified Claude 2.1.233 tuple, bind complex Build Packages to daemon-issued native Agent handles, and derive completion only from durable child lifecycle evidence.
Export bounded parent-tool, Child Agent, and Child-tool spans through the existing legacy and OTLP task hierarchy without exposing raw tool inputs, outputs, provider ids, paths, or credentials.
Validated with focused contracts and daemon suites, the 17-case real-server chain, workspace typecheck, guard, and the 26-unit task harness.
* fix(daemon): repair OD Next rollout authority and controls
* fix(daemon): harden OD Next public canaries
* refactor(daemon): extract OD Next prompt preparation
* test(daemon): align plugin fixture with project schema
* test(e2e): assert daemon-owned prototype routing
* fix(daemon): restore OD Next task observability
Default eligible OD Next tasks to privacy-aware Langfuse hierarchy delivery through relay or direct sinks, with a versioned safe quality projection.
Persist lightweight representation ownership before suppressing mapped Runs, retain best-effort startup retry semantics, and preserve single-Run compatibility when Task delivery is not eligible.
Adopt the active payload relay for historical packaged launchers and cover the real sidecar environment handoff.
Validated with the full daemon suite, focused contracts/packaged/e2e/tools-pack suites, workspace guard, and workspace typecheck.
* fix(daemon): make OD Next capability fallback invisible
Admit capability-certified runtime adapters across CLI version drift while keeping recorded fixture versions as auditable evidence and reserving a narrow incompatibility denylist.
Fall back before Run claim on preparation failures, keep continuation bound to the frozen capability snapshot, and report truthful child coverage across Langfuse legacy and OTLP without replaying an active task.
Validated with focused contracts and daemon suites, the automatic server suite, pnpm guard, pnpm typecheck, daemon typecheck, LSP diagnostics, and git diff --check.
* fix(strategy): isolate OD Next automatic task routing
* fix(daemon): persist blocked strategy-task attribution
Every blocked strategy task now stores its gate reason codes and the
agent-visible turn text (blocked_reason_codes_json / blocked_visible_text)
so operators can diagnose a blocked task from the store alone. Covers the
coordinator blockTask gate, the automatic-continuation fail-closed path,
and startup run-terminal reconciliation.
* fix(daemon): accept form-only clarification turns by deterministic inference
A first Full-Plan request turn that renders exactly one question form and no
machine-protocol block has exactly one valid protocol meaning: outcome
clarification_required with an unlocked execution mode. The coordinator now
recovers that state deterministically instead of dead-ending the task as
blocked, stamps od_next_protocol_runtime_state_inferred into the accepted
state's reasonCodes for attribution, and keeps every ambiguous shape (extra
forms, recovered plan blocks, later stages, spent clarification budget,
any other protocol issue) fail-closed. This closes the observed field
failure where the agent's first reply produced a discovery form, the task
went blocked, and the user's form answer then failed with 409
STRATEGY_TASK_STATE_MISMATCH.
* feat(contracts,daemon): project blocked strategy-task attribution to clients
A task the OD Next protocol gate settles as blocked persists its
attribution (reasonCodes + agent-visible text) since
|
||
|
|
82c607d70a |
fix(packaged): report the daemon log tail when startup failure is unparseable (#7291)
The largest startup-failure bucket in production (macOS daemon-start, 968 events across 293 people over the 14 days to 2026-08-22) exits code=1 with the native module present and error_code / missing_module / daemon_error all null. The reason was printed in a log tail reportStartupFailure had already read and then discarded, because parseDaemonLogTail only names shapes we already know (ERR_*, a missing module, an XError: headline). When that parse yields nothing, send the tail itself: last 40 lines, scrubbed of POSIX and Windows home dirs before truncation, hard-capped at 4000 chars keeping the end (the tail is chronological, so the fatal line sits nearest the exit). Narrow by design — when the cause is already named the raw tail is bytes and privacy surface for no new information, so a present value also means "this log defeated the parser". |
||
|
|
262c1f8f00 |
fix: complete AMR environment switching (#6991)
* fix: keep AMR environment switching consistent * fix: package every AMR console environment * fix: discover daemon directly for profile switch * fix: apply selected AMR profile to billing * fix: gate personal runs by workspace balance * fix: complete feature-test account switching * fix: close AMR environment review gaps |
||
|
|
ba8fca14fa | Updating sidecars to accept the allowed internal host env variable (#6802) | ||
|
|
f5235aa423 |
fix(packaged): widen macOS sidecar status timeout to 90s for 0.18.1 cold starts (#6762)
Packaged 0.18.1 on Apple Silicon can exceed the 35s daemon/web status budget during a cold launch, causing startPackagedSidecars() to time out, tear the sidecars down, and leave the desktop looping on a stale currentWebUrl / od:// 502. Give darwin the same 90s "slow, not dead" safety net already used on win32 and linux for similar cold-start failure classes (issue #6637). Generated with [Devin](https://devin.ai) Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
a0474c540e |
fix(packaged): refresh install.json launchPath on payload launches (#6621)
The payload branch of resolvePackagedLauncherRuntime only READ the persisted install.json launchPath (written once by the cold-start current-package branch) and never refreshed it. After an update that moved the launcher executable (0.17.0 Local\Programs\... exe to the 0.18.0 launcher payload), the stale path kept flowing into the MCP bootstrap command published by /api/mcp/install-info, so MCP clients relaunched the old executable on the same sidecar pipe until the launcher's stale-sidecar sweep killed the fresh daemon and desktop restart-looped. The payload branch now rewrites install.json when the persisted launchPath no longer matches the current launcher executable, so launchPath tracks the current launcher across updates. Only the launcher process refreshes the descriptor; a delegated payload desktop keeps the stable launch path the launcher persisted. Regression test goes red on main and green on this branch. Fixes #6494 |
||
|
|
34192c6719 |
fix(diagnostics): keep the previous session's daemon log and cut event tails on line boundaries (#6531)
* fix(diagnostics): keep pre-restart daemon log and line-aligned event tails Two gaps made incident support bundles useless after a relaunch: 1. Every packaged launch opened each sidecar's latest.log with mode "w", destroying the previous session's log — the bundle held only the ~70 lines written since the restart while the incident-time daemon log was gone. openLog now rotates the prior file aside as previous.log (exactly one prior session, rename overwrites), and the diagnostics export bundles logs/<app>/previous.log whenever it exists, under the same per-file tail cap. The source entry is existence-conditional so non-rotating launchers (tools-dev appends) do not gain missing-file placeholder noise. 2. The 2MB tail cap on runs/*/events.jsonl cut bytes from mid-file, so the first kept line was half a JSON object and jsonl consumers fell over on line 1. readMaybeTail now advances the cut to the next line boundary (with a guard byte so an already-aligned cut loses nothing); a window with no newline keeps the raw cut. * fix(packaged): keep the prior log when rotation fails instead of truncating it A non-ENOENT rename failure (Windows share-lock on previous.log, read-only or exotic filesystem) still fell through to open(path, "w"), destroying the only copy of the pre-restart log while previous.log stayed unavailable — the exact data loss this rotation exists to prevent. Truncate only when the prior bytes are provably elsewhere: moved aside, or never written (first-launch ENOENT). Otherwise open in append mode, since a merged two-session log is recoverable and an erased one is not. * fix(diagnostics): never export a partial record, and never hide an unreadable log Two holes in the truncation/collection contract: - A single event larger than the whole tail budget left no complete line to align to, and the fallback kept the raw cut — so the export shipped the interior of one JSON record and any consumer streaming the bundle through a jsonl parser died on line 1, exactly what alignment exists to prevent. Signal "no complete line" instead and let the collector record it, so the bundle carries a self-describing placeholder rather than half an object. - The optional-source gate treated EVERY access failure as absence, so a previous.log that exists but is unreachable (EACCES on the log directory, EIO) vanished with no manifest entry and no warning. Only ENOENT may drop the entry now; anything else stays listed and reports the real error. |
||
|
|
1347ce4e48 |
fix(packaged): fail od:// proxy fast on local resource exhaustion (#6530)
When the machine is out of sockets/file descriptors (net::ERR_INSUFFICIENT_RESOURCES, EMFILE, ENFILE, EADDRNOTAVAIL, ENOBUFS), the proxy's two resilience layers amplified the outage: the undici fallback re-issued every failed net.fetch (7890 doubled requests measured in the incident) and the linear-backoff transient retry stacked another 1334 attempts on top — each consuming exactly the resource the machine had run out of. Classify these errors through one whitelist helper (isLocalResourceExhaustionError, matching both Error.code and the message since Electron net.fetch reports net::ERR_... in the message with no code) and make both layers fail fast: no undici fallback, no retry. Everything outside the whitelist keeps today's behavior — ECONNREFUSED still buys the full retry budget (daemon startup race) and generic net.fetch rejections still fall back to undici (CSS-mask GET rescue). |
||
|
|
5f5a589cd8 |
feat(packaged): ship Workspace Team on production builds (#6459)
Production was deliberately held outside the workspace-team profile allowlist until its Vela backend could actually serve the feature. It can now: WORKSPACE_TEAM_ENABLED and the three billing-scope flags are true on prod amr-api, and the resource hub it needs for team file sharing is configured (S3-backed blob store instead of the chart's mock default, which would have failed every push with 'unsupported protocol scheme mock' while comments kept syncing through Postgres). - Add prod to WORKSPACE_TEAM_AMR_PROFILES. - Resolve OD_VELA_WEB_URL for prod from secrets.VELA_WEB_URL_PROD, so release builds bake the production console origin. - Drop the temporary amr_profile=test default on release/v0.18.0; release builds now ship prod, with manual dispatch still able to target test or feature-test. The origin half of the gate is unchanged and still load-bearing: a build without an injected origin stays dormant on every profile rather than pointing at an unknown backend. Tests updated to lock the new prod behaviour and to keep local/profile-less builds dormant. |
||
|
|
356c8c364f |
feat(workspace-team): team workspaces, shared resources, workspace-scoped billing, and the #5517 redesign (#6142)
* fix(web): scope plugin URL imports to workspace * test(web): cover billing interest remount lifecycle * feat(packaged): enable the workspace-team transport for test-profile builds The vela test backend now serves the workspace-team API, so a packaged build baked with the test AMR profile should drive team projects / collab / resource sharing there instead of leaving them dormant. Replace the single feature-test equality check with a profile -> vela web origin map so adding a backend is one entry, and keep every unlisted profile (prod above all) off. * test(daemon): cover billing catch-up after SSE reconnect * fix(collab): surface and start first materialization when opening a shared project QA P0: a brand-new member on a fresh install joins someone's workspace, opens a project from it, and sees no loading state and no files — content only appears on a SECOND open, much later. Two defects, both on the first `/collab/status` request that opening a shared project makes. 1. No pull is started. The daemon's self-materialization block was gated on `callerIsOwner`, so a non-owner member got the placeholder record registered and nothing else. The web's auto-pull is gated on `publishedVersion` advancing past its cursor, and a fresh daemon's first status response cannot carry a published head: `collab.publishedVersion()` reads an in-process map that has never been written, and the real hub head is fetched fire-and-forget into `headEnrichmentCache` for a LATER poll to consume. Materialization therefore arrived only whenever a proactive lane (hub push / reconnect catch-up / the 30s recovery floor) next fired — the "second open" the report describes. 2. No download state is shown. `useProjectCollab.downloadPending` — which picks DesignFilesPanel's "Syncing files from the team…" over its empty state and create-a-file CTAs — reads only `publishedVersion > cursor`, `contentTransferState`, and an in-flight pull. All three are blank on that first response, so the member was shown an empty project inviting them to start creating over content that was still on its way. The fix makes the placeholder stamp the load-bearing signal on both sides: - `materializePlaceholderOnOpen` (routes/collab-sync.ts) replaces the owner-only block: any viewer opening a shared project whose only local record is an unmaterialized placeholder starts its pull on that same request, through the same coalesced flow. The retracted-share heal in its catch stays owner-only — a member who hits the hub tombstone has merely lost access and must not unshare anyone's project. - `/collab/status` reports `awaitingFirstMaterialization`, a purely local, synchronous fact that needs no hub round-trip and is therefore available on the very first response. `od collab status` prints it too. - `localFilesAreNotTheContentYet` (useProjectCollab.ts) makes it always download-pending, bypassing the member-only `shouldAutoPull` gate: whether the local files are the content is a fact about the record, not about who may pull it, so the owner of an unmaterialized placeholder (the reinstall case, recvqzaDvUU6B3) stops seeing the same empty state too. Red evidence: all six new specs fail on origin/feat/workspace-team @ |
||
|
|
e1c277c593 |
fix(packaged): recover od:// after web sidecar exits (#6364)
* fix(packaged): resolve od:// target per request instead of snapshotting it registerOdProtocol captured the web sidecar URL once at startup. When the sidecar died or was respawned on a fresh ephemeral port, the od:// proxy stayed pinned to the dead port for the rest of the process lifetime and every renderer fetch returned OD_PROTOCOL_PROXY_FAILED until the user quit and relaunched the app. Take a resolver instead so the target is re-read on each request. * feat(packaged): add bounded restart policy helpers for sidecars createRestartPolicy caps respawns to a sliding window so a sidecar that crashes during boot cannot respawn forever. resolveWebRestart wraps one policy-gated attempt and swallows spawn failures, so the supervisor wired up next can call it straight from an exit handler. * fix(packaged): respawn the web sidecar on exit and serve od:// from the live URL The web sidecar was spawned once and never watched. When it died mid-session, nothing respawned it and the od:// proxy kept forwarding to a dead port, so the whole UI returned OD_PROTOCOL_PROXY_FAILED until the user quit and relaunched. Supervise the child: on an unexpected exit, respawn it under the bounded restart policy and publish the new URL through PackagedSidecarHandle.currentWebUrl(), which the od:// resolver reads per request. close() flips a `closing` flag first so an intentional shutdown is not mistaken for a crash. Adjacent, not fixed here: index.ts discoverDaemonUrl() reads the same kind of boot snapshot for the daemon sidecar, which has no supervisor of its own. * test(packaged): update headless sidecar handle mock * fix(packaged): close web sidecar restart races --------- Co-authored-by: Bassi <info@beazyagency.it> |
||
|
|
809d45f27c |
feat(integrations): add the local Open Design Cloud flow for Codex (#6055)
* feat(daemon): expose Vela login through CLI and MCP * feat(mcp): add interactive local brief card * feat(packaged): bootstrap local MCP headlessly * feat(daemon): secure local BYOK credential profiles * feat(cli): manage secure BYOK profiles * feat(web): store BYOK keys in secure profiles * fix(runs): deduplicate cloud generation requests * feat(daemon): add end-to-end plugin observability * fix(pack): include native PTY runtime in desktop packages Lazy-load node-pty in the daemon so missing native binaries only disable Terminal and interactive Keychain operations instead of crashing startup. Ship and validate target prebuilds in macOS and Windows packages. Repair the macOS spawn helper before signing, and invalidate stale Windows packaging caches. Cover the packaged PTY path in macOS and Windows smoke tests. Require Vela CLI for every beta desktop build target. * fix(mcp): localize and stabilize plugin briefs Keep collect and confirm on one MCP Apps card, report intrinsic size changes, and remove the fragile widget-state fallback. Localize brief forms, summaries, status, and public errors from the current request or Host locale while preserving stable protocol ids and selections. Keep internal runtime identifiers out of user-facing MCP guidance. * fix(packaged): register live Studio URLs with daemon Register the packaged web sidecar loopback origin over namespace-scoped daemon IPC after dynamic binding. Invalidate install-info by the live web port and remove the second MCP URL cache so run and project responses use the current Studio address. Validate loopback origins and cover registration, rebind, and cache refresh. * fix(mcp): stabilize brief confirmation lifecycle Keep confirmed briefs locked after Host publication failures and retry only the cached follow-up message instead of confirming twice. Replace blank initialization with a compact loading state, accept immediate and delayed tool results, and bump the MCP Apps resource to v3 so Codex does not reuse the stale card. Add an executable JSDOM Host bridge harness covering double-submit, publication retry, delayed results, and repeated draft notifications. Validated with the full daemon suite, workspace typecheck, and guard. * fix(mcp): prevent brief app resize feedback loops Replace the self-observed intrinsic-height loop with deduplicated body measurements so Codex MCP app iframes do not repeatedly resize themselves and fail sandbox startup. Bump the brief resource URI to v4 to avoid cached v3 cards and cover the regression with the focused brief-app spec. Validated with daemon tests/build, workspace guard/typecheck, a verified beta DMG, and a direct packaged MCP resource smoke. * fix(mcp): use the final Open Design plugin identity Make open-design the only accepted external plugin ID across MCP tools, run attribution, artifact version origins, and telemetry. Rename the Brief MCP App resource to v5 and reject the unpublished old ID instead of aliasing it. Validated with 171 daemon tests, 5 web tests, daemon/web typechecks, and guard. * chore(pack): bump Vela CLI to 0.0.27 * chore(nix): refresh pnpm dependency hashes * fix(mcp): honor host and plugin request contracts Respect independently advertised MCP Apps capabilities and prefer the Codex-native follow-up bridge so confirmed briefs render as readable user turns instead of context-only messages. Bump the brief resource to v6 to invalidate stale cards.\n\nMark Vela login and account probes as open-world interactions, and require stable request IDs for attributed generation so lost responses cannot create a second logical run. * fix(cli): support keyless BYOK profiles Add an explicit --no-api-key save mode for local and self-hosted providers while keeping credential-bearing profiles stdin-only. Reject missing or conflicting credential modes and cover both paths in the CLI tests. * fix(pack): replace headless owner when desktop opens Advertise headless packaged runtimes as having no visible window, then shut them down before a normal desktop launch continues instead of treating SHOW as a successful focus. Validated with the focused packaged headless and launcher lifecycle tests (20 passed). * fix(pack): clean up failed headless startup Acquire the headless identity, sidecars, and IPC server through one failure-atomic lifecycle so later bootstrap errors close every previously acquired owner in reverse order. Cover MCP-install and web-identity publication failures; validated with 22 focused tests and the packaged typecheck. * fix(byok): remove raw provider request contract Expose only daemon-owned BYOK profile references from shared run types and the web transport, while retaining the daemon's fail-closed rejection for legacy or untyped raw credential payloads. Validated with 76 web provider tests plus web and contracts typechecks. * fix(daemon): preserve interrupted run idempotency Hydrate queued or running durable requests as DAEMON_RESTARTED failures before idempotency reuse, preserving the original request and workflow mappings instead of creating a second cloud operation. Share the restart transition with boot reconciliation and expose synthetic terminal events to reattaching clients. Validated with 48 focused tests and the daemon typecheck. * fix(byok): roll back failed credential metadata writes Snapshot secure-store values before mutation and compensate create, update, and delete operations when profile metadata cannot be persisted, preventing orphaned or lost credentials. Validated with nine focused credential-service tests and the daemon typecheck. * fix(web): reconcile selected BYOK profile metadata Treat the daemon's selected secure profile as authoritative for protocol, endpoint, model, and API version so CLI profile edits cannot leave the browser showing stale execution settings. Validated with 66 config tests and the web typecheck. * fix(byok): migrate legacy credentials before cleanup Import each supported legacy browser credential into a stable daemon-owned secure profile before removing plaintext copies. Keep the original browser record on secure-store or unsupported-provider failures and surface a Settings recovery path. Cover successful migration, duplicate projections, and injected secure-backend failure while preserving existing Bedrock downgrade behavior in memory. * fix(byok): secure Windows profiles with DPAPI Dispatch native Windows BYOK profiles to a CurrentUser DPAPI backend rooted under the resolved daemon data directory. Secrets enter PowerShell only through stdin, encrypted blobs stay separate from non-secret profile metadata, and API responses remain secret-free. Add platform dispatch coverage, a Windows-only real DPAPI round-trip test, and the packaged Windows smoke path for create, resolve, response-redaction, and delete behavior. * fix(web): preserve config writes during hydration * fix(byok): persist secure credentials across entry flows * test(byok): cover secure onboarding persistence --------- Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com> Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
a2ba3ee2ad |
feat(updater): manual cache clear, installer-reinstall floor, and crash-recovery lifecycle (#6032)
* feat(updater): manual cache clear + installer-reinstall floor on the installed outer version
Two disaster-recovery capabilities for the packaged updater:
- Reuse control.launcher.version.min properly: the gate now compares the
physically installed outer package version (read at check time from the
outer bundle's open-design-config.json via the launcher launch path;
OD_UPDATE_INSTALLED_VERSION overrides for tests), not the running payload
version. When the floor trips - or min is set but the outer version is
unreadable (conservative) - the updater selects the installer artifact and
offers a same-version installer reinstall when no newer release exists
(clamped to min <= candidate so the offer always converges). The status
snapshot carries a reinstall block {reason, installedVersion, minVersion,
url}; UpdateDialog/UpdaterPopup render reinstall copy with an optional
operator jump link. tools-release publish-metadata publishes the block from
RELEASE_LAUNCHER_VERSION_MIN(_URL) (per-channel repo vars with a _STABLE
fallback wired in all release workflows) and hard-fails when min exceeds
the release version; verify-metadata re-checks the published block and
summary-metadata surfaces the floor.
- Manual clear-cache action (od:update:clear-cache IPC, sidecar clear-cache
action, Settings > About row with a two-stage inline confirm): resets
one-shot update state (downloaded release, install freeze) back to idle,
purges releases/staging/downloads/.back, removes a stale launcher
attempt.json plus any non-confirmed desktop-handoff journal, and deletes
non-retained payload versions. Runtime active/lastSuccessful versions,
retained cleanup entries, install.json, and a confirmed handoff journal
are never touched; locked files defer through the existing cleanup.json
retry machinery.
Also: tools-pack --update-action now validates through sidecar-proto's
exported isDesktopUpdateAction so clear-cache reaches the ops surface;
tools-serve updater fixture gains control min/url knobs and CLI flags;
9 new i18n keys across all 19 locales; tools/pack/AGENTS.md documents the
gate semantics and clear-cache boundaries.
Validated locally per the updater matrix (desktop/web/tools-serve/tools-pack
suites, guard, typechecks) plus a mac release-beta closed loop: platform full
spec, same-version reinstall against a real outer/payload version split,
clear-cache recovery, and a real-feed payload update to 0.15.1-beta.4.
* test(updater): close Windows recovery acceptance
* test(updater): mirror Windows same-version reinstall recovery on the mac lane
Port the Windows runSameVersionUpdaterRecoveryAcceptance shape into the mac
full profile: after the payload cold-start acceptance, restart the packaged
app against a fixture publishing an installed-outer floor at the running
payload version and assert the same-version installer reinstall snapshot
(reason/installedVersion/minVersion/url), the popup reinstall learn-more
link, clear-cache back to idle with launcher pointers untouched, explicit
re-check recovery, and the installer open in dry-run mode — macOS has no
silent DMG install to execute, unlike the Windows NSIS transaction lane.
Extends the popup eval expression/validator with reinstallLinkVisible and
records an updaterRecovery block in the smoke summary. Full-profile test
timeout raised 240s -> 360s for the extra app restart.
Validated locally: release-smoke full profile green in 80s with the recovery
summary populated (reinstall block exact, cleared idle, recovered dmg,
dryRun install).
* refactor(release): centralize launcher version floor channel policy in one resolver
Channel policy for control.launcher.version.{min,url} is now managed as one
repo-vars pair per channel (RELEASE_LAUNCHER_VERSION_MIN[_URL]_<CHANNEL>).
Workflows pass the channel pair plus the STABLE pair through verbatim — the
|| fallback expressions are gone from YAML — and the shared resolver in
tools/release/src/storage/launcher-version-floor.ts owns resolution and
validation: pair-level stable fallback for non-stable channels (never mixing
one channel's min with another's url), version format, http(s) url, orphan
url rejection, and the floor <= releaseVersion guard. publish-metadata and
verify-metadata consume the same resolver, so verify re-derives the expected
block from the same channel policy instead of trusting a pre-resolved env.
release-workflows.test.ts pins the verbatim passthrough keys in all five
release lanes and rejects any reintroduced YAML fallback.
* feat(updater): let clear-cache rebuild a provably-owned corrupt update store
A corrupt store is one of the blocking scenarios the manual clear exists to
recover from, yet the action previously bailed on the very store errors it
should heal. clear-cache now rebuilds the update root when — and only when —
ownership is provable: the current-generation sentinel is the proof, and
everything else inside an owned root is updater cache by definition. Roots
without a sentinel, with a foreign-generation marker, or failing IO are never
touched; the original store error surfaces unchanged. Four specs pin the
boundary (corrupt metadata rebuilt, stray entries rebuilt, unowned root
refused with files intact, foreign-generation marker refused).
* fix(launcher): pre-arm delegated payload launches so pre-bookkeeping crashes roll back
A payload that spawned successfully but died before reaching its own launcher
bookkeeping left no attempt.json behind, so every later cold start re-selected
the same broken active pointer and re-delegated to the dead payload — a
permanent dead loop the installer fallback could never surface (found while
designing the crash-rollback acceptance).
The delegating parent now arms attempt.json BEFORE spawning the payload and
passes the pointer as --od-launcher-delegated-* argv. Selection gains an
active-delegated reason: an attempt matching active AND the delegated pointer
is the launch in progress, not a previous failure; only an exact active match
qualifies, so a stale pointer cannot defeat the rollback. Rollback
(last-successful) delegations deliberately carry no marker and never re-arm —
the attempt on disk IS the rollback evidence the child must re-derive.
Covered end to end: packaged outer delegation pre-arms (and skips pre-arm on
rollback), the updater's payload activation pre-arms and threads the pointer
through the deferred relaunch, and confirm clears the attempt for delegated
launches. launcher-proto 18, packaged 237, desktop 264 all green.
* fix(updater): scrub a stale payload install freeze after a rollback
A payload install freezes the updater with installResult.activeVersion
awaiting the relaunch. When that payload crashed and the launcher rolled
back, the app restarts on the OLD version with the freeze still persisted —
every later check became a frozen no-op, so a rolled-back install never saw
another update offer (the crash-rollback acceptance exposed this in its
self-heal phase). Cold-start restore now detects the broken promise —
installResult.activeVersion newer than the running version on a live process
— and drops the freeze and stale install result while keeping the verified
downloaded release actionable. The installer-artifact freeze (no
activeVersion) keeps its existing restore semantics. Red spec:
'clears a stale payload install freeze when the promised relaunch never
became the running version'.
* test(updater): full-lifecycle acceptance — silent startup, crash rollback, coverage map
Two new packaged acceptance tests on both platform lanes (mac validated
locally; win symmetric for the Windows box):
- 'applies a downloaded payload silently on the next cold start': enables the
daemon-owned allowSilentUpdates through the production GET+PUT
/api/app-config path, restarts, and asserts the first scheduler tick
installs, quits, and relaunches with converged pointers — no updater action
issued.
- 'rolls back a crashing payload and self-heals on the next good update':
repacks the real payload archive with a crash-before-bookkeeping stub
(mac: shebang script via ditto; win: a real executable — System32 where.exe
— via the installed app's bundled 7z, since a script cannot stand in for an
exe), drives the update through the popup, asserts the pre-armed attempt
survives the crash as rollback evidence, cold-starts into the rolled-back
base version (degraded steady state pinned: broken pointer stays active
with its attempt), then self-heals via a version-bumped healthy payload —
real recovery releases ship as version+1.
Spec hygiene: resetPackagedRuntimeState wipes launcher/runtime/daemon state
before each lifecycle test (uninstall keeps runtime data by design, and
leftover pointers silently delegate fresh installs onto stale payloads);
mac waitForHealthyDesktopVersion gains win's requireSettledLauncher opt-out
for rollback waits.
docs/testing/updater-lifecycle.md is the new lifecycle-to-test coverage map
(incl. deliberate manual-only nodes), linked from tools/pack/AGENTS.md and
the e2e coverage status doc.
* fix(updater): harden Windows full-lifecycle acceptance
* test(release): make channel-prepare hermetic against local git tags
prepare-preview derives its latest-stable floor from the clone's real
open-design-v* tags, so the channel-prepare tests were green on tagless CI
checkouts but permanently red on any developer clone once shipped stable
tags advanced past main's package version (0.15.1 vs v0.15.1/v0.16.0 today).
The spawned scripts now run with GIT_DIR pointing at a throwaway repo
holding exactly the tags each test declares, and a new negative case pins
the floor rejection itself (packaged version below a v99.0.0 stable tag).
* test(e2e): model delegated payload launch
Pass the updater's pre-armed payload pointer into the cross-runtime launcher simulation so it represents the spawned payload process instead of a later crash-recovery launch.
Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
* test(web): wait for question form readiness
Wait for the asynchronously derived submit-disabled state before asserting it, removing the suite-order race observed by the Web workspace tests check.
Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
* fix(updater): preserve recovery state across locks and restarts
Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
---------
Co-authored-by: Looper <looper@noreply.github.com>
|
||
|
|
dcdb0c4204 |
fix packaged updates after payload cwd cleanup (#5967)
* fix packaged payload startup after cwd cleanup * fix deferred installer helper cwd Generated-By: looper 0.11.0 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
2e377a5152 |
name every packaged startup failure instead of bucketing it as unknown (#5956)
* name every packaged startup failure instead of bucketing it as unknown
The weekly `packaged_runtime_failed` alert is dominated by failures the event
had enough evidence to name and reported as opaque anyway. Triaging a 7d window
turned up three places where the emitter threw away a cause it was already
holding:
- 62 devices died with the daemon log tail read successfully, but
`parseDaemonLogTail` only ever matched `ERR_*`. A daemon that threw anything
else (SQLite corruption, EPERM, a plain throw) reported error_code=null AND
missing_module=null with its reason printed in the tail we had just read.
- 21 devices hit win32 CreateProcess failures. Node puts the real cause on the
error's `code`/`errno`/`syscall`; the event sent `.message` only, so
`spawn UNKNOWN` was indistinguishable from any other opaque failure.
- 149 devices produced an Error with an empty `.message` and no `.stack`. Every
free-form field went null, leaving residue that could not even be counted
apart from "no error at all".
So: parse the sidecar's own fatal line as a backstop when `ERR_*` misses, carry
the errno triplet off the thrown object, classify a rejected spawn as its own
`spawn-failed` kind rather than `unknown`, and guarantee a thrown error never
serializes to error_message=null — an unnamed leftover is now a named, countable
bucket.
Classification-only; the failures themselves are unchanged. Every test input is
a verbatim field payload from the alert window.
* reduce syscall to its operation token before sending it
Review catch, and a real leak. Node does not guarantee `syscall` holds only the
operation name: spawning a missing binary sets it to the whole invocation.
Verified against real Node —
spawn('/Users/elian/nonexistent/bin/thing')
→ syscall === 'spawn /Users/elian/nonexistent/bin/thing'
Forwarding that verbatim would have put the local username and install path
into an event that is retained even for opted-out users, while every other path
this module sends goes through scrubUserPaths.
Keep the first token — the operation is the whole analytic value, and the path
is already available (scrubbed) via error_message — then scrub what survives
and cap it, as a second line of defence. `code` is capped too.
This also fixes a classification miss the same review implies: the spawn-failed
branch compared the RAW syscall to 'spawn', so a spawn error carrying a path
never matched and fell through to `unknown` — the exact bucket this PR exists
to drain.
|
||
|
|
bb6c79c86d | fix packaged Windows obsolete outer cleanup (#5955) | ||
|
|
447b18b98e | fix packaged mac relaunch blocked by obsolete outer (#5940) | ||
|
|
a5f0e060b3 |
fix packaged upgrades blocked by stale payloads (#5915)
* fix packaged upgrades blocked by stale payloads * fix packaged duplicate launchers exiting cleanly |
||
|
|
06ce4eeba2 |
fix(packaged): prewarm linux AppImage sidecar payload + widen linux status budget (#5836)
Every AppImage launch mounts a fresh FUSE squashfs whose VFS page cache is cold, so the daemon sidecar demand-pages its 124 MB bundled node binary (plus dist and the ~70 MB bundled plugins registry) through FUSE on EVERY launch while Electron faults through the same mount. The daemon could not bind its IPC socket within the 35s DAEMON_STATUS_TIMEOUT_MS and every launch failed with a sidecar status timeout (white screen / recovery error). - Add apps/packaged/src/prewarm.ts: best-effort sequential read of the sidecar cold-start set into the page cache before spawning, gated to linux + FUSE-backed payloads (plain-file installs skip). Sequential reads measure ~45 MB/s through squashfuse vs ~5 MB/s demand-paged under launch contention; daemon ready drops from ~25-60s+ to ~3-19s. - Widen the linux status-wait baseline to 90s as a safety net for slow devices, mirroring the win32 rationale (#5515): same "slow, not dead" failure class. Fixes #5835 |
||
|
|
39a2dedc53 | fix(packaged): use bundled node for wrapper env (#5786) | ||
|
|
3447f60a34 |
fix packaged payload desktop handoff (#5678)
* fix packaged payload desktop handoff * fix beta mac full smoke fixture wiring * fix tools-pack mac payload cold start * test payload desktop update restart * fix Nix daemon launcher protocol build * fix(pack): harden Windows long-jump updates * fix(pack): harden mac long-jump acceptance * fix(handoff): defer armed journal writes until spawn and shutdown succeed Previously executeLegacyPayloadDesktopHandoff wrote the armed handoff journal, attempt, and runtime state before spawning the payload desktop and before the old desktop accepted shutdown. When spawn() threw or the shutdown request failed, the armed journal was stranded on disk, so the next cold start bailed out of prepareLegacyPayloadDesktopHandoff() with reason "already-armed" and the install stayed pinned to the old desktop generation indefinitely. Move the three writes to after both the payload child has spawned and the shutdown has been accepted. The old desktop is still alive while it acks the shutdown, and the payload waits for the old pid to exit before resuming, so the state still lands before the payload reads it. Add regression coverage for both the spawn-failed and shutdown-failed paths, asserting the journal stays "prepared" and a later cold start can retry. Generated-By: looper 0.10.3 (runner=fixer, agent=claude-code) * fix(updater): await payload spawn acceptance * fix(packaged): advance confirmed handoff recovery --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
358ac21a0f |
fix(packaged): force-stop a lingering skewed desktop on relaunch (#5677)
An updated daemon can connect to an old desktop main process that never quit and still holds the fixed `desktop.sock`. The old desktop rejects newer sidecar messages (e.g. `render-slides`, added in 0.13.0) as "unknown sidecar message", which surfaces as the version-skew PPTX export failure. The launcher relaunch path only ever waited for the old process to leave on its own: `waitForLauncherAfterQuit` warned and continued on timeout, and `inspectExistingDesktopForLauncher` gave up (returned `exit`) when a running-but-stale-sidecar desktop ignored SHUTDOWN — leaving the user pinned to the skewed process. Meanwhile daemon/web children already get a SIGTERM->SIGKILL escalation via `stopProcesses` in `closeManagedChild`. Close that gap: escalate the same `stopProcesses` helper against the lingering desktop in both launcher spots, then restart fresh so the relaunched app binds a matching-version desktop on the socket. Scope: the JS launcher paths only. The mac/win deferred-installer scripts (`macDeferredInstallerScript` / `windowsDeferredInstallerScript`) still give up on timeout and are left as a follow-up for desktop infra review. |
||
|
|
f1e8cb157a |
fix(packaged): label main-process startup telemetry production, not development (#5681)
Every `packaged_runtime_failed` event was tagged `env: development` in production — 1,241 development vs 2 production over 3 days — so real packaged startup crashes were filtered out of the env=production dashboards and the daily stability report couldn't tell real users from dev machines. Cause: the daemon child is always spawned with NODE_ENV=production (spawnSidecarChild), so daemon/web events correctly report `production`. But the packaged MAIN process — which emits packaged_runtime_failed — has no NODE_ENV of its own, and resolveTelemetryEnv defaulted an unset NODE_ENV to `development`. apps/packaged only ever runs as a packaged build, so that default was wrong. Fix: resolveTelemetryEnv now treats anything that isn't an explicit development marker as `production`, matching the daemon it spawns. Explicit overrides (OD_TELEMETRY_ENV / OPEN_DESIGN_ENV / POSTHOG_ENV / LANGFUSE_ENVIRONMENT) still win. Red-spec tests: env resolves to production by default (unset NODE_ENV) and honors an explicit override. |
||
|
|
d7151b2b60 |
feat(analytics): link downloads and first-party browser opens (#5442)
* feat(analytics): attribute desktop downloads * fix(analytics): initialize attribution routes after HTTP deps * feat(analytics): bridge first-party browser opens * feat(analytics): bridge first-party anchor opens * fix(analytics): make attribution claims idempotent * fix(analytics): record pending attribution results * chore(analytics): bind landing attribution KV * fix(ci): remove landing preview wrangler config override * fix(landing): resolve download attribution function * fix(analytics): harden attribution token consumption * fix(analytics): preserve same-installation claim retries * fix(analytics): merge recovered attribution retries * fix(analytics): preserve attributed browser links * fix(analytics): clear attribution on privacy reset * fix(analytics): bridge stopped AMR console links * fix(ci): deploy attribution schema before Pages * fix(ci): run attribution migrations with Wrangler 4 --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: PerishCode <perishcode@gmail.com> |
||
|
|
83d67d5a62 |
fix(packaged): widen win32 daemon status-wait budget + back off polling (#5515)
* fix(packaged): widen win32 daemon status-wait budget + back off polling Windows first launches are the single biggest packaged startup-crash bucket (packaged_runtime_failed, failure_kind=unknown): ~178 events / 61 devices/day, all status-wait timeouts with no exit code, signal, or daemon log. PostHog shows ~90% of those devices opened the app on a later launch — the daemon was slow, not dead — because Defender scanning freshly-written packaged binaries inflates the cold start (native better-sqlite3 load + first SQLite open/migrate + status-pipe bind) past the 35s wait budget. - resolveDaemonStatusTimeoutMs is now platform-aware: win32 gets 90s of AV-scan headroom, other OSes keep 35s. The OD_LEGACY_DATA_DIR migration override still wins on every platform. The web sidecar wait uses the same widened baseline (it has no legacy path). - waitForStatus backs off geometrically (150ms -> 1.5s cap) between connect polls instead of a flat 150ms, so a not-yet-bound pipe is not hammered with connects that add contention to an already-slow start. - classifyStartupFailure tags the timeout message as `status-timeout` instead of `unknown`, so the bucket is measurable — the signal for whether the budget raise actually drained the AV-scan-slow launches. * fix(packaged): keep timeoutMs a hard bound — cap the backoff sleep to remaining budget Review follow-up (@nettee): with the new geometric backoff, waitForStatus could overshoot the configured status-wait budget by a full backoff interval — a slow/dead sidecar could sleep the whole 1.5s cap after the deadline had passed before the while-condition re-checked it (~2.3s over, vs ~0.95s pre-change). Since this PR intentionally widens the win32 budget, the overshoot matters. Cap each poll sleep to the time remaining before the deadline (and break out immediately when none remains), so timeoutMs stays a hard-ish upper bound; the only residual overshoot is the single in-flight requestJsonIpc connect timeout. |
||
|
|
e4e127d058 |
fix(desktop): recover from first-launch document-level 502 (#5186)
On initial packaged desktop launch the window could be covered by a raw 502 page near the end of the splash. Two root causes: 1. The od:// protocol handler proxied the top navigation to the web sidecar with a single fetch; a transient undici socket throw (setTypeOfService EINVAL, #895) on that one attempt became the 502 document the window rendered. 2. An HTTP 502 response with a body is a successful load to Electron (did-fail-load only fires for net::ERR_*), so the existing renderer- recovery loop never retried it and the splash revealed the raw 502 after its 15s ceiling. Fixes: - protocol.ts: retry idempotent (GET/HEAD) od:// fetches up to 3x with short backoff before surfacing the 502; resolved responses (incl. upstream 5xx) and non-idempotent methods keep single-attempt semantics. - runtime.ts: route 5xx main-frame documents from did-navigate into the markRendererFailed reload path, clear rendererFailed before awaiting loadURL (so a mid-load did-navigate flag survives), and re-poll a still- failed renderer at the prompt cadence. The window now self-heals without a manual reload. Red specs added first (protocol retry contract; 5xx-document recovery wiring), verified red on main and green on this branch. Co-authored-by: 박세원 <s-w.park@samsung.com> |
||
|
|
ba6435f6a4 |
feat(packaged): attach crash-scene evidence to packaged_runtime_failed (#5224)
* feat(packaged): attach crash-scene evidence to packaged_runtime_failed The pre-daemon startup crash class (`packaged_runtime_failed`, #4696) reports only structured buckets today: failure_kind, exit_code, error_name, and a log-tail-parsed error_code/missing_module. That is enough to see THAT startup failed, but not WHY on a given machine: - The mac `daemon-start` failures are better-sqlite3 ERR_MODULE_NOT_FOUND, yet the shipped 0.13.0 DMG's `better_sqlite3.node` is verified present, arm64, signed, notarized and resolvable — so this is a machine-side subset, not a build defect, and we have no per-machine signal to explain the subset. - The Windows `unknown` bucket (the single largest slice) carries no exit code and no daemon log to parse, so today it is a dead end. Enrich the event with on-machine crash evidence: the scrubbed + truncated top-level error message/stack (the only signal the `unknown` bucket has), and a best-effort probe of the daemon's better-sqlite3 binding on THIS machine (present + size), which separates "file missing" from "file present but unloadable" (arch mismatch / quarantine / AV). All paths and free-form text are run through the existing `scrubUserPaths` and length-capped before send. - startup-telemetry.ts: add `error_message`, `error_stack`, `native_module_present/size/path`; new `nativeModulePath` arg + injectable `statNativeModule` dep. - index.ts: pass the packaged binding path (`getAppPath()/node_modules/better-sqlite3/build/Release/better_sqlite3.node`, layout verified against the shipped DMG) through the fatal-exit report. - contracts: extend `PackagedRuntimeFailedProps` with the optional fields. - tests: red-spec first — assert scrubbed message/stack and the native probe (present/missing) via the injected `statNativeModule`. * fix(packaged): scrub full Windows profile segment even with spaces Review (PerishCode/Looper): the new free-form error_message/error_stack fields run through scrubUserPaths, but its Windows branch matched `[^\\\s]+` — it stopped at the first whitespace. A Windows profile dir can contain a space ("C:\Users\John Doe\..."), so it produced "C:\Users\<redacted> Doe\..." and leaked the rest of the segment, breaking this PR's stated privacy bound. Consume the whole segment up to the next backslash (`[^\\]+`). POSIX home segments cannot contain spaces and file:// URLs percent-encode them, so only this backslash form needs the whitespace-tolerant boundary. Add fixture coverage for the spaced profile — both standalone and embedded in a crash message — asserting the surname never survives. * fix(packaged): make Windows-home scrub separator-agnostic Review round 2 (PerishCode/Looper): the prior fix covered the backslash form, but slash-normalized Windows paths ("C:/Users/John Doe/...", which JS/Electron/ Node diagnostics commonly emit) still leaked the surname — the POSIX "/Users/" rule matched them and stopped at the first space, producing "C:/Users/<redacted> Doe/...". Replace the backslash-only Windows rule with a separator-agnostic one that matches `<drive>:[\\/]Users[\\/]` and consumes the whole segment up to the next slash OR backslash (spaces allowed), running before the POSIX rule. The `\r\n` in the class keeps it from running across lines in a multi-line stack. POSIX segments can't contain spaces, so that rule is left with its whitespace boundary. Fixtures added for the slash form (standalone + embedded) and a multi-line no-over-redaction case. |
||
|
|
e899fb93fe |
feat(packaged): main-process telemetry for pre-daemon startup failures (#4696)
* feat(packaged): main-process telemetry for pre-daemon startup failures The daemon hosts the PostHog client, so when daemon/web sidecars die before reporting status (issue #4638: better-sqlite3 vanished from the bundle -> ERR_MODULE_NOT_FOUND), nothing emits telemetry and the whole pre-daemon crash class is invisible on every dashboard. Add a main-process direct capture on the fatal-exit path: classify daemon-vs-web by log-path segment, parse the real error code + missing module from the sidecar log tail, scrub home dirs, and POST one packaged_runtime_failed event over plain fetch (no posthog-node SDK, no new dependency). Zero happy-path side-effects by construction: all logic runs only inside main().catch, fetch is wrapped in Promise.race with a hard timeout, errors are swallowed, and it is a no-op without a PostHog key. Crash telemetry follows the existing captureSafety policy (stability data is retained even for opted-out users); Settings -> Privacy copy follow-up tracked in the PR. Slice B of the crash-governance spec (PR #4694). * fix(packaged): Windows web-path classify + main-process installationId (review) Address PerishCode review on #4696: - classifyStartupFailure normalizes backslashes before the /web/ segment check so Windows web-sidecar failures aren't misreported as daemon-start. - resolveStartupDistinctId now takes an explicit installationRoot (threaded from paths.installationRoot); OD_INSTALLATION_DIR is only set in the daemon child env, so the main process previously always fell back to the synthetic id. Adds a Windows web-path fixture and an installationId-resolution test (18 total). * fix(packaged): raise crash-telemetry flush timeout 1.5s -> 5s (e2e finding) Real-machine e2e (local packaged build -> delete better-sqlite3 to reproduce issue #4638 -> launch -> query PostHog) showed the 1.5s cap silently DROPPED the event: a cold DNS+TLS handshake to us.i.posthog.com from a fresh main process exceeds 1.5s, so Promise.race timed out and process.exit(1) killed the in-flight POST. Confirmed with a standalone repro (1.5s never landed, 6s did). 5s lets the single request complete on a cold connection; an offline machine still exits fast because fetch rejects on DNS failure (send resolves early), so only a black-hole network pays the full bound — acceptable on a crash exit. * feat(packaged): stamp shared safety-event envelope on crash telemetry (review) Address PerishCode review on #4696: the direct PostHog emitter only sent the startup props + $os, omitting the envelope captureSafety always stamps. Mirror it so env/schema-filtered dashboards bucket packaged_runtime_failed beside the rest of the stream: event_schema_version, env, device_id, client_type (packaged_main), capture_source (packaged/startup), ui_version, event_id and $insert_id (dedup key). EVENT_SCHEMA_VERSION + the env resolver are replicated (packaged doesn't depend on contracts) with lockstep comments. Adds a typed PackagedRuntimeFailedProps + AnalyticsEventPayload entry in contracts, and a test asserting the envelope wire fields (19 tests). * fix(contracts): restore packaged_runtime_failed in AnalyticsEventName (review) The name union member was clobbered when the envelope change synced events.ts; only the AnalyticsEventPayload entry survived. PerishCode caught the regression — restore the canonical AnalyticsEventName member so the event name and its typed payload stay in lockstep. |
||
|
|
0bf1b6d6b8 |
[codex] converge release workflows and stable dry-runs (#4390)
* fix(tools-pack): use junctions for Windows standalone peer deps * fix(desktop): expose IPC during startup * fix(tools-pack): preserve Windows inspect diagnostics * fix(tools-pack): report Windows inspect status errors * fix(packaged): use Electron net fetch for app protocol * fix(packaged): load Windows renderer from web sidecar * fix(desktop): show Windows packaged window during startup * fix(packaged): disable Windows GPU startup * fix(tools-pack): keep Windows core smoke observable * fix(packaged): remove Windows startup probes * fix(tools-pack): trace Windows desktop IPC status * fix(tools-pack): add Windows IPC diagnose loop * fix(release): default beta-s Windows updater feed * chore: clean merged test eof * refactor(release): unify prerelease channel model * chore(release): close prerelease doc escape hatches * refactor(release): converge release channel workflows * fix(release): install toolchain in metadata jobs * fix(release): build release package before contracts * chore(release): bump development version to 0.10.1 * fix(e2e): seed windows packaged smoke runtime config * fix(release): install toolchain for metadata publish * fix(release): materialize betas metadata checkout * chore(release): bump development version to 0.10.2 * fix(release): allow betas metadata cold start from s3 * fix(e2e): support betas packaged update scenarios * fix(release): pass betas channel into packaged smoke * fix(release): set betas channel during self-hosted builds * fix(release): verify counted channel reservations * fix(release): use pnpm cmd for betas windows publish * fix(release): add betas manifest artifact fallback * fix(release): skip beta-s public metadata fetch * fix(release): read beta-s manifests from storage * fix(release): cache beta windows tools-pack builds * fix(release): inline beta mac tools-pack builds * fix(pack): deep sign unsigned mac bundles * docs(pack): document payload-first beta updater validation * fix(release): align preview tools-pack cache flow * fix(release): align prerelease tools-pack cache flow * fix(release): pass github token to prerelease metadata * fix(release): setup pnpm before feishu notify * fix(release): add stable dry-run prepublish flow * fix(release): accept completed prerelease metadata gate * fix(release): require stable release branches * fix(release): converge r2 access checks * fix(updater): use release channel parser for defaults * fix(updater): harden windows payload relaunch * fix(release): converge updater smoke fixture contract * test(e2e): require silent updater fixture output * fix(release): align stable windows smoke build path * fix(ci): include release workspace in validation * fix(ci): repair release validation lanes Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(ci): restore zero-install Feishu notification Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
d3896fa51a |
[codex] Clean deprecated launcher payloads on updater startup (#4524)
* fix(packaged): recover stale launcher and sidecar state * fix(packaged): write launcher cleanup from installer sync * perf(tools-pack): reuse windows payload caches * perf(tools-pack): avoid slow windows 7z filters * fix(tools-pack): bound windows payload archive hangs * test(packaged): stabilize sidecar tests on windows * fix(tools-pack): harden launcher runtime sync helper * fix(tools-pack): invalidate nsis cache for installer helpers * fix(tools-pack): hash nsis helper source in bundled cli * fix(packaged): restart when existing desktop has stale sidecars * chore(release): bump beta base to 0.11.1 * fix(e2e): seed windows smoke onboarding in runtime data * ci(release): let beta runs use default queueing * ci(release): restore beta concurrency guard * ci(release): enable beta mac x64 by default * ci(release): disable beta mac x64 by default * fix(updater): clean deprecated launcher payloads on startup * fix(e2e): align stable dry-run fixture version Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
0c4af7e1de |
fix: back off offline star fetch logging (#3592)
* fix: back off offline star fetch logging * fix: ignore aborted star fetch cleanup |
||
|
|
2ce9d09f41 |
Fix Windows launcher beta update lifecycle (#3960)
* fix windows beta updater acceptance harness * fix: harden windows launcher beta updates * fix: align launcher payload e2e relaunch stub Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * fix: gate windows uninstall version sync Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * fix: verify launcher payload before activation Generated-By: looper 0.9.5 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
7a1ad1a438 |
feat(packaged): add launcher payload updates (#3812)
* feat(packaged): add launcher payload runtime * ci: focus launcher payload windows smoke * ci: publish beta mac x64 launcher payload * test(e2e): harden payload updater smoke * fix(pack): inject launch config for installed windows smoke * fix(daemon): allow packaged payload resource roots * fix(updater): relaunch after payload update * test(e2e): refresh windows updater UI status * test(e2e): ensure windows smoke reaches main shell * test(e2e): skip onboarding before windows updater smoke * fix(updater): detach windows payload relaunch helper * test(e2e): run payload smoke without updater dry run * fix(desktop): relaunch windows payload updates on quit * fix(updater): preserve installed payload relaunch target * fix(updater): require launcher target for payload updates Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * test(e2e): align mac x64 artifact mode assertion * test(e2e): canonicalize launcher relaunch root * fix(updater): validate launcher payload config before activation Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * fix(updater): require live launcher target for payload updates Generated-By: looper 0.9.5 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
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> |
||
|
|
338cb4d423 |
fix(platform): support live system proxy changes (#3093)
* fix(platform): support live system proxy changes * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Honor lowercase proxy env vars within a single source before merging proxy-aware envs.\n\nGenerated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Refresh provider request proxy env on each dispatcher creation and cover it with a focused regression test. Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): enable node env proxy for user proxy vars * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) * fix(platform): support live system proxy changes Generated-By: looper 0.9.1 (runner=fixer, agent=opencode) |
||
|
|
df8a0faff6 |
feat(runtimes): register AMR (vela) as an ACP stdio agent (#2355)
* feat(runtimes): register AMR (vela) as an ACP stdio agent
AMR is the vela CLI's ACP runtime mode. `vela agent run --runtime opencode`
speaks ACP JSON-RPC over stdio (see vela's
`specs/current/runtime/manual-agent-run-openrouter.md`); per
`docs/new-agent-runtime-acp.md` we expose it through the same `streamFormat:
'acp-json-rpc'` transport that already powers Hermes, Devin, Kimi, etc.
The new `defs/amr.ts` is the entire wiring — `buildArgs` returns
`['agent', 'run', '--runtime', 'opencode']`, `fetchModels` reuses
`detectAcpModels`, and the fallback list seeds the OpenRouter ids vela's
e2e baseline uses. `executables.ts`/`app-config.ts`/`metadata.ts` get the
matching `VELA_BIN`/`VELA_LINK_URL`/`VELA_RUNTIME_KEY`/`VELA_OPENCODE_BIN`
allowlist + install/docs URLs, so users can configure the per-agent env in
Settings without leaking into other adapters.
Coverage: `tests/fixtures/fake-vela.mjs` is a minimal ACP stub that returns
the documented `initialize` / `session/new` / `session/set_model` /
`session/prompt` shapes; `tests/amr-acp-integration.test.ts` spawns it via
`child_process.spawn` and drives a full turn through `attachAcpSession` and
`detectAcpModels`, so the ACP transport contract for AMR is end-to-end
verified locally even before a real `vela` binary is installed.
Validated:
- pnpm guard
- pnpm typecheck (all workspace projects)
- pnpm --filter @open-design/daemon test (2881/2881)
Deferred: real OpenRouter-backed turn through a built `vela` binary —
the runtime def needs no changes for that path, only `VELA_RUNTIME_KEY`
and `VELA_LINK_URL` in env (or Settings).
* fix(runtimes/amr): pin a concrete default model and bare openai ids
End-to-end validation against a freshly-built `vela` (nexu-io/vela@main)
+ OpenRouter surfaced two contract details the first AMR runtime def
got wrong:
1. vela rejects `session/prompt` with `session/set_model must be called
before session/prompt`. attachAcpSession in apps/daemon/src/acp.ts
skips set_model whenever the picked model is the synthetic 'default'
id, so AMR's fallback list must NOT include DEFAULT_MODEL_OPTION. The
def now ships a concrete `gpt-5.4-mini` as both `fetchModels`'
default option and `fallbackModels[0]`, which makes attachAcpSession
always send a real `session/set_model` for AMR turns.
2. `vela --runtime opencode` auto-prepends `openai/` to whatever modelId
it forwards to opencode's openai provider. With OpenRouter-style ids
like `openai/gpt-5.4-mini`, opencode receives the double-prefixed
`openai/openai/gpt-5.4-mini` and replies `ProviderModelNotFoundError`.
The new fallback list ships the bare ids opencode's openai registry
actually knows about (gpt-5.4, gpt-5.4-mini, gpt-5.4-fast, etc.).
Stub + tests:
- tests/fixtures/fake-vela.mjs now enforces the set_model gate the same
way real vela does, so a regression that silently goes back to
model: 'default' would surface as a fatal error in tests instead of a
hidden production failure.
- tests/amr-acp-integration.test.ts pins both contracts: no 'default' /
no 'openai/' prefix in fallbackModels, and a negative case that
asserts session/prompt fails when no model is set.
Adds `apps/daemon/scripts/verify-amr-real-vela.mjs` — a small dev-time
runner that drives `attachAcpSession` against a real `vela` binary and
prints the daemon's chat events, so future protocol drift can be checked
against an actual OpenRouter call.
Verified locally: `vela agent run --runtime opencode` + OpenRouter
returns the prompted string ("AMR-E2E-PASS") through the full daemon
pipeline; daemon test suite stays 2883/2883.
* fix(runtimes/amr): substitute concrete model when chat run sends 'default'
A plugin-driven AMR run from the UI surfaced a real-world hole in the
prior commit:
json-rpc id 3: session/set_model must be called before session/prompt
The Default-design-router plugin (and any caller that doesn't pin a
real model) sends `model: 'default'` straight through, which the AMR
runtime def cannot accept — vela rejects `session/prompt` without
`session/set_model` and attachAcpSession skips set_model whenever
model === 'default'. Just leaving DEFAULT_MODEL_OPTION out of the
adapter's `fallbackModels` is not enough: the chat-run handler in
server.ts still forwarded 'default' verbatim.
This adds `resolveModelForAgent(def, resolved, env?)` as the
single source of truth for the substitution:
1. If the caller picked a real id, pass it through.
2. Else, if `def.defaultModelEnvVar` is set and the daemon process
env has a non-empty value for it, return that (operator escape
hatch — see below).
3. Else, if the def's `fallbackModels` does NOT contain a 'default'
id, return `fallbackModels[0].id`.
4. Else, return the original value (the historic shape — defs that
list 'default' themselves are untouched).
AMR sets `defaultModelEnvVar: 'VELA_DEFAULT_MODEL'`, so when
opencode's openai-provider registry deprecates `gpt-5.4-mini`
upstream, an operator can swap the fallback id without a code change
by exporting `VELA_DEFAULT_MODEL=gpt-5.5` before launching tools-dev
/ od. Worth noting the env var must live in the daemon's `process.env`
(Settings-UI per-agent env values only reach the spawned child, not
the daemon's resolver) — the new field's docblock spells this out.
Coverage:
- `tests/runtimes/resolve-model.test.ts` — 8 unit tests covering all
four resolver branches plus the env-override happy path / fallback /
ignore-when-user-picked-a-real-id case.
- `pnpm --filter @open-design/daemon typecheck` clean.
* chore(runtimes/amr): move AMR to the top of the base agent list
So `AMR (vela)` shows up first in the agent picker / status views,
ahead of claude / codex. Pure ordering change; no behavior delta.
* feat(amr): Sign-in / Sign-out button on the AMR Settings card
The first half of the AMR work assumed the operator would set
VELA_RUNTIME_KEY / VELA_LINK_URL on the daemon process and never
surfaced login state to users. This adds the missing UX so a fresh
install can drive the full path from Settings:
- GET /api/integrations/vela/status reads ~/.vela/config.json
for the active profile and returns { loggedIn, profile, user }
(without leaking the runtime/control keys themselves).
- POST /api/integrations/vela/login spawns `vela login` once
(409 if one is already in flight). The vela CLI opens the user's
browser to the device-authorization page itself — Open Design
only needs to kick the subprocess off.
- POST /api/integrations/vela/logout removes ~/.vela/config.json
so the next status read returns logged-out.
`AmrAgentCard` is a dedicated agent-card component for AMR because
the existing `<button>` row can't host an interactive sub-control
(nested interactive elements). It polls /status after a login click
until the daemon reports loggedIn=true (or 5 minutes elapse), and
exposes a Sign-out action on hover. Other adapters (claude, codex,
hermes, …) keep their existing `<button>` card.
i18n: 8 new keys (settings.amrLogin / Logout / LoggingIn / etc.)
added to en + zh-CN. Other locales spread `en` and inherit the
English copy until translations land.
Coverage:
- `tests/integrations/vela.test.ts` pins the config.json reader
against a tmp HOME — including the negative case where a profile
has user info but no runtimeKey (still logged-out), and the
secret-leak guard ("rt-secret-*" must not appear in the projection
payload).
- `tests/components/AmrAgentCard.test.tsx` covers all four UI
states (logged-out, logging-in, logged-in, logging-out) plus the
click-propagation invariant the divergent card was built to keep.
`pnpm --filter @open-design/daemon test` 2901 / 2901 passing.
`pnpm --filter @open-design/web test` 1719 / 1719 passing.
`pnpm typecheck` + `pnpm guard` clean.
Dev script side-effects: `apps/daemon/scripts/verify-amr-real-vela.mjs`
no longer requires both VELA_RUNTIME_KEY and VELA_LINK_URL — if
VELA_PROFILE is set, the vela CLI is allowed to resolve credentials
from `~/.vela/config.json`. Added the two AMR `.mjs` fixtures to
`scripts/guard.ts` allowlist with the executable-fixture / dev-runner
rationale.
* fix(connection-test): substitute model for AMR before attachAcpSession
The chat-run path in server.ts already routes the requested model through
`resolveModelForAgent` so AMR / vela (whose CLI demands an explicit
`session/set_model` before `session/prompt`) gets the def's first
concrete fallback id when the chat run ships `model: 'default'`.
`connectionTest.ts` was wiring `attachAcpSession({ ..., model: model ?? null })`
directly, which made the Test Connection button on the AMR Settings
card deadlock with the same `session/set_model must be called before
session/prompt` error the chat-run path already handles — surfaced as a
permanent "Testing connection…" spinner in the UI.
Reuse the same helper here so Test Connection mirrors chat-run behavior.
* test(amr): three-layer end-to-end coverage for the AMR login + turn flow
The PR up to this point shipped runtime + UI code with unit-level Vitest
coverage. This commit adds the cross-layer regression net the live demo
relied on:
1. apps/daemon/tests/integrations/vela.routes.test.ts (HTTP, Vitest)
Spins up the real daemon Express app via `startServer({port:0,...})`,
persists `agentCliEnv.amr.VELA_BIN = <fake>` into app-config.json,
and exercises every /api/integrations/vela/* endpoint against the
extended fake-vela stub:
- status reads ~/.vela/config.json under various states
- login spawns the fake, waits for config.json to appear, returns
pid + startedAt + profile
- 409 already-running guard with the stub's delay knob
- logout removes the file (idempotent)
- secrets (runtimeKey / controlKey) never leak in the projection
- login → status round-trip flips loggedIn=false → true
2. e2e/tests/amr/turn.test.ts (tools-dev orchestrated, Vitest)
Boots a namespaced daemon + web pair through `createSmokeSuite`,
inlines a self-contained fake `vela` binary that handles BOTH
`vela login` (writes ~/.vela/config.json) and
`vela agent run --runtime opencode` (ACP stdio with the
`session/set_model must precede session/prompt` gate the real binary
enforces), then drives a complete /api/runs lifecycle for
`agentId: 'amr', model: 'default'` and asserts the assistant message
captures the fake's streamed text. This is the test that would have
surfaced today's plugin-default-model regression (the `set_model
before prompt` error) at PR time instead of demo time.
3. e2e/ui/amr-login-pill.test.ts (Playwright)
Mocks /api/agents + /api/integrations/vela/{status,login,logout}
to drive the Settings AMR card through the full Sign in → Signed in
→ Sign out cycle. Pins the AmrLoginPill polling contract and the
aria-label semantics (the pill's accessible name is "Sign out" once
logged in, regardless of which label the hover-state text shows).
fake-vela.mjs extensions:
- Handles `vela login` argv by writing
~/.vela/config.json for the active VELA_PROFILE and exiting 0 —
mirrors real vela's on-disk side-effect without the device-auth
loop.
- FAKE_VELA_LOGIN_DELAY_MS knob so route tests can observe the
in-flight state of the spawn lifecycle.
- FAKE_VELA_LOGIN_USER_EMAIL / _USER_PLAN to assert the surfaced
user fields end-to-end.
Validated:
- `pnpm guard` + `pnpm typecheck` (all workspace projects)
- `pnpm --filter @open-design/daemon test`: 2998 / 2998 passing,
including the new 8-test integration suite.
- `cd e2e && pnpm test tests/amr`: 1 / 1 passing.
- `cd e2e && pnpm exec playwright test ui/amr-login-pill.test.ts`:
1 / 1 passing (6.7s).
* feat(amr): package native cli and refine login ui
* feat(amr): wire vela cli beta packaging
* docs(amr): document vela ci packaging review
* docs(amr): refine vela ci integration review
* fix(ci): refresh nix pnpm dependency hashes
* fix(pack): clean up Vela CLI packaging
* fix(pack): bundle Vela CLI support files
* fix(amr): recover login attempts from stale auth state
* test: expand AMR and automations coverage
* fix(amr): address review follow-ups
* test(web): align tasks fixtures with contracts
* fix(daemon): type wildcard route params
* fix(ci): refresh PR merge validation
* fix(amr): clear env credentials on logout
* feat(settings): inline local CLI model configuration
* fix(amr): recognize daemon env credentials
* [codex] Fix Vela companion packaging (#2979)
* Fix Vela companion packaging
* Update Nix pnpm dependency hashes
* [codex] Surface AMR account failures (#2980)
* fix: surface AMR account failures
* fix: cover AMR recovery error guidance
* chore: bump beta base version to 0.8.1 (#2990)
* Fix AMR profile and packaged runtime review issues
* Detect packaged AMR OpenCode companion tree
* feat(web): polish AMR frontend flows
* Polish AMR onboarding card
* fix: read AMR login state from dot-amr config (#3048)
* test: tighten AMR credential and packaging coverage
* test: restore AMR executable test env helper
* [codex] Fix packaged mac Dock identity and AMR label (#3076)
* Fix packaged mac sidecar Dock identity
* Rename AMR assistant label
* Fix AMR live models and dot-amr login state (#3073)
* fix: read AMR login state from dot-amr config
* fix: load live AMR models before runs
* fix: point AMR onboarding link to production wallet
* fix: address AMR model review feedback
* fix: persist live AMR model fallback
* [codex] Fix AMR link catalog model ids (#3088)
* Fix packaged mac sidecar Dock identity
* Rename AMR assistant label
* Fix AMR link catalog model ids
* Fix AMR model normalization typecheck
* Use live AMR model for default runs
* fix: polish AMR runtime settings UI
* Accelerate AMR startup defaults (#3092)
* Surface AMR insufficient balance wallet URL (#3099)
* fix(web): polish onboarding controls (#3112)
* fix(web): show CLI scan loading state
* Avoid duplicate AMR wallet recharge links (#3117)
* Avoid duplicate AMR wallet recharge links
* Use Vela CLI 0.0.3 test package
* chore(nix): refresh pnpm deps hash
* Fix AMR wallet guidance display
---------
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
* chore(pack): pin Vela CLI 0.0.3-test.1 (#3127)
* chore(nix): refresh pnpm deps hash
* chore(pack): pin Vela CLI 0.0.3
* chore(nix): refresh pnpm deps hash
* fix(web): suppress AMR exit 130 fallback (#3136)
* feat(web): nudge users to hosted AMR on model/auth/quota failures (#3083)
* feat(web): nudge users to hosted AMR on model/auth/quota failures
When a non-AMR agent run fails with an auth / quota / upstream model
error, surface an inline nudge under the error pill linking to Open
Design's hosted AMR gateway (https://open-design.ai/amr). The nudge
fires `surface_view` (element=run_failed_toast) on impression and
`ui_click` (element=go_amr) on the link.
Also teach the daemon to classify CLI-agent auth/quota/upstream failures
(Claude Code, codex, ...) into specific API error codes
(AGENT_AUTH_REQUIRED / RATE_LIMITED / UPSTREAM_UNAVAILABLE) instead of
the generic AGENT_EXECUTION_FAILED, so both the error message and the
nudge key off accurate codes. AMR's own runs are excluded from the
nudge — they keep the dedicated sign-in / recharge affordances.
* feat(web): rework failed-run AMR guidance into per-case error UI
Replace the single inline nudge with a per-case failed-run experience
driven by the run's error code + agent:
- The error card is now neutral gray (was red) and always carries a
retry button; it is driven by the persisted per-message error event so
it survives a reload.
- Non-AMR agent hitting a model/auth/quota wall: a theme-color promotion
card under the error card offers "switch to AMR & retry" — switches the
run to AMR, opens Settings on the AMR card, and auto-retries once the
account signs in (ProjectView polls vela login status, independent of
the Settings pill lifecycle, with success / 5-min-timeout / unmount
exits).
- AMR agent unauthorized: clearer copy + an "authorize & retry" button.
- AMR agent out of balance: clearer copy + a "top up" button to the AMR
wallet, with manual retry.
- Settings AMR card: when opened from the nudge, it scrolls into view and
pulses, and an authorize-button coachmark (a fake hand cursor that
rises in and dismisses on hover) points at the sign-in control when not
yet authorized.
analytics: surface_view (run_failed_toast) on the promotion card and
ui_click (go_amr) on its action are retained. i18n adds chat.amrCard.*
and chat.amrError.* (en / zh-CN / zh-TW translated; other locales fall
back to en) and drops the old chat.amrErrorGuidance keys.
* fix(daemon): require status context for numeric service-failure codes
Per review on #3083: the model-service classifier matched bare HTTP
status numbers (`500`, `502`, `429`, `401`), so ordinary CLI output like
`line 500`, `read 502 bytes`, or `exit code 401` could be misclassified
as a provider outage / auth wall and wrongly surface the AMR nudge. Now
a status number only counts when it carries explicit context (`HTTP 500`,
`status 503`, `code: 401`, `502 Bad Gateway`); textual provider phrases
(overloaded, bad gateway, service unavailable, rate limit, …) are
unchanged. Adds fixtures proving unrelated numeric output stays null.
* fix(web): keep error pill for failed runs ChatPane's card doesn't cover
Per review on #3083: the per-message gray error pill was suppressed for
every persisted error status event, but ChatPane only renders the
replacement top-level error card for `retryableAssistantMessage` (the
last failed assistant). So a failed turn that is no longer last (after a
follow-up) or an older failed run in history showed neither the pill nor
the card — its error detail vanished, undercutting reload/history
survival. ChatPane now passes `errorCardOwnerId` (the assistant id whose
error the card represents); AssistantMessage suppresses only that one
pill and keeps rendering StatusPill for all other error events.
* fix(daemon): don't treat a process exit code as an HTTP status
Follow-up to review on #3083: the status-context helper accepted a bare
`code` prefix, so `exit code 401` / `process exited with code 429` still
matched and got classified as AGENT_AUTH_REQUIRED / RATE_LIMITED (the
very `exit code 401` case the comment calls out as noise). `code` now
only counts when qualified (`status code` / `error code` / `response
code`) or punctuation-bound (`code: 401`); bare `exit code N` no longer
matches. Adds fixtures for exit-code lines returning null.
* chore(web): translate AMR card / error keys for 16 remaining locales
PR #3083 added 10 new `chat.amrCard.*` / `chat.amrError.*` keys but only
provided en/zh-CN/zh-TW translations; the other 16 locales fell back to
English. Translate the card title/body, three chips, primary CTA, and
the AMR self-error (auth / balance) messages and buttons for ar, de,
es-ES, fa, fr, hu, id, it, ja, ko, pl, pt-BR, ru, th, tr, uk.
* fix(amr): address review feedback on #2355
Targeted fixes for the unresolved review threads on #2355. Each fix
includes / updates a focused test.
- runtimes/executables.ts: `packagedVelaOpenCodeCompanionTree` now
verifies the inner `opencode` executable exists + is runnable, not
just the directory. This closes the false-positive availability path
that let `detectAgents()` surface AMR as available even when the
packaged companion was empty / partially copied (mrcfps, 4 threads).
- runtimes/executables.ts: `resolveAmrOpenCodeExecutable` now prefers
the bundled `<OD_RESOURCE_ROOT>/bin/libexec/opencode/opencode` over a
stale `opencode` on the user's PATH, so packaged AMR builds can't be
hijacked by a global installation.
- web/EntryShell.tsx: when the Local CLI scan returns an available
agent and the previously-selected agent is AMR, switch the selection
to the first available local agent so the runtime and persisted
agent agree before Continue.
- server.ts (model-probe branch): for AMR, check `readVelaLoginStatus`
BEFORE rejecting on an empty live-model catalog — a signed-out user
was getting `AMR_MODEL_UNAVAILABLE` ("choose a model") instead of
the correct `AMR_AUTH_REQUIRED` (sign-in affordance).
- server.ts (default model fallback): if the user asked for the AMR
agent default and the cached id is no longer in the FRESH catalog,
fall back to `liveModels[0]` from the probe instead of rejecting the
run as `AMR_MODEL_UNAVAILABLE`.
- integrations/vela.ts: route `vela login` through
`createCommandInvocation` so an npm/Node-style `vela.cmd` / `.bat`
shim on Windows gets the correct `cmd.exe /d /s /c …` wrapping with
verbatim args (matches `execAgentFile` / chat-run spawning).
- tools/pack/src/linux.ts: in containerized Linux builds, bind-mount
the host directory of `OPEN_DESIGN_VELA_CLI_BIN` and rewrite the env
to the container-side path. The host path was being passed in as-is
even though the default container only mounts /project, /tools-pack
and cache/home — `copyOptionalVelaCliBinary` saw a missing path.
Deferred (out of scope for this PR):
- `od amr status/login/logout/cancel` CLI subcommands (AGENTS.md
UI/CLI dual-track rule, server.ts:5763) — sizable surface; tracked
for a separate focused PR.
- Strict `--require-vela-cli` for Windows + mac-x64 beta builds:
prematurely blocked — `@powerformer/vela-cli` only publishes the
`darwin-arm64` platform binary today; adding the flag elsewhere
would fail the builds. Revisit once win/x64/linux binaries ship.
* fix(amr): hoist sendAmrAccountFailure above the AMR catalog preflight (TDZ)
The new signed-out AMR branch in the catalog preflight at server.ts:10875
calls `sendAmrAccountFailure(...)` to emit AMR_AUTH_REQUIRED, but the
const declaration sat ~100 lines below at the outer function scope. Because
`const` is TDZ-aware, that branch would have thrown `ReferenceError:
Cannot access 'sendAmrAccountFailure' before initialization` for the
exact users it tries to help — defeating the original intent.
Hoist the helper to just above the AMR preflight block so it's available
to every AMR code path in this function. Behavior elsewhere is unchanged.
Also rerun the daemon test suite: `launch.test.ts > resolveAgentLaunch
uses packaged built-in Vela for AMR` was creating the
`<resourceRoot>/bin/libexec/opencode/` companion *directory* only, but
this PR's earlier tightening of `packagedVelaOpenCodeCompanionTree`
also requires the inner `opencode` executable. Add it to that fixture
to match the new contract; the test was a sibling of the executables /
env-and-detection fixtures already updated in
|
||
|
|
1b9caf50a0 |
fix(packaged): honor OD_DATA_DIR in desktop runtime (#2162)
* fix(packaged): honor OD_DATA_DIR in desktop runtime Co-authored-by: multica-agent <github@multica.ai> * fix(packaged): scope OD_DATA_DIR by namespace Co-authored-by: multica-agent <github@multica.ai> * fix(packaged): reject relative OD_DATA_DIR overrides Co-authored-by: multica-agent <github@multica.ai> * fix(packaged): preserve scoped OD_DATA_DIR overrides Co-authored-by: multica-agent <github@multica.ai> * fix(packaged): surface OD_DATA_DIR validation as PackagedPathAccessError Relative OD_DATA_DIR in packaged mode now throws PackagedPathAccessError instead of a plain Error. apps/packaged/src/index.ts main() only routes PackagedPathAccessError to dialog.showErrorBox, so the prior plain Error made the app exit silently for GUI launches with an invalid override. Extract PackagedPathAccessError into apps/packaged/src/errors.ts so paths.ts can throw it without an inter-module value cycle with launch.ts. Co-authored-by: multica-agent <github@multica.ai> * fix(packaged): make OD_DATA_DIR absolute-path guard platform-aware The previous guard ran `win32.isAbsolute(expanded)` unconditionally on every platform, so on macOS/Linux a value like `C:\Users\Fred\OD` passed the check (win32 considers it absolute) and silently flowed into `join(expanded, "namespaces", namespace, "data")`, producing a cwd-relative POSIX path instead of throwing. Branch the check on `process.platform === "win32"` so Windows paths are only accepted on Windows. Update the existing Windows-themed test fixtures to stub `process.platform = "win32"` (the omission was what masked this bug) and add a regression that stubs `linux` and asserts `C:\foo` and `\\server\share` are rejected as PackagedPathAccessError. Co-authored-by: multica-agent <github@multica.ai> * fix(packaged): reject mismatched scoped OD_DATA_DIR Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: multica-agent <github@multica.ai> Co-authored-by: kami.c <kami.c@chative.com> |
||
|
|
db79db04a9 |
Forward Node proxy env to packaged sidecars (#2763)
Co-authored-by: Qian Wang <wangqian5730@gmail.com> |
||
|
|
ec96585a8f | fix: harden Windows packaged updater flow (#2595) | ||
|
|
6bb0f0fd91 |
feat(observability): web lifecycle telemetry + stable installationId migration (#2527)
* feat(observability): web lifecycle telemetry + stable installationId migration Two intertwined safety-telemetry additions for the 0.8.0 release. Web lifecycle observability --------------------------- New `apps/web/src/observability/` module installed at module load via client-app.tsx — alongside the existing error-tracking exception hooks from #2521. Reuses error-tracking's direct-fetch transport (the same consent-bypass + early-buffer guarantees) so every event flows even when the user has opted out of general analytics: - client_long_task PerformanceObserver longtask >100ms (real "feels janky" signal, FPS proxy) - client_white_screen app fails to mount after 5s; MutationObserver cancels the timer the moment the React root renders so a normal boot is zero events - client_resource_error capture-phase window.error catches failed <script>/<link>/<img>/<iframe> loads (chunk-load failures, broken artifact refs) - client_boot_timing navigationStart → load timings via Navigation Timing v2 - client_visibility_change visibilitychange + page lifetime - client_session_summary real foreground duration emitted on pagehide - client_run_stuck 5min watchdog on SSE runs that don't progress (#2464 / #2405 / #1451 in data form) - client_iframe_error FileViewer iframe load failures (iframe errors don't bubble to window, so the global resource-error observer can't see them) - desktop_renderer_crash Electron main observes render-process-gone and forwards to daemon /api/observability/event - daemon_uncaught_exception daemon_unhandled_rejection process-level handlers on the daemon error-tracking.ts is generalised: `reportSafetyEvent(name, props)` now exposes the same buffer + direct-fetch transport that `reportHandledException` used, with identical $exception wire shape preserved for the existing exception path. Daemon cross-process bridge --------------------------- New `AnalyticsService.captureSafety()` skips the consent re-check and posts via posthog-node with installationId as distinct_id. Wired into: - `POST /api/observability/event` for desktop main and any future helper process that needs to ship a safety event (no consent check — same contract as web's direct-fetch path) - `process.on('uncaughtException')` / `unhandledRejection` on the daemon itself Stable installationId across reinstalls (critical for 0.8.0 rollout) -------------------------------------------------------------------- installationId previously lived in `<namespace>/data/app-config.json`, so a packaged reinstall that churned the namespace token (or any future namespace-scoped data wipe) rotated the id and the user showed up as a brand-new PostHog person. This is the immediate trigger: when 0.8.0 ships, every 0.7.x user upgrading would silently double the user count. New module `apps/daemon/src/installation.ts` reads/writes `<installationDir>/installation.json` at the channel root. The daemon gets the path from `OD_INSTALLATION_DIR`, set by `apps/packaged/src/sidecars.ts` to `paths.installationRoot` (one level above `namespaces/` — e.g. `~/Library/Application Support/Open Design Nightly/` on mac). `readAppConfig` transparently merges: if installation.json has an id it wins; if only app-config.json has one (the 0.7.x state), it gets mirrored to installation.json on the next read. `writeAppConfig` mirrors any explicit installationId write, including the null-clear path used by Settings → "Delete my data". 7 call sites of readAppConfig keep their signatures unchanged. Survives: - same-channel reinstall (DMG drag-replace, NSIS reinstall) - namespace churn between packaged builds - per-namespace data reset (future installer that clears `<ns>/data/`) Still rotates (intentionally): - explicit "Delete my data" - manual `rm -rf "~/Library/Application Support/Open Design <Channel>/"` - different channel (Stable vs Nightly stay distinct because userData paths differ; that's the existing channel-isolation contract) What this changes for posthog-js -------------------------------- client.ts had `capture_exceptions: false` from #2521; nothing else changes. autocapture / $pageview / $autocapture / track() / daemon analyticsService.capture() — all unchanged. New events are additive. Validation ---------- - pnpm guard pass - pnpm typecheck whole repo pass - pnpm --filter @open-design/web test 200 files / 1824 tests - pnpm --filter @open-design/daemon test 251 files / 2981 tests (includes 10 new tests in installation.test.ts pinning the 0.7.x → 0.8.0 migration, namespace-wipe survival, delete-my-data clear, and fresh-id rotation) - pnpm --filter @open-design/packaged test 9 files / 89 tests - Pre-existing baseline: apps/desktop/src/main/updater.ts has typecheck references to RELEASE_CHANNEL_NAMES.PREVIEW/NIGHTLY on release/v0.8.0; unrelated to this PR. * fix(observability): preserve fatal exit on uncaught + skip loading shell in white-screen check Addresses codex review on PR #2527 (Siri-Ray). 1) Daemon process handlers must keep Node fatal semantics Installing an uncaughtException listener silences Node's default crash/exit; Node 15+ does the same for unhandledRejection when a listener is present. The previous handlers logged telemetry and let control return to the event loop, leaving a corrupted daemon serving requests instead of letting the supervisor restart it cleanly. triggerFatalShutdown() now: - dispatches captureSafety once (guarded against re-entry from cascading faults) - races posthog-node's shutdown against a 1s bounded timeout so a slow flush can't keep the process alive - calls process.exit(1) after the race resolves Both uncaughtException and unhandledRejection route through it. apps/daemon/tests/uncaught-fatal-shutdown.test.ts pins: - captureSafety is invoked exactly once even on repeated faults - exit(1) fires on the happy path - exit(1) still fires when shutdown hangs past the timeout - exit(1) still fires when captureSafety itself throws 2) White-screen detector treated the loading shell as a successful mount apps/web/app/[[...slug]]/client-app.tsx renders the dynamic-import fallback as <div class="od-loading-shell">Loading Open Design…</div> whose visible text (19 chars) exceeded the previous 10-char floor. monitorMount() would therefore cancel the 5s timer the instant Next swapped the loading shell in, completely missing the white-screen signal the observer is meant to add. isAppMounted() now: - primary signal: <html data-od-app-mounted="1"> set by App.tsx's first useEffect — authoritative because once App has mounted at least once, any later tree crash is an $exception story, not a white-screen story - fallback: only counts children of the root container whose classList does NOT include known loading-shell markers (od-loading-shell). Their visible text drives the > MIN_VISIBLE_TEXT check, so the loading sentinel can never be mistaken for a mount. apps/web/tests/observability/white-screen.test.ts pins: - fires client_white_screen when only the loading shell is present after the timeout - does NOT fire when data-od-app-mounted is set before the timeout - cancels the timer the moment a real workspace-shell child appears alongside the loading shell - still fires when only sub-MIN_VISIBLE_TEXT non-shell content is present (effectively blank) Validation: - pnpm guard pass - pnpm typecheck pass - pnpm --filter @open-design/daemon test 252 files / 2985 tests - pnpm --filter @open-design/web test 201 files / 1828 tests * fix(observability): await captureSafety enqueue before fatal shutdown flush Addresses second-pass codex review on PR #2527 (Siri-Ray, 3279268246). The previous fatal-shutdown path called `analyticsService.captureSafety()` synchronously and immediately raced `analyticsService.shutdown()` against the bounded timeout. captureSafety in apps/daemon/src/analytics.ts does its real `client.capture()` call only inside an async IIFE after `await readInstallationIdSafe()` — so shutdown could win the race, drain an empty posthog-node queue, and let `process.exit(1)` run BEFORE the daemon crash event ever got enqueued. We'd then preserve the process-lifecycle contract but lose the exact signal this PR is adding. Changes: - AnalyticsService.captureSafety now returns Promise<void>. The async IIFE is gone; the body awaits readInstallationIdSafe directly so the returned promise resolves only AFTER client.capture() has been invoked (which is when posthog-node's local buffer contains the event). - server.ts triggerFatalShutdown awaits captureSafety, then calls shutdown, and races that whole sequence against the 1s bounded timeout. Capture failures still don't block exit (try/catch around the await). - NOOP_SERVICE.captureSafety becomes `async () => undefined` to match the new signature. - Fire-and-forget callers (/api/observability/event) are unaffected; voiding the returned promise keeps them non-blocking. apps/daemon/tests/uncaught-fatal-shutdown.test.ts adds the reviewer- requested fixture: - 'waits for the captureSafety promise to settle before invoking shutdown' — gives capture a 50ms delay and shutdown a separate 50ms delay so the intermediate "capture done / shutdown not yet" state is observable. - 'still aborts and exits if captureSafety hangs past the bounded timeout' — captureSafety never resolves; the outer 1s timeout still forces process.exit(1). Validation: - pnpm guard pass - pnpm typecheck whole repo pass - pnpm --filter @open-design/daemon test 252 files / 2987 tests |
||
|
|
31ca20f2c6 | Add packaged update apply observations (#2429) | ||
|
|
4424f08be0 |
[codex] Add packaged desktop auto-update (#1375)
* Add packaged desktop auto-update * Handle counted beta nightly update versions * Refresh desktop auto-update branch for main * Serialize desktop updater operations * Refresh auto-update branch for packaged paths |
||
|
|
74637f1cb5 |
Add Linux packaged client parity smoke coverage (#1204)
* docs: plan linux client issue 709 * fix: complete linux headless lifecycle routing * feat: add linux packaged inspect * test: add linux headless packaged smoke * ci: add linux headless packaged smoke * ci: smoke linux AppImage release artifacts * docs: document linux packaged client status * chore: finalize linux client audit remediation * docs: add linux client publication packet * test: harden linux client smoke coverage * ci: preserve linux smoke audit evidence * refactor: consolidate linux e2e helpers Move pathExists and the desktop/web/daemon app-key array out of linux.spec.ts into linux-helpers.ts, where expectPathInside and linuxUserHome already live. Keeps the spec file focused on tests and the helpers file as the canonical home for shared Linux e2e utilities. * fix: move linux e2e helpers to lib * fix: address linux release review blockers * fix: drop npm dependency from containerized linux build writeAssembledApp() previously called runNpmInstall() which executed `npm install` directly. Inside the containerized build path, electronuserland/builder:base strips npm/npx/corepack, so the inner tools-pack build would fail at the assembled-app install step. Route the install through OD_TOOLS_PACK_PNPM_BIN: buildDockerArgs sets the env to the standalone pnpm binary it bootstraps, and the new resolveProductionInstallCommand helper consumes that env to run `<bin> install --prod --no-lockfile --config.node-linker=hoisted`. Host invocations with no env set keep the prior npm behavior. --config.node-linker=hoisted preserves the flat node_modules layout that electron-builder packs the same way as npm-installed trees. New tests cover the resolver branches and assert the docker-arg-to- resolver chain end-to-end so reviewers can see the container's inner build receives the env that switches its install away from npm. * fix: harden linux container bootstrap * fix: validate desktop marker liveness in headless cleanup cleanup --headless previously skipped on any parseable desktop-root.json, trapping recovery when the AppImage had crashed and left a stale marker. Validate the marker the same way stopPackedLinuxApp does: if the PID is not in the live snapshot list, proceed through cleanup instead of skipping. Extract the validation into validateDesktopAppImageMarker so the stop and cleanup paths share one definition of live and owned. Tests cover both branches: a stale marker drives cleanup to remove the runtime/output roots, while a live marker drives cleanup to skip and preserve them. |