Skip to content

Spaces: one Harbor client for the desktop and the phone - #1175

Merged
ramnique merged 1 commit into
mainfrom
ramnique/spaces-independent-web-app
Oct 9, 2026
Merged

ramnique merged 1 commit into
mainfrom
ramnique/spaces-independent-web-app

Conversation

@ramnique

@ramnique ramnique commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

First step of the Spaces web-app plan: the Harbor client moves into one package every app can use.

What changes

  • New package @x/spaces-client (apps/x/packages/spaces-client): the REST client and the live socket, moved from packages/core/src/spaces/ with their tests. Git tracks them as renames.
  • Core, the desktop main process, and rowboat-server import it. Core's spaces/index.ts no longer re-exports the client.
  • The phone's copy is gone. lib/spaces/live.ts is deleted. lib/spaces/client.ts drops from 587 lines to a subclass that passes expo-crypto's SHA-256, so the 14 places that construct a client didn't change.
  • The merged client has every method from both copies. That's core's newer methods (agents, invocations, approvals, transport-failure reporting) plus the phone's profile-image and push methods, which now use the protocol's routes.
  • It runs anywhere fetch, WebSocket, and WebCrypto exist.
    • The blob hash uses WebCrypto by default instead of node:crypto.
    • The default fetch is called unbound. A browser throws "Illegal invocation" when fetch is called as a method of another object.
    • Blob and image uploads share one bytes-PUT path, and every response goes through one contract check.
  • Wiring: root deps/test/typecheck scripts, the Forge build hook, and the phone's eas-build-post-install all build the package. The lockfile adds only the new importer.

What the phone notices

  • A failed fetch is now a SpacesRequestError with code unreachable, as on desktop. The offline banner (isNetworkError) checks that code.
  • Responses from profile-image routes are now checked against the contract.
  • space_removed frames now reach member handlers. The phone registers none today.

Desktop behavior is unchanged.

Verified locally

  • npm run typecheck (apps/x) passes. tsc --noEmit passes for main.
  • npm test (apps/x) passes: shared 321, spaces-client 34, core 1024, server 29, renderer 1152.
  • apps/main npm run build: the main process and rowboat-server bundle with esbuild.
  • The phone: expo export --platform ios bundles with Metro.
    • tsc on the phone reports two errors from missing CSS typings, in files this PR doesn't touch. The cause is Expo's generated expo-env.d.ts, which is absent in a fresh checkout.
    • Not run on a device.

🤖 Generated with Claude Code

The phone carried a copy of core's Harbor client (lib/spaces/client.ts,
live.ts) that had drifted both ways: core gained agents, invocations,
approvals and transport-failure reporting; the phone alone had profile
images and push. Both now use @x/spaces-client, a new workspace package
holding the one REST client and live socket, moved from core with their
tests.

It runs anywhere fetch, WebSocket and WebCrypto do, the first step of the
Spaces web-app plan: the blob hash is WebCrypto by default (React Native
passes expo-crypto's), and the default fetch is called unbound so a
browser does not throw "Illegal invocation". Blob and image uploads share
one bytes-PUT path, and every response goes through one contract check.

For the phone this brings core's behavior: a failed fetch is a
SpacesRequestError with code 'unreachable' (the offline banner checks
that code), image responses are schema-checked, and space_removed frames
reach member handlers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ramnique
ramnique merged commit acbefd0 into main Oct 9, 2026
3 checks passed
replicas-connector Bot added a commit that referenced this pull request Oct 9, 2026
Main moved the Harbor client into @x/spaces-client (#1175); the alert-hook
calls move with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: arkml <6592213+arkml@users.noreply.github.com>
Co-Authored-By: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant