@awiki/dsh-plugin 0.3.7 → 0.3.10

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 (213) hide show
  1. package/README.md +109 -71
  2. package/README.zh.md +89 -61
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/cordis.patch.yml +6 -5
  5. package/lib/builtin-tenants.json +22 -0
  6. package/lib/builtin-tenants.sha256 +1 -0
  7. package/lib/client.js +7973 -2264
  8. package/lib/client.js.map +1 -1
  9. package/lib/index.js +3481 -1145
  10. package/lib/model-proxy-contract.js +11 -3
  11. package/lib/provider.js +73 -17
  12. package/lib/{sdk-adapter--trNlr-T.mjs → sdk-adapter-CYcJH7sM.mjs} +374 -101
  13. package/lib/typert.host.js +1595 -168
  14. package/lib/typert.remote-client.d.ts +43 -7
  15. package/lib/typert.remote-client.d.ts.map +1 -1
  16. package/lib/typert.remote-client.js +1595 -168
  17. package/lib/types/builtin-tenant-config.d.ts +19 -0
  18. package/lib/types/builtin-tenant-config.d.ts.map +1 -0
  19. package/lib/types/builtin-tenant-config.js +57 -0
  20. package/lib/types/builtin-tenant-config.js.map +1 -0
  21. package/lib/types/client/AwikiDeviceJoinReminder.d.ts +15 -0
  22. package/lib/types/client/AwikiDeviceJoinReminder.d.ts.map +1 -0
  23. package/lib/types/client/AwikiDeviceJoinReminder.js +74 -0
  24. package/lib/types/client/AwikiDeviceJoinReminder.js.map +1 -0
  25. package/lib/types/client/AwikiDevices.d.ts +33 -0
  26. package/lib/types/client/AwikiDevices.d.ts.map +1 -0
  27. package/lib/types/client/AwikiDevices.js +141 -0
  28. package/lib/types/client/AwikiDevices.js.map +1 -0
  29. package/lib/types/client/AwikiGroupDetails.d.ts.map +1 -1
  30. package/lib/types/client/AwikiGroupDetails.js +16 -13
  31. package/lib/types/client/AwikiGroupDetails.js.map +1 -1
  32. package/lib/types/client/AwikiIdentityAccess.d.ts +15 -8
  33. package/lib/types/client/AwikiIdentityAccess.d.ts.map +1 -1
  34. package/lib/types/client/AwikiIdentityAccess.js +203 -39
  35. package/lib/types/client/AwikiIdentityAccess.js.map +1 -1
  36. package/lib/types/client/AwikiIntegrationSettings.d.ts +21 -0
  37. package/lib/types/client/AwikiIntegrationSettings.d.ts.map +1 -0
  38. package/lib/types/client/AwikiIntegrationSettings.js +105 -0
  39. package/lib/types/client/AwikiIntegrationSettings.js.map +1 -0
  40. package/lib/types/client/AwikiMail.d.ts +1 -1
  41. package/lib/types/client/AwikiMail.d.ts.map +1 -1
  42. package/lib/types/client/AwikiMail.js +17 -137
  43. package/lib/types/client/AwikiMail.js.map +1 -1
  44. package/lib/types/client/AwikiOverlay.d.ts +0 -1
  45. package/lib/types/client/AwikiOverlay.d.ts.map +1 -1
  46. package/lib/types/client/AwikiOverlay.js +26 -28
  47. package/lib/types/client/AwikiOverlay.js.map +1 -1
  48. package/lib/types/client/AwikiProfileCard.d.ts.map +1 -1
  49. package/lib/types/client/AwikiProfileCard.js +17 -18
  50. package/lib/types/client/AwikiProfileCard.js.map +1 -1
  51. package/lib/types/client/AwikiRecoveryForm.d.ts +5 -1
  52. package/lib/types/client/AwikiRecoveryForm.d.ts.map +1 -1
  53. package/lib/types/client/AwikiRecoveryForm.js +73 -30
  54. package/lib/types/client/AwikiRecoveryForm.js.map +1 -1
  55. package/lib/types/client/AwikiSettingsSection.d.ts +28 -13
  56. package/lib/types/client/AwikiSettingsSection.d.ts.map +1 -1
  57. package/lib/types/client/AwikiSettingsSection.js +93 -61
  58. package/lib/types/client/AwikiSettingsSection.js.map +1 -1
  59. package/lib/types/client/AwikiUpdates.d.ts +10 -0
  60. package/lib/types/client/AwikiUpdates.d.ts.map +1 -0
  61. package/lib/types/client/AwikiUpdates.js +57 -0
  62. package/lib/types/client/AwikiUpdates.js.map +1 -0
  63. package/lib/types/client/awiki-client-bridge.d.ts +1 -1
  64. package/lib/types/client/awiki-client-bridge.d.ts.map +1 -1
  65. package/lib/types/client/awiki-client-bridge.js +4 -1
  66. package/lib/types/client/awiki-client-bridge.js.map +1 -1
  67. package/lib/types/client/controller.d.ts +84 -44
  68. package/lib/types/client/controller.d.ts.map +1 -1
  69. package/lib/types/client/controller.js +515 -309
  70. package/lib/types/client/controller.js.map +1 -1
  71. package/lib/types/client/drafts.d.ts +31 -0
  72. package/lib/types/client/drafts.d.ts.map +1 -0
  73. package/lib/types/client/drafts.js +94 -0
  74. package/lib/types/client/drafts.js.map +1 -0
  75. package/lib/types/client/image-cache.d.ts +2 -2
  76. package/lib/types/client/image-cache.d.ts.map +1 -1
  77. package/lib/types/client/image-cache.js +15 -2
  78. package/lib/types/client/image-cache.js.map +1 -1
  79. package/lib/types/client/index.d.ts.map +1 -1
  80. package/lib/types/client/index.js +63 -19
  81. package/lib/types/client/index.js.map +1 -1
  82. package/lib/types/client/integration-operation.d.ts +9 -0
  83. package/lib/types/client/integration-operation.d.ts.map +1 -0
  84. package/lib/types/client/integration-operation.js +54 -0
  85. package/lib/types/client/integration-operation.js.map +1 -0
  86. package/lib/types/client/mail-list-cache.d.ts +2 -0
  87. package/lib/types/client/mail-list-cache.d.ts.map +1 -1
  88. package/lib/types/client/mail-list-cache.js +18 -0
  89. package/lib/types/client/mail-list-cache.js.map +1 -1
  90. package/lib/types/client/otp-cooldown.d.ts +6 -0
  91. package/lib/types/client/otp-cooldown.d.ts.map +1 -0
  92. package/lib/types/client/otp-cooldown.js +18 -0
  93. package/lib/types/client/otp-cooldown.js.map +1 -0
  94. package/lib/types/client/settings-controller.d.ts +34 -0
  95. package/lib/types/client/settings-controller.d.ts.map +1 -1
  96. package/lib/types/client/settings-controller.js +182 -2
  97. package/lib/types/client/settings-controller.js.map +1 -1
  98. package/lib/types/client/settings-locales.d.ts +1 -1
  99. package/lib/types/client/settings-locales.d.ts.map +1 -1
  100. package/lib/types/client/settings-locales.js +192 -14
  101. package/lib/types/client/settings-locales.js.map +1 -1
  102. package/lib/types/client/slots.d.ts +20 -10
  103. package/lib/types/client/slots.d.ts.map +1 -1
  104. package/lib/types/client/slots.js +0 -1
  105. package/lib/types/client/slots.js.map +1 -1
  106. package/lib/types/conversation-preferences.d.ts.map +1 -1
  107. package/lib/types/conversation-preferences.js +0 -17
  108. package/lib/types/conversation-preferences.js.map +1 -1
  109. package/lib/types/desktop-distribution.d.ts +25 -0
  110. package/lib/types/desktop-distribution.d.ts.map +1 -0
  111. package/lib/types/desktop-distribution.js +57 -0
  112. package/lib/types/desktop-distribution.js.map +1 -0
  113. package/lib/types/domain.d.ts +1 -1
  114. package/lib/types/domain.d.ts.map +1 -1
  115. package/lib/types/domain.js +2 -1
  116. package/lib/types/domain.js.map +1 -1
  117. package/lib/types/index.d.ts +164 -41
  118. package/lib/types/index.d.ts.map +1 -1
  119. package/lib/types/index.js +1562 -529
  120. package/lib/types/index.js.map +1 -1
  121. package/lib/types/integration-client.d.ts +17 -0
  122. package/lib/types/integration-client.d.ts.map +1 -0
  123. package/lib/types/integration-client.js +233 -0
  124. package/lib/types/integration-client.js.map +1 -0
  125. package/lib/types/legacy-sent-mail-cache.d.ts +4 -0
  126. package/lib/types/legacy-sent-mail-cache.d.ts.map +1 -0
  127. package/lib/types/legacy-sent-mail-cache.js +29 -0
  128. package/lib/types/legacy-sent-mail-cache.js.map +1 -0
  129. package/lib/types/listener-state.d.ts +5 -3
  130. package/lib/types/listener-state.d.ts.map +1 -1
  131. package/lib/types/listener-state.js +28 -13
  132. package/lib/types/listener-state.js.map +1 -1
  133. package/lib/types/listener.d.ts +9 -32
  134. package/lib/types/listener.d.ts.map +1 -1
  135. package/lib/types/listener.js +11 -127
  136. package/lib/types/listener.js.map +1 -1
  137. package/lib/types/mail-list-client.d.ts +12 -0
  138. package/lib/types/mail-list-client.d.ts.map +1 -0
  139. package/lib/types/mail-list-client.js +254 -0
  140. package/lib/types/mail-list-client.js.map +1 -0
  141. package/lib/types/mail-recovery-observability.d.ts +8 -0
  142. package/lib/types/mail-recovery-observability.d.ts.map +1 -0
  143. package/lib/types/mail-recovery-observability.js +119 -0
  144. package/lib/types/mail-recovery-observability.js.map +1 -0
  145. package/lib/types/mail.d.ts +2 -28
  146. package/lib/types/mail.d.ts.map +1 -1
  147. package/lib/types/mail.js +2 -79
  148. package/lib/types/mail.js.map +1 -1
  149. package/lib/types/model-proxy-contract.d.ts.map +1 -1
  150. package/lib/types/model-proxy-contract.js +7 -0
  151. package/lib/types/model-proxy-contract.js.map +1 -1
  152. package/lib/types/package-version.generated.d.ts +4 -0
  153. package/lib/types/package-version.generated.d.ts.map +1 -0
  154. package/lib/types/package-version.generated.js +4 -0
  155. package/lib/types/package-version.generated.js.map +1 -0
  156. package/lib/types/profile-state.d.ts +2 -13
  157. package/lib/types/profile-state.d.ts.map +1 -1
  158. package/lib/types/profile-state.js +3 -20
  159. package/lib/types/profile-state.js.map +1 -1
  160. package/lib/types/provider-api.d.ts +134 -43
  161. package/lib/types/provider-api.d.ts.map +1 -1
  162. package/lib/types/provider.d.ts +8 -2
  163. package/lib/types/provider.d.ts.map +1 -1
  164. package/lib/types/provider.js +76 -16
  165. package/lib/types/provider.js.map +1 -1
  166. package/lib/types/realtime-supervisor.d.ts +60 -0
  167. package/lib/types/realtime-supervisor.d.ts.map +1 -0
  168. package/lib/types/realtime-supervisor.js +255 -0
  169. package/lib/types/realtime-supervisor.js.map +1 -0
  170. package/lib/types/sdk-adapter.d.ts +62 -11
  171. package/lib/types/sdk-adapter.d.ts.map +1 -1
  172. package/lib/types/sdk-adapter.js +285 -123
  173. package/lib/types/sdk-adapter.js.map +1 -1
  174. package/lib/types/settings-rpc-contract.d.ts +58 -0
  175. package/lib/types/settings-rpc-contract.d.ts.map +1 -1
  176. package/lib/types/settings-rpc-contract.js +103 -0
  177. package/lib/types/settings-rpc-contract.js.map +1 -1
  178. package/lib/types/settings-rpc.d.ts +14 -1
  179. package/lib/types/settings-rpc.d.ts.map +1 -1
  180. package/lib/types/settings-rpc.js +130 -1
  181. package/lib/types/settings-rpc.js.map +1 -1
  182. package/lib/types/tenant-registry.d.ts +74 -0
  183. package/lib/types/tenant-registry.d.ts.map +1 -0
  184. package/lib/types/tenant-registry.js +440 -0
  185. package/lib/types/tenant-registry.js.map +1 -0
  186. package/lib/types/tools.d.ts +1 -1
  187. package/lib/types/tools.d.ts.map +1 -1
  188. package/lib/types/tools.js +4 -20
  189. package/lib/types/tools.js.map +1 -1
  190. package/lib/types/types.d.ts +249 -66
  191. package/lib/types/types.d.ts.map +1 -1
  192. package/lib/types/types.js.map +1 -1
  193. package/lib/types/update-policy.d.ts +51 -0
  194. package/lib/types/update-policy.d.ts.map +1 -0
  195. package/lib/types/update-policy.js +379 -0
  196. package/lib/types/update-policy.js.map +1 -0
  197. package/lib/types/version.d.ts +4 -0
  198. package/lib/types/version.d.ts.map +1 -0
  199. package/lib/types/version.js +44 -0
  200. package/lib/types/version.js.map +1 -0
  201. package/package.json +26 -8
  202. package/lib/types/base64.d.ts +0 -4
  203. package/lib/types/base64.d.ts.map +0 -1
  204. package/lib/types/base64.js +0 -28
  205. package/lib/types/base64.js.map +0 -1
  206. package/lib/types/client/mail-attachment.d.ts +0 -40
  207. package/lib/types/client/mail-attachment.d.ts.map +0 -1
  208. package/lib/types/client/mail-attachment.js +0 -187
  209. package/lib/types/client/mail-attachment.js.map +0 -1
  210. package/lib/types/sent-mail-store.d.ts +0 -27
  211. package/lib/types/sent-mail-store.d.ts.map +0 -1
  212. package/lib/types/sent-mail-store.js +0 -348
  213. package/lib/types/sent-mail-store.js.map +0 -1
