mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-07 17:04:42 +00:00
8df495b9c7144bbef4ff54d3786b6cfddf6f2321
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
74a7e5803b |
Choose voice providers and local speech models from a Voice settings page (#7295)
* feat(voice): add a Voice settings page with provider choice and a local model catalog Each host gets a Voice page under host settings. Dictation and voice mode each pick a provider (Local or OpenAI) and a model. Provider settings sit in one group of collapsible rows: local speech-to-text and text-to-speech list every catalog model with its size, languages and description before download, and OpenAI takes a write-only API key and an optional base URL. The local catalog grows from Parakeet/Kokoro to Whisper, SenseVoice, Dolphin, GigaAM, Parakeet Japanese, multilingual Kokoro, Kitten and Piper voices. Each entry declares its sherpa engine family, so the recognizer and TTS build the matching model config and the downloader verifies the files that family needs. Kitten v0.8 is left out: it crashes the pinned sherpa-onnx 1.12.28. Voice mode is now opt-in. The default lived only in code (true), never in config.json, so hosts that never toggled it find it off after upgrading. OpenAI speech-to-text resolved one model for both features, with voice mode's choice taking precedence, so dictation silently used voice mode's model. The resolved config now carries a model per feature; STT_MODEL still overrides both. Rows revealed under a collapsible settings row are a nested density level set by the container: tighter padding, smaller text, and xs controls, with controls taking their size from the row instead of each caller. * test(app): pre-bundle the JSX dev runtime for browser tests Compiling test JSX with the automatic runtime imports react/jsx-dev-runtime. Vite discovered it mid-run on a cold cache and reloaded the page, which failed the first browser test file to import it. * refactor(voice): keep speech provider settings at each use site Store credentials and endpoint options beside the speech feature that consumes them so saved page values cannot be shadowed by a separate provider block. Normalize existing config on load and mirror the inline shape on config reads and patches. This is the config, resolver and wire phase; the provider sheet follows separately. * fix(voice): preserve saved keys when resaving provider settings Forms send the selected provider on each save but cannot read back its API key. Merge patches for the existing provider so these saves retain credentials; replace the site only when the provider changes. * feat(voice): configure each speech use site from a provider sheet The Voice page now lists Speech-to-text, Listening and Speaking as one-line summaries. Tapping one opens a sheet with the provider choice and only that provider's settings: the local catalog (size, languages and description before download, download state per model) or the OpenAI key, base URL, model and language or voice. The sheet's form model sends only the fields the user changed, so re-saving never clears a saved key. Fields an env var decides are read-only with a "Set by" hint; the API key and base URL stay editable because a saved value wins over the env fallback. Save failures show a toast and keep the sheet open with the input. E2E daemons pin speech providers through env vars to avoid model downloads, so the browser spec covers the locked-provider path, the key fallback and the failed save; provider switching is covered by the form model tests. * refactor(voice): press settings and catalog rows through PressHighlight Settings rows that lead somewhere and local model rows now use the standard row press primitive, so native shows the finger-down flash the rest of the app's rows have. Web hover and press styling are unchanged. * fix(voice): preserve STT language for local providers Language belongs to every STT use site. Preserve legacy local language settings through config loading and saving, resolve them without provider gating, and expose them in the provider form. |
||
|
|
e1c769c018 |
Make password-protected daemons work across local and remote connections (#5393)
* feat(auth): authenticate daemon clients through hello Give local CLI and desktop clients a per-run credential while remote clients send the host password inside the protocol. Keep relay passwordless admission for this mobile release so existing saved hosts keep working until the follow-up enforcement release. Move password recovery for saved hosts into host settings and keep pairing credentials in the add flow. Include isolated web QA evidence for both flows. * fix(auth): preserve Hub bootstrap and local credential expectations Hub-owned sockets already carry admission; keep their hello handling synchronous through session bootstrap while resolving credentials asynchronously for ordinary sockets. Keep the resolver out of lightweight configuration imports. Update CLI expectations for same-home credentials, let a rejected connection yield to another usable connection, and clear pairing secrets when add-flow targets change. * fix(pairing): retain passwords across edits to the same target Track the last valid pairing host while a URI is edited. This preserves an entered password for whitespace and partial edits but clears it when a different host becomes the target. * test(auth): align local credential checks across platforms Expect the CLI to authenticate through the credential in its selected home, and verify POSIX file modes only where Node exposes them. * feat(app): move host password into a settings row with a modal The host page rendered an always-visible password form above Name on every host. Replace it with a Password row under a Security section below Appearance; tapping it opens a modal with Save and, when a password is saved, Clear. The connection-error callout keeps its guidance and gains a Set password button that opens the same modal. Drop the unused pairing.hostPassword body/reopen/saveError strings. * chore: remove committed QA screenshots QA evidence stays out of the repository; the PR body describes it in words. * feat(app): keep the host password out of the host page The saved password is connection data, entered only when a host is added. A Password setting on the host page reads as the daemon's own password, so the row, modal, and callout button are gone. A rejected host shows the daemon's reason with guidance to remove the host and add it again with the password. useHostMutations no longer exposes setHostPassword; relay imports still set it inside the runtime. * feat(app): show host connection errors in an error alert HostConnectionError renders the existing Alert with the connection error as its title. Auth rejections add the re-add guidance as the description; other errors show the title only. The Overview and Connections pages share it. * style(app): soften alert borders to half-opacity accent * feat(app): size alerts on the button scale Alert takes a size prop (xs/sm/md/lg, default md) whose geometry lives next to the button's in control-geometry: one font size for title and description, the button icon size centered on the first text line, button padding and radius, and a one-line alert as tall as the button of the same size. Consumers pick sm among settings rows, cards, panels, and modals, and md when the alert is the whole page or sheet state. * style(app): roomier, rounder alerts with a tight title block Alert sm padding returns to the original 12/16 and every size is at least borderRadius.xl. Title and description sit a small gap apart with no line height override. The icon slot carries a zero-width text strut in the alert's font so the icon centers on the first line for titled, title-only, and description-only alerts. * refactor(app): align the alert icon with a centered lead row Drop the zero-width strut. The icon and the alert's first text (title, else description) share one row centered on each other; the description and actions sit below, indented by the icon slot width plus gap so they start at the lead text's left edge. * refactor(app): drop the unused Alert icon override |
||
|
|
4c6b79dc44 |
feat(app): refine agent profile creation (#3680)
Keep profiles as the richer primitive while restoring the familiar star cue and clearer guidance for agent selection. Account for borders in shared field geometry so controls preserve their declared heights across form consumers. |
||
|
|
5ec26f0c09 |
feat(app): align interface typography to base size
Treat the appearance setting as the rendered base size so the type ramp scales predictably. Native starts one pixel larger while web and desktop preserve the authored 14px base, with legacy values migrated on load. |
||
|
|
ac6a0afdc7 |
fix(app): calm the segmented control's selected segment
The selected segment was an inverted fill — theme foreground behind surface0 text — which in dark mode dropped a white slab into thin chrome like the file toolbar, and the fully rounded corners made it read as a lozenge rather than a tab. It now uses a surface3 fill with foreground text, and each segment takes the corner radius of the button at its size tier. Segments also drop one padding step below the equivalent button. The gap between segments already supplies the visual padding, so matching button padding made the track wider than it needed to be and ate the breathing room around it in a 32px toolbar row. Selection changes colour only. No weight or size change, so labels never reflow as you switch segments. Carries the buttonControlHeight extraction that was already sitting in control-geometry.ts, since the two files could not be split apart cleanly for this commit. Its callers stay uncommitted. |
||
|
|
4bda2dfea9 |
Edit workspace files directly on web (#2270)
* feat(files): edit workspace files on web Keep source buffers synchronized with host file changes and require an explicit overwrite or reload when revisions diverge. * feat(panels): surface and protect modified tabs Expose tooltip and modification state through the generic panel boundary so tabs can show stable metadata and guard every close route consistently. * fix(tests): use portable fake timeout handle * fix(files): harden editor conflict handling Preserve modified panel state across tab eviction, use precise revisions for optimistic writes, coalesce concurrent file watchers, and localize the editor interface. * fix(files): close editor concurrency gaps Coalesce clean reloads, preserve subscriber identities and file permissions, suspend pending saves during close confirmation, and carry precise revisions through file reads. * test(files): expect read revision metadata |
||
|
|
d9b65e269f |
Scheduled runs each get their own workspace in the sidebar (#1934)
* feat(schedules): per-run workspaces, isolation and archive controls Scheduled agents never appeared in the sidebar: each schedule reused one stamped workspace and archived the run's agent on completion. Now every run mints its own workspace — the entity the sidebar shows — with per-schedule controls for isolation (local or worktree) and whether to archive that workspace when the run finishes. The schedule form is rebuilt on a non-React form model (open/commands/close) to end the flicker, edit-into-create contamination, and multi-host hydration bugs that came from effect-choreographed shared state. That lands the reusable foundations it needed: a form kit over a single control-geometry owner, a data-access taxonomy (replica/snapshot/fetch) with real load-state semantics, and lint/boundary guardrails so new screens inherit the paved road. Also fixes desktop combobox popovers truncating options when the trigger is narrower than the content. New schedule protocol fields are optional on both create and update, so old and new clients/daemons stay compatible. * test(app): complete mock themes for control-geometry tokens switch and terminal-profile-edit-modal now style through createControlGeometry, which reads theme.borderWidth[1], theme.opacity[50], and theme.colors.borderAccent. The hand-rolled mock themes in these two suites lacked those tokens, so the eager StyleSheet.create mock threw at import (collection error), not on any assertion. Add the missing tokens. * fix(schedules): address review findings on run cleanup, edit isolation, load error, sheet dismiss, and preference hydration - Server: archive the run's workspace even when agent creation fails, so a misconfigured provider no longer orphans a sidebar workspace/worktree. - Edit form: keep a stored worktree isolation while worktree eligibility is still resolving, instead of silently downgrading a saved schedule to local. - Schedules screen: show the load error/retry UI when every host fails, rather than spinning forever behind the loading branch. - Form sheet: fire the parent onClose on native gesture/backdrop dismiss so the sheet closes instead of re-opening. - Form model: apply late-loading saved preferences to untouched create-mode fields (never to edited schedules or user-modified fields). * fix(schedules): review batch — reconnect resubscribe, worktree prune, Android dismiss, cadence and provider edit safety - Push-router: re-send terminal and checkout-diff subscriptions after a reconnect; the old per-hook effect resubscribed on isConnected and the extracted router did not, so daemon restarts silently stopped terminals_changed pushes (root cause of the terminal-activity e2e failures). - Server: pass the run's source repo root when archiving worktree runs so the worktree is unregistered (git worktree remove/prune), not just deleted; also archive the workspace when agent creation fails even with archive-off (an agentless workspace has nothing to inspect). - Sheet: RN Modal onDismiss is iOS-only — notify dismiss once-per-close on the Android native path too; replace the JSDOM component test with a real Playwright dismiss spec and inline the trivial dismiss decision. - Form model: editing an interval schedule no longer rewrites its cadence to cron unless the cadence UI is touched (90-minute intervals have no cron equivalent); switching projects clears stale provider/model state and gates submit until the new host's snapshot resolves. * chore(lint): drop custom lint wrapper and boundary script, plain oxlint The import bans stay in .oxlintrc.json (oxlint-native no-restricted-imports). The receiver-sensitive checks the custom script enforced are not worth a parallel lint pipeline; if they come back it will be as oxlint rules. * fix(schedules): crash-safe run cleanup, capability-gated run options, resilient mutations - Persist the run's workspace/agent ids on the running-run record so a daemon crash mid-run can be recovered: restart archives the interrupted run's workspace under the same policy as normal cleanup (agentless always archives, otherwise archiveOnFinish is respected). - Hide Archive on finish (and omit archiveOnFinish/isolation from payloads) on hosts without workspaceMultiplicity — an old daemon ignores the fields, so offering the switch there would lie. - Optimistic pause/resume/delete no longer throw when the schedules cache holds a still-connecting entry alongside loaded data. - Mode field is gated on provider mode options, not a selected model, so model-less providers can pick their advertised modes. |