119 Commits
Author SHA1 Message Date
Mohamed Boudra 3e59adb4dc Add Claude Fable 5.1 to the model catalog (#4179)
* feat(claude): add Fable 5.1 model

Expose the new 1M-context model through the curated Claude catalog and normalize its dated and context-suffixed runtime IDs back to one canonical entry.

* fix(claude): group Fable models in catalog

* chore(release): cut 0.7.1

* fix(nix): refresh 0.7.1 dependency hash

* test(cli): follow package version in plugin scaffold

* test(cli): keep Claude catalog checks extensible
2026-09-01 21:51:51 +02:00
Mohamed Boudra dd5e8f95b1 Fix graceful daemon shutdown on Windows (#4168)
* test(server): probe supervised Windows cleanup

* test(server): report both cleanup failures

* fix(server): gracefully stop supervised workers
2026-09-01 19:59:03 +02:00
Mohamed Boudra a8734a9724 Update project licensing (#3944) 2026-08-27 14:25:31 +02:00
Mohamed Boudra ecfb77b014 feat(plugins): install and update Git sources (#3920)
Make every trusted Git repository directly distributable without introducing a registry or package manager. Managed checkouts retain their resolved commit, track branches explicitly, and stage validation before activation so failed updates restore the running version.
2026-08-27 15:24:01 +08:00
Mohamed Boudra 4748aad103 Reload daemon configuration without restarting (#3365)
* feat(daemon): reload configuration without restarting

Keep config validation, reloadability classification, override handling, and atomic runtime application inside the daemon so local and remote clients share one authoritative workflow.

* fix(daemon): preserve reload resource ownership

Keep every materialized provider client under daemon-lifetime ownership and classify speech overrides from resolved providers. Restore the complete WebSocket config-store test contract exposed by CI.
2026-08-14 22:46:32 +02:00
Mohamed Boudra 23853a1515 Add managed local plugin lifecycle (#3222)
* feat(plugins): add local plugin surfaces and RPCs

Keep plugin execution scoped to its daemon while allowing one local TypeScript entry point to contribute validated RPCs and native client surfaces. Paseo owns host selection, navigation chrome, and per-installation query caches.

* feat(plugins): add Linear attachment source

* fix(nix): refresh npm dependency hash

* test(server): exclude internal sessions from Hub counts

* test(server): distinguish Hub execution sessions

* feat(plugins): make local plugins explicitly opt-in

Keep plugin loading dormant until configuration enables it, and collect unsupported examples under one directory.

* refactor(plugins): establish host boundaries

* fix(nix): refresh plugin dependency hash

* fix(plugins): complete packaging and startup rollback

* feat(plugins): add managed local lifecycle

Make trusted local plugins recoverable and authorable through daemon-owned lifecycle operations, host settings, and a capability-gated CLI. Reloads fully stop the previous plugin before starting new code, while generated projects provide strict TSX checking without changing runtime dependency ownership.

* fix(nix): refresh plugin dependency hash
2026-08-14 17:12:49 +02:00
Mohamed Boudra 599846650c Stabilize live relay status coverage (#3337)
* test(cli): stabilize live relay status coverage

The regression fixture deleted the supervisor's active PID lock to model a reachable daemon without local process state. Under CI load, worker readiness could race that deletion and make the supervisor tear down the daemon while status and pairing were probing it.\n\nLaunch the real worker directly so the no-PID state exists naturally, then wait on the CLI-visible live relay state before asserting behavior.

* test(cli): wait for complete relay probe state

Status readiness alone does not guarantee the next pairing RPC or the foreign-home identity probe will finish inside the CLI's per-call timeout under CI contention. Retry each exact observable outcome within the fixture deadline and resolve the real worker entry through the server package.

* test(cli): name retry mechanics once

Keep the relay scenarios expressed as CLI probes and exact outcomes while one file-local helper owns the shared deadline, worker-liveness check, and retry cadence.
2026-08-13 23:10:28 +02:00
Mohamed Boudra d012b6f071 Help agents diagnose Paseo provider problems (#3243)
* feat(skills): add Paseo help and provider diagnostics

Give support agents a topology-aware troubleshooting entry point backed by the deployed documentation index, and expose the daemon provider diagnostic through the CLI so agents can inspect the affected host directly. Agent-launching skills now use configured profiles instead of the removed orchestration preferences.

* test(cli): keep provider diagnostics on real boundaries

Remove the internal client mock and preserve its normalization and host-targeting assertions through the existing isolated-daemon coverage.
2026-08-12 00:57:33 +02:00
Martin HanzíkandClaude Opus 5 a39959219f feat: Implement workspace rename cli (#3209)
* feat(cli): add workspace rename command

`paseo workspace rename <workspace-id> <title>` sets a workspace's
user-visible title through the existing workspace.title.set RPC, and
`--reset` clears the override so the name reverts to the branch or
directory. The command reads the descriptor back so the output shows
what a reset reverted to.

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

* fix(cli): harden workspace rename against read-back and arg failures

Review findings on the rename command:

- A failed workspace list sweep after a successful title change reported
  the whole command as failed. The read-back is display-only, so it now
  runs outside the mutation's error path and degrades to a null name.
- Only --reset needs the descriptor read back; a set title is already the
  resolved display name, so the common path no longer pages the list.
- Dropped the `"code" in error` rethrow. Nothing in that block throws a
  CommandError, but DaemonRpcError always carries a `code` property even
  when it is undefined, so the guard let those through to render as
  UNKNOWN_ERROR with a stack instead of WORKSPACE_RENAME_FAILED.
- Commander 12 allows excess positionals, so an unquoted multi-word title
  renamed to its first word and dropped the rest. The command now rejects
  excess arguments.

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

* refactor(cli): report the rename RPC response instead of reading back

Reading the descriptor back to show what --reset reverted to was the only
reason rename needed a paged workspace sweep, and that sweep dragged in
everything around it: a failure path that could report an applied rename
as failed, a nullable name, and a bespoke warning sink to tell the two
null cases apart.

Sibling commands don't do this. `workspace archive`, `agent mode`, and
`schedule update` all report what the RPC returned and stop; the one
command that reads back is `agent update`, which has the same "applied
but reported as failed" bug. So rename now mirrors `workspace archive`.

`--reset` reports `title: null` rather than naming what it reverted to;
`paseo workspace ls` shows the resolved name. This also reverts the
`collectWorkspaces` extraction, whose only second caller was rename.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 16:36:58 +00:00
Mohamed Boudra 94bda1f925 Remove chat rooms and agent loops before storage migration (#3053)
* refactor(storage): remove chat rooms and agent loops

This is the prerequisite cleanup for the storage backend migration. Legacy wire schemas remain temporarily so mixed-version peers can still parse old messages, while daemon callers now use query-shaped AgentStorage methods that can map directly to SQL later.

* test(cli): remove retired chat and loop coverage
2026-08-10 21:06:47 +02:00
Mohamed Boudra 05a0cabc07 Deploy multi-file Hub workflows (#3128)
* feat(hub): deploy canonical workflow bundles

Keep CLI deployment aligned with Hub's authored bundle boundary so validation and activation receive the same deterministic source files. Public documentation now teaches that boundary as the only configuration format.

* test(hub): assert validation diagnostics directly

* refactor(hub): deepen HTTP client module

* feat(hub): validate named agent configurations

* docs(hub): align Claude mode example
2026-08-10 12:32:59 +02:00
Mohamed Boudra f2054cc701 Preserve Claude model and thinking preferences (#2912)
* fix(agents): preserve Claude thinking selections

Model switches now resolve thinking against the target model's saved preference instead of resetting to the catalog default. Claude owns its configured-model defaults and legacy Fable alias handling, while persisted permission modes remain unchanged.

* chore(claude): tag Fable compatibility shim

* fix(app): resolve persisted model aliases

* fix(models): preserve aliases for older clients

* fix(models): hide compatibility aliases from listings

* fix(settings): hide compatibility model aliases

* test(claude): cover legacy catalog entry

* test(app): expect mock thinking controls in schedules

* fix(app): preserve queued thinking preferences

* fix(app): reconcile schedule provider snapshots

* fix(app): preserve schedule model selections

* fix(claude): preserve exact configured model ids

* fix(app): preserve committed thinking preferences

* fix(app): preserve aliased schedule thinking
2026-08-06 11:33:18 +02:00
Mohamed Boudra 5a30affd7f Skip unrelated required checks without losing their names (#2542)
* fix(ci): skip unrelated required checks cleanly

Matrix jobs had to start no-op runners to preserve interpolated required-check names. Static named jobs let GitHub report genuine skipped conclusions while keeping those names stable.

* fix(ci): gate changes to install patching script

* fix(ci): route cross-package test contracts narrowly

* fix(ci): keep routed contracts merge-blocking

* fix(server): exclude nested test utilities from builds

* fix(ci): cover app-owned native and browser domains

* refactor(ci): align tests with runtime domains

Own browser specs, desktop specs, and Electron-only app code by stable directories so PR routing does not depend on filename conventions. Keep desktop integration coverage inside the required desktop check.

* fix(ci): keep routing and desktop suites isolated

The routing regression must run before dependency installation, and desktop Vitest must not collect Playwright-owned specs.

* fix(ci): isolate desktop e2e runtime

* perf(test): isolate Playwright workers

* perf(test): parallelize Playwright within specs

* fix(test): keep Playwright file scheduling

* fix(test): share dynamic Metro fixture

* fix(test): preserve own-host restart fixtures

* fix(ci): preserve routed contracts after rebase

* Stabilize Playwright wheel-scroll assertions
2026-08-02 00:56:05 +08:00
Shintaro Sakata a54cb66bf6 fix(nix): keep runtime mode out of agent environment (#2697) 2026-07-31 23:29:02 +02:00
Mohamed Boudra d2de309fc3 Make relay opt-in when pairing devices (#2706)
* feat: make relay opt-in for device pairing

* fix(relay): keep pairing state authoritative

* fix(relay): refresh pairing state across transports

* fix(onboard): honor explicit relay opt-out

* fix(relay): surface transport startup failures

* fix(pairing): gate offers for older daemons

* test(cli): rely on real pairing transport coverage

* fix(cli): report live relay without a pid file

* fix(relay): synchronize config during daemon startup

* fix(relay): preserve mutability for ignored overrides

* fix(cli): use reachable daemon for pairing

* fix(app): redirect invalid pair device routes

* fix(pairing): support remote host device pairing

Keep Pair Device host-relative through the existing settings and daemon RPC flow. Route CLI output through an injected adapter so workflow tests do not mutate process globals.

* fix(pairing): validate pairing destinations

Expose the host-relative Pair Device flow on every supported app platform. Reject a reachable daemon whose identity does not match the requested Paseo home before reading or mutating its pairing state.

* fix(pairing): render QR codes across platforms

Generate SVG text without DOM or canvas and render it through the existing cross-platform SVG stack.

* fix(cli): pair from persisted relay state

Allow explicit relay pairing while the daemon is stopped when relay is already enabled in persisted configuration.
2026-08-01 04:35:06 +08:00
Mohamed Boudra 963d4f9240 Configure agent thinking from the CLI (#2533)
* feat(cli): update agent thinking from the CLI

* fix(cli): harden agent thinking updates

* feat(cli): configure thinking for schedules

* fix(cli): report applied thinking updates

* fix(cli): report current agent thinking state
2026-07-28 22:30:50 +08:00
Mohamed Boudra f91a984348 fix(claude): show a single 1M-context Opus 5 model (#2497) 2026-07-28 18:18:21 +08:00
Mohamed Boudra c9fb31f709 Fix Claude 5 context window selection (#2433)
* fix(claude): select the correct Opus 5 context window

Bare Opus 5 IDs resolve to 200K behind third-party gateways. Expose explicit context variants and require a Claude Code version that recognizes the model.

* fix(claude): add Fable and Sonnet context variants

* test(cli): expect Claude context variants

* test(cli): compose Claude catalog expectations

* fix(claude): preserve catalog on version probe failure

* fix(claude): preserve parsed context variants

* chore(release): cut 0.2.2
2026-07-26 10:03:44 +02:00
维她命@ 51ab86bab6 test(cli): include Opus 5 in provider expectations (#2425) 2026-07-25 20:45:55 +02:00
Mohamed Boudra 967edab497 Connect daemons to Hub through browser approval (#2208)
* feat(cli): connect daemons to Hub through browser approval

Let interactive setup complete through a short-lived browser authorization while preserving --token for automation and existing integrations.

* ci: build server before CLI tests

* fix(cli): keep Hub approval polling within expiry

Bound both response headers and body consumption to the original authorization lifetime so stalled responses remain retryable without extending approval. Run the CLI test helper through Node and the resolved tsx entry for cross-platform behavior.

* fix(cli): bound Hub registration startup

Fail a stalled authorization start within a fixed timeout without retrying the non-idempotent request. Declare the response validator as a direct CLI runtime dependency.

* fix(cli): restrict Hub activation URLs

* fix(cli): harden Hub approval transport
2026-07-24 21:10:21 +08:00
Mohamed Boudra 246c07fba5 fix(cli): make new workspace creation explicit (#2315)
Agent callers now stay in their current workspace unless --new-workspace explicitly requests a separate local or worktree workspace.
2026-07-22 18:26:40 +08:00
Mohamed Boudra ffe76a7e57 Make workspace, agent, and schedule automation consistent (#2186)
* feat(workspaces): align agent and schedule automation

Make workspace identity the shared placement boundary for MCP and CLI, while caller identity determines parentage. Keep heartbeats minimal and cron-based without changing legacy rolling interval semantics.

* test(cli): expect canonical schedule cadence

* fix(automation): preserve workspace and schedule compatibility

* fix(automation): preserve compatibility edges

* fix(workspaces): align MCP lifecycle resolution

* fix(workspaces): preserve creation intent

* fix(workspaces): preserve branch and schedule identity
2026-07-18 14:04:48 +02:00
Mohamed Boudra f41dde8c72 chore(release): sync Sonnet 5 stable release to main 2026-07-01 22:36:37 +02:00
Mohamed Boudra df36a958f8 Make daemon status report health without loading agents (#1810)
* fix(cli): avoid agent inventory in daemon status

* fix(cli): keep daemon status reachable on detail failure
2026-06-29 20:40:11 +00:00
Mohamed Boudra e63a971968 Make daemon shutdowns easier to diagnose (#1790)
* fix(daemon): log stop reasons and client identity

Record websocket client identity, process memory/uptime, and shutdown reasons across CLI, desktop, supervisor, and worker paths so daemon drops can be traced from the triggering client to worker termination.

* fix(daemon): keep shutdown diagnostics in sync

Test drift: supervisor and relay tests still asserted the old log text and metadata shape after shutdown diagnostics started logging structured reasons and relay connection ids. Update those assertions to the new diagnostic contract.

Also centralize client lifecycle reason normalization and derive desktop daemon stop reasons from one tuple so future changes cannot silently drift.
2026-06-29 23:31:11 +08:00
Mohamed Boudra c00121273b Fix Windows daemon status output (#1725) 2026-06-25 19:17:02 +08:00
56b1def06e Add Claude Fable 5 to the model catalog (#1443)
* Add Claude Fable 5 to the model catalog

Fable 5 (`claude-fable-5`) is the new top-tier Claude model above Opus,
but the Claude provider's model list is hardcoded in `CLAUDE_MODELS` and
was not fetched dynamically, so it never appeared in the selector.

- Add `claude-fable-5` to `CLAUDE_MODELS` (non-default; Opus 4.8 stays the
  default). Uses the Opus extended-thinking effort levels (low/medium/high/
  xhigh/max). No `[1m]` variant: Fable 5 is natively 1M context, unlike the
  Opus/Sonnet entries whose `[1m]` opts a 200K-default model into 1M.
- Teach `normalizeClaudeRuntimeModelId` the Fable family. Its version is a
  single segment (`fable-5`) rather than the `{major}-{minor}` scheme, so it
  needs its own match to map dated runtime IDs back to the catalog ID.
- Update the model-list and normalization test expectations, plus the CLI
  provider e2e catalog fixture.

Fast Mode is correctly unaffected — its allowlist is Opus 4.6/4.7/4.8 only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Simplify Fable runtime-ID normalization

Drop the unused `[1m]` capture from the Fable match branch. There is no
`claude-fable-5[1m]` catalog entry — Fable 5 is natively 1M context, so
there is no 200K-default model to opt into 1M — which made that path dead
code (and an untested one). Keep the `[-_ ]+` separator class for
consistency with the sibling opus/sonnet/haiku regex right below it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: lumingjun <lumingjun@bytedance.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 14:48:50 +08:00
Mohamed Boudra b04ff0e6b8 Restore global agent listing (#1420) 2026-06-08 23:53:54 +08:00
Mohamed Boudra a1fbc91163 Add OMP as a built-in importable provider (#1388)
* Support imports from Pi-compatible providers

* Add OMP as a built-in provider

* Address Pi session scanner review

* Restore Pi session import discovery

* Update provider test for disabled OMP
2026-06-08 08:17:57 +00:00
Mohamed Boudra 893e3376b0 Recover stale supervised daemons
Teach daemon stop to use lifecycle shutdown when the API is reachable even if the owner pid is stale, then wait for the API to disappear and clean the stale pidfile.

Launch desktop-managed daemons detached from desktop stdio, preserve stale reachable daemon ownership for version checks, and allow desktop stop/restart to use the CLI recovery path.

Add supervisor heartbeats so supervised workers shut down when their supervisor disappears instead of surviving as orphaned reachable daemons.
2026-06-07 23:18:48 +07:00
Mohamed Boudra 9b21ccd7f1 Report daemon auth failures in status 2026-06-05 23:03:32 +07:00
Mohamed Boudra 04fb0f9b82 Keep local voice memory out of the daemon (#1217)
* Move local speech work out of daemon

Run local speech models in a lazily spawned worker so native model memory and blocking synthesis/transcription work stay out of the daemon process. The worker exits after idle time so local speech RSS can be reclaimed.

* Update supervisor stop test for process title
2026-05-29 13:27:28 +08:00
Mohamed Boudra 0170eba233 Add Opus 4.8 to the Claude model picker
Opus 4.8 (and its 1M-context variant) become the default Claude
models, pushing Opus 4.6 off the default slot. Opus 4.7 stays in
the list as the previous release.
2026-05-29 00:03:39 +07:00
Mohamed Boudra 53c14d9855 Extract client SDK package (#1052)
* Extract client SDK package

* Polish SDK client identity defaults

* Build client before dependent CI jobs

* Restore daemon client server export

* Extract protocol and client SDK packages

* Fix provider override schema validation

* Fix app test daemon client imports

* Simplify workspace build targets

* Fix CLI test server build bootstrap

* Run SDK package tests in CI

* Fix rebase package split drift

* Restore lockfile registry metadata

* Update SDK config test for prompt default

* Move terminal stream router test to client package

* Fix rebase drift for protocol imports

* Fix SDK agent capability fixture

* Restore legacy server client exports

* Fix server export compatibility test

* Advertise custom mode icon client capability

* Remove server daemon-client exports

* Format rebased mode control import

* Fix rebase drift for protocol imports

Files added by upstream PRs (#893, #1147, #1154) referenced the pre-split
shared/ paths that this branch moves into @getpaseo/protocol. Redirect
those imports to the protocol package so typecheck stays green after the
rebase.
2026-05-28 01:58:18 +08:00
Mohamed Boudra a2d8ce07d6 Stop OpenCode probes from creating empty sessions (#1079)
* Avoid empty OpenCode sessions during metadata probes

* Stabilize supervised restart regression test
2026-05-18 09:58:34 +08:00
mehmet turac 675817f0b2 fix(cli): mention remote daemon host on ls connect failure (#1043) 2026-05-16 05:12:49 +00:00
Mohamed Boudra e4acd6cb7a refactor(server): extract task document persistence (#883)
* refactor(server): extract task document persistence

* test(cli): wait for loop list visibility
2026-05-10 08:23:38 +00:00
Mohamed Boudra 4c11f7c40b test(cli): add Sonnet 4.6 1M to provider models expectation
CLI provider e2e test (15-provider.test.ts) pinned the claude catalog
size; PR #799 added claude-sonnet-4-6[1m] but did not update this list.
Sibling fix to 50405c3b.
2026-05-07 20:04:52 +07:00
Mohamed Boudra faf664d803 Fix desktop CLI passthrough tty handling (#791)
* Fix desktop CLI passthrough tty handling

* Fix desktop daemon manager test drift

* Update daemon stop test after main merge

* test(cli): isolate npx cache per CLI test
2026-05-07 15:14:18 +08:00
Mohamed Boudraandgithub-actions[bot] 80bdb4d45b Use tree-kill for daemon shutdown (#788)
* Use tree-kill for daemon shutdown

* fix: update lockfile signatures and Nix hash

* Use tree-kill for daemon shutdown

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-05-07 13:18:39 +08:00
Mohamed Boudra 55ec13f153 fix(cli): honor PASEO_PASSWORD env var (fix #776) (#782)
* fix(cli): honor PASEO_PASSWORD env var (fix #776)

The CLI only extracted passwords from `tcp://host?password=` URIs, so
`PASEO_PASSWORD=xxxx paseo ls` connected without auth and was rejected
by the daemon with "Password required". Fall back to the env var when
the host (TCP or otherwise) carries no password.

* docs: document PASEO_PASSWORD env var as a CLI auth source

Pairs with the CLI fix in this branch — the "Connecting with a password"
section now lists both the tcp URI query and the env-var fallback, with
their precedence. Also clarify the dual role (daemon vs CLI) of
PASEO_PASSWORD in the env var reference.
2026-05-06 23:22:22 +08:00
Mohamed Boudra b92fb9392e fix(cli-tests): prepend root node_modules/.bin to PATH in test runner (#737)
When npm runs a workspace script, it only adds the workspace-local
node_modules/.bin to PATH. packages/cli/node_modules/.bin doesn't exist
because all packages are hoisted to the root. This caused `npx paseo`
inside test files to miss the local binary and fall back to the npm
registry, where a stale npx cache entry for @getpaseo/cli was missing
bin/paseo — failing the chmod with ENOENT and exiting 254.

07-agent-stop was the first test in shard 2/3 to call `npx paseo` without
spinning up a daemon first, so it reliably hit the broken cache path.

Fix: prepend root/node_modules/.bin to PATH in the spawn env for each
test subprocess.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 8d3946c36c perf(cli): run CLI E2E tests in parallel (#708)
* perf(cli): run E2E tests in parallel via worker pool

The custom CLI test runner ran 35 tsx test files sequentially, making the
cli-tests CI job the longest in main CI (~17 minutes). Each test file
already isolates its own daemon (ephemeral port + tmp PASEO_HOME), so
parallelism was just gated by the runner.

Replace the sequential recursion with a fixed-size worker pool (default
concurrency=4 to match GitHub Actions standard runners; override via
PASEO_CLI_TEST_CONCURRENCY). Buffer per-test stdout/stderr and flush as
a contiguous block on completion so concurrent output stays readable,
and report per-test wall clock plus the five slowest tests.

Local wall clock drops from ~12-15 minutes serial to ~2:49 with
concurrency=4. The slowest single test (05-agent-run, 49s) is now the
floor; CI should land near 4-5 minutes.

* fix(cli-tests): deflake 30-chat under load and shard CI across 3 runners

`chat wait` reads the latest message id and then subscribes for newer
messages. Under CI load the subprocess takes >1s to bootstrap, so the
old test's 250ms head start before posting "second message" raced
against that read. When the post landed first, the subprocess saw the
second message as latest and timed out waiting for a newer one. Replace
the brittle delay with a post-and-race loop: every iteration posts a
fresh "second message" and races a 250ms tick against the wait promise,
so whichever message lands after the snapshot wakes wait deterministically.

CI was also slower than local (10.3min vs 2.8min). On 4-vCPU GHA
runners, 35 sequential-CPU-time of ~1850s caps wall clock around 8 min
even at concurrency=4. Shard the suite across 3 GHA runners via matrix
strategy. The runner now reads PASEO_CLI_TEST_SHARD/SHARD_TOTAL and
distributes files into buckets — known long-pole tests
(05/06/11/13/14-...) round-robin first so they spread across shards
instead of clustering by their numeric prefixes, then the remainder
fills in the reverse direction to balance light load.

Local run is unchanged (single shard by default). Expected per-shard
wall on CI: ~2:30 + setup ≈ ~4:30 total.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 4b260eb516 fix(cli): update schedule provider/mode error message substring in test
The error message gained a `--mode` mention when the schedule mode flag
landed; the existing CLI integration test still asserted on the old
exact-prefix substring and broke main CI for all PR builds.
2026-05-05 19:56:51 +07:00
Mohamed Boudra 4cd9e76bd2 Remove unnecessary type assertions across codebase
Add oxlint-tsgolint and configure typescript/no-unnecessary-type-assertion
to flag redundant `!` and `as Foo` casts. Type-aware mode is left off by
default to keep `npm run lint` fast; the rule sits configured for when we
turn type-aware on intentionally. Auto-fix removed ~283 redundant casts;
two manual touch-ups: a real tsgolint false positive in split-container.tsx
and a stale ChildProcess import after a double-cast collapsed.
2026-05-05 19:56:26 +07:00
Mohamed Boudra 0cb9da17cd Daemon hardening epic 2026-05-05 18:21:10 +07:00
Mohamed Boudraandgithub-actions[bot] 088a6c14c0 feat: direct TCP URI with SSL toggle and optional password auth (#635)
* feat: direct TCP URI with SSL toggle and optional password auth

Replaces the heuristic-driven direct-connection model with a user-controlled
one. The Add Host dialog now exposes structured Host, Port, "Use SSL", and
masked Password fields that compose the canonical
`tcp://host:port?ssl=true&password=xxx` URI used as the storage form.

The daemon gains optional shared-secret auth: `Authorization: Bearer <pw>` on
HTTP and `Sec-WebSocket-Protocol: paseo.bearer.<pw>` on the WS upgrade
(browser WebSocket can't set custom headers). Configured via config.json
`auth.password` or `PASEO_PASSWORD` env. Off by default — old clients keep
working unchanged.

The `port === 443` heuristic for ws/wss is gone; the explicit `useTls` flag
drives scheme selection at every call site.

* fix: stabilize direct tcp auth ci checks

* fix: restore fetch stub in bootstrap smoke test

* fix(app): collapse Advanced section in add-host modal

* feat(server): hash daemon password in config

* fix: update lockfile signatures and Nix hash

* Improve direct TCP auth failures

* Fix workspace cwd updates after rebase

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-30 22:05:49 +08:00
Mohamed Boudra 30f7842e8f feat(cli): connect via relay using pairing offer URL (#639)
Pass `--host https://app.paseo.sh/#offer=...` (or `PASEO_HOST=...`) to
any CLI command and the connection routes through the relay with E2EE,
the same way the mobile and desktop apps connect. Same `paseo daemon
pair` link the app already accepts — no new pairing flow.

Closes #181
2026-04-30 21:37:51 +08:00
Mohamed Boudra 0daf3c209b test(cli): pass --provider explicitly in schedule create test
Commit d3f9655e removed the implicit 'claude' default for --provider on
schedule create. Test 1 still relied on the default, which fails fast
with MISSING_PROVIDER. Pass --provider claude so the assertion path that
expects target=new-agent:claude continues to hold.
2026-04-26 23:07:01 +07:00
Mohamed Boudra 08fbddae4a test(cli): align disabled-provider expectation with daemon message
Daemon emits 'Provider <id> is disabled' for disabled providers (see
session.ts emitProviderDisabledResponse). The test was asserting the
older 'is not available' phrasing, which never matched the actual
output.
2026-04-26 22:46:32 +07:00