@dxos/client-services 0.8.2-staging.7ac8446 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/lib/browser/{chunk-2TKMQ2UP.mjs → chunk-IFPYIR2N.mjs} +535 -551
  2. package/dist/lib/browser/chunk-IFPYIR2N.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1 -1
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +1 -1
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/{chunk-HUMVSL5Y.cjs → chunk-VC4EAGT6.cjs} +704 -709
  9. package/dist/lib/node/chunk-VC4EAGT6.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +47 -47
  11. package/dist/lib/node/index.cjs.map +3 -3
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +8 -8
  14. package/dist/lib/node/testing/index.cjs.map +3 -3
  15. package/dist/lib/node-esm/{chunk-DQCPFIVI.mjs → chunk-SV2U4CXT.mjs} +535 -540
  16. package/dist/lib/node-esm/chunk-SV2U4CXT.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +1 -1
  18. package/dist/lib/node-esm/index.mjs.map +3 -3
  19. package/dist/lib/node-esm/meta.json +1 -1
  20. package/dist/lib/node-esm/testing/index.mjs +1 -1
  21. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  22. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  23. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +1 -1
  24. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  25. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  26. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  27. package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
  28. package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -1
  29. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  30. package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
  31. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  32. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  33. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  34. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  35. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +1 -1
  36. package/dist/types/src/packlets/identity/identity-manager.d.ts +2 -2
  37. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  38. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +1 -1
  39. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  40. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  41. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  42. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  43. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  44. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  45. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  46. package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
  47. package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
  48. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  49. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +1 -1
  50. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  51. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  52. package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
  53. package/dist/types/src/packlets/locks/node.d.ts.map +1 -1
  54. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  55. package/dist/types/src/packlets/network/network-service.d.ts +3 -1
  56. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  57. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  58. package/dist/types/src/packlets/services/service-context.d.ts +1 -0
  59. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  60. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  61. package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
  62. package/dist/types/src/packlets/services/util.d.ts.map +1 -1
  63. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +1 -1
  64. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  65. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  66. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  67. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +1 -1
  68. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  69. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  70. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  71. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
  72. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  73. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  74. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  75. package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
  76. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  77. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  78. package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
  79. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  80. package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -1
  81. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  82. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  83. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  84. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  85. package/dist/types/src/version.d.ts +1 -1
  86. package/dist/types/src/version.d.ts.map +1 -1
  87. package/dist/types/tsconfig.tsbuildinfo +1 -1
  88. package/package.json +39 -38
  89. package/src/packlets/agents/edge-agent-manager.ts +6 -6
  90. package/src/packlets/agents/edge-agent-service.ts +8 -11
  91. package/src/packlets/devices/devices-service.ts +5 -3
  92. package/src/packlets/identity/authenticator.ts +2 -2
  93. package/src/packlets/identity/default-space-state-machine.ts +1 -1
  94. package/src/packlets/identity/identity-manager.ts +13 -9
  95. package/src/packlets/identity/identity-recovery-manager.ts +6 -4
  96. package/src/packlets/identity/identity-service.ts +4 -4
  97. package/src/packlets/identity/identity.test.ts +9 -6
  98. package/src/packlets/identity/identity.ts +5 -5
  99. package/src/packlets/invitations/device-invitation-protocol.ts +1 -1
  100. package/src/packlets/invitations/edge-invitation-handler.ts +3 -3
  101. package/src/packlets/invitations/invitation-guest-extenstion.ts +3 -3
  102. package/src/packlets/invitations/invitation-host-extension.ts +5 -5
  103. package/src/packlets/invitations/invitation-topology.ts +1 -1
  104. package/src/packlets/invitations/invitations-handler.ts +2 -2
  105. package/src/packlets/invitations/invitations-manager.ts +15 -4
  106. package/src/packlets/invitations/space-invitation-protocol.ts +1 -1
  107. package/src/packlets/locks/browser.ts +4 -4
  108. package/src/packlets/locks/node.ts +2 -2
  109. package/src/packlets/logging/logging-service.ts +2 -2
  110. package/src/packlets/network/network-service.ts +11 -17
  111. package/src/packlets/services/client-rpc-server.ts +2 -2
  112. package/src/packlets/services/service-context.ts +10 -6
  113. package/src/packlets/services/service-host.ts +13 -5
  114. package/src/packlets/services/service-registry.ts +3 -3
  115. package/src/packlets/space-export/space-archive-reader.ts +2 -1
  116. package/src/packlets/space-export/space-archive-writer.ts +3 -3
  117. package/src/packlets/spaces/automerge-space-state.ts +3 -3
  118. package/src/packlets/spaces/data-space-manager.ts +47 -41
  119. package/src/packlets/spaces/data-space.ts +27 -20
  120. package/src/packlets/spaces/edge-feed-replicator.test.ts +2 -1
  121. package/src/packlets/spaces/edge-feed-replicator.ts +14 -13
  122. package/src/packlets/spaces/epoch-migrations.ts +3 -2
  123. package/src/packlets/spaces/notarization-plugin.test.ts +1 -1
  124. package/src/packlets/spaces/notarization-plugin.ts +18 -18
  125. package/src/packlets/spaces/spaces-service.ts +7 -6
  126. package/src/packlets/storage/profile-archive.ts +2 -1
  127. package/src/packlets/system/system-service.ts +2 -2
  128. package/src/packlets/testing/test-builder.ts +3 -3
  129. package/src/packlets/worker/worker-runtime.ts +4 -4
  130. package/src/packlets/worker/worker-session.ts +3 -3
  131. package/src/version.ts +5 -1
  132. package/dist/lib/browser/chunk-2TKMQ2UP.mjs.map +0 -7
  133. package/dist/lib/node/chunk-HUMVSL5Y.cjs.map +0 -7
  134. package/dist/lib/node-esm/chunk-DQCPFIVI.mjs.map +0 -7