@@ -1,4 +1,5 @@
1
1
  /** Rust IM Core adapter that copies native values into Host-owned public DTOs. */
2
+ import { mailRecoveryFailureFields } from "./mail-recovery-observability.js";
2
3
  const GROUP_LOOKUP_LIMIT = 100;
3
4
  const MAX_GROUP_LOOKUP_PAGES = 20;
4
5
  const RUST_FAILURE_CODES = {
@@ -16,14 +17,16 @@ const RUST_FAILURE_CODES = {
16
17
  permission_denied: 'forbidden',
17
18
  group_not_member: 'group-membership-required',
18
19
  group_identity_stale: 'group-identity-stale',
19
- auth_revoked: 'identity-recovery-required',
20
+ auth_revoked: 'device-rejoin-required',
21
+ local_identity_recovery_required: 'identity-recovery-required',
20
22
  conflict: 'conflict',
21
23
  join_required: 'handle-unavailable',
22
- state_in_use: 'state-in-use',
24
+ state_in_use: 'conflict',
23
25
  rate_limited: 'rate-limited',
24
26
  timeout: 'network',
25
27
  transport_unavailable: 'network',
26
28
  sync_failed: 'network',
29
+ sync_blocked: 'conflict',
27
30
  session_expired: 'network',
28
31
  attachment_transfer_network: 'network',
29
32
  recovery_reconciliation_unavailable: 'network',
@@ -32,15 +35,72 @@ const RUST_FAILURE_CODES = {
32
35
  /** Closed provider error consumed by the Host's fixed public failure mapping. */
33
36
  export class AwikiSdkError extends Error {
34
37
  code;
38
+ realtimeFailureCode;
35
39
  name = 'AwikiSdkError';
36
- constructor(code) {
40
+ mail_ingress_classification;
41
+ auth_status_class;
42
+ auth_stable_machine_code;
43
+ retryable;
44
+ mail_closed_classification;
45
+ constructor(code, realtimeFailureCode, mailRecoveryFailure) {
37
46
  super(`AWiki SDK operation failed: ${code}`);
38
47
  this.code = code;
48
+ this.realtimeFailureCode = realtimeFailureCode;
49
+ if (mailRecoveryFailure !== undefined)
50
+ Object.assign(this, mailRecoveryFailure);
39
51
  }
40
52
  }
41
53
  function fail(code = 'remote') {
42
54
  throw new AwikiSdkError(code);
43
55
  }
56
+ const REALTIME_RETRY_WARNING_PRIORITY = [
57
+ 'sync.retry.local_state.actor_closed',
58
+ 'sync.retry.local_state.database_busy',
59
+ 'sync.retry.local_state.constraint_failed',
60
+ 'sync.retry.local_state.schema_unavailable',
61
+ 'sync.retry.local_state.storage_unavailable',
62
+ 'sync.retry.local_state.codec_unavailable',
63
+ 'sync.retry.local_state.other',
64
+ 'sync.retry.transport_unavailable',
65
+ 'sync.retry.service_unavailable',
66
+ 'sync.retry.local_state_unavailable',
67
+ ];
68
+ function realtimeSyncFailureCode(status, warnings, errorCode) {
69
+ if (status === 'retryable_failure') {
70
+ return REALTIME_RETRY_WARNING_PRIORITY.find(code => warnings.includes(code))
71
+ ?? 'sync.retryable_failure';
72
+ }
73
+ if (status === 'recovery_required')
74
+ return 'sync.recovery_required';
75
+ if (status === 'auth_revoked')
76
+ return 'sync.auth_revoked';
77
+ if (status === 'blocked') {
78
+ if (errorCode === 'sync.client_upgrade_required') {
79
+ return 'sync.blocked.client_upgrade_required';
80
+ }
81
+ if (errorCode === 'device_reprovision_required') {
82
+ return 'sync.blocked.device_reprovision_required';
83
+ }
84
+ if (errorCode === 'server_repair_required') {
85
+ return 'sync.blocked.server_repair_required';
86
+ }
87
+ if (errorCode === 'sync.snapshot_item_too_large'
88
+ || errorCode === 'sync.snapshot_required_state_too_large') {
89
+ return 'sync.blocked.snapshot_capacity';
90
+ }
91
+ if (errorCode === 'sync.invalid_request')
92
+ return 'sync.blocked.invalid_request';
93
+ if (errorCode === 'sync.invalid_cursor')
94
+ return 'sync.blocked.invalid_cursor';
95
+ return errorCode === undefined ? 'sync.blocked' : 'sync.blocked.other';
96
+ }
97
+ return 'sync.unexpected_status';
98
+ }
99
+ function syncResultErrorCode(result) {
100
+ if (!('errorCode' in result))
101
+ return undefined;
102
+ return typeof result.errorCode === 'string' ? result.errorCode : undefined;
103
+ }
44
104
  function mapError(error, ambiguousSend = false) {
45
105
  if (error instanceof AwikiSdkError)
46
106
  throw error;
@@ -56,7 +116,7 @@ function mapError(error, ambiguousSend = false) {
56
116
  }
57
117
  }
58
118
  catch { }
59
- fail(code);
119
+ throw new AwikiSdkError(code, undefined, mailRecoveryFailureFields(error));
60
120
  }
61
121
  function safeInteger(value, minimum = 0) {
62
122
  if (!/^(?:0|[1-9]\d*)$/u.test(value))
@@ -111,24 +171,6 @@ function mailAddress(value) {
111
171
  fail();
112
172
  return value;
113
173
  }
114
- function mailFileName(value) {
115
- if (typeof value !== 'string'
116
- || value.length === 0
117
- || value.trim() !== value
118
- || value.replace(/[. ]+$/u, '') !== value
119
- || value === '.'
120
- || value === '..'
121
- || Buffer.byteLength(value, 'utf8') > 255
122
- || /[\\/\p{C}]/u.test(value))
123
- fail();
124
- return value;
125
- }
126
- function mailContentType(value) {
127
- if (typeof value !== 'string'
128
- || !/^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+$/u.test(value))
129
- fail();
130
- return value;
131
- }
132
174
  function mailAddresses(value) {
133
175
  if (!Array.isArray(value) || value.length > 100)
134
176
  fail();
@@ -148,14 +190,6 @@ function uint32(value) {
148
190
  fail();
149
191
  return value;
150
192
  }
151
- function recoveryE2eeGroupCount(impact) {
152
- if (typeof impact !== 'object' || impact === null)
153
- fail();
154
- const value = impact;
155
- return uint32(value.unsupportedE2eeGroupCount !== undefined
156
- ? value.unsupportedE2eeGroupCount
157
- : value.unsupportedE2EeGroupCount);
158
- }
159
193
  function boolean(value) {
160
194
  if (typeof value !== 'boolean')
161
195
  fail();
@@ -254,6 +288,26 @@ function identity(value) {
254
288
  registeredAt: safeInteger(value.registeredAtMs),
255
289
  };
256
290
  }
291
+ function joinProgress(value) {
292
+ return {
293
+ joinSessionId: required(value.joinSessionId),
294
+ localPhase: value.localPhase,
295
+ remoteState: value.remoteState,
296
+ expiresAt: required(value.expiresAt),
297
+ ...value.sas === undefined ? {} : { sas: required(value.sas) },
298
+ completed: boolean(value.completed),
299
+ ...value.identity === undefined ? {} : { identity: identity(value.identity) },
300
+ };
301
+ }
302
+ function adminJoinProgress(value) {
303
+ return {
304
+ joinSessionId: required(value.joinSessionId),
305
+ localPhase: value.localPhase,
306
+ remoteState: value.remoteState,
307
+ expiresAt: required(value.expiresAt),
308
+ ...value.sas === undefined ? {} : { sas: required(value.sas) },
309
+ };
310
+ }
257
311
  function profile(value) {
258
312
  return {
259
313
  did: required(value.did),
@@ -377,20 +431,51 @@ function externalHttpAttempt(value) {
377
431
  }
378
432
  /** Adapt the Rust Node bridge to the frozen Host provider interface. */
379
433
  export class RustSdkAdapter {
434
+ trustedUserPresenceSupported = process.platform === 'darwin' && process.arch === 'x64';
380
435
  client;
436
+ refreshingDisplayPeers = new Set();
437
+ scheduleDisplayRefresh(client, peers) {
438
+ if (this.disposal !== undefined)
439
+ return;
440
+ const pending = [...new Set(peers)].filter(peer => peer.startsWith('did:') && !this.refreshingDisplayPeers.has(peer)).slice(0, 100);
441
+ if (pending.length === 0)
442
+ return;
443
+ for (const peer of pending)
444
+ this.refreshingDisplayPeers.add(peer);
445
+ void client.refreshDisplayProfiles({ peers: pending }).catch(() => undefined).finally(() => {
446
+ for (const peer of pending)
447
+ this.refreshingDisplayPeers.delete(peer);
448
+ });
449
+ }
450
+ getDisplayProfiles(peers) {
451
+ return this.run(async (client) => {
452
+ const profiles = await client.hydrateDisplayProfiles({ peers });
453
+ this.scheduleDisplayRefresh(client, peers);
454
+ return profiles.flatMap(profile => profile.did === undefined ? [] : [{
455
+ did: profile.did, cacheHit: profile.cacheHit,
456
+ ...profile.handle === undefined ? {} : { handle: profile.handle },
457
+ ...profile.displayName === undefined ? {} : { displayName: profile.displayName },
458
+ }]);
459
+ });
460
+ }
381
461
  attachmentConversations = new Map();
382
462
  disposal;
463
+ realtime;
464
+ agentInbox;
383
465
  listener;
384
466
  constructor(client) {
385
467
  this.client = Promise.resolve(client);
386
- this.listener = {
468
+ this.realtime = {
387
469
  syncNow: reason => this.listenerSyncNow(reason),
388
470
  startRealtime: () => this.listenerStartRealtime(),
471
+ };
472
+ this.agentInbox = {
389
473
  listConversations: request => this.listenerConversations(request),
390
474
  getHistory: request => this.listenerHistory(request),
391
475
  markConversationRead: conversationId => this.markConversationRead(conversationId),
392
476
  sendText: request => this.sendText(request),
393
477
  };
478
+ this.listener = { ...this.realtime, ...this.agentInbox };
394
479
  }
395
480
  async run(operation, ambiguousSend = false) {
396
481
  try {
@@ -404,13 +489,12 @@ export class RustSdkAdapter {
404
489
  const messages = values.filter(displayableMessage);
405
490
  const peers = [...new Set(messages
406
491
  .filter(message => (message.conversationKind === 'group'
407
- && !message.outgoing
408
- && message.senderHandle === undefined
409
- && message.senderDisplayName === undefined))
492
+ && !message.outgoing))
410
493
  .map(message => message.senderDid))];
411
494
  if (peers.length === 0)
412
495
  return [...messages];
413
496
  const profiles = await client.hydrateDisplayProfiles({ peers });
497
+ this.scheduleDisplayRefresh(client, peers);
414
498
  const byDid = new Map();
415
499
  for (const profile of profiles) {
416
500
  if (profile.did !== undefined)
@@ -418,10 +502,11 @@ export class RustSdkAdapter {
418
502
  }
419
503
  return messages.map((message) => {
420
504
  const profile = byDid.get(message.senderDid);
421
- if (profile === undefined)
505
+ if (profile === undefined || !profile.cacheHit)
422
506
  return message;
507
+ const { senderDisplayName: _snapshot, ...rest } = message;
423
508
  return {
424
- ...message,
509
+ ...rest,
425
510
  ...profile.handle === undefined ? {} : { senderHandle: profile.handle },
426
511
  ...profile.displayName === undefined ? {} : { senderDisplayName: profile.displayName },
427
512
  };
@@ -567,7 +652,7 @@ export class RustSdkAdapter {
567
652
  ...value.peerPersonaId === undefined ? {} : { peerPersonaId: value.peerPersonaId },
568
653
  ...value.did === undefined ? {} : { did: value.did },
569
654
  ...value.credentialDid === undefined ? {} : { credentialDid: value.credentialDid },
570
- ...value.handle === undefined ? {} : { handle: value.handle },
655
+ ...(profile?.handle ?? value.handle) === undefined ? {} : { handle: (profile?.handle ?? value.handle) },
571
656
  ...profile?.displayName === undefined ? {} : { displayName: profile.displayName },
572
657
  ...value.role === undefined ? {} : { role: value.role },
573
658
  ...value.status === undefined ? {} : { status: value.status },
@@ -608,11 +693,14 @@ export class RustSdkAdapter {
608
693
  listenerSyncNow(reason) {
609
694
  return this.run(async (client) => {
610
695
  const result = await client.syncNow({ reason });
611
- if (result.status === 'idle' || result.status === 'changed')
612
- return;
613
- if (result.status === 'auth_revoked')
614
- fail('identity-recovery-required');
615
- fail('network');
696
+ if (result.status === 'idle' || result.status === 'changed') {
697
+ return {
698
+ pagesFetched: uint32(result.pagesFetched),
699
+ messagesHydrated: uint32(result.messagesHydrated),
700
+ olderHistoryExcluded: boolean(result.olderHistoryExcluded),
701
+ };
702
+ }
703
+ throw new AwikiSdkError(result.status === 'auth_revoked' ? 'device-rejoin-required' : 'network', realtimeSyncFailureCode(result.status, result.warnings, syncResultErrorCode(result)));
616
704
  });
617
705
  }
618
706
  listenerStartRealtime() {
@@ -620,6 +708,10 @@ export class RustSdkAdapter {
620
708
  const session = await client.startRealtime();
621
709
  return {
622
710
  nextEvent: () => this.run(() => session.nextEvent()),
711
+ getStatus: () => this.run(async () => {
712
+ const status = await session.getStatus();
713
+ return { connected: status.connected };
714
+ }),
623
715
  stop: () => this.run(() => session.stop()),
624
716
  };
625
717
  });
@@ -676,7 +768,137 @@ export class RustSdkAdapter {
676
768
  });
677
769
  }
678
770
  registerIdentity(request) {
679
- return this.run(async (client) => identity(await client.completeRegistration(request)));
771
+ return this.run(async (client) => {
772
+ const value = await client.completeRegistrationWithOutcome(request);
773
+ if (value.status === 'registered') {
774
+ return { status: 'registered', identity: identity(value.identity) };
775
+ }
776
+ return {
777
+ status: 'join-required',
778
+ continuationId: required(value.existingHandle.continuationId),
779
+ fullHandle: required(value.existingHandle.fullHandle),
780
+ mode: value.existingHandle.mode === 'handle_recovery_rebind'
781
+ ? 'handle-recovery-rebind'
782
+ : 'ordinary',
783
+ requiresUserPresence: boolean(value.existingHandle.requiresUserPresence),
784
+ };
785
+ });
786
+ }
787
+ beginDeviceJoin(request) {
788
+ return this.run(async (client) => joinProgress(await client.beginPreparedRegistrationJoin(request)));
789
+ }
790
+ getDeviceJoinStatus(joinSessionId) {
791
+ return this.run(async (client) => joinProgress(await client.resumePreparedRegistrationJoin({ joinSessionId })));
792
+ }
793
+ listLocalDeviceJoinSessions() {
794
+ return this.run(async (client) => (await client.listLocalDeviceJoinSessions()).map(value => ({
795
+ joinSessionId: required(value.joinSessionId),
796
+ side: value.side,
797
+ localPhase: value.localPhase,
798
+ expiresAt: required(value.expiresAt),
799
+ })));
800
+ }
801
+ cancelDeviceJoin(joinSessionId) {
802
+ return this.run(async (client) => {
803
+ const value = await client.cancelPreparedRegistrationJoin({ joinSessionId });
804
+ return {
805
+ joinSessionId: required(value.joinSessionId),
806
+ side: value.side,
807
+ localPhase: value.localPhase,
808
+ expiresAt: required(value.expiresAt),
809
+ };
810
+ });
811
+ }
812
+ getCurrentDeviceSummary() {
813
+ return this.run(async (client) => {
814
+ const value = await client.getCurrentDeviceSummary();
815
+ return {
816
+ ...value.role === undefined ? {} : { role: value.role },
817
+ readiness: value.readiness,
818
+ canManage: boolean(value.canManage),
819
+ };
820
+ });
821
+ }
822
+ syncDeviceManagement() {
823
+ return this.run(async (client) => {
824
+ await client.syncNow({ reason: 'foreground_reconcile' });
825
+ });
826
+ }
827
+ getDeviceRegistry() {
828
+ return this.run(async (client) => (await client.getDeviceRegistry()).devices.map(value => ({
829
+ deviceId: required(value.protocolDeviceId),
830
+ status: value.status,
831
+ role: value.role,
832
+ managementReady: boolean(value.managementReady),
833
+ isCurrent: boolean(value.isCurrent),
834
+ })));
835
+ }
836
+ listLocalDeviceJoinRequests() {
837
+ return this.run(async (client) => (await client.listLocalDeviceJoinRequests()).map(value => ({
838
+ joinSessionId: required(value.joinSessionId),
839
+ protocolDeviceId: required(value.protocolDeviceId),
840
+ candidateKeyFingerprint: required(value.candidateKeyFingerprint),
841
+ issuedAt: required(value.issuedAt),
842
+ expiresAt: required(value.expiresAt),
843
+ state: value.state,
844
+ claimedByCurrentDevice: boolean(value.claimedByCurrentDevice),
845
+ canStartVerification: boolean(value.canStartVerification),
846
+ })));
847
+ }
848
+ startDeviceJoinVerification(request) {
849
+ return this.run(async (client) => adminJoinProgress(await client.startDeviceJoinVerification(request)));
850
+ }
851
+ getLocalDeviceJoinVerificationProgress(joinSessionId) {
852
+ return this.run(async (client) => adminJoinProgress(await client.getLocalDeviceJoinVerificationProgress({ joinSessionId })));
853
+ }
854
+ prepareDeviceJoinApproval(joinSessionId) {
855
+ return this.run(async (client) => {
856
+ const value = await client.prepareDeviceJoinApproval({ joinSessionId, sasConfirmed: true });
857
+ return { approvalHandle: required(value.approvalHandle) };
858
+ });
859
+ }
860
+ confirmDeviceJoinApproval(approvalHandle) {
861
+ return this.run(async (client) => adminJoinProgress(await client.confirmDeviceJoinApproval({
862
+ approvalHandle,
863
+ userPresenceConfirmed: true,
864
+ })));
865
+ }
866
+ rejectDeviceJoin(joinSessionId, reason) {
867
+ return this.run(async (client) => adminJoinProgress(await client.rejectDeviceJoin({ joinSessionId, reason })));
868
+ }
869
+ revokeDevice(deviceId) {
870
+ return this.run(async (client) => {
871
+ await client.revokeDevice({ targetDeviceId: deviceId, userPresenceConfirmed: true });
872
+ });
873
+ }
874
+ confirmUserPresence(reason) {
875
+ return this.run(client => client.confirmUserPresence({ reason }));
876
+ }
877
+ prepareRootKeyTransfer(deviceId) {
878
+ return this.run(async (client) => {
879
+ const value = await client.prepareRootKeyTransfer({ recipientDeviceId: deviceId });
880
+ return {
881
+ authorizationHandle: required(value.authorizationHandle),
882
+ recipient: {
883
+ did: required(value.recipient.did),
884
+ deviceId: required(value.recipient.deviceId),
885
+ registryVersion: required(value.recipient.registryVersion),
886
+ },
887
+ expiresAt: required(value.expiresAt),
888
+ };
889
+ });
890
+ }
891
+ confirmAndSendRootKeyTransfer(authorizationHandle) {
892
+ return this.run(async (client) => {
893
+ const value = await client.confirmAndSendRootKeyTransfer({
894
+ authorizationHandle,
895
+ userPresenceConfirmed: true,
896
+ });
897
+ return {
898
+ recipientDeviceId: required(value.recipientDeviceId),
899
+ acceptedAt: required(value.acceptedAt),
900
+ };
901
+ });
680
902
  }
681
903
  updateDisplayName(request) {
682
904
  return this.run(async (client) => identity(await client.updateDisplayName(request.displayName)));
@@ -698,12 +920,11 @@ export class RustSdkAdapter {
698
920
  ...value.previousDid === undefined ? {} : { previousDid: value.previousDid },
699
921
  currentDid: required(value.currentDid),
700
922
  phase: value.phase,
923
+ allowedActions: [...(value.allowedActions ?? [])],
701
924
  ...value.failureCode === undefined ? {} : { failureCode: value.failureCode },
702
925
  retryable: boolean(value.retryable),
703
926
  localOrdinaryDataWillMigrate: boolean(value.impact.localOrdinaryDataWillMigrate),
704
927
  otherDevicesMustRejoin: boolean(value.impact.otherDevicesMustRejoin),
705
- unsupportedE2eeGroupCount: recoveryE2eeGroupCount(value.impact),
706
- unsupportedDidOnlyGroupCount: uint32(value.impact.unsupportedDidOnlyGroupCount),
707
928
  };
708
929
  }
709
930
  sendRecoveryOtp(request) {
@@ -723,21 +944,17 @@ export class RustSdkAdapter {
723
944
  activateRecovery(request) {
724
945
  return this.run(async (client) => this.recoveryProgress(await client.activateHandleRecovery(request)));
725
946
  }
947
+ listPendingRecoveries() {
948
+ return this.run(async (client) => (await client.listPendingHandleRecoveryOperations()).map(value => ({
949
+ operationId: required(value.operationId), fullHandle: required(value.fullHandle),
950
+ })));
951
+ }
726
952
  getRecoveryStatus(request) {
727
953
  return this.run(async (client) => this.recoveryProgress(await client.getHandleRecoveryStatus(request)));
728
954
  }
729
955
  resumeRecovery(request) {
730
956
  return this.run(async (client) => this.recoveryProgress(await client.resumeHandleRecovery(request)));
731
957
  }
732
- issueRecoveryAttestation(request) {
733
- return this.run(async (client) => {
734
- const value = await client.issueHandleRecoveryAttestation(request);
735
- return {
736
- attestation: required(value.attestation),
737
- expiresAt: required(value.expiresAt),
738
- };
739
- });
740
- }
741
958
  discardRecovery(request) {
742
959
  return this.run(async (client) => {
743
960
  await client.discardHandleRecovery(request);
@@ -781,6 +998,7 @@ export class RustSdkAdapter {
781
998
  });
782
999
  const peers = [...new Set(value.items.flatMap(member => member.did ?? member.handle ?? []))];
783
1000
  const profiles = peers.length === 0 ? [] : await client.hydrateDisplayProfiles({ peers });
1001
+ this.scheduleDisplayRefresh(client, peers);
784
1002
  const byPeer = new Map();
785
1003
  for (const [index, profile] of profiles.entries()) {
786
1004
  const requested = peers[index];
@@ -808,48 +1026,6 @@ export class RustSdkAdapter {
808
1026
  member,
809
1027
  })));
810
1028
  }
811
- resumeGroupRebindRecovery() {
812
- return this.run(async (client) => {
813
- const value = await client.resumeGroupRebindRecovery(100);
814
- const journal = value;
815
- const statuses = new Map();
816
- for (const item of journal.items ?? []) {
817
- const { groupDid: rawGroupDid, layer: rawLayer, phase: rawPhase } = item;
818
- if (typeof rawGroupDid !== 'string'
819
- || typeof rawLayer !== 'string'
820
- || typeof rawPhase !== 'string'
821
- || typeof item.blocked !== 'boolean') {
822
- throw new TypeError('invalid group recovery item');
823
- }
824
- const groupDid = required(rawGroupDid);
825
- const layer = required(rawLayer);
826
- const phase = required(rawPhase);
827
- if (layer !== 'p4' && layer !== 'p6')
828
- throw new TypeError('invalid group recovery item');
829
- if (phase === 'complete')
830
- continue;
831
- const status = item.blocked || phase === 'blocked' ? 'blocked' : 'pending';
832
- if (statuses.get(groupDid) !== 'blocked')
833
- statuses.set(groupDid, status);
834
- }
835
- for (const group of journal.sendPausedGroups ?? []) {
836
- if (typeof group !== 'string')
837
- throw new TypeError('invalid paused recovery group');
838
- const groupDid = required(group);
839
- if (!statuses.has(groupDid))
840
- statuses.set(groupDid, 'pending');
841
- }
842
- const items = [...statuses].map(([groupDid, status]) => ({ groupDid, status }));
843
- const hasJournal = journal.items !== undefined || journal.sendPausedGroups !== undefined;
844
- return {
845
- processed: uint32(value.processed),
846
- completed: uint32(value.completed),
847
- pending: hasJournal ? items.filter(item => item.status === 'pending').length : uint32(value.pending),
848
- blocked: hasJournal ? items.filter(item => item.status === 'blocked').length : uint32(value.blocked),
849
- items,
850
- };
851
- });
852
- }
853
1029
  listConversations(request) {
854
1030
  return this.run(async (client) => {
855
1031
  const conversations = await client.listConversations(request);
@@ -968,21 +1144,12 @@ export class RustSdkAdapter {
968
1144
  });
969
1145
  }
970
1146
  sendMail(request) {
971
- const attachments = request.attachments?.map(attachment => ({
972
- fileName: attachment.fileName,
973
- contentType: attachment.contentType,
974
- bytes: Uint8Array.from(attachment.bytes),
975
- }));
976
1147
  return this.run(async (client) => {
977
- const input = {
1148
+ const value = await client.sendMail({
978
1149
  to: [...request.to],
979
1150
  ...request.cc === undefined ? {} : { cc: [...request.cc] },
980
1151
  subject: request.subject,
981
1152
  bodyText: request.bodyText,
982
- };
983
- const value = await client.sendMail({
984
- ...input,
985
- ...attachments === undefined || attachments.length === 0 ? {} : { attachments },
986
1153
  });
987
1154
  if (!Array.isArray(value.warnings) || value.warnings.length > 100)
988
1155
  fail();
@@ -996,26 +1163,21 @@ export class RustSdkAdapter {
996
1163
  };
997
1164
  }, true);
998
1165
  }
999
- downloadMailAttachment(request) {
1000
- return this.run(async (client) => {
1001
- const value = await client.downloadMailAttachment({
1002
- messageId: mailToken(request.messageId, 2_048),
1003
- attachmentIndex: uint32(request.attachmentIndex),
1004
- });
1005
- const sizeBytes = safeInteger(remoteString(value.sizeBytes, 20));
1006
- if (!(value.bytes instanceof Uint8Array) || value.bytes.byteLength !== sizeBytes)
1007
- fail();
1008
- return {
1009
- fileName: mailFileName(value.fileName),
1010
- contentType: mailContentType(value.contentType),
1011
- sizeBytes,
1012
- bytes: Uint8Array.from(value.bytes),
1013
- };
1014
- });
1015
- }
1016
1166
  clearLocalData() {
1017
1167
  return this.run(client => client.clearLocalData());
1018
1168
  }
1169
+ retireDefaultIdentityForRejoin() {
1170
+ return this.run((client) => {
1171
+ const retire = client.retireDefaultIdentityForRejoin;
1172
+ if (typeof retire !== 'function') {
1173
+ throw Object.assign(new Error('device rejoin is unavailable in this IM Core build'), {
1174
+ name: 'AwikiSdkError',
1175
+ code: 'remote',
1176
+ });
1177
+ }
1178
+ return retire.call(client);
1179
+ });
1180
+ }
1019
1181
  dispose() {
1020
1182
  this.disposal ??= this.client.then(async (client) => {
1021
1183
  try {