You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: optimize capnweb integration to eliminate wasteful operations and improve security
Client (share-next.ts):
- Reuse a single capnweb RPC session instance instead of creating a new one on
every sync tick and every create() call; the session is lazily initialized and
then cached for the lifetime of the process.
- Cache the base URL after the first config read so Config.get() is not awaited
on every operation.
- Fix queue deduplication: the previous key logic evaluated `"id" in item` on the
SyncData wrapper (which never has a top-level id), so every event generated a
fresh ulid key and updates for the same message/part accumulated rather than
collapsing. Keys are now type-scoped
("session", "message:<id>", "part:<id>", etc.) so repeated updates within the
debounce window correctly overwrite each other.
- Pipeline create + initial full-sync into a single RPC call: gatherFullSnapshot
is started concurrently with session creation; both results are passed together
to createShare so no extra round-trip is needed for the initial sync.
- Parallelize gatherFullSnapshot: Session.get, Session.diff, and
MessageV2.stream are now fetched with Promise.all instead of sequentially.
- Combine message + model into one sync call in the MessageV2.Updated handler to
avoid a second setTimeout enqueue for the same session.
- Use RPC for remove() via the new deleteShare method (consistent with the rest
of the RPC transport path).
- Extract syncHttp helper to deduplicate the HTTP fallback path.
RPC contract (both packages):
- createShare now accepts optional initialData so the initial full snapshot can
be sent in the same request as the share creation (one round trip instead of
two).
- Add deleteShare(shareID, secret) so the RPC transport can handle deletions
without falling back to the HTTP API.
Server (rpc.ts):
- Move StorageAdapter instantiation to the constructor so adapters are created
once per request instead of on every method call.
- Extract applyData() helper so createShare and syncShare share the same
data-merge logic rather than duplicating it.
- createShare applies initialData when provided and stores the correct index
counts immediately, eliminating the need for a follow-up syncShare call.
- Implement deleteShare with the same secret-validation pattern as syncShare.
Storage (storage.ts):
- exists() now uses bucket.head() instead of bucket.get() so only object
metadata is fetched; the previous implementation downloaded the full body just
to check existence.
Security (index.tsx):
- /api/sessions was completely unauthenticated, exposing an enumeration of all
shared sessions. It now requires the same x-opencode-share-key header as the
RPC endpoint (SESSIONS_RPC_SHARED_KEY). If the key is not configured the
endpoint returns 401 rather than defaulting to open access.
https://claude.ai/code/session_01S5woDoxCnN62WNGjRhqWJ3
0 commit comments