@@ -41,7 +41,7 @@ export class IdentityServiceImpl extends Resource implements IdentityService {
41
41
  super();
42
42
  }
43
43
 
44
- protected override async _open() {
44
+ protected override async _open(): Promise<void> {
45
45
  const identity = this._identityManager.identity;
46
46
  if (identity && !identity.defaultSpaceId) {
47
47
  await this._fixIdentityWithoutDefaultSpace(identity);
@@ -49,13 +49,13 @@ export class IdentityServiceImpl extends Resource implements IdentityService {
49
49
  }
50
50
 
51
51
  async createIdentity(request: CreateIdentityRequest): Promise<IdentityProto> {
52
- await this._createIdentity({ displayName: request.profile?.displayName, deviceProfile: request.deviceProfile });
52
+ await this._createIdentity({ profile: request.profile, deviceProfile: request.deviceProfile });
53
53
  const dataSpaceManager = this._dataSpaceManagerProvider();
54
54
  await this._createDefaultSpace(dataSpaceManager);
55
55
  return this._getIdentity()!;
56
56
  }
57
57
 
58
- private async _createDefaultSpace(dataSpaceManager: DataSpaceManager) {
58
+ private async _createDefaultSpace(dataSpaceManager: DataSpaceManager): Promise<void> {
59
59
  const space = await dataSpaceManager!.createDefaultSpace();
60
60
  const identity = this._identityManager.identity;
61
61
  invariant(identity);
@@ -141,7 +141,7 @@ export class IdentityServiceImpl extends Resource implements IdentityService {
141
141
  });
142
142
  }
143
143
 
144
- private async _fixIdentityWithoutDefaultSpace(identity: Identity) {
144
+ private async _fixIdentityWithoutDefaultSpace(identity: Identity): Promise<void> {
145
145
  let recodedDefaultSpace = false;
146
146
  let foundDefaultSpace = false;
147
147
  const dataSpaceManager = this._dataSpaceManagerProvider();
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { onTestFinished, describe, expect, test } from 'vitest';
6
6
 
7
+ import { Event } from '@dxos/async';
7
8
  import { Context } from '@dxos/context';
8
9
  import { createDidFromIdentityKey, CredentialGenerator, verifyCredential } from '@dxos/credentials';
9
10
  import {
@@ -22,6 +23,7 @@ import { Keyring } from '@dxos/keyring';
22
23
  import { type PublicKey } from '@dxos/keys';
23
24
  import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
24
25
  import { MemoryTransportFactory, SwarmNetworkManager } from '@dxos/network-manager';
26
+ import { EdgeStatus } from '@dxos/protocols/proto/dxos/client/services';
25
27
  import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
26
28
  import { AdmittedFeed } from '@dxos/protocols/proto/dxos/halo/credentials';
27
29
  import { createStorage, StorageType } from '@dxos/random-access-storage';
@@ -107,21 +109,22 @@ describe('identity/identity', () => {
107
109
 
108
110
  test('edge feed replicator', async () => {
109
111
  let replicationStarted = false;
110
- let isConnected = false;
112
+ let status = EdgeStatus.NOT_CONNECTED;
111
113
  const listeners: Array<() => void> = [];
112
114
  const setup = await setupIdentity({
113
115
  edgeConnection: {
116
+ statusChanged: new Event(),
117
+ get status() {
118
+ return status;
119
+ },
114
120
  onReconnected: (listener) => {
115
- if (isConnected) {
121
+ if (status === EdgeStatus.CONNECTED) {
116
122
  listener();
117
123
  } else {
118
124
  listeners.push(listener);
119
125
  }
120
126
  return () => {};
121
127
  },
122
- get isConnected() {
123
- return isConnected;
124
- },
125
128
  open: async () => {},
126
129
  close: async () => {},
127
130
  onMessage: (_: MessageListener): (() => void) => {
@@ -135,7 +138,7 @@ describe('identity/identity', () => {
135
138
 
136
139
  await writeGenesisCredential(setup);
137
140
  listeners.forEach((callback) => callback());
138
- isConnected = true;
141
+ status = EdgeStatus.CONNECTED;
139
142
 
140
143
  await expect.poll(() => replicationStarted).toBeTruthy();
141
144
  });
@@ -116,7 +116,7 @@ export class Identity {
116
116
  }
117
117
 
118
118
  @trace.span()
119
- async open(ctx: Context) {
119
+ async open(ctx: Context): Promise<void> {
120
120
  await this._presence?.open();
121
121
  await this.space.spaceState.addCredentialProcessor(this._deviceStateMachine);
122
122
  await this.space.spaceState.addCredentialProcessor(this._profileStateMachine);
@@ -127,13 +127,13 @@ export class Identity {
127
127
  await this.space.open(ctx);
128
128
  }
129
129
 
130
- public async joinNetwork() {
130
+ public async joinNetwork(): Promise<void> {
131
131
  await this.space.startProtocol();
132
132
  await this._edgeFeedReplicator?.open();
133
133
  }
134
134
 
135
135
  @trace.span()
136
- async close(ctx: Context) {
136
+ async close(ctx: Context): Promise<void> {
137
137
  await this._presence?.close();
138
138
  await this.authVerifier.close();
139
139
  await this.space.spaceState.removeCredentialProcessor(this._defaultSpaceStateMachine);
@@ -149,7 +149,7 @@ export class Identity {
149
149
  await this.space.close();
150
150
  }
151
151
 
152
- async ready() {
152
+ async ready(): Promise<void> {
153
153
  await this._deviceStateMachine.deviceChainReady.wait();
154
154
 
155
155
  await this.controlPipeline.state.waitUntilReachedTargetTimeframe({ timeout: LOAD_CONTROL_FEEDS_TIMEOUT });
@@ -210,7 +210,7 @@ export class Identity {
210
210
  return createCredentialSignerWithKey(this._signer, this.deviceKey);
211
211
  }
212
212
 
213
- async updateDefaultSpace(spaceId: SpaceId) {
213
+ async updateDefaultSpace(spaceId: SpaceId): Promise<void> {
214
214
  const credential = await this.getDeviceCredentialSigner().createCredential({
215
215
  subject: this.identityKey,
216
216
  assertion: { '@type': 'dxos.halo.credentials.DefaultSpace', spaceId },
@@ -66,7 +66,7 @@ export class DeviceInvitationProtocol implements InvitationProtocol {
66
66
  };
67
67
  }
68
68
 
69
- checkInvitation(invitation: Partial<Invitation>) {
69
+ checkInvitation(invitation: Partial<Invitation>): AlreadyJoinedError | undefined {
70
70
  try {
71
71
  const identity = this._getIdentity();
72
72
  if (identity) {
@@ -61,7 +61,7 @@ export class EdgeInvitationHandler implements FlowLockHolder {
61
61
  guardedState: GuardedInvitationState,
62
62
  protocol: InvitationProtocol,
63
63
  deviceProfile?: DeviceProfileDocument,
64
- ) {
64
+ ): void {
65
65
  if (!this._client) {
66
66
  log('edge disabled');
67
67
  return;
@@ -118,7 +118,7 @@ export class EdgeInvitationHandler implements FlowLockHolder {
118
118
  guardedState: GuardedInvitationState,
119
119
  admissionRequest: SpaceAdmissionRequest,
120
120
  spaceId: SpaceId,
121
- ) {
121
+ ): Promise<void> {
122
122
  try {
123
123
  log('edge invitation flow');
124
124
  this._flowLock = await tryAcquireBeforeContextDisposed(ctx, guardedState.mutex);
@@ -182,7 +182,7 @@ export class EdgeInvitationHandler implements FlowLockHolder {
182
182
  return this._flowLock != null;
183
183
  }
184
184
 
185
- private _calculateNextRetryMs() {
185
+ private _calculateNextRetryMs(): number {
186
186
  return this._retryInterval + Math.random() * this._retryJitter;
187
187
  }
188
188
  }
@@ -82,7 +82,7 @@ export class InvitationGuestExtension
82
82
  };
83
83
  }
84
84
 
85
- override async onOpen(context: ExtensionContext) {
85
+ override async onOpen(context: ExtensionContext): Promise<void> {
86
86
  await super.onOpen(context);
87
87
 
88
88
  try {
@@ -115,7 +115,7 @@ export class InvitationGuestExtension
115
115
  }
116
116
  }
117
117
 
118
- override async onClose() {
118
+ override async onClose(): Promise<void> {
119
119
  await this._destroy();
120
120
  }
121
121
 
@@ -123,7 +123,7 @@ export class InvitationGuestExtension
123
123
  await this._destroy();
124
124
  }
125
125
 
126
- private async _destroy() {
126
+ private async _destroy(): Promise<void> {
127
127
  await this._ctx.dispose();
128
128
  if (this._invitationFlowLock != null) {
129
129
  this._invitationFlowLock.release();
@@ -232,7 +232,7 @@ export class InvitationHostExtension
232
232
  };
233
233
  }
234
234
 
235
- override async onOpen(context: ExtensionContext) {
235
+ override async onOpen(context: ExtensionContext): Promise<void> {
236
236
  await super.onOpen(context);
237
237
 
238
238
  try {
@@ -272,7 +272,7 @@ export class InvitationHostExtension
272
272
  return invitation;
273
273
  }
274
274
 
275
- private _assertInvitationState(stateOrMany: Invitation.State | Invitation.State[]) {
275
+ private _assertInvitationState(stateOrMany: Invitation.State | Invitation.State[]): void {
276
276
  const invitation = this._requireActiveInvitation();
277
277
  const validStates = Array.isArray(stateOrMany) ? stateOrMany : [stateOrMany];
278
278
  if (!validStates.includes(invitation.state)) {
@@ -283,15 +283,15 @@ export class InvitationHostExtension
283
283
  }
284
284
  }
285
285
 
286
- override async onClose() {
286
+ override async onClose(): Promise<void> {
287
287
  await this._destroy();
288
288
  }
289
289
 
290
- override async onAbort() {
290
+ override async onAbort(): Promise<void> {
291
291
  await this._destroy();
292
292
  }
293
293
 
294
- private async _destroy() {
294
+ private async _destroy(): Promise<void> {
295
295
  await this._ctx.dispose();
296
296
  if (this._invitationFlowLock != null) {
297
297
  this._invitationFlowLock?.release();
@@ -81,7 +81,7 @@ export class InvitationTopology implements Topology {
81
81
  this._seenPeers.clear();
82
82
  }
83
83
 
84
- toString() {
84
+ toString(): string {
85
85
  return `InvitationTopology(${this._role === InvitationOptions.Role.GUEST ? 'guest' : 'host'})`;
86
86
  }
87
87
  }
@@ -453,7 +453,7 @@ export class InvitationsHandler {
453
453
  setState: (newState: Invitation.State) => void,
454
454
  authenticated: Trigger<string>,
455
455
  options: { timeout: number },
456
- ) {
456
+ ): Promise<void> {
457
457
  for (let attempt = 1; attempt <= MAX_OTP_ATTEMPTS; attempt++) {
458
458
  log('guest waiting for authentication code...');
459
459
  setState(Invitation.State.READY_FOR_AUTHENTICATION);
@@ -482,7 +482,7 @@ export class InvitationsHandler {
482
482
  setState: (newState: Invitation.State) => void,
483
483
  invitation: Invitation,
484
484
  introductionResponse: IntroductionResponse,
485
- ) {
485
+ ): Promise<void> {
486
486
  if (invitation.guestKeypair?.privateKey == null) {
487
487
  throw new Error('keypair missing in the invitation');
488
488
  }
@@ -182,7 +182,7 @@ export class InvitationsManager {
182
182
  return [...this._acceptInvitations.values()].map((i) => i.get());
183
183
  }
184
184
 
185
- onPersistentInvitationsLoaded(ctx: Context, callback: () => void) {
185
+ onPersistentInvitationsLoaded(ctx: Context, callback: () => void): void {
186
186
  if (this._persistentInvitationsLoaded) {
187
187
  callback();
188
188
  } else {
@@ -231,7 +231,10 @@ export class InvitationsManager {
231
231
  } satisfies Invitation;
232
232
  }
233
233
 
234
- private _createObservableInvitation(handler: InvitationProtocol, invitation: Invitation) {
234
+ private _createObservableInvitation(
235
+ handler: InvitationProtocol,
236
+ invitation: Invitation,
237
+ ): { ctx: Context; stream: PushStream<Invitation>; observableInvitation: CancellableInvitation } {
235
238
  const stream = new PushStream<Invitation>();
236
239
  const ctx = new Context({
237
240
  onError: (err) => {
@@ -254,7 +257,15 @@ export class InvitationsManager {
254
257
  return { ctx, stream, observableInvitation };
255
258
  }
256
259
 
257
- private _createObservableAcceptingInvitation(handler: InvitationProtocol, initialState: Invitation) {
260
+ private _createObservableAcceptingInvitation(
261
+ handler: InvitationProtocol,
262
+ initialState: Invitation,
263
+ ): {
264
+ ctx: Context;
265
+ invitation: AuthenticatingInvitation;
266
+ stream: PushStream<Invitation>;
267
+ otpEnteredTrigger: Trigger<string>;
268
+ } {
258
269
  const otpEnteredTrigger = new Trigger<string>();
259
270
  const stream = new PushStream<Invitation>();
260
271
  const ctx = new Context({
@@ -310,7 +321,7 @@ export class InvitationsManager {
310
321
  }
311
322
  }
312
323
 
313
- private _onInvitationComplete(invitation: CancellableInvitation, callback: () => void) {
324
+ private _onInvitationComplete(invitation: CancellableInvitation, callback: () => void): void {
314
325
  invitation.subscribe(
315
326
  () => {},
316
327
  () => {},
@@ -145,7 +145,7 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
145
145
  await writeMessages(space.inner.controlPipeline.writer, [credential]);
146
146
  }
147
147
 
148
- checkInvitation(invitation: Partial<Invitation>) {
148
+ checkInvitation(invitation: Partial<Invitation>): InvalidInvitationError | AlreadyJoinedError | undefined {
149
149
  if (invitation.spaceKey == null) {
150
150
  return new InvalidInvitationError('No spaceKey was provided for a space invitation.');
151
151
  }
@@ -33,7 +33,7 @@ export class Lock implements ResourceLock {
33
33
  return this._lockKey;
34
34
  }
35
35
 
36
- async acquire() {
36
+ async acquire(): Promise<void> {
37
37
  this._broadcastChannel.postMessage({
38
38
  message: Message.ACQUIRING,
39
39
  });
@@ -49,17 +49,17 @@ export class Lock implements ResourceLock {
49
49
  }
50
50
  }
51
51
 
52
- async release() {
52
+ async release(): Promise<void> {
53
53
  this._releaseTrigger.wake();
54
54
  }
55
55
 
56
- private _onMessage(event: MessageEvent<any>) {
56
+ private _onMessage(event: MessageEvent<any>): void {
57
57
  if (event.data.message === Message.ACQUIRING) {
58
58
  this._releaseTrigger.wake();
59
59
  }
60
60
  }
61
61
 
62
- private async _requestLock(steal = false) {
62
+ private async _requestLock(steal = false): Promise<void> {
63
63
  log('requesting lock...', { steal });
64
64
  const acquired = new Trigger();
65
65
 
@@ -28,7 +28,7 @@ export class Lock implements ResourceLock {
28
28
  return this._lockPath;
29
29
  }
30
30
 
31
- async acquire() {
31
+ async acquire(): Promise<void> {
32
32
  log('acquiring lock...');
33
33
  this._fileHandle = await LockFile.acquire(this._lockPath);
34
34
 
@@ -37,7 +37,7 @@ export class Lock implements ResourceLock {
37
37
  log('acquired lock');
38
38
  }
39
39
 
40
- async release() {
40
+ async release(): Promise<void> {
41
41
  await this._onRelease?.();
42
42
  invariant(this._fileHandle, 'Lock is not acquired');
43
43
  await LockFile.release(this._fileHandle);
@@ -32,11 +32,11 @@ export class LoggingServiceImpl implements LoggingService {
32
32
  private readonly _started = Date.now();
33
33
  private readonly _sessionId = PublicKey.random().toHex();
34
34
 
35
- async open() {
35
+ async open(): Promise<void> {
36
36
  log.runtimeConfig.processors.push(this._logProcessor);
37
37
  }
38
38
 
39
- async close() {
39
+ async close(): Promise<void> {
40
40
  const index = log.runtimeConfig.processors.findIndex((processor) => processor === this._logProcessor);
41
41
  log.runtimeConfig.processors.splice(index, 1);
42
42
  }
@@ -3,6 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Stream } from '@dxos/codec-protobuf/stream';
6
+ import { type EdgeConnection } from '@dxos/edge-client';
6
7
  import { type SignalManager } from '@dxos/messaging';
7
8
  import { type SwarmNetworkManager } from '@dxos/network-manager';
8
9
  import {
@@ -23,10 +24,11 @@ export class NetworkServiceImpl implements NetworkService {
23
24
  constructor(
24
25
  private readonly networkManager: SwarmNetworkManager,
25
26
  private readonly signalManager: SignalManager,
27
+ private readonly edgeConnection?: EdgeConnection,
26
28
  ) {}
27
29
 
28
- queryStatus() {
29
- return new Stream<NetworkStatus>(({ next }) => {
30
+ queryStatus(): Stream<NetworkStatus> {
31
+ return new Stream<NetworkStatus>(({ ctx, next }) => {
30
32
  const update = () => {
31
33
  next({
32
34
  swarm: this.networkManager.connectionState,
@@ -35,18 +37,13 @@ export class NetworkServiceImpl implements NetworkService {
35
37
  });
36
38
  };
37
39
 
38
- const unsubscribeSwarm = this.networkManager.connectionStateChanged.on(() => update());
39
- const unsubscribeSignal = this.signalManager.statusChanged?.on(() => update());
40
+ this.networkManager.connectionStateChanged.on(ctx, () => update());
41
+ this.signalManager.statusChanged?.on(ctx, () => update());
40
42
  update();
41
-
42
- return () => {
43
- unsubscribeSwarm();
44
- unsubscribeSignal?.();
45
- };
46
43
  });
47
44
  }
48
45
 
49
- async updateConfig(request: UpdateConfigRequest) {
46
+ async updateConfig(request: UpdateConfigRequest): Promise<void> {
50
47
  await this.networkManager.setConnectionState(request.swarm);
51
48
  }
52
49
 
@@ -63,13 +60,12 @@ export class NetworkServiceImpl implements NetworkService {
63
60
  }
64
61
 
65
62
  subscribeSwarmState(request: SubscribeSwarmStateRequest): Stream<SwarmResponse> {
66
- return new Stream<SwarmResponse>(({ next }) => {
67
- const unsubscribe = this.signalManager.swarmState?.on((state) => {
63
+ return new Stream<SwarmResponse>(({ ctx, next }) => {
64
+ this.signalManager.swarmState?.on(ctx, (state) => {
68
65
  if (request.topic.equals(state.swarmKey)) {
69
66
  next(state);
70
67
  }
71
68
  });
72
- return unsubscribe;
73
69
  });
74
70
  }
75
71
 
@@ -78,14 +74,12 @@ export class NetworkServiceImpl implements NetworkService {
78
74
  }
79
75
 
80
76
  subscribeMessages(peer: Peer): Stream<Message> {
81
- return new Stream<Message>(({ next }) => {
82
- const unsubscribe = this.signalManager.onMessage.on((message) => {
77
+ return new Stream<Message>(({ ctx, next }) => {
78
+ this.signalManager.onMessage.on(ctx, (message) => {
83
79
  if (message.recipient.peerKey === peer.peerKey) {
84
80
  next(message);
85
81
  }
86
82
  });
87
-
88
- return unsubscribe;
89
83
  });
90
84
  }
91
85
  }
@@ -80,11 +80,11 @@ export class ClientRpcServer {
80
80
  });
81
81
  }
82
82
 
83
- async open() {
83
+ async open(): Promise<void> {
84
84
  await this._rpcPeer.open();
85
85
  }
86
86
 
87
- async close() {
87
+ async close(): Promise<void> {
88
88
  await this._rpcPeer.close();
89
89
  }
90
90
 
@@ -59,6 +59,7 @@ export type ServiceContextRuntimeParams = Pick<
59
59
  DataSpaceManagerRuntimeParams & {
60
60
  invitationConnectionDefaultParams?: InvitationConnectionParams;
61
61
  disableP2pReplication?: boolean;
62
+ enableVectorIndexing?: boolean;
62
63
  };
63
64
  /**
64
65
  * Shared backend for all client services.
@@ -155,6 +156,9 @@ export class ServiceContext extends Resource {
155
156
  kv: this.level,
156
157
  peerIdProvider: () => this.identityManager.identity?.deviceKey?.toHex(),
157
158
  getSpaceKeyByRootDocumentId: (documentId) => this.spaceManager.findSpaceByRootDocumentId(documentId)?.key,
159
+ indexing: {
160
+ vector: this._runtimeParams?.enableVectorIndexing,
161
+ },
158
162
  });
159
163
 
160
164
  this._meshReplicator = new MeshEchoReplicator();
@@ -193,7 +197,7 @@ export class ServiceContext extends Resource {
193
197
  }
194
198
 
195
199
  @Trace.span()
196
- protected override async _open(ctx: Context) {
200
+ protected override async _open(ctx: Context): Promise<void> {
197
201
  await this._checkStorageVersion();
198
202
 
199
203
  log('opening...');
@@ -231,7 +235,7 @@ export class ServiceContext extends Resource {
231
235
  log('opened');
232
236
  }
233
237
 
234
- protected override async _close(ctx: Context) {
238
+ protected override async _close(ctx: Context): Promise<void> {
235
239
  log('closing...');
236
240
  if (this._deviceSpaceSync && this.identityManager.identity) {
237
241
  await this.identityManager.identity.space.spaceState.removeCredentialProcessor(this._deviceSpaceSync);
@@ -268,7 +272,7 @@ export class ServiceContext extends Resource {
268
272
  return factory(invitation);
269
273
  }
270
274
 
271
- async broadcastProfileUpdate(profile: ProfileDocument | undefined) {
275
+ async broadcastProfileUpdate(profile: ProfileDocument | undefined): Promise<void> {
272
276
  if (!profile || !this.dataSpaceManager) {
273
277
  return;
274
278
  }
@@ -287,7 +291,7 @@ export class ServiceContext extends Resource {
287
291
  return identity;
288
292
  }
289
293
 
290
- private async _checkStorageVersion() {
294
+ private async _checkStorageVersion(): Promise<void> {
291
295
  await this.metadataStore.load();
292
296
  if (this.metadataStore.version !== STORAGE_VERSION) {
293
297
  throw new InvalidStorageVersionError(STORAGE_VERSION, this.metadataStore.version);
@@ -297,7 +301,7 @@ export class ServiceContext extends Resource {
297
301
 
298
302
  // Called when identity is created.
299
303
  @Trace.span()
300
- private async _initialize(ctx: Context) {
304
+ private async _initialize(ctx: Context): Promise<void> {
301
305
  log('initializing spaces...');
302
306
  const identity = this.identityManager.identity ?? failUndefined();
303
307
  const signingContext: SigningContext = {
@@ -375,7 +379,7 @@ export class ServiceContext extends Resource {
375
379
  await identity.space.spaceState.addCredentialProcessor(this._deviceSpaceSync);
376
380
  }
377
381
 
378
- private async _setNetworkIdentity(params?: { deviceCredential: Credential }) {
382
+ private async _setNetworkIdentity(params?: { deviceCredential: Credential }): Promise<void> {
379
383
  using _ = await this._edgeIdentityUpdateMutex.acquire();
380
384
 
381
385
  let edgeIdentity: EdgeIdentity;
@@ -125,6 +125,10 @@ export class ClientServicesHost {
125
125
  this._runtimeParams.disableP2pReplication = config?.get('runtime.client.disableP2pReplication', false);
126
126
  }
127
127
 
128
+ if (this._runtimeParams.enableVectorIndexing === undefined) {
129
+ this._runtimeParams.enableVectorIndexing = config?.get('runtime.client.enableVectorIndexing', false);
130
+ }
131
+
128
132
  if (config) {
129
133
  this.initialize({ config, transportFactory, signalManager });
130
134
  }
@@ -199,7 +203,7 @@ export class ClientServicesHost {
199
203
  * Config can also be provided in the constructor.
200
204
  * Can only be called once.
201
205
  */
202
- initialize({ config, ...options }: InitializeOptions) {
206
+ initialize({ config, ...options }: InitializeOptions): void {
203
207
  invariant(!this._open, 'service host is open');
204
208
  log('initializing...');
205
209
 
@@ -252,7 +256,7 @@ export class ClientServicesHost {
252
256
 
253
257
  @synchronized
254
258
  @Trace.span()
255
- async open(ctx: Context) {
259
+ async open(ctx: Context): Promise<void> {
256
260
  if (this._open) {
257
261
  return;
258
262
  }
@@ -329,7 +333,11 @@ export class ClientServicesHost {
329
333
  DataService: this._serviceContext.echoHost.dataService,
330
334
  QueryService: this._serviceContext.echoHost.queryService,
331
335
 
332
- NetworkService: new NetworkServiceImpl(this._serviceContext.networkManager, this._serviceContext.signalManager),
336
+ NetworkService: new NetworkServiceImpl(
337
+ this._serviceContext.networkManager,
338
+ this._serviceContext.signalManager,
339
+ this._edgeConnection,
340
+ ),
333
341
 
334
342
  LoggingService: this._loggingService,
335
343
  TracingService: this._tracingService,
@@ -369,7 +377,7 @@ export class ClientServicesHost {
369
377
 
370
378
  @synchronized
371
379
  @Trace.span()
372
- async close() {
380
+ async close(): Promise<void> {
373
381
  if (!this._open) {
374
382
  return;
375
383
  }
@@ -387,7 +395,7 @@ export class ClientServicesHost {
387
395
  log('closed', { deviceKey });
388
396
  }
389
397
 
390
- async reset() {
398
+ async reset(): Promise<void> {
391
399
  const traceId = PublicKey.random().toHex();
392
400
  log.trace('dxos.sdk.client-services-host.reset', trace.begin({ id: traceId }));
393
401
 
@@ -22,15 +22,15 @@ export class ServiceRegistry<Services> {
22
22
  return this._handlers;
23
23
  }
24
24
 
25
- setServices(services: Partial<Services>) {
25
+ setServices(services: Partial<Services>): void {
26
26
  this._handlers = services;
27
27
  }
28
28
 
29
- addService(name: keyof Services, service: Services[keyof Services]) {
29
+ addService(name: keyof Services, service: Services[keyof Services]): void {
30
30
  this._handlers[name] = service;
31
31
  }
32
32
 
33
- removeService(name: keyof Services) {
33
+ removeService(name: keyof Services): void {
34
34
  delete this._handlers[name];
35
35
  }
36
36
  }
@@ -2,7 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import type { DocumentId } from '@dxos/automerge/automerge-repo';
5
+ import type { DocumentId } from '@automerge/automerge-repo';
6
+
6
7
  import { assertArgument, failedInvariant, invariant } from '@dxos/invariant';
7
8
  import { log } from '@dxos/log';
8
9
  import { SpaceArchiveFileStructure, type SpaceArchiveMetadata } from '@dxos/protocols';
@@ -36,21 +36,21 @@ export class SpaceArchiveWriter extends Resource {
36
36
  return Promise.resolve();
37
37
  }
38
38
 
39
- async begin(meta: SpaceArchiveBeginProps) {
39
+ async begin(meta: SpaceArchiveBeginProps): Promise<void> {
40
40
  assertState(this._tar, 'Not open');
41
41
  assertState(!this._meta, 'Already started');
42
42
  this._meta = meta;
43
43
  this._archive = new this._tar.Archive();
44
44
  }
45
45
 
46
- async setCurrentRootUrl(url: string) {
46
+ async setCurrentRootUrl(url: string): Promise<void> {
47
47
  assertArgument(url.startsWith('automerge:'), 'Invalid root URL');
48
48
  assertState(this._tar, 'Not open');
49
49
  assertState(this._meta, 'Not started');
50
50
  this._currentRootUrl = url;
51
51
  }
52
52
 
53
- async writeDocument(documentId: string, data: Uint8Array) {
53
+ async writeDocument(documentId: string, data: Uint8Array): Promise<void> {
54
54
  assertArgument(!documentId.startsWith('automerge:'), 'Invalid document ID');
55
55
  assertState(this._archive, 'Not open');
56
56
  this._archive.addBinaryFile(`${SpaceArchiveFileStructure.documents}/${documentId}.bin`, data);