* fix(client): restore provider readiness on mobile
React Native uses an AbortSignal without throwIfAborted. Check aborted with the existing API disposal error so readiness works while preserving cleanup and cancellation.
Co-authored-by: GeorgeR <897457+GeorgeR@users.noreply.github.com>
* test(plugins): run mobile readiness regression in CI
---------
Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
Co-authored-by: GeorgeR <897457+GeorgeR@users.noreply.github.com>
* feat(server): let clients create internal agents
The daemon's own branch-name and commit-message generators run as
internal agents: never persisted, listed, flagged, announced, or seen by
plugin lifecycle hooks. Nothing outside the daemon could ask for one,
because the wire config schema strips `internal` and the agent.create
transform re-pins it. A plugin that runs a one-turn helper per event
therefore left an archived session in History every time.
Add an optional `internal` flag to `create_agent_request` (inherited by
`agent.create.request`), copy it onto the config in the session's create
path, and skip provider session persistence for it like the generators
do. The client SDK forwards the flag on both creation paths and gates it
once on `server_info.features.internalAgents`.
Two daemon paths assumed every agent is public and had to follow:
`resolveAgentIdentifier` now accepts a live agent by exact id, since the
id set it matched against came from listings that exclude internal
agents and left `wait_for_finish` answering "Agent not found"; and
archiving an internal agent now closes it without writing the record
that `registry.applySnapshot` used to leave behind, so `autoArchive`
does not accumulate hidden files on disk.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix(server): keep internal agents whole through failure, archive, and wait
Review follow-ups for internal agents:
- A create that fails after the runtime is registered now closes the
internal agent before rethrowing, so a hidden runtime cannot outlive
the failed request. Public agents keep today's behaviour.
- Archiving an internal agent cascades to attached children like any
parent. cascadeArchiveChildren takes the parent record instead of
reading it back from storage, where an internal agent never is.
- The archived snapshot and last message of an internal agent stay
readable by exact id for ten minutes, so create-then-waitForFinish
returns the finished turn whether the wait lands before or after an
auto-archive. Storage plays that role for public agents.
- The internal-agent e2e scenarios live in the existing
create_agent_request lifecycle suite rather than a new file.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix(server): cascade to live internal children and keep a failed internal create's worktree until it closes
Internal children never reach storage, so the parent archive cascade scans
live agents for them as well. A failed internal create now clears the
created id only after the runtime is archived, so worktree cleanup cannot
delete the directory under a runtime that would not close. Stored agent
payloads carry lastError, so a retained failed helper reports its error
through wait_for_finish instead of the generic message.
* feat(cli,mcp): expose internal agents and document --no-wait
paseo run gains --internal and create_agent gains internal, both forwarded
to the create request. --no-wait becomes the documented spelling for
returning immediately, matching paseo send; --background and --detach stay
as hidden aliases under COMPAT tags.
* test: follow the --no-wait rename and stub getRetiredInternalAgent
* feat: list internal agents on request and add internal workspaces
Internal agents stay hidden by default, but a caller can now ask for
them: `fetch_agents_request` takes `filter.includeInternal`, snapshots
carry `internal: true`, and `paseo ls --internal` shows them in an
INTERNAL column. The app never passes the flag.
Workspaces get the same flag. `workspace.create.request` with
`internal: true` persists a hidden workspace: listings, update
subscriptions, sync reads, empty-project counting, open-by-path, MCP
`list_workspaces`, and plugin workspace hooks all skip it unless the
caller opts in with `filter.includeInternal`. Every agent created inside
an internal workspace is internal and unpersisted; AgentManager applies
that from the workspace id before the plugin hook so creators cannot
opt out. Archive and shutdown enumerate internal agents so nothing
inside an internal workspace outlives it.
Surfaces: `paseo workspace create --internal`, `paseo workspace ls
--internal`, `paseo run --internal --new-workspace`, MCP
`create_workspace({ internal })`, SDK `workspaces.create({ internal })`
and `list({ filter: { includeInternal } })`. Clients gate on
`features.internalWorkspaces`.
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(workspaces): add background visibility with inherited creation defaults
* fix(cli): resolve workspace callers on the selected daemon
* test(workspaces): keep caller integration coverage in server suite
* test(cli): exercise workspace callers through CLI integration harness
* test(mcp): remove obsolete execution flags from browser fixtures
---------
Co-authored-by: marvin-ambrozio <marvin@gustavo.eng.br>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
PaseoAgentSendOptions was a hand-copied subset of the daemon client's
SendMessageOptions and dropped activeTurnBehavior, so
agents.ref(id).send(text, { activeTurnBehavior: "steer" }) and run() failed
to typecheck even though the value is forwarded to the daemon. The public
type is now the options type send() passes through, so the two cannot
drift again.
Closes#4555
Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
Co-authored-by: Daye <2077152374@qq.com>
* fix(subscriptions): preserve older-host workflows and explicit timeline recovery
Keep established app and SDK workflows available on older daemons without emulating independent directory filters. Restore live timeline membership without choosing the consumer's history recovery policy. Preserve daemon filesystem paths separately from legacy workspace IDs.
* fix(client): keep legacy workspace replies scoped to the requested page
Give each observation a server-issued ID owned by its physical connection. Preserve snapshot-only reads and combined list-and-subscribe, source-bound replies, lifecycle cleanup and legacy wire compatibility.
Move supported protocol capabilities into client defaults and make session traffic subscription-driven. Preserve timeline readiness and reconnect recovery across SDK, CLI, and plugin consumers.
* feat(terminals): expose workspace ownership through the SDK and CLI
Directory-based terminal creation selected the oldest workspace sharing that path. Expose explicit workspace ownership in the shared public API and CLI, retain ownership and process directories in listings, and acknowledge terminal deletion after teardown.
* fix(file-observer): preserve nested shallow reconciliation scopes
A parent directory scan does not visit its descendants. Collapsing change scopes discarded nested scans and left coalesced native deletions unseen until a full audit.
* test(terminals): extract output waits from end-to-end scenarios
Plugins can transform live timeline source items at render time, append durable plugin rows from daemon handlers, and register client-only slash commands in the composer.
Related to #3940 and #3952.
* feat(sdk): expose a session's own commands on the agent handle
`DaemonClient.listCommands` has always been able to ask a running session
which slash commands and skills it loaded, but `PaseoAgentHandle` never
surfaced it, so SDK and plugin consumers could only see what they could
find on disk. Provider built-ins — the ones bundled inside the agent
binary rather than installed into a scannable directory — were therefore
invisible to them.
Add `agent.commands()` as a thin delegation to the existing RPC. Every
provider that implements `listCommands` (claude, codex, opencode, acp,
omp, pi) answers it, so a consumer no longer needs per-provider
filesystem knowledge to enumerate what a session can run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(sdk): expose the observed agent snapshot on the agent handle
The handle mirrored four snapshot fields (workspaceId, cwd, status, id)
and hid the rest behind current(). Add getters for capabilities,
availableModes, pendingPermissions, activeTurn, lastUsage, lastError,
features, runtimeInfo, and archivedAt so callers can read one field
without destructuring the whole snapshot and null-checking it.
Each reads the last observed snapshot and never fetches, matching the
existing getters. null means "not observed yet".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(sdk): clarify nullable snapshot getters
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: marvin-ambrozio <marvin@gustavo.eng.br>
Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
* feat(plugins): add workspace panels and command center contributions
Give local plugins contextual UI entry points without making the daemon interpret client placement or callbacks. Panels receive stable IDs and read cached client state through required selectors with shallow equality, avoiding unrelated guest rerenders and context-discovery RPCs.
* fix(plugins): align shared client state ownership
Workspace panels and Command Center callbacks consume the same frozen client snapshots, so their adapter belongs to the plugin boundary rather than either contribution surface. Refresh the Nix dependency hash for the selector-store dependency added by this feature.
* feat(plugins): expose Paseo API to local plugins
Plugin surfaces borrow the selected host connection while subprocess handlers receive an exclusively owned IPC session, so plugins can use normal workspace and agent operations without inventing another transport.
* feat(plugins): reload global enablement safely
Treat the global plugin switch as a live daemon setting and teach plugin automation to inspect it before acting. Enabling remains permission-gated because plugin backend code can access the daemon machine and client contributions execute inside the app.
* feat(plugins): expose plugin logs
Capture plugin stdout and stderr separately from IPC so authors can debug initialization, RPC, cleanup, and crash behavior from the app or CLI. Keep a bounded tail across lifecycle recovery while preserving structured output in the daemon log.
* fix(build): order plugin dependency builds
* test(plugins): align startup and CLI expectations
* feat(client): publish the TypeScript SDK surface
Make the high-level client API usable for external integrations and document complete agent, workspace, provider, event, and recipe flows.
* fix(client): correlate provider snapshots by daemon cwd
Return the daemon's canonical snapshot identity so waitForReady can match updates for relative, tilde, and otherwise non-canonical paths without duplicating filesystem rules in the SDK.
* test(server): make snapshot cwd assertion portable
* fix(client): gate canonical provider snapshot waits
Older daemons do not expose the canonical snapshot identity needed to correlate workspace updates safely. Require the advertised capability and fail with an update-host message instead of guessing across workspaces.
* fix(desktop): restore direct LAN connections
Desktop 0.3.0 routed remote WebSockets through the Electron main process, causing previously working macOS LAN connections to fail with EHOSTUNREACH. Revert custom direct headers and restore the renderer WebSocket path used before the regression.
* fix(app): replace host connections by identity
Keep one connection per stable ID when TLS or password settings change. This preserves the current-main upsert invariant while the custom-header rollback removes the unrelated transport feature.
* Reapply: Stop completed turns from appearing stuck (#2484)
* Reapply: Keep older chat history and image previews stable (#2490)
* Lock timeline layout stability with user-driven specs
Two reds reproduce the reported jank:
- new agent, first prompt: the row paints at top=100 then jumps to 144 through
authoritative hydration, because the draft tab and the agent panel each render
their own AgentStreamView for the same logical row.
- long loaded timeline, submit: scrollHeight collapses 10793 -> 9111 mid-turn,
because splitOrderedTail reclassifies measured rows into the virtualized segment
where the virtualizer falls back to estimateStreamItemHeight.
Also restores centered timeline rows: the pagination anchor wrapper introduced in
#2490 was a plain block div, which broke alignSelf: center.
* Measure the turn footer blink from when the footer appears
Bounding the window at the prompt row conflated two things: the footer arriving a
frame after the row, and the footer leaving the layout and coming back. Bounded from
the footer's first frame, the blink still reproduces, so the footer-ownership race is
real rather than a sampling artifact.
* Rename the shadowed prompt row binding in the frame recorder
* fix(desktop): allow concurrent worktree dev instances
Desktop terminals can inherit another instance's profile path and debugging flags. Scope the profile to the current dev root and select an available debugging port so instances do not share global runtime state.
* fix(desktop): expose development providers in dev builds
Desktop-managed daemons inherited no Paseo runtime mode, so dev builds constructed the production provider registry. Mark unpackaged internal launches as development while continuing to force packaged launches to production.
* fix(timeline): stabilize optimistic turn layout
Keep initial history loading dormant until user intent and preserve active-turn layout across delayed transport updates. Add painted-frame coverage for optimistic timeline transitions.
* fix(timeline): preserve optimistic prompts through hydration
Canonical replacement relied on a transport submission record that can settle before a provider echoes the user row. Keep presentation continuity owned by the unreconciled row while destructive history replacement remains governed by active transactions.
* fix(timeline): make submitted prompts canonical
Submission settlement previously depended on status updates that could arrive after the optimistic row. Persist every accepted prompt in the canonical timeline and keep the footer active until RPC and canonical acknowledgement converge.
* fix(timeline): stop older history pages repeating entries
Backward pagination counted source sequence rows, so page boundaries inside a merged projected item could return that item repeatedly. Count projected entries and advance from their display anchors instead, with server and browser regressions covering the contract.
* fix(timeline): resume agents from the latest history
Use a bounded tail probe on resume so long background runs appear atomically instead of replaying every missed page. Preserve unchanged views, reconcile local/live rows, and keep skipped history reachable through backward pagination.
* fix(timeline): reconcile turn state after missed updates
Turn completion events can be missed while an agent timeline is unsubscribed, leaving footer activity stale even after the directory reports idle. Reconcile the single-owned turn lifecycle from authoritative resume snapshots while preserving newer live evidence.
* test(timeline): cover running state across refresh
Protect the hydration boundary where directory state must restore consistent tab, composer, and footer activity. Expose the running indicator semantically so the regression checks user-visible state instead of spinner implementation details.
* fix(timeline): keep history loading geometry stable
Reserve a fixed history-start gutter regardless of pagination state so showing or hiding the loader cannot shift timeline content.
* fix(timeline): keep turn activity coherent
Derive footer, tab, and composer activity from one lifecycle and submission projection. Idle directory transitions now request an authoritative resume so missed terminal events converge without treating directory delivery order as turn authority.
* fix(tests): align checks with runtime boundaries
* fix(desktop): stop dev app surviving its terminal
Electron was detached from the desktop runner, allowing it to outlive a stopped workspace terminal with broken output pipes and retain the single-instance lock. Keep Electron owned by the runner and preserve explicit process-group cleanup for detached child trees.
* fix(timeline): preserve activity through turn handoff
Correlate lifecycle events and snapshots with daemon-owned turn identity, and keep optimistic submissions active until their canonical row arrives. This prevents stale updates and RPC timing from exposing a false idle state.
* refactor(timeline): remove submission timing state
* fix(timeline): restore prompt identity on resume
* fix(timeline): exclude attachments from canonical prompt text
Structured provider prompts can include hidden history attachments before the user's text. Persist only plain prompt blocks so authoritative user messages match what the composer displayed while provider input remains unchanged.
* refactor(agent): remove unused pending-run message identity
* fix(desktop): let Chromium allocate the debugging port
* refactor(agent): remove impossible finalized-turn tracking
* fix(timeline): load history after keyboard scrolling
Treat observed upward displacement as user intent so keyboard and scrollbar navigation can wake dormant pagination.
* test(server): preserve accepted turn stream order
The manager-owned accepted turn boundary intentionally precedes coalesced output. Assert that lifecycle event explicitly while retaining the timeline-before-terminal ordering contract.
* test(app): scope sidebar fixtures by identity
Shared E2E daemon state may contain unrelated projects. Keep stale-route coverage tied to its named missing project and drag only the two rows seeded by the reorder spec.
* fix(timeline): gate prompt revisions by client capability
* fix(timeline): finalize canonical prompt delivery
Treat provider identity as a single stored-row transition so legacy clients receive one deliverable canonical prompt. Release identity-pending rows before later foreground output or the current terminal while preserving stale-turn isolation.
* fix(server): preserve legacy prompt pagination
* fix(timeline): keep assistant block identity stable
Assign canonical block IDs during live promotion so terminal finalization cannot remount image-bearing rows.
* fix(timeline): apply covered revisions during resume append
Run the exact canonical revision pass before overlapping resume pages append newer rows, while leaving cursor advancement to the incremental path.
* fix(server): preserve queued agent transitions
Project each queued live snapshot before awaiting stored metadata so later lifecycle state cannot overwrite an earlier transition.
* fix(server): snapshot queued agent updates
Capture each live agent payload before it enters the per-agent queue so shared nested state cannot change while an earlier storage read is pending.
* docs(app): date agent turn compatibility cleanup
* refactor(timeline): mint submitted prompt identity at acceptance
Canonical prompt rows now keep one immutable wire identity while provider identity remains internal for rewind translation. This removes the unreleased same-sequence revision and legacy projection contract.
* refactor(app): remove prompt revision reconciliation
Submitted prompt rows are immutable on the wire, so resume and live reducers no longer need to apply already-covered same-sequence updates.
* test(app): cover submitted prompt rewind roundtrip
* docs(timeline): describe immutable submitted prompt identity
Provider echoes now enrich daemon-internal identity only; wire rows keep their acceptance-time identity and rewind performs the provider translation.
* test(server): validate mock rewind targets
Reject unknown provider message IDs so app rewind coverage exercises wire-to-provider identity translation.
* fix(server): validate rewind before interrupting
* fix(server): omit rewind identity for daemon prompts
* test(app): guard rewind eligibility and rejection
* fix(server): preserve prompt identity across hydration
* refactor(timeline): remove stale revision remnants
* Revert "fix(server): preserve prompt identity across hydration"
This reverts commit 6adcf7e5b0.
* fix(timeline): settle missed submission acknowledgements
* Add npm release track invariant and beta dist-tag procedure
* Revert "Keep older chat history and image previews stable (#2490)"
The timeline optimistic/pagination rework needs more work than main releases can wait for. Reverted together with #2484; both are reapplied on integration/timeline-optimistic-rework.
* Revert "Stop completed turns from appearing stuck (#2484)"
See the #2490 revert. #2490 built on this submission-authority change, so the two revert and reapply as a pair.
* fix(app): stop completed turns from appearing stuck
Turn activity was inferred from a user-message row flag, so a stale duplicate row could keep the working footer active after the turn ended. Track submission lifecycle separately and route every send path through the shared submission flow.
* fix(app): guard pending message identity
* test(app): measure submission layout independent of scroll
* fix(app): keep submitted messages consistent through reconnects
Track each in-flight send until its own RPC establishes acceptance, and keep canonical timeline placement authoritative. Restore legacy cached rewind IDs during cache deserialization.
* fix(app): close canonical submission races
* test(app): cover canonical submission races in browser
* fix(app): keep replacement submissions authoritative
Keep current pending rows out of legacy cache migration and leave ambiguous terminal lifecycle events to the daemon snapshot. This prevents fabricated rewind identities and stale completion events from marking replacement turns idle.
* fix(app): keep submitted messages stable across sync
Give submission transport and canonical timeline ingestion separate authority. Preserve every unresolved local send across replacement, reconcile provider identity once, and bridge RPC acceptance to authoritative running state without deriving lifecycle from timeline rows.
* fix(app): settle submissions in either acknowledgement order
Complete submission transactions when RPC and provider acknowledgement arrive in either order. Cache only transaction-owned local rows as transient data, preserve canonical ID-less prompts, and invalidate ambiguous legacy display caches instead of inventing provider identity.
* fix(app): keep agent visible during history handoff
Running and terminal updates could clear create continuity before the initial authoritative timeline arrived, leaving a streaming agent behind the loading screen. End the handoff only when authoritative history is applied.
* fix(app): settle attachment-only submissions
Canonical providers can acknowledge image-only prompts with empty text. Reconcile those events by client identity without rendering a blank canonical row.
* fix(agent): settle out-of-band message submissions
Accepted commands that do not allocate a foreground turn previously had no canonical user acknowledgement. Record the command before its handler runs so submission state and reconnect history converge through the normal timeline producer.
* fix(app): settle out-of-band submissions compatibly
* fix(app): preserve canonical prompt order
* test(app): keep workspace status check timing-independent
The workspace-status scenario asserted footer settlement before initial agent creation had necessarily completed. The dedicated draft-handoff coverage owns that lifecycle contract.
* Add opt-in browser tools for desktop tabs
Adds the daemon opt-in, desktop tab routing, MCP tools, and real browser automation surfaces for Paseo desktop browser tabs.
* Fix browser tools CI expectations
* Address browser tools review findings
* Restrict browser file automation paths
* Fix browser upload test on Windows
* Harden browser navigation inputs
* Make browser tools create usable tabs
* Update browser MCP empty-state test
* Fail browser tab creation when registration times out
* Fix browser screenshots for agents
* Hide disabled browser tools from agents
* Address browser tools architecture review
* Replace browser tools review tests
* Wrap browser tab registration errors
* Mock Expo Router in app unit tests
* Handle invalid browser automation requests
* Return browser failure on desktop disconnect
* Update browser disconnect websocket test
* Relax browser timeout polling test
* Handle invalid browser responses
* Return browser failure when send fails
* Remove local diagnostics and fixture paths
* Fix dev service home fallback
* Use worktree home for dev services
* Use managed daemon in desktop dev
* fix(browser): keep agent tabs addressable
Track agent-active browser targets separately from human-focused tabs and keep resident webviews alive for automation. Browser tool visibility now comes from registration while the broker reports disabled execution.
* refactor(browser): register tools through catalog
Move browser tool registration onto the shared Paseo tool catalog so the MCP server remains only the transport adapter.
* fix(settings): translate browser tools host error
* fix(client): wait longer for session responses
* fix(client): default RPC waits to sixty seconds
* fix(app): preserve detached stream scroll on delayed history
Code drift: longer client RPC waits let delayed timeline responses arrive after a user scroll-away, so web stream anchoring must not reattach on transient scroll-top resets.
Restore the 15s connect deadline and leave app initialization slack above the default 60s session RPC wait.
* fix(client): keep helper waits within caller deadlines
Review fix: the 60s default session RPC wait leaked into wait previews and waitForAgentUpsert helper fetches. Bound those helper RPCs to the caller deadline or a short best-effort preview timeout, and allow small scroll ranges to reattach at bottom.
* fix(client): respect caller timeout budgets
* fix(cli): keep diagnostic probes responsive
* Refactor daemon client request options
* Preserve daemon client legacy overloads
* Make workspace IDs opaque, independent of the filesystem path
Workspace IDs were the resolved checkout/worktree path, so code could
treat an ID as a path: prefix matching, deriving directories from it,
falling back to a path when a lookup missed. IDs are now opaque -
compared only by exact equality and never used as a path. Anything
path-shaped resolves the workspace record first and reads its cwd.
New workspaces get a generated `wks_` ID; existing path-shaped IDs are
read from disk and never regenerated, so there is no migration and no
change to the wire or persisted schemas. Groundwork for running
multiple workspaces in a single directory.
* Keep attachment scope key stable and align refetch test
The attachment scope key keeps `workspace=` instead of `wsid=` so existing
persisted drafts are not orphaned; the rename was cosmetic. The SDK refetch
test no longer asserts a filter, matching refetch fetching one page and
selecting by id client-side.
* Fix live agent updates in directories without a registered workspace
The opaque-ID work removed buildProjectPlacementForCwd's directory
fallback, so an agent running in a folder with no registered workspace
(e.g. a fresh non-git dir) produced a null placement. forwardAgentUpdate
then threw "Workspace not found", the error was swallowed by its catch,
and no agent_update was emitted — live model/thinking switches and status
updates silently stopped. Caught by the live-preferences e2e suite.
The fallback builds a directory-scoped project placement keyed by the
path. That key is a project grouping key (non-git projects group by
path), not a workspace id, so it stays within the opaque-id rule.
* Always run server worktree archive, even without a resolved workspace
Archiving bailed out entirely when the workspace was not found in the
client store, so a race or stale state could make "archive" do nothing
server-side with only a console.warn. The server archive is keyed by
worktreePath, which is always available, so it now runs regardless; only
the optimistic client-side updates (keyed by workspace id) are gated on
the workspace being resolved.
* Expect a directory-scoped placement for unregistered agent dirs
This unit test asserted the no-placement behavior reverted in the live
agent-update fix, which had broken live model/thinking switching. Update
it to expect the directory-scoped placement now emitted for an agent in a
directory with no registered workspace.
* Fix opaque workspace routing in app E2E
* Preserve workspace IDs during partial bootstrap
* Fix archive flows for opaque workspace IDs
* Stop treating opaque workspace IDs as filesystem paths
Workspace IDs are opaque (wks_<hex>), but several call sites still passed
the id where a directory was expected, which broke those flows for opaque
IDs. The branch switcher sent the id as a cwd to branch/stash/checkout git
operations, and server archive/reconcile cleanup keyed git-watch and
subscription teardown by id, leaking that state.
Git and filesystem operations now take the workspace directory; the opaque
id is used only for identity and cache keys. Archive/reconcile cleanup
routes through a single teardownArchivedWorkspace helper that keeps the key
split explicit: runtime store by id, git watch and subscription by cwd.
Path-derived grouping keys are renamed to directory keys, and the helpers
are split into workspace-identity and workspace-directory so the id-vs-path
boundary is obvious.
* 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.