@awiki/dsh-plugin 0.3.10 → 0.3.11-rc.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 (126) hide show
  1. package/README.md +14 -5
  2. package/README.zh.md +11 -4
  3. package/lib/client.js +2067 -272
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +536 -167
  6. package/lib/model-proxy-contract.js +8 -8
  7. package/lib/provider.js +32 -2
  8. package/lib/{sdk-adapter-CYcJH7sM.mjs → sdk-adapter-DpqT2en9.mjs} +17 -7
  9. package/lib/typert.host.js +181 -117
  10. package/lib/typert.remote-client.d.ts +3 -1
  11. package/lib/typert.remote-client.d.ts.map +1 -1
  12. package/lib/typert.remote-client.js +181 -117
  13. package/lib/types/base64.d.ts +4 -0
  14. package/lib/types/base64.d.ts.map +1 -0
  15. package/lib/types/base64.js +28 -0
  16. package/lib/types/base64.js.map +1 -0
  17. package/lib/types/client/AwikiIdentityAccess.d.ts +6 -4
  18. package/lib/types/client/AwikiIdentityAccess.d.ts.map +1 -1
  19. package/lib/types/client/AwikiIdentityAccess.js +147 -58
  20. package/lib/types/client/AwikiIdentityAccess.js.map +1 -1
  21. package/lib/types/client/AwikiMail.d.ts +1 -1
  22. package/lib/types/client/AwikiMail.d.ts.map +1 -1
  23. package/lib/types/client/AwikiMail.js +139 -6
  24. package/lib/types/client/AwikiMail.js.map +1 -1
  25. package/lib/types/client/AwikiOverlay.js +2 -2
  26. package/lib/types/client/AwikiOverlay.js.map +1 -1
  27. package/lib/types/client/AwikiRecoveryForm.d.ts +1 -0
  28. package/lib/types/client/AwikiRecoveryForm.d.ts.map +1 -1
  29. package/lib/types/client/AwikiRecoveryForm.js +3 -2
  30. package/lib/types/client/AwikiRecoveryForm.js.map +1 -1
  31. package/lib/types/client/AwikiSettingsSection.d.ts +1 -1
  32. package/lib/types/client/AwikiSettingsSection.d.ts.map +1 -1
  33. package/lib/types/client/awiki-client-bridge.d.ts +1 -1
  34. package/lib/types/client/awiki-client-bridge.d.ts.map +1 -1
  35. package/lib/types/client/awiki-client-bridge.js +1 -1
  36. package/lib/types/client/awiki-client-bridge.js.map +1 -1
  37. package/lib/types/client/controller.d.ts +15 -1
  38. package/lib/types/client/controller.d.ts.map +1 -1
  39. package/lib/types/client/controller.js +303 -54
  40. package/lib/types/client/controller.js.map +1 -1
  41. package/lib/types/client/index.d.ts +1 -1
  42. package/lib/types/client/index.d.ts.map +1 -1
  43. package/lib/types/client/index.js +4 -1
  44. package/lib/types/client/index.js.map +1 -1
  45. package/lib/types/client/mail-attachment.d.ts +40 -0
  46. package/lib/types/client/mail-attachment.d.ts.map +1 -0
  47. package/lib/types/client/mail-attachment.js +187 -0
  48. package/lib/types/client/mail-attachment.js.map +1 -0
  49. package/lib/types/client/otp-cooldown.d.ts +1 -0
  50. package/lib/types/client/otp-cooldown.d.ts.map +1 -1
  51. package/lib/types/client/otp-cooldown.js +12 -1
  52. package/lib/types/client/otp-cooldown.js.map +1 -1
  53. package/lib/types/client/settings-controller.d.ts +4 -2
  54. package/lib/types/client/settings-controller.d.ts.map +1 -1
  55. package/lib/types/client/settings-controller.js +24 -8
  56. package/lib/types/client/settings-controller.js.map +1 -1
  57. package/lib/types/client/slots.d.ts +6 -1
  58. package/lib/types/client/slots.d.ts.map +1 -1
  59. package/lib/types/client/store.d.ts +1 -1
  60. package/lib/types/client/store.d.ts.map +1 -1
  61. package/lib/types/client/store.js +1 -1
  62. package/lib/types/client/store.js.map +1 -1
  63. package/lib/types/external-http-auth.d.ts +3 -1
  64. package/lib/types/external-http-auth.d.ts.map +1 -1
  65. package/lib/types/external-http-auth.js +2 -2
  66. package/lib/types/external-http-auth.js.map +1 -1
  67. package/lib/types/identity-handle.d.ts +5 -0
  68. package/lib/types/identity-handle.d.ts.map +1 -0
  69. package/lib/types/identity-handle.js +33 -0
  70. package/lib/types/identity-handle.js.map +1 -0
  71. package/lib/types/index.d.ts +11 -2
  72. package/lib/types/index.d.ts.map +1 -1
  73. package/lib/types/index.js +101 -20
  74. package/lib/types/index.js.map +1 -1
  75. package/lib/types/listener.d.ts.map +1 -1
  76. package/lib/types/listener.js +2 -1
  77. package/lib/types/listener.js.map +1 -1
  78. package/lib/types/mail-attachment-client.d.ts +14 -0
  79. package/lib/types/mail-attachment-client.d.ts.map +1 -0
  80. package/lib/types/mail-attachment-client.js +173 -0
  81. package/lib/types/mail-attachment-client.js.map +1 -0
  82. package/lib/types/mail.d.ts +28 -2
  83. package/lib/types/mail.d.ts.map +1 -1
  84. package/lib/types/mail.js +79 -2
  85. package/lib/types/mail.js.map +1 -1
  86. package/lib/types/model-proxy-contract.d.ts +8 -8
  87. package/lib/types/model-proxy-contract.d.ts.map +1 -1
  88. package/lib/types/model-proxy-contract.js +8 -8
  89. package/lib/types/model-proxy-contract.js.map +1 -1
  90. package/lib/types/package-version.generated.d.ts +2 -2
  91. package/lib/types/package-version.generated.d.ts.map +1 -1
  92. package/lib/types/package-version.generated.js +2 -2
  93. package/lib/types/package-version.generated.js.map +1 -1
  94. package/lib/types/provider.d.ts +1 -1
  95. package/lib/types/provider.d.ts.map +1 -1
  96. package/lib/types/provider.js +12 -1
  97. package/lib/types/provider.js.map +1 -1
  98. package/lib/types/registration-policy.d.ts +5 -0
  99. package/lib/types/registration-policy.d.ts.map +1 -0
  100. package/lib/types/registration-policy.js +13 -0
  101. package/lib/types/registration-policy.js.map +1 -0
  102. package/lib/types/sdk-adapter.d.ts +2 -1
  103. package/lib/types/sdk-adapter.d.ts.map +1 -1
  104. package/lib/types/sdk-adapter.js +13 -4
  105. package/lib/types/sdk-adapter.js.map +1 -1
  106. package/lib/types/settings-rpc-contract.d.ts +14 -14
  107. package/lib/types/settings-rpc-contract.d.ts.map +1 -1
  108. package/lib/types/settings-rpc-contract.js +14 -14
  109. package/lib/types/settings-rpc-contract.js.map +1 -1
  110. package/lib/types/settings-rpc.d.ts.map +1 -1
  111. package/lib/types/settings-rpc.js +2 -2
  112. package/lib/types/settings-rpc.js.map +1 -1
  113. package/lib/types/settings-transport.d.ts +7 -0
  114. package/lib/types/settings-transport.d.ts.map +1 -0
  115. package/lib/types/settings-transport.js +52 -0
  116. package/lib/types/settings-transport.js.map +1 -0
  117. package/lib/types/tools.d.ts +1 -1
  118. package/lib/types/tools.d.ts.map +1 -1
  119. package/lib/types/tools.js +20 -4
  120. package/lib/types/tools.js.map +1 -1
  121. package/lib/types/types.d.ts +39 -2
  122. package/lib/types/types.d.ts.map +1 -1
  123. package/lib/types/types.js.map +1 -1
  124. package/lib/types/update-policy.d.ts +2 -2
  125. package/lib/types/update-policy.d.ts.map +1 -1
  126. package/package.json +84 -75
package/lib/client.js CHANGED
@@ -8,7 +8,6 @@ window.__ModuleLoader__.load({
8
8
  let react = require("react");
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
10
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
11
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
12
11
  //#region node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
13
12
  var _a$1;
14
13
  function $constructor(name, initializer, params) {
@@ -155,7 +154,7 @@ window.__ModuleLoader__.load({
155
154
  return false;
156
155
  }
157
156
  });
158
- function isPlainObject(o) {
157
+ function isPlainObject$1(o) {
159
158
  if (isObject(o) === false) return false;
160
159
  const ctor = o.constructor;
161
160
  if (ctor === void 0) return true;
@@ -166,7 +165,7 @@ window.__ModuleLoader__.load({
166
165
  return true;
167
166
  }
168
167
  function shallowClone(o) {
169
- if (isPlainObject(o)) return { ...o };
168
+ if (isPlainObject$1(o)) return { ...o };
170
169
  if (Array.isArray(o)) return [...o];
171
170
  if (o instanceof Map) return new Map(o);
172
171
  if (o instanceof Set) return new Set(o);
@@ -249,7 +248,7 @@ window.__ModuleLoader__.load({
249
248
  }));
250
249
  }
251
250
  function extend(schema, shape) {
252
- if (!isPlainObject(shape)) throw new Error("Invalid input to extend: expected a plain object");
251
+ if (!isPlainObject$1(shape)) throw new Error("Invalid input to extend: expected a plain object");
253
252
  const checks = schema._zod.def.checks;
254
253
  if (checks && checks.length > 0) {
255
254
  const existingShape = schema._zod.def.shape;
@@ -265,7 +264,7 @@ window.__ModuleLoader__.load({
265
264
  } }));
266
265
  }
267
266
  function safeExtend(schema, shape) {
268
- if (!isPlainObject(shape)) throw new Error("Invalid input to safeExtend: expected a plain object");
267
+ if (!isPlainObject$1(shape)) throw new Error("Invalid input to safeExtend: expected a plain object");
269
268
  return clone(schema, mergeDefs(schema._zod.def, { get shape() {
270
269
  const _shape = {
271
270
  ...schema._zod.def.shape,
@@ -589,7 +588,7 @@ window.__ModuleLoader__.load({
589
588
  const ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
590
589
  const cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
591
590
  const cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
592
- const base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
591
+ const base64$1 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
593
592
  const base64url = /^[A-Za-z0-9_-]*$/;
594
593
  const httpProtocol = /^https?$/;
595
594
  const e164 = /^\+[1-9]\d{6,14}$/;
@@ -1326,7 +1325,7 @@ window.__ModuleLoader__.load({
1326
1325
  }
1327
1326
  }
1328
1327
  const $ZodBase64 = /*@__PURE__*/ $constructor("$ZodBase64", (inst, def) => {
1329
- def.pattern ?? (def.pattern = base64);
1328
+ def.pattern ?? (def.pattern = base64$1);
1330
1329
  $ZodStringFormat.init(inst, def);
1331
1330
  inst._zod.bag.contentEncoding = "base64";
1332
1331
  inst._zod.check = (payload) => {
@@ -1821,7 +1820,7 @@ window.__ModuleLoader__.load({
1821
1820
  valid: true,
1822
1821
  data: a
1823
1822
  };
1824
- if (isPlainObject(a) && isPlainObject(b)) {
1823
+ if (isPlainObject$1(a) && isPlainObject$1(b)) {
1825
1824
  const bKeys = Object.keys(b);
1826
1825
  const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
1827
1826
  const newObj = {
@@ -2865,7 +2864,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
2865
2864
  }
2866
2865
  }
2867
2866
  }
2868
- function finalize(ctx, schema) {
2867
+ function finalize$1(ctx, schema) {
2869
2868
  const root = ctx.seen.get(schema);
2870
2869
  if (!root) throw new Error("Unprocessed schema. This is a bug in Zod.");
2871
2870
  const flattenRef = (zodSchema) => {
@@ -2997,7 +2996,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
2997
2996
  });
2998
2997
  process(schema, ctx);
2999
2998
  extractDefs(ctx, schema);
3000
- return finalize(ctx, schema);
2999
+ return finalize$1(ctx, schema);
3001
3000
  };
3002
3001
  const createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
3003
3002
  const { libraryOptions, target } = params ?? {};
@@ -3009,7 +3008,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3009
3008
  });
3010
3009
  process(schema, ctx);
3011
3010
  extractDefs(ctx, schema);
3012
- return finalize(ctx, schema);
3011
+ return finalize$1(ctx, schema);
3013
3012
  };
3014
3013
  //#endregion
3015
3014
  //#region node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/json-schema-processors.js
@@ -4109,11 +4108,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4109
4108
  literal("invalid-otp"),
4110
4109
  literal("challenge-expired"),
4111
4110
  literal("handle-unavailable"),
4111
+ literal("short-handle-invite-required"),
4112
4112
  literal("not-found"),
4113
4113
  literal("forbidden"),
4114
4114
  literal("device-rejoin-required"),
4115
4115
  literal("identity-recovery-required"),
4116
4116
  literal("conflict"),
4117
+ literal("state-in-use"),
4117
4118
  literal("rate-limited"),
4118
4119
  literal("group-membership-required"),
4119
4120
  literal("group-identity-stale"),
@@ -4232,11 +4233,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4232
4233
  literal("invalid-otp"),
4233
4234
  literal("challenge-expired"),
4234
4235
  literal("handle-unavailable"),
4236
+ literal("short-handle-invite-required"),
4235
4237
  literal("not-found"),
4236
4238
  literal("forbidden"),
4237
4239
  literal("device-rejoin-required"),
4238
4240
  literal("identity-recovery-required"),
4239
4241
  literal("conflict"),
4242
+ literal("state-in-use"),
4240
4243
  literal("rate-limited"),
4241
4244
  literal("group-membership-required"),
4242
4245
  literal("group-identity-stale"),
@@ -4303,11 +4306,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4303
4306
  literal("invalid-otp"),
4304
4307
  literal("challenge-expired"),
4305
4308
  literal("handle-unavailable"),
4309
+ literal("short-handle-invite-required"),
4306
4310
  literal("not-found"),
4307
4311
  literal("forbidden"),
4308
4312
  literal("device-rejoin-required"),
4309
4313
  literal("identity-recovery-required"),
4310
4314
  literal("conflict"),
4315
+ literal("state-in-use"),
4311
4316
  literal("rate-limited"),
4312
4317
  literal("group-membership-required"),
4313
4318
  literal("group-identity-stale"),
@@ -4379,11 +4384,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4379
4384
  literal("invalid-otp"),
4380
4385
  literal("challenge-expired"),
4381
4386
  literal("handle-unavailable"),
4387
+ literal("short-handle-invite-required"),
4382
4388
  literal("not-found"),
4383
4389
  literal("forbidden"),
4384
4390
  literal("device-rejoin-required"),
4385
4391
  literal("identity-recovery-required"),
4386
4392
  literal("conflict"),
4393
+ literal("state-in-use"),
4387
4394
  literal("rate-limited"),
4388
4395
  literal("group-membership-required"),
4389
4396
  literal("group-identity-stale"),
@@ -4455,11 +4462,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4455
4462
  literal("invalid-otp"),
4456
4463
  literal("challenge-expired"),
4457
4464
  literal("handle-unavailable"),
4465
+ literal("short-handle-invite-required"),
4458
4466
  literal("not-found"),
4459
4467
  literal("forbidden"),
4460
4468
  literal("device-rejoin-required"),
4461
4469
  literal("identity-recovery-required"),
4462
4470
  literal("conflict"),
4471
+ literal("state-in-use"),
4463
4472
  literal("rate-limited"),
4464
4473
  literal("group-membership-required"),
4465
4474
  literal("group-identity-stale"),
@@ -4519,11 +4528,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4519
4528
  literal("invalid-otp"),
4520
4529
  literal("challenge-expired"),
4521
4530
  literal("handle-unavailable"),
4531
+ literal("short-handle-invite-required"),
4522
4532
  literal("not-found"),
4523
4533
  literal("forbidden"),
4524
4534
  literal("device-rejoin-required"),
4525
4535
  literal("identity-recovery-required"),
4526
4536
  literal("conflict"),
4537
+ literal("state-in-use"),
4527
4538
  literal("rate-limited"),
4528
4539
  literal("group-membership-required"),
4529
4540
  literal("group-identity-stale"),
@@ -4645,11 +4656,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4645
4656
  literal("invalid-otp"),
4646
4657
  literal("challenge-expired"),
4647
4658
  literal("handle-unavailable"),
4659
+ literal("short-handle-invite-required"),
4648
4660
  literal("not-found"),
4649
4661
  literal("forbidden"),
4650
4662
  literal("device-rejoin-required"),
4651
4663
  literal("identity-recovery-required"),
4652
4664
  literal("conflict"),
4665
+ literal("state-in-use"),
4653
4666
  literal("rate-limited"),
4654
4667
  literal("group-membership-required"),
4655
4668
  literal("group-identity-stale"),
@@ -4715,11 +4728,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4715
4728
  literal("invalid-otp"),
4716
4729
  literal("challenge-expired"),
4717
4730
  literal("handle-unavailable"),
4731
+ literal("short-handle-invite-required"),
4718
4732
  literal("not-found"),
4719
4733
  literal("forbidden"),
4720
4734
  literal("device-rejoin-required"),
4721
4735
  literal("identity-recovery-required"),
4722
4736
  literal("conflict"),
4737
+ literal("state-in-use"),
4723
4738
  literal("rate-limited"),
4724
4739
  literal("group-membership-required"),
4725
4740
  literal("group-identity-stale"),
@@ -4790,11 +4805,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4790
4805
  literal("invalid-otp"),
4791
4806
  literal("challenge-expired"),
4792
4807
  literal("handle-unavailable"),
4808
+ literal("short-handle-invite-required"),
4793
4809
  literal("not-found"),
4794
4810
  literal("forbidden"),
4795
4811
  literal("device-rejoin-required"),
4796
4812
  literal("identity-recovery-required"),
4797
4813
  literal("conflict"),
4814
+ literal("state-in-use"),
4798
4815
  literal("rate-limited"),
4799
4816
  literal("group-membership-required"),
4800
4817
  literal("group-identity-stale"),
@@ -4920,11 +4937,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4920
4937
  literal("invalid-otp"),
4921
4938
  literal("challenge-expired"),
4922
4939
  literal("handle-unavailable"),
4940
+ literal("short-handle-invite-required"),
4923
4941
  literal("not-found"),
4924
4942
  literal("forbidden"),
4925
4943
  literal("device-rejoin-required"),
4926
4944
  literal("identity-recovery-required"),
4927
4945
  literal("conflict"),
4946
+ literal("state-in-use"),
4928
4947
  literal("rate-limited"),
4929
4948
  literal("group-membership-required"),
4930
4949
  literal("group-identity-stale"),
@@ -4987,11 +5006,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4987
5006
  literal("invalid-otp"),
4988
5007
  literal("challenge-expired"),
4989
5008
  literal("handle-unavailable"),
5009
+ literal("short-handle-invite-required"),
4990
5010
  literal("not-found"),
4991
5011
  literal("forbidden"),
4992
5012
  literal("device-rejoin-required"),
4993
5013
  literal("identity-recovery-required"),
4994
5014
  literal("conflict"),
5015
+ literal("state-in-use"),
4995
5016
  literal("rate-limited"),
4996
5017
  literal("group-membership-required"),
4997
5018
  literal("group-identity-stale"),
@@ -5047,6 +5068,81 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5047
5068
  "bytesBase64": string().readonly()
5048
5069
  }).readonly()
5049
5070
  })]);
5071
+ const _awiki_dsh_plugin_awiki_downloadMailAttachment_parameter_0$schema = object({
5072
+ "localMessageId": intersection(string(), unknown()).readonly(),
5073
+ "attachmentIndex": number().readonly()
5074
+ });
5075
+ const _awiki_dsh_plugin_awiki_downloadMailAttachment_result$schema = union([object({
5076
+ "ok": literal(false).readonly(),
5077
+ "error": object({
5078
+ "code": union([
5079
+ literal("client-version-unsupported"),
5080
+ literal("not-registered"),
5081
+ literal("signed-out"),
5082
+ literal("already-registered"),
5083
+ literal("invalid-request"),
5084
+ literal("invalid-otp"),
5085
+ literal("challenge-expired"),
5086
+ literal("handle-unavailable"),
5087
+ literal("short-handle-invite-required"),
5088
+ literal("not-found"),
5089
+ literal("forbidden"),
5090
+ literal("device-rejoin-required"),
5091
+ literal("identity-recovery-required"),
5092
+ literal("conflict"),
5093
+ literal("state-in-use"),
5094
+ literal("rate-limited"),
5095
+ literal("group-membership-required"),
5096
+ literal("group-identity-stale"),
5097
+ literal("attachment-too-large"),
5098
+ literal("summary-unavailable"),
5099
+ literal("summary-timeout"),
5100
+ literal("summary-cancelled"),
5101
+ literal("summary-invalid-output"),
5102
+ literal("summary-failed"),
5103
+ literal("delivery-unknown"),
5104
+ literal("network"),
5105
+ literal("remote")
5106
+ ]).readonly(),
5107
+ "message": string().readonly(),
5108
+ "mailRecoveryObservability": object({
5109
+ "current_principal_matches_recovery": boolean().readonly(),
5110
+ "request_generation_classification": union([literal("current"), literal("replaced")]).readonly(),
5111
+ "mail_ingress_classification": union([
5112
+ literal("reached"),
5113
+ literal("not_reached"),
5114
+ literal("unknown")
5115
+ ]).readonly(),
5116
+ "auth_status_class": union([
5117
+ literal("unknown"),
5118
+ literal("accepted"),
5119
+ literal("rejected"),
5120
+ literal("dependency_unavailable")
5121
+ ]).readonly(),
5122
+ "auth_stable_machine_code": string().readonly().optional(),
5123
+ "retryable": boolean().readonly(),
5124
+ "mail_closed_classification": union([
5125
+ literal("unknown"),
5126
+ literal("dependency_unavailable"),
5127
+ literal("success"),
5128
+ literal("authentication_rejected"),
5129
+ literal("no_active_handle"),
5130
+ literal("multiple_active_handles"),
5131
+ literal("no_mailbox"),
5132
+ literal("owner_conflict")
5133
+ ]).readonly()
5134
+ }).readonly().optional()
5135
+ }).readonly()
5136
+ }), object({
5137
+ "ok": literal(true).readonly(),
5138
+ "value": object({
5139
+ "fileName": string().readonly(),
5140
+ "contentType": string().readonly(),
5141
+ "sizeBytes": number().readonly(),
5142
+ "sha256": string().readonly(),
5143
+ "bytesBase64": string().readonly()
5144
+ }).readonly()
5145
+ })]);
5050
5146
  const _awiki_dsh_plugin_awiki_enterRecoveredSession_parameter_0$schema = object({ "operationId": string().readonly() });
5051
5147
  const _awiki_dsh_plugin_awiki_enterRecoveredSession_result$schema = union([object({
5052
5148
  "ok": literal(false).readonly(),
@@ -5060,11 +5156,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5060
5156
  literal("invalid-otp"),
5061
5157
  literal("challenge-expired"),
5062
5158
  literal("handle-unavailable"),
5159
+ literal("short-handle-invite-required"),
5063
5160
  literal("not-found"),
5064
5161
  literal("forbidden"),
5065
5162
  literal("device-rejoin-required"),
5066
5163
  literal("identity-recovery-required"),
5067
5164
  literal("conflict"),
5165
+ literal("state-in-use"),
5068
5166
  literal("rate-limited"),
5069
5167
  literal("group-membership-required"),
5070
5168
  literal("group-identity-stale"),
@@ -5178,11 +5276,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5178
5276
  literal("invalid-otp"),
5179
5277
  literal("challenge-expired"),
5180
5278
  literal("handle-unavailable"),
5279
+ literal("short-handle-invite-required"),
5181
5280
  literal("not-found"),
5182
5281
  literal("forbidden"),
5183
5282
  literal("device-rejoin-required"),
5184
5283
  literal("identity-recovery-required"),
5185
5284
  literal("conflict"),
5285
+ literal("state-in-use"),
5186
5286
  literal("rate-limited"),
5187
5287
  literal("group-membership-required"),
5188
5288
  literal("group-identity-stale"),
@@ -5238,7 +5338,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5238
5338
  "services": object({
5239
5339
  "modelProxy": object({ "enabled": boolean().readonly() }).readonly(),
5240
5340
  "guestGateway": object({ "enabled": boolean().readonly() }).readonly()
5241
- }).readonly()
5341
+ }).readonly(),
5342
+ "mailAttachmentDownloadMaxBytes": number().readonly(),
5343
+ "mailAttachmentMaxCount": number().readonly(),
5344
+ "mailAttachmentMaxBytes": number().readonly(),
5345
+ "mailAttachmentTotalMaxBytes": number().readonly()
5242
5346
  }).readonly()
5243
5347
  })]);
5244
5348
  const _awiki_dsh_plugin_awiki_getConversationPreferences_result$schema = union([object({
@@ -5253,11 +5357,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5253
5357
  literal("invalid-otp"),
5254
5358
  literal("challenge-expired"),
5255
5359
  literal("handle-unavailable"),
5360
+ literal("short-handle-invite-required"),
5256
5361
  literal("not-found"),
5257
5362
  literal("forbidden"),
5258
5363
  literal("device-rejoin-required"),
5259
5364
  literal("identity-recovery-required"),
5260
5365
  literal("conflict"),
5366
+ literal("state-in-use"),
5261
5367
  literal("rate-limited"),
5262
5368
  literal("group-membership-required"),
5263
5369
  literal("group-identity-stale"),
@@ -5337,11 +5443,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5337
5443
  literal("invalid-otp"),
5338
5444
  literal("challenge-expired"),
5339
5445
  literal("handle-unavailable"),
5446
+ literal("short-handle-invite-required"),
5340
5447
  literal("not-found"),
5341
5448
  literal("forbidden"),
5342
5449
  literal("device-rejoin-required"),
5343
5450
  literal("identity-recovery-required"),
5344
5451
  literal("conflict"),
5452
+ literal("state-in-use"),
5345
5453
  literal("rate-limited"),
5346
5454
  literal("group-membership-required"),
5347
5455
  literal("group-identity-stale"),
@@ -5414,11 +5522,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5414
5522
  literal("invalid-otp"),
5415
5523
  literal("challenge-expired"),
5416
5524
  literal("handle-unavailable"),
5525
+ literal("short-handle-invite-required"),
5417
5526
  literal("not-found"),
5418
5527
  literal("forbidden"),
5419
5528
  literal("device-rejoin-required"),
5420
5529
  literal("identity-recovery-required"),
5421
5530
  literal("conflict"),
5531
+ literal("state-in-use"),
5422
5532
  literal("rate-limited"),
5423
5533
  literal("group-membership-required"),
5424
5534
  literal("group-identity-stale"),
@@ -5483,11 +5593,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5483
5593
  literal("invalid-otp"),
5484
5594
  literal("challenge-expired"),
5485
5595
  literal("handle-unavailable"),
5596
+ literal("short-handle-invite-required"),
5486
5597
  literal("not-found"),
5487
5598
  literal("forbidden"),
5488
5599
  literal("device-rejoin-required"),
5489
5600
  literal("identity-recovery-required"),
5490
5601
  literal("conflict"),
5602
+ literal("state-in-use"),
5491
5603
  literal("rate-limited"),
5492
5604
  literal("group-membership-required"),
5493
5605
  literal("group-identity-stale"),
@@ -5559,11 +5671,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5559
5671
  literal("invalid-otp"),
5560
5672
  literal("challenge-expired"),
5561
5673
  literal("handle-unavailable"),
5674
+ literal("short-handle-invite-required"),
5562
5675
  literal("not-found"),
5563
5676
  literal("forbidden"),
5564
5677
  literal("device-rejoin-required"),
5565
5678
  literal("identity-recovery-required"),
5566
5679
  literal("conflict"),
5680
+ literal("state-in-use"),
5567
5681
  literal("rate-limited"),
5568
5682
  literal("group-membership-required"),
5569
5683
  literal("group-identity-stale"),
@@ -5656,11 +5770,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5656
5770
  literal("invalid-otp"),
5657
5771
  literal("challenge-expired"),
5658
5772
  literal("handle-unavailable"),
5773
+ literal("short-handle-invite-required"),
5659
5774
  literal("not-found"),
5660
5775
  literal("forbidden"),
5661
5776
  literal("device-rejoin-required"),
5662
5777
  literal("identity-recovery-required"),
5663
5778
  literal("conflict"),
5779
+ literal("state-in-use"),
5664
5780
  literal("rate-limited"),
5665
5781
  literal("group-membership-required"),
5666
5782
  literal("group-identity-stale"),
@@ -5724,11 +5840,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5724
5840
  literal("invalid-otp"),
5725
5841
  literal("challenge-expired"),
5726
5842
  literal("handle-unavailable"),
5843
+ literal("short-handle-invite-required"),
5727
5844
  literal("not-found"),
5728
5845
  literal("forbidden"),
5729
5846
  literal("device-rejoin-required"),
5730
5847
  literal("identity-recovery-required"),
5731
5848
  literal("conflict"),
5849
+ literal("state-in-use"),
5732
5850
  literal("rate-limited"),
5733
5851
  literal("group-membership-required"),
5734
5852
  literal("group-identity-stale"),
@@ -5859,11 +5977,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5859
5977
  literal("invalid-otp"),
5860
5978
  literal("challenge-expired"),
5861
5979
  literal("handle-unavailable"),
5980
+ literal("short-handle-invite-required"),
5862
5981
  literal("not-found"),
5863
5982
  literal("forbidden"),
5864
5983
  literal("device-rejoin-required"),
5865
5984
  literal("identity-recovery-required"),
5866
5985
  literal("conflict"),
5986
+ literal("state-in-use"),
5867
5987
  literal("rate-limited"),
5868
5988
  literal("group-membership-required"),
5869
5989
  literal("group-identity-stale"),
@@ -5956,11 +6076,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5956
6076
  literal("invalid-otp"),
5957
6077
  literal("challenge-expired"),
5958
6078
  literal("handle-unavailable"),
6079
+ literal("short-handle-invite-required"),
5959
6080
  literal("not-found"),
5960
6081
  literal("forbidden"),
5961
6082
  literal("device-rejoin-required"),
5962
6083
  literal("identity-recovery-required"),
5963
6084
  literal("conflict"),
6085
+ literal("state-in-use"),
5964
6086
  literal("rate-limited"),
5965
6087
  literal("group-membership-required"),
5966
6088
  literal("group-identity-stale"),
@@ -6023,11 +6145,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6023
6145
  literal("invalid-otp"),
6024
6146
  literal("challenge-expired"),
6025
6147
  literal("handle-unavailable"),
6148
+ literal("short-handle-invite-required"),
6026
6149
  literal("not-found"),
6027
6150
  literal("forbidden"),
6028
6151
  literal("device-rejoin-required"),
6029
6152
  literal("identity-recovery-required"),
6030
6153
  literal("conflict"),
6154
+ literal("state-in-use"),
6031
6155
  literal("rate-limited"),
6032
6156
  literal("group-membership-required"),
6033
6157
  literal("group-identity-stale"),
@@ -6094,11 +6218,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6094
6218
  literal("invalid-otp"),
6095
6219
  literal("challenge-expired"),
6096
6220
  literal("handle-unavailable"),
6221
+ literal("short-handle-invite-required"),
6097
6222
  literal("not-found"),
6098
6223
  literal("forbidden"),
6099
6224
  literal("device-rejoin-required"),
6100
6225
  literal("identity-recovery-required"),
6101
6226
  literal("conflict"),
6227
+ literal("state-in-use"),
6102
6228
  literal("rate-limited"),
6103
6229
  literal("group-membership-required"),
6104
6230
  literal("group-identity-stale"),
@@ -6212,11 +6338,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6212
6338
  literal("invalid-otp"),
6213
6339
  literal("challenge-expired"),
6214
6340
  literal("handle-unavailable"),
6341
+ literal("short-handle-invite-required"),
6215
6342
  literal("not-found"),
6216
6343
  literal("forbidden"),
6217
6344
  literal("device-rejoin-required"),
6218
6345
  literal("identity-recovery-required"),
6219
6346
  literal("conflict"),
6347
+ literal("state-in-use"),
6220
6348
  literal("rate-limited"),
6221
6349
  literal("group-membership-required"),
6222
6350
  literal("group-identity-stale"),
@@ -6288,11 +6416,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6288
6416
  literal("invalid-otp"),
6289
6417
  literal("challenge-expired"),
6290
6418
  literal("handle-unavailable"),
6419
+ literal("short-handle-invite-required"),
6291
6420
  literal("not-found"),
6292
6421
  literal("forbidden"),
6293
6422
  literal("device-rejoin-required"),
6294
6423
  literal("identity-recovery-required"),
6295
6424
  literal("conflict"),
6425
+ literal("state-in-use"),
6296
6426
  literal("rate-limited"),
6297
6427
  literal("group-membership-required"),
6298
6428
  literal("group-identity-stale"),
@@ -6355,11 +6485,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6355
6485
  literal("invalid-otp"),
6356
6486
  literal("challenge-expired"),
6357
6487
  literal("handle-unavailable"),
6488
+ literal("short-handle-invite-required"),
6358
6489
  literal("not-found"),
6359
6490
  literal("forbidden"),
6360
6491
  literal("device-rejoin-required"),
6361
6492
  literal("identity-recovery-required"),
6362
6493
  literal("conflict"),
6494
+ literal("state-in-use"),
6363
6495
  literal("rate-limited"),
6364
6496
  literal("group-membership-required"),
6365
6497
  literal("group-identity-stale"),
@@ -6427,11 +6559,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6427
6559
  literal("invalid-otp"),
6428
6560
  literal("challenge-expired"),
6429
6561
  literal("handle-unavailable"),
6562
+ literal("short-handle-invite-required"),
6430
6563
  literal("not-found"),
6431
6564
  literal("forbidden"),
6432
6565
  literal("device-rejoin-required"),
6433
6566
  literal("identity-recovery-required"),
6434
6567
  literal("conflict"),
6568
+ literal("state-in-use"),
6435
6569
  literal("rate-limited"),
6436
6570
  literal("group-membership-required"),
6437
6571
  literal("group-identity-stale"),
@@ -6494,11 +6628,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6494
6628
  literal("invalid-otp"),
6495
6629
  literal("challenge-expired"),
6496
6630
  literal("handle-unavailable"),
6631
+ literal("short-handle-invite-required"),
6497
6632
  literal("not-found"),
6498
6633
  literal("forbidden"),
6499
6634
  literal("device-rejoin-required"),
6500
6635
  literal("identity-recovery-required"),
6501
6636
  literal("conflict"),
6637
+ literal("state-in-use"),
6502
6638
  literal("rate-limited"),
6503
6639
  literal("group-membership-required"),
6504
6640
  literal("group-identity-stale"),
@@ -6584,11 +6720,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6584
6720
  literal("invalid-otp"),
6585
6721
  literal("challenge-expired"),
6586
6722
  literal("handle-unavailable"),
6723
+ literal("short-handle-invite-required"),
6587
6724
  literal("not-found"),
6588
6725
  literal("forbidden"),
6589
6726
  literal("device-rejoin-required"),
6590
6727
  literal("identity-recovery-required"),
6591
6728
  literal("conflict"),
6729
+ literal("state-in-use"),
6592
6730
  literal("rate-limited"),
6593
6731
  literal("group-membership-required"),
6594
6732
  literal("group-identity-stale"),
@@ -6672,11 +6810,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6672
6810
  literal("invalid-otp"),
6673
6811
  literal("challenge-expired"),
6674
6812
  literal("handle-unavailable"),
6813
+ literal("short-handle-invite-required"),
6675
6814
  literal("not-found"),
6676
6815
  literal("forbidden"),
6677
6816
  literal("device-rejoin-required"),
6678
6817
  literal("identity-recovery-required"),
6679
6818
  literal("conflict"),
6819
+ literal("state-in-use"),
6680
6820
  literal("rate-limited"),
6681
6821
  literal("group-membership-required"),
6682
6822
  literal("group-identity-stale"),
@@ -6754,11 +6894,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6754
6894
  literal("invalid-otp"),
6755
6895
  literal("challenge-expired"),
6756
6896
  literal("handle-unavailable"),
6897
+ literal("short-handle-invite-required"),
6757
6898
  literal("not-found"),
6758
6899
  literal("forbidden"),
6759
6900
  literal("device-rejoin-required"),
6760
6901
  literal("identity-recovery-required"),
6761
6902
  literal("conflict"),
6903
+ literal("state-in-use"),
6762
6904
  literal("rate-limited"),
6763
6905
  literal("group-membership-required"),
6764
6906
  literal("group-identity-stale"),
@@ -6830,11 +6972,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6830
6972
  literal("invalid-otp"),
6831
6973
  literal("challenge-expired"),
6832
6974
  literal("handle-unavailable"),
6975
+ literal("short-handle-invite-required"),
6833
6976
  literal("not-found"),
6834
6977
  literal("forbidden"),
6835
6978
  literal("device-rejoin-required"),
6836
6979
  literal("identity-recovery-required"),
6837
6980
  literal("conflict"),
6981
+ literal("state-in-use"),
6838
6982
  literal("rate-limited"),
6839
6983
  literal("group-membership-required"),
6840
6984
  literal("group-identity-stale"),
@@ -6906,11 +7050,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6906
7050
  literal("invalid-otp"),
6907
7051
  literal("challenge-expired"),
6908
7052
  literal("handle-unavailable"),
7053
+ literal("short-handle-invite-required"),
6909
7054
  literal("not-found"),
6910
7055
  literal("forbidden"),
6911
7056
  literal("device-rejoin-required"),
6912
7057
  literal("identity-recovery-required"),
6913
7058
  literal("conflict"),
7059
+ literal("state-in-use"),
6914
7060
  literal("rate-limited"),
6915
7061
  literal("group-membership-required"),
6916
7062
  literal("group-identity-stale"),
@@ -6970,11 +7116,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6970
7116
  literal("invalid-otp"),
6971
7117
  literal("challenge-expired"),
6972
7118
  literal("handle-unavailable"),
7119
+ literal("short-handle-invite-required"),
6973
7120
  literal("not-found"),
6974
7121
  literal("forbidden"),
6975
7122
  literal("device-rejoin-required"),
6976
7123
  literal("identity-recovery-required"),
6977
7124
  literal("conflict"),
7125
+ literal("state-in-use"),
6978
7126
  literal("rate-limited"),
6979
7127
  literal("group-membership-required"),
6980
7128
  literal("group-identity-stale"),
@@ -7038,11 +7186,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7038
7186
  literal("invalid-otp"),
7039
7187
  literal("challenge-expired"),
7040
7188
  literal("handle-unavailable"),
7189
+ literal("short-handle-invite-required"),
7041
7190
  literal("not-found"),
7042
7191
  literal("forbidden"),
7043
7192
  literal("device-rejoin-required"),
7044
7193
  literal("identity-recovery-required"),
7045
7194
  literal("conflict"),
7195
+ literal("state-in-use"),
7046
7196
  literal("rate-limited"),
7047
7197
  literal("group-membership-required"),
7048
7198
  literal("group-identity-stale"),
@@ -7157,11 +7307,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7157
7307
  literal("invalid-otp"),
7158
7308
  literal("challenge-expired"),
7159
7309
  literal("handle-unavailable"),
7310
+ literal("short-handle-invite-required"),
7160
7311
  literal("not-found"),
7161
7312
  literal("forbidden"),
7162
7313
  literal("device-rejoin-required"),
7163
7314
  literal("identity-recovery-required"),
7164
7315
  literal("conflict"),
7316
+ literal("state-in-use"),
7165
7317
  literal("rate-limited"),
7166
7318
  literal("group-membership-required"),
7167
7319
  literal("group-identity-stale"),
@@ -7225,11 +7377,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7225
7377
  literal("invalid-otp"),
7226
7378
  literal("challenge-expired"),
7227
7379
  literal("handle-unavailable"),
7380
+ literal("short-handle-invite-required"),
7228
7381
  literal("not-found"),
7229
7382
  literal("forbidden"),
7230
7383
  literal("device-rejoin-required"),
7231
7384
  literal("identity-recovery-required"),
7232
7385
  literal("conflict"),
7386
+ literal("state-in-use"),
7233
7387
  literal("rate-limited"),
7234
7388
  literal("group-membership-required"),
7235
7389
  literal("group-identity-stale"),
@@ -7314,11 +7468,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7314
7468
  literal("invalid-otp"),
7315
7469
  literal("challenge-expired"),
7316
7470
  literal("handle-unavailable"),
7471
+ literal("short-handle-invite-required"),
7317
7472
  literal("not-found"),
7318
7473
  literal("forbidden"),
7319
7474
  literal("device-rejoin-required"),
7320
7475
  literal("identity-recovery-required"),
7321
7476
  literal("conflict"),
7477
+ literal("state-in-use"),
7322
7478
  literal("rate-limited"),
7323
7479
  literal("group-membership-required"),
7324
7480
  literal("group-identity-stale"),
@@ -7419,11 +7575,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7419
7575
  literal("invalid-otp"),
7420
7576
  literal("challenge-expired"),
7421
7577
  literal("handle-unavailable"),
7578
+ literal("short-handle-invite-required"),
7422
7579
  literal("not-found"),
7423
7580
  literal("forbidden"),
7424
7581
  literal("device-rejoin-required"),
7425
7582
  literal("identity-recovery-required"),
7426
7583
  literal("conflict"),
7584
+ literal("state-in-use"),
7427
7585
  literal("rate-limited"),
7428
7586
  literal("group-membership-required"),
7429
7587
  literal("group-identity-stale"),
@@ -7499,11 +7657,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7499
7657
  literal("invalid-otp"),
7500
7658
  literal("challenge-expired"),
7501
7659
  literal("handle-unavailable"),
7660
+ literal("short-handle-invite-required"),
7502
7661
  literal("not-found"),
7503
7662
  literal("forbidden"),
7504
7663
  literal("device-rejoin-required"),
7505
7664
  literal("identity-recovery-required"),
7506
7665
  literal("conflict"),
7666
+ literal("state-in-use"),
7507
7667
  literal("rate-limited"),
7508
7668
  literal("group-membership-required"),
7509
7669
  literal("group-identity-stale"),
@@ -7579,11 +7739,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7579
7739
  literal("invalid-otp"),
7580
7740
  literal("challenge-expired"),
7581
7741
  literal("handle-unavailable"),
7742
+ literal("short-handle-invite-required"),
7582
7743
  literal("not-found"),
7583
7744
  literal("forbidden"),
7584
7745
  literal("device-rejoin-required"),
7585
7746
  literal("identity-recovery-required"),
7586
7747
  literal("conflict"),
7748
+ literal("state-in-use"),
7587
7749
  literal("rate-limited"),
7588
7750
  literal("group-membership-required"),
7589
7751
  literal("group-identity-stale"),
@@ -7714,11 +7876,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7714
7876
  literal("invalid-otp"),
7715
7877
  literal("challenge-expired"),
7716
7878
  literal("handle-unavailable"),
7879
+ literal("short-handle-invite-required"),
7717
7880
  literal("not-found"),
7718
7881
  literal("forbidden"),
7719
7882
  literal("device-rejoin-required"),
7720
7883
  literal("identity-recovery-required"),
7721
7884
  literal("conflict"),
7885
+ literal("state-in-use"),
7722
7886
  literal("rate-limited"),
7723
7887
  literal("group-membership-required"),
7724
7888
  literal("group-identity-stale"),
@@ -7783,11 +7947,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7783
7947
  literal("invalid-otp"),
7784
7948
  literal("challenge-expired"),
7785
7949
  literal("handle-unavailable"),
7950
+ literal("short-handle-invite-required"),
7786
7951
  literal("not-found"),
7787
7952
  literal("forbidden"),
7788
7953
  literal("device-rejoin-required"),
7789
7954
  literal("identity-recovery-required"),
7790
7955
  literal("conflict"),
7956
+ literal("state-in-use"),
7791
7957
  literal("rate-limited"),
7792
7958
  literal("group-membership-required"),
7793
7959
  literal("group-identity-stale"),
@@ -7901,11 +8067,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7901
8067
  literal("invalid-otp"),
7902
8068
  literal("challenge-expired"),
7903
8069
  literal("handle-unavailable"),
8070
+ literal("short-handle-invite-required"),
7904
8071
  literal("not-found"),
7905
8072
  literal("forbidden"),
7906
8073
  literal("device-rejoin-required"),
7907
8074
  literal("identity-recovery-required"),
7908
8075
  literal("conflict"),
8076
+ literal("state-in-use"),
7909
8077
  literal("rate-limited"),
7910
8078
  literal("group-membership-required"),
7911
8079
  literal("group-identity-stale"),
@@ -7968,11 +8136,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7968
8136
  literal("invalid-otp"),
7969
8137
  literal("challenge-expired"),
7970
8138
  literal("handle-unavailable"),
8139
+ literal("short-handle-invite-required"),
7971
8140
  literal("not-found"),
7972
8141
  literal("forbidden"),
7973
8142
  literal("device-rejoin-required"),
7974
8143
  literal("identity-recovery-required"),
7975
8144
  literal("conflict"),
8145
+ literal("state-in-use"),
7976
8146
  literal("rate-limited"),
7977
8147
  literal("group-membership-required"),
7978
8148
  literal("group-identity-stale"),
@@ -8141,11 +8311,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8141
8311
  literal("invalid-otp"),
8142
8312
  literal("challenge-expired"),
8143
8313
  literal("handle-unavailable"),
8314
+ literal("short-handle-invite-required"),
8144
8315
  literal("not-found"),
8145
8316
  literal("forbidden"),
8146
8317
  literal("device-rejoin-required"),
8147
8318
  literal("identity-recovery-required"),
8148
8319
  literal("conflict"),
8320
+ literal("state-in-use"),
8149
8321
  literal("rate-limited"),
8150
8322
  literal("group-membership-required"),
8151
8323
  literal("group-identity-stale"),
@@ -8226,7 +8398,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8226
8398
  "to": array(string()).readonly(),
8227
8399
  "cc": array(string()).readonly().optional(),
8228
8400
  "subject": string().readonly(),
8229
- "bodyText": string().readonly()
8401
+ "bodyText": string().readonly(),
8402
+ "attachments": array(object({
8403
+ "fileName": string().readonly(),
8404
+ "contentType": string().readonly(),
8405
+ "sizeBytes": number().readonly(),
8406
+ "bytesBase64": string().readonly()
8407
+ })).readonly().optional()
8230
8408
  });
8231
8409
  const _awiki_dsh_plugin_awiki_sendMail_result$schema = union([object({
8232
8410
  "ok": literal(false).readonly(),
@@ -8240,11 +8418,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8240
8418
  literal("invalid-otp"),
8241
8419
  literal("challenge-expired"),
8242
8420
  literal("handle-unavailable"),
8421
+ literal("short-handle-invite-required"),
8243
8422
  literal("not-found"),
8244
8423
  literal("forbidden"),
8245
8424
  literal("device-rejoin-required"),
8246
8425
  literal("identity-recovery-required"),
8247
8426
  literal("conflict"),
8427
+ literal("state-in-use"),
8248
8428
  literal("rate-limited"),
8249
8429
  literal("group-membership-required"),
8250
8430
  literal("group-identity-stale"),
@@ -8311,11 +8491,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8311
8491
  literal("invalid-otp"),
8312
8492
  literal("challenge-expired"),
8313
8493
  literal("handle-unavailable"),
8494
+ literal("short-handle-invite-required"),
8314
8495
  literal("not-found"),
8315
8496
  literal("forbidden"),
8316
8497
  literal("device-rejoin-required"),
8317
8498
  literal("identity-recovery-required"),
8318
8499
  literal("conflict"),
8500
+ literal("state-in-use"),
8319
8501
  literal("rate-limited"),
8320
8502
  literal("group-membership-required"),
8321
8503
  literal("group-identity-stale"),
@@ -8383,11 +8565,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8383
8565
  literal("invalid-otp"),
8384
8566
  literal("challenge-expired"),
8385
8567
  literal("handle-unavailable"),
8568
+ literal("short-handle-invite-required"),
8386
8569
  literal("not-found"),
8387
8570
  literal("forbidden"),
8388
8571
  literal("device-rejoin-required"),
8389
8572
  literal("identity-recovery-required"),
8390
8573
  literal("conflict"),
8574
+ literal("state-in-use"),
8391
8575
  literal("rate-limited"),
8392
8576
  literal("group-membership-required"),
8393
8577
  literal("group-identity-stale"),
@@ -8467,11 +8651,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8467
8651
  literal("invalid-otp"),
8468
8652
  literal("challenge-expired"),
8469
8653
  literal("handle-unavailable"),
8654
+ literal("short-handle-invite-required"),
8470
8655
  literal("not-found"),
8471
8656
  literal("forbidden"),
8472
8657
  literal("device-rejoin-required"),
8473
8658
  literal("identity-recovery-required"),
8474
8659
  literal("conflict"),
8660
+ literal("state-in-use"),
8475
8661
  literal("rate-limited"),
8476
8662
  literal("group-membership-required"),
8477
8663
  literal("group-identity-stale"),
@@ -8561,11 +8747,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8561
8747
  literal("invalid-otp"),
8562
8748
  literal("challenge-expired"),
8563
8749
  literal("handle-unavailable"),
8750
+ literal("short-handle-invite-required"),
8564
8751
  literal("not-found"),
8565
8752
  literal("forbidden"),
8566
8753
  literal("device-rejoin-required"),
8567
8754
  literal("identity-recovery-required"),
8568
8755
  literal("conflict"),
8756
+ literal("state-in-use"),
8569
8757
  literal("rate-limited"),
8570
8758
  literal("group-membership-required"),
8571
8759
  literal("group-identity-stale"),
@@ -8641,11 +8829,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8641
8829
  literal("invalid-otp"),
8642
8830
  literal("challenge-expired"),
8643
8831
  literal("handle-unavailable"),
8832
+ literal("short-handle-invite-required"),
8644
8833
  literal("not-found"),
8645
8834
  literal("forbidden"),
8646
8835
  literal("device-rejoin-required"),
8647
8836
  literal("identity-recovery-required"),
8648
8837
  literal("conflict"),
8838
+ literal("state-in-use"),
8649
8839
  literal("rate-limited"),
8650
8840
  literal("group-membership-required"),
8651
8841
  literal("group-identity-stale"),
@@ -8745,11 +8935,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8745
8935
  literal("invalid-otp"),
8746
8936
  literal("challenge-expired"),
8747
8937
  literal("handle-unavailable"),
8938
+ literal("short-handle-invite-required"),
8748
8939
  literal("not-found"),
8749
8940
  literal("forbidden"),
8750
8941
  literal("device-rejoin-required"),
8751
8942
  literal("identity-recovery-required"),
8752
8943
  literal("conflict"),
8944
+ literal("state-in-use"),
8753
8945
  literal("rate-limited"),
8754
8946
  literal("group-membership-required"),
8755
8947
  literal("group-identity-stale"),
@@ -8830,11 +9022,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8830
9022
  literal("invalid-otp"),
8831
9023
  literal("challenge-expired"),
8832
9024
  literal("handle-unavailable"),
9025
+ literal("short-handle-invite-required"),
8833
9026
  literal("not-found"),
8834
9027
  literal("forbidden"),
8835
9028
  literal("device-rejoin-required"),
8836
9029
  literal("identity-recovery-required"),
8837
9030
  literal("conflict"),
9031
+ literal("state-in-use"),
8838
9032
  literal("rate-limited"),
8839
9033
  literal("group-membership-required"),
8840
9034
  literal("group-identity-stale"),
@@ -8971,11 +9165,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8971
9165
  literal("invalid-otp"),
8972
9166
  literal("challenge-expired"),
8973
9167
  literal("handle-unavailable"),
9168
+ literal("short-handle-invite-required"),
8974
9169
  literal("not-found"),
8975
9170
  literal("forbidden"),
8976
9171
  literal("device-rejoin-required"),
8977
9172
  literal("identity-recovery-required"),
8978
9173
  literal("conflict"),
9174
+ literal("state-in-use"),
8979
9175
  literal("rate-limited"),
8980
9176
  literal("group-membership-required"),
8981
9177
  literal("group-identity-stale"),
@@ -9055,7 +9251,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9055
9251
  },
9056
9252
  sourceLocation: {
9057
9253
  "file": "packages/dsh-awiki/src/index.ts",
9058
- "line": 204,
9254
+ "line": 206,
9059
9255
  "column": 9
9060
9256
  }
9061
9257
  },
@@ -9082,7 +9278,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9082
9278
  },
9083
9279
  sourceLocation: {
9084
9280
  "file": "packages/dsh-awiki/src/index.ts",
9085
- "line": 240,
9281
+ "line": 242,
9086
9282
  "column": 3
9087
9283
  }
9088
9284
  },
@@ -9109,7 +9305,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9109
9305
  },
9110
9306
  sourceLocation: {
9111
9307
  "file": "packages/dsh-awiki/src/index.ts",
9112
- "line": 164,
9308
+ "line": 166,
9113
9309
  "column": 9
9114
9310
  }
9115
9311
  },
@@ -9127,7 +9323,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9127
9323
  },
9128
9324
  sourceLocation: {
9129
9325
  "file": "packages/dsh-awiki/src/index.ts",
9130
- "line": 144,
9326
+ "line": 146,
9131
9327
  "column": 9
9132
9328
  }
9133
9329
  },
@@ -9145,7 +9341,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9145
9341
  },
9146
9342
  sourceLocation: {
9147
9343
  "file": "packages/dsh-awiki/src/index.ts",
9148
- "line": 153,
9344
+ "line": 155,
9149
9345
  "column": 9
9150
9346
  }
9151
9347
  },
@@ -9172,7 +9368,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9172
9368
  },
9173
9369
  sourceLocation: {
9174
9370
  "file": "packages/dsh-awiki/src/index.ts",
9175
- "line": 295,
9371
+ "line": 302,
9176
9372
  "column": 3
9177
9373
  }
9178
9374
  },
@@ -9199,7 +9395,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9199
9395
  },
9200
9396
  sourceLocation: {
9201
9397
  "file": "packages/dsh-awiki/src/index.ts",
9202
- "line": 112,
9398
+ "line": 114,
9203
9399
  "column": 3
9204
9400
  }
9205
9401
  },
@@ -9226,7 +9422,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9226
9422
  },
9227
9423
  sourceLocation: {
9228
9424
  "file": "packages/dsh-awiki/src/index.ts",
9229
- "line": 184,
9425
+ "line": 186,
9230
9426
  "column": 9
9231
9427
  }
9232
9428
  },
@@ -9253,7 +9449,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9253
9449
  },
9254
9450
  sourceLocation: {
9255
9451
  "file": "packages/dsh-awiki/src/index.ts",
9256
- "line": 222,
9452
+ "line": 224,
9257
9453
  "column": 9
9258
9454
  }
9259
9455
  },
@@ -9280,7 +9476,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9280
9476
  },
9281
9477
  sourceLocation: {
9282
9478
  "file": "packages/dsh-awiki/src/index.ts",
9283
- "line": 103,
9479
+ "line": 105,
9284
9480
  "column": 3
9285
9481
  }
9286
9482
  },
@@ -9307,7 +9503,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9307
9503
  },
9308
9504
  sourceLocation: {
9309
9505
  "file": "packages/dsh-awiki/src/index.ts",
9310
- "line": 216,
9506
+ "line": 218,
9311
9507
  "column": 9
9312
9508
  }
9313
9509
  },
@@ -9334,7 +9530,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9334
9530
  },
9335
9531
  sourceLocation: {
9336
9532
  "file": "packages/dsh-awiki/src/index.ts",
9337
- "line": 277,
9533
+ "line": 279,
9534
+ "column": 9
9535
+ }
9536
+ },
9537
+ {
9538
+ id: "@awiki/dsh-plugin#awiki/downloadMailAttachment",
9539
+ service: "awiki",
9540
+ namespace: "awiki",
9541
+ method: "downloadMailAttachment",
9542
+ invocation: { kind: "direct" },
9543
+ parameters: [{
9544
+ name: "request",
9545
+ wire: "request",
9546
+ source: "json",
9547
+ codec: {
9548
+ mode: "strict",
9549
+ typeSymbol: "@awiki/dsh-plugin/types#AwikiMailAttachmentDownloadRequest",
9550
+ schema: _awiki_dsh_plugin_awiki_downloadMailAttachment_parameter_0$schema
9551
+ }
9552
+ }],
9553
+ result: {
9554
+ mode: "strict",
9555
+ typeSymbol: "@awiki/dsh-plugin/types#AwikiResult",
9556
+ schema: _awiki_dsh_plugin_awiki_downloadMailAttachment_result$schema
9557
+ },
9558
+ sourceLocation: {
9559
+ "file": "packages/dsh-awiki/src/index.ts",
9560
+ "line": 297,
9338
9561
  "column": 9
9339
9562
  }
9340
9563
  },
@@ -9361,7 +9584,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9361
9584
  },
9362
9585
  sourceLocation: {
9363
9586
  "file": "packages/dsh-awiki/src/index.ts",
9364
- "line": 213,
9587
+ "line": 215,
9365
9588
  "column": 9
9366
9589
  }
9367
9590
  },
@@ -9379,7 +9602,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9379
9602
  },
9380
9603
  sourceLocation: {
9381
9604
  "file": "packages/dsh-awiki/src/index.ts",
9382
- "line": 97,
9605
+ "line": 99,
9383
9606
  "column": 9
9384
9607
  }
9385
9608
  },
@@ -9397,7 +9620,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9397
9620
  },
9398
9621
  sourceLocation: {
9399
9622
  "file": "packages/dsh-awiki/src/index.ts",
9400
- "line": 246,
9623
+ "line": 248,
9401
9624
  "column": 3
9402
9625
  }
9403
9626
  },
@@ -9415,7 +9638,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9415
9638
  },
9416
9639
  sourceLocation: {
9417
9640
  "file": "packages/dsh-awiki/src/index.ts",
9418
- "line": 150,
9641
+ "line": 152,
9419
9642
  "column": 9
9420
9643
  }
9421
9644
  },
@@ -9442,7 +9665,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9442
9665
  },
9443
9666
  sourceLocation: {
9444
9667
  "file": "packages/dsh-awiki/src/index.ts",
9445
- "line": 234,
9668
+ "line": 236,
9446
9669
  "column": 3
9447
9670
  }
9448
9671
  },
@@ -9469,7 +9692,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9469
9692
  },
9470
9693
  sourceLocation: {
9471
9694
  "file": "packages/dsh-awiki/src/index.ts",
9472
- "line": 225,
9695
+ "line": 227,
9473
9696
  "column": 3
9474
9697
  }
9475
9698
  },
@@ -9496,7 +9719,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9496
9719
  },
9497
9720
  sourceLocation: {
9498
9721
  "file": "packages/dsh-awiki/src/index.ts",
9499
- "line": 257,
9722
+ "line": 259,
9500
9723
  "column": 3
9501
9724
  }
9502
9725
  },
@@ -9514,7 +9737,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9514
9737
  },
9515
9738
  sourceLocation: {
9516
9739
  "file": "packages/dsh-awiki/src/index.ts",
9517
- "line": 118,
9740
+ "line": 120,
9518
9741
  "column": 9
9519
9742
  }
9520
9743
  },
@@ -9532,7 +9755,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9532
9755
  },
9533
9756
  sourceLocation: {
9534
9757
  "file": "packages/dsh-awiki/src/index.ts",
9535
- "line": 147,
9758
+ "line": 149,
9536
9759
  "column": 3
9537
9760
  }
9538
9761
  },
@@ -9550,7 +9773,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9550
9773
  },
9551
9774
  sourceLocation: {
9552
9775
  "file": "packages/dsh-awiki/src/index.ts",
9553
- "line": 100,
9776
+ "line": 102,
9554
9777
  "column": 3
9555
9778
  }
9556
9779
  },
@@ -9577,7 +9800,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9577
9800
  },
9578
9801
  sourceLocation: {
9579
9802
  "file": "packages/dsh-awiki/src/index.ts",
9580
- "line": 260,
9803
+ "line": 262,
9581
9804
  "column": 3
9582
9805
  }
9583
9806
  },
@@ -9595,7 +9818,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9595
9818
  },
9596
9819
  sourceLocation: {
9597
9820
  "file": "packages/dsh-awiki/src/index.ts",
9598
- "line": 280,
9821
+ "line": 282,
9599
9822
  "column": 3
9600
9823
  }
9601
9824
  },
@@ -9613,7 +9836,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9613
9836
  },
9614
9837
  sourceLocation: {
9615
9838
  "file": "packages/dsh-awiki/src/index.ts",
9616
- "line": 192,
9839
+ "line": 194,
9617
9840
  "column": 3
9618
9841
  }
9619
9842
  },
@@ -9640,7 +9863,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9640
9863
  },
9641
9864
  sourceLocation: {
9642
9865
  "file": "packages/dsh-awiki/src/index.ts",
9643
- "line": 207,
9866
+ "line": 209,
9644
9867
  "column": 9
9645
9868
  }
9646
9869
  },
@@ -9658,7 +9881,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9658
9881
  },
9659
9882
  sourceLocation: {
9660
9883
  "file": "packages/dsh-awiki/src/index.ts",
9661
- "line": 121,
9884
+ "line": 123,
9662
9885
  "column": 9
9663
9886
  }
9664
9887
  },
@@ -9685,7 +9908,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9685
9908
  },
9686
9909
  sourceLocation: {
9687
9910
  "file": "packages/dsh-awiki/src/index.ts",
9688
- "line": 130,
9911
+ "line": 132,
9689
9912
  "column": 9
9690
9913
  }
9691
9914
  },
@@ -9712,7 +9935,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9712
9935
  },
9713
9936
  sourceLocation: {
9714
9937
  "file": "packages/dsh-awiki/src/index.ts",
9715
- "line": 228,
9938
+ "line": 230,
9716
9939
  "column": 3
9717
9940
  }
9718
9941
  },
@@ -9739,7 +9962,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9739
9962
  },
9740
9963
  sourceLocation: {
9741
9964
  "file": "packages/dsh-awiki/src/index.ts",
9742
- "line": 231,
9965
+ "line": 233,
9743
9966
  "column": 9
9744
9967
  }
9745
9968
  },
@@ -9767,7 +9990,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9767
9990
  },
9768
9991
  sourceLocation: {
9769
9992
  "file": "packages/dsh-awiki/src/index.ts",
9770
- "line": 254,
9993
+ "line": 256,
9771
9994
  "column": 3
9772
9995
  }
9773
9996
  },
@@ -9794,7 +10017,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9794
10017
  },
9795
10018
  sourceLocation: {
9796
10019
  "file": "packages/dsh-awiki/src/index.ts",
9797
- "line": 237,
10020
+ "line": 239,
9798
10021
  "column": 3
9799
10022
  }
9800
10023
  },
@@ -9822,7 +10045,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9822
10045
  },
9823
10046
  sourceLocation: {
9824
10047
  "file": "packages/dsh-awiki/src/index.ts",
9825
- "line": 283,
10048
+ "line": 285,
9826
10049
  "column": 9
9827
10050
  }
9828
10051
  },
@@ -9840,7 +10063,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9840
10063
  },
9841
10064
  sourceLocation: {
9842
10065
  "file": "packages/dsh-awiki/src/index.ts",
9843
- "line": 127,
10066
+ "line": 129,
9844
10067
  "column": 3
9845
10068
  }
9846
10069
  },
@@ -9867,7 +10090,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9867
10090
  },
9868
10091
  sourceLocation: {
9869
10092
  "file": "packages/dsh-awiki/src/index.ts",
9870
- "line": 124,
10093
+ "line": 126,
9871
10094
  "column": 3
9872
10095
  }
9873
10096
  },
@@ -9894,7 +10117,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9894
10117
  },
9895
10118
  sourceLocation: {
9896
10119
  "file": "packages/dsh-awiki/src/index.ts",
9897
- "line": 268,
10120
+ "line": 270,
9898
10121
  "column": 3
9899
10122
  }
9900
10123
  },
@@ -9921,7 +10144,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9921
10144
  },
9922
10145
  sourceLocation: {
9923
10146
  "file": "packages/dsh-awiki/src/index.ts",
9924
- "line": 289,
10147
+ "line": 291,
9925
10148
  "column": 3
9926
10149
  }
9927
10150
  },
@@ -9948,7 +10171,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9948
10171
  },
9949
10172
  sourceLocation: {
9950
10173
  "file": "packages/dsh-awiki/src/index.ts",
9951
- "line": 201,
10174
+ "line": 203,
9952
10175
  "column": 3
9953
10176
  }
9954
10177
  },
@@ -9975,7 +10198,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9975
10198
  },
9976
10199
  sourceLocation: {
9977
10200
  "file": "packages/dsh-awiki/src/index.ts",
9978
- "line": 179,
10201
+ "line": 181,
9979
10202
  "column": 9
9980
10203
  }
9981
10204
  },
@@ -10002,7 +10225,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10002
10225
  },
10003
10226
  sourceLocation: {
10004
10227
  "file": "packages/dsh-awiki/src/index.ts",
10005
- "line": 286,
10228
+ "line": 288,
10006
10229
  "column": 9
10007
10230
  }
10008
10231
  },
@@ -10020,7 +10243,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10020
10243
  },
10021
10244
  sourceLocation: {
10022
10245
  "file": "packages/dsh-awiki/src/index.ts",
10023
- "line": 156,
10246
+ "line": 158,
10024
10247
  "column": 3
10025
10248
  }
10026
10249
  },
@@ -10047,7 +10270,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10047
10270
  },
10048
10271
  sourceLocation: {
10049
10272
  "file": "packages/dsh-awiki/src/index.ts",
10050
- "line": 138,
10273
+ "line": 140,
10051
10274
  "column": 9
10052
10275
  }
10053
10276
  },
@@ -10074,7 +10297,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10074
10297
  },
10075
10298
  sourceLocation: {
10076
10299
  "file": "packages/dsh-awiki/src/index.ts",
10077
- "line": 169,
10300
+ "line": 171,
10078
10301
  "column": 9
10079
10302
  }
10080
10303
  },
@@ -10101,7 +10324,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10101
10324
  },
10102
10325
  sourceLocation: {
10103
10326
  "file": "packages/dsh-awiki/src/index.ts",
10104
- "line": 243,
10327
+ "line": 245,
10105
10328
  "column": 3
10106
10329
  }
10107
10330
  },
@@ -10128,7 +10351,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10128
10351
  },
10129
10352
  sourceLocation: {
10130
10353
  "file": "packages/dsh-awiki/src/index.ts",
10131
- "line": 115,
10354
+ "line": 117,
10132
10355
  "column": 3
10133
10356
  }
10134
10357
  },
@@ -10155,7 +10378,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10155
10378
  },
10156
10379
  sourceLocation: {
10157
10380
  "file": "packages/dsh-awiki/src/index.ts",
10158
- "line": 219,
10381
+ "line": 221,
10159
10382
  "column": 3
10160
10383
  }
10161
10384
  },
@@ -10182,7 +10405,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10182
10405
  },
10183
10406
  sourceLocation: {
10184
10407
  "file": "packages/dsh-awiki/src/index.ts",
10185
- "line": 210,
10408
+ "line": 212,
10186
10409
  "column": 9
10187
10410
  }
10188
10411
  },
@@ -10200,7 +10423,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10200
10423
  },
10201
10424
  sourceLocation: {
10202
10425
  "file": "packages/dsh-awiki/src/index.ts",
10203
- "line": 141,
10426
+ "line": 143,
10204
10427
  "column": 3
10205
10428
  }
10206
10429
  },
@@ -10227,7 +10450,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10227
10450
  },
10228
10451
  sourceLocation: {
10229
10452
  "file": "packages/dsh-awiki/src/index.ts",
10230
- "line": 174,
10453
+ "line": 176,
10231
10454
  "column": 9
10232
10455
  }
10233
10456
  },
@@ -10254,7 +10477,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10254
10477
  },
10255
10478
  sourceLocation: {
10256
10479
  "file": "packages/dsh-awiki/src/index.ts",
10257
- "line": 109,
10480
+ "line": 111,
10258
10481
  "column": 3
10259
10482
  }
10260
10483
  },
@@ -10281,7 +10504,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10281
10504
  },
10282
10505
  sourceLocation: {
10283
10506
  "file": "packages/dsh-awiki/src/index.ts",
10284
- "line": 274,
10507
+ "line": 276,
10285
10508
  "column": 9
10286
10509
  }
10287
10510
  },
@@ -10308,7 +10531,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10308
10531
  },
10309
10532
  sourceLocation: {
10310
10533
  "file": "packages/dsh-awiki/src/index.ts",
10311
- "line": 292,
10534
+ "line": 294,
10312
10535
  "column": 9
10313
10536
  }
10314
10537
  },
@@ -10335,7 +10558,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10335
10558
  },
10336
10559
  sourceLocation: {
10337
10560
  "file": "packages/dsh-awiki/src/index.ts",
10338
- "line": 198,
10561
+ "line": 200,
10339
10562
  "column": 3
10340
10563
  }
10341
10564
  },
@@ -10362,7 +10585,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10362
10585
  },
10363
10586
  sourceLocation: {
10364
10587
  "file": "packages/dsh-awiki/src/index.ts",
10365
- "line": 135,
10588
+ "line": 137,
10366
10589
  "column": 9
10367
10590
  }
10368
10591
  },
@@ -10389,7 +10612,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10389
10612
  },
10390
10613
  sourceLocation: {
10391
10614
  "file": "packages/dsh-awiki/src/index.ts",
10392
- "line": 271,
10615
+ "line": 273,
10393
10616
  "column": 3
10394
10617
  }
10395
10618
  },
@@ -10416,7 +10639,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10416
10639
  },
10417
10640
  sourceLocation: {
10418
10641
  "file": "packages/dsh-awiki/src/index.ts",
10419
- "line": 159,
10642
+ "line": 161,
10420
10643
  "column": 9
10421
10644
  }
10422
10645
  },
@@ -10443,7 +10666,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10443
10666
  },
10444
10667
  sourceLocation: {
10445
10668
  "file": "packages/dsh-awiki/src/index.ts",
10446
- "line": 263,
10669
+ "line": 265,
10447
10670
  "column": 9
10448
10671
  }
10449
10672
  },
@@ -10470,7 +10693,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10470
10693
  },
10471
10694
  sourceLocation: {
10472
10695
  "file": "packages/dsh-awiki/src/index.ts",
10473
- "line": 249,
10696
+ "line": 251,
10474
10697
  "column": 3
10475
10698
  }
10476
10699
  },
@@ -10497,7 +10720,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10497
10720
  },
10498
10721
  sourceLocation: {
10499
10722
  "file": "packages/dsh-awiki/src/index.ts",
10500
- "line": 189,
10723
+ "line": 191,
10501
10724
  "column": 9
10502
10725
  }
10503
10726
  },
@@ -10524,7 +10747,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10524
10747
  },
10525
10748
  sourceLocation: {
10526
10749
  "file": "packages/dsh-awiki/src/index.ts",
10527
- "line": 106,
10750
+ "line": 108,
10528
10751
  "column": 3
10529
10752
  }
10530
10753
  },
@@ -10551,7 +10774,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10551
10774
  },
10552
10775
  sourceLocation: {
10553
10776
  "file": "packages/dsh-awiki/src/index.ts",
10554
- "line": 195,
10777
+ "line": 197,
10555
10778
  "column": 3
10556
10779
  }
10557
10780
  }
@@ -10739,6 +10962,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10739
10962
  return [store === void 0 ? local : store.read(scope, key, initial, dirty), set];
10740
10963
  }
10741
10964
  //#endregion
10965
+ //#region lib/types/registration-policy.js
10966
+ /** Registration presentation and Handle normalization; admission is owned by the server. */
10967
+ const SHORT_HANDLE_INVITE_MESSAGE = "注册少于5位的handle需要使用邀请码,目前暂不支持自主注册。";
10968
+ //#endregion
10742
10969
  //#region lib/types/client/otp-cooldown.js
10743
10970
  /** Retain the server cooldown across panel remounts, without persisting OTPs. */
10744
10971
  function useRecoveryOtpCooldown() {
@@ -10753,13 +10980,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10753
10980
  clearInterval(timer);
10754
10981
  };
10755
10982
  }, [deadline]);
10983
+ const restore = (0, react.useCallback)((retryAt) => {
10984
+ if (retryAt === null || retryAt === void 0) return;
10985
+ const parsed = Date.parse(retryAt);
10986
+ if (!Number.isFinite(parsed) || parsed <= Date.now()) return;
10987
+ setNow(Date.now());
10988
+ setDeadline((deadline) => Math.max(deadline, parsed));
10989
+ }, [setDeadline]);
10756
10990
  return {
10757
10991
  seconds: Math.max(0, Math.ceil((deadline - now) / 1e3)),
10758
10992
  start: (seconds) => {
10759
10993
  const now = Date.now();
10760
10994
  setNow(now);
10761
10995
  setDeadline(now + Math.max(0, seconds) * 1e3);
10762
- }
10996
+ },
10997
+ restore
10763
10998
  };
10764
10999
  }
10765
11000
  //#endregion
@@ -11016,6 +11251,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11016
11251
  setNotice(null);
11017
11252
  setError(null);
11018
11253
  }, [props.operationId]);
11254
+ (0, react.useEffect)(() => {
11255
+ cooldown.restore(props.retryAt);
11256
+ }, [cooldown.restore, props.retryAt]);
11019
11257
  (0, react.useEffect)(() => {
11020
11258
  const progress = props.progress;
11021
11259
  if (progress === null || !canResume(progress) || progress.phase === "awaiting_factor" || progress.phase === "ready_to_commit" || progress.phase === "applied" || progress.phase === "quarantined_key_unavailable" || props.pending || props.statusError || autoAttempt || error !== null) return;
@@ -11134,7 +11372,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11134
11372
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 24 })
11135
11373
  }),
11136
11374
  (0, react_jsx_runtime.jsx)("h3", { children: props.requestTitle ?? "恢复已有身份" }),
11137
- (0, react_jsx_runtime.jsx)("p", { children: props.requestDescription ?? "输入原来的完整 Handle 和绑定手机号,我们会发送验证码来确认身份归属。" }),
11375
+ (0, react_jsx_runtime.jsx)("p", { children: props.requestDescription ?? "输入原来的完整 Handle 和绑定手机号。发送验证码会开始一次替换 DID 的恢复,使其他设备的旧凭证失效。" }),
11138
11376
  props.fixedHandle === void 0 ? (0, react_jsx_runtime.jsxs)("label", { children: ["完整 Handle", (0, react_jsx_runtime.jsx)("input", {
11139
11377
  ref: handle,
11140
11378
  value: handleDraft,
@@ -11162,7 +11400,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11162
11400
  type: "submit",
11163
11401
  className: _dsh_awiki_css_AwikiOverlay_module_css_default.primary,
11164
11402
  disabled: props.pending || cooldown.seconds > 0 || phoneDraft.trim() === "",
11165
- children: "获取恢复验证码"
11403
+ children: "发送恢复验证码并替换 DID"
11166
11404
  }),
11167
11405
  (error ?? props.requestError) && (0, react_jsx_runtime.jsx)("small", {
11168
11406
  className: _dsh_awiki_css_AwikiOverlay_module_css_default.inlineError,
@@ -11372,7 +11610,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11372
11610
  }
11373
11611
  //#endregion
11374
11612
  //#region \0dsh-awiki-css:AwikiIdentityAccess.module.css.mjs
11375
- const css$4 = ".r_slHG_accessFlow{width:100%;min-width:0;color:var(--dsw-alias-label-secondary);gap:14px;display:grid}.r_slHG_identityIcon,.r_slHG_progressIcon{width:48px;height:48px;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-interactive-bg-active);border-radius:50%;place-items:center;margin:0 auto;display:grid}.r_slHG_progressIcon svg{animation:1s linear infinite r_slHG_identity-spin}@keyframes r_slHG_identity-spin{to{transform:rotate(360deg)}}.r_slHG_headingGroup{text-align:center;gap:6px;display:grid}.r_slHG_headingGroup h3,.r_slHG_headingGroup p,.r_slHG_existingNotice p,.r_slHG_dangerPanel p{margin:0}.r_slHG_headingGroup h3{color:var(--dsw-alias-label-primary);font-size:18px;line-height:26px}.r_slHG_headingGroup p,.r_slHG_existingNotice p,.r_slHG_dangerPanel p{font-size:13px;line-height:20px}.r_slHG_headingGroup strong{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere}.r_slHG_identitySummary{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:8px;grid-template-columns:max-content minmax(0,1fr);gap:6px 14px;padding:12px 14px;font-size:12px;line-height:18px;display:grid}.r_slHG_identitySummary span{color:var(--dsw-alias-label-tertiary)}.r_slHG_identitySummary strong{overflow-wrap:anywhere;min-width:0;color:var(--dsw-alias-label-primary)}.r_slHG_field{color:var(--dsw-alias-label-secondary);text-align:left;gap:6px;font-size:13px;line-height:20px;display:grid}.r_slHG_field input{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);width:100%;height:40px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);font:inherit;border-radius:8px;padding:0 12px}.r_slHG_field input:focus-visible,.r_slHG_primary:focus-visible,.r_slHG_secondary:focus-visible,.r_slHG_linkButton:focus-visible,.r_slHG_dangerLink:focus-visible,.r_slHG_dangerButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.r_slHG_primary,.r_slHG_secondary,.r_slHG_dangerButton{cursor:pointer;min-height:40px;font:inherit;border-radius:8px;padding:0 14px}.r_slHG_primary{color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-button-primary-fill);border:0}.r_slHG_primary:hover{background:var(--dsw-alias-button-primary-hover)}.r_slHG_secondary{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.r_slHG_secondary:hover{background:var(--dsw-alias-interactive-bg-hover)}.r_slHG_primary:disabled,.r_slHG_secondary:disabled,.r_slHG_linkButton:disabled,.r_slHG_dangerLink:disabled,.r_slHG_dangerButton:disabled{cursor:default;opacity:.5}.r_slHG_linkButton,.r_slHG_dangerLink{cursor:pointer;min-height:32px;font:inherit;background:0 0;border:0;padding:0;font-size:12px}.r_slHG_linkButton{color:var(--dsw-alias-brand-primary)}.r_slHG_dangerLink{color:var(--dsw-alias-state-error-primary)}.r_slHG_actionStack{gap:8px;display:grid}.r_slHG_existingNotice,.r_slHG_dangerPanel{border-left:3px solid var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2);gap:10px;padding:12px 14px;display:grid}.r_slHG_existingNotice strong{color:var(--dsw-alias-label-primary)}.r_slHG_dangerPanel{border-left-color:var(--dsw-alias-state-error-primary)}.r_slHG_dangerPanel strong{color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px}.r_slHG_confirmation{color:var(--dsw-alias-label-secondary);align-items:flex-start;gap:8px;font-size:12px;line-height:18px;display:flex}.r_slHG_confirmation input{width:16px;height:16px;accent-color:var(--dsw-alias-state-error-primary);flex:none;margin:1px 0 0}.r_slHG_dangerButton{border:1px solid var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary);background:0 0}.r_slHG_dangerButton:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}.r_slHG_recoveryHelp{border-top:1px solid var(--dsw-alias-border-l1);gap:10px;padding-top:14px;display:grid}.r_slHG_recoveryHelp p{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}.r_slHG_notice,.r_slHG_error{overflow-wrap:anywhere;font-size:12px;line-height:18px}.r_slHG_notice{color:var(--dsw-alias-label-secondary)}.r_slHG_error{color:var(--dsw-alias-state-error-primary)}.r_slHG_sas{letter-spacing:.2em;text-align:center;font-variant-numeric:tabular-nums;font-size:32px}@media (height<=560px){.r_slHG_accessFlow{gap:8px}.r_slHG_identityIcon,.r_slHG_progressIcon{width:32px;height:32px}}@media (prefers-reduced-motion:reduce){.r_slHG_primary,.r_slHG_secondary,.r_slHG_linkButton,.r_slHG_dangerLink,.r_slHG_dangerButton{transition-duration:.001ms!important}.r_slHG_progressIcon svg{animation-duration:.001ms!important}}";
11613
+ const css$4 = ".r_slHG_accessFlow{width:100%;min-width:0;color:var(--dsw-alias-label-secondary);gap:14px;display:grid}.r_slHG_identityIcon,.r_slHG_progressIcon{width:48px;height:48px;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-interactive-bg-active);border-radius:50%;place-items:center;margin:0 auto;display:grid}.r_slHG_progressIcon svg{animation:1s linear infinite r_slHG_identity-spin}@keyframes r_slHG_identity-spin{to{transform:rotate(360deg)}}.r_slHG_headingGroup{text-align:center;gap:6px;display:grid}.r_slHG_headingGroup h3,.r_slHG_headingGroup p,.r_slHG_existingNotice p,.r_slHG_dangerPanel p{margin:0}.r_slHG_headingGroup h3{color:var(--dsw-alias-label-primary);font-size:18px;line-height:26px}.r_slHG_headingGroup p,.r_slHG_existingNotice p,.r_slHG_dangerPanel p{font-size:13px;line-height:20px}.r_slHG_headingGroup strong{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere}.r_slHG_identitySummary{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:8px;grid-template-columns:max-content minmax(0,1fr);gap:6px 14px;padding:12px 14px;font-size:12px;line-height:18px;display:grid}.r_slHG_identitySummary span{color:var(--dsw-alias-label-tertiary)}.r_slHG_identitySummary strong{overflow-wrap:anywhere;min-width:0;color:var(--dsw-alias-label-primary)}.r_slHG_field{color:var(--dsw-alias-label-secondary);text-align:left;gap:6px;font-size:13px;line-height:20px;display:grid}.r_slHG_field input{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);width:100%;height:40px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);font:inherit;border-radius:8px;padding:0 12px}.r_slHG_field input:focus-visible,.r_slHG_primary:focus-visible,.r_slHG_secondary:focus-visible,.r_slHG_linkButton:focus-visible,.r_slHG_dangerLink:focus-visible,.r_slHG_dangerButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.r_slHG_primary,.r_slHG_secondary,.r_slHG_dangerButton{cursor:pointer;min-height:40px;font:inherit;border-radius:8px;padding:0 14px}.r_slHG_primary{color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-button-primary-fill);border:0}.r_slHG_primary:hover{background:var(--dsw-alias-button-primary-hover)}.r_slHG_secondary{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.r_slHG_secondary:hover{background:var(--dsw-alias-interactive-bg-hover)}.r_slHG_primary:disabled,.r_slHG_secondary:disabled,.r_slHG_linkButton:disabled,.r_slHG_dangerLink:disabled,.r_slHG_dangerButton:disabled{cursor:default;opacity:.5}.r_slHG_linkButton,.r_slHG_dangerLink{cursor:pointer;min-height:32px;font:inherit;background:0 0;border:0;padding:0;font-size:12px}.r_slHG_linkButton{color:var(--dsw-alias-brand-primary)}.r_slHG_dangerLink{color:var(--dsw-alias-state-error-primary)}.r_slHG_actionStack{gap:8px;display:grid}.r_slHG_existingNotice,.r_slHG_dangerPanel,.r_slHG_inviteNotice{border-left:3px solid var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2);gap:10px;padding:12px 14px;display:grid}.r_slHG_existingNotice strong,.r_slHG_inviteNotice strong{color:var(--dsw-alias-label-primary)}.r_slHG_inviteNotice p{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}.r_slHG_inviteNotice a{color:var(--dsw-alias-brand-primary);overflow-wrap:anywhere}.r_slHG_dangerPanel{border-left-color:var(--dsw-alias-state-error-primary)}.r_slHG_dangerPanel strong{color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px}.r_slHG_confirmation{color:var(--dsw-alias-label-secondary);align-items:flex-start;gap:8px;font-size:12px;line-height:18px;display:flex}.r_slHG_confirmation input{width:16px;height:16px;accent-color:var(--dsw-alias-state-error-primary);flex:none;margin:1px 0 0}.r_slHG_dangerButton{border:1px solid var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary);background:0 0}.r_slHG_dangerButton:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}.r_slHG_recoveryHelp{border-top:1px solid var(--dsw-alias-border-l1);gap:10px;padding-top:14px;display:grid}.r_slHG_recoveryHelp p{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}.r_slHG_notice,.r_slHG_error{overflow-wrap:anywhere;font-size:12px;line-height:18px}.r_slHG_notice{color:var(--dsw-alias-label-secondary)}.r_slHG_error{color:var(--dsw-alias-state-error-primary)}.r_slHG_sas{letter-spacing:.2em;text-align:center;font-variant-numeric:tabular-nums;font-size:32px}@media (height<=560px){.r_slHG_accessFlow{gap:8px}.r_slHG_identityIcon,.r_slHG_progressIcon{width:32px;height:32px}}@media (prefers-reduced-motion:reduce){.r_slHG_primary,.r_slHG_secondary,.r_slHG_linkButton,.r_slHG_dangerLink,.r_slHG_dangerButton{transition-duration:.001ms!important}.r_slHG_progressIcon svg{animation-duration:.001ms!important}}";
11376
11614
  const tagId$4 = "@awiki/dsh-plugin/AwikiIdentityAccess.module.css";
11377
11615
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
11378
11616
  const tag = document.createElement("style");
@@ -11395,6 +11633,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11395
11633
  "identity-spin": "r_slHG_identity-spin",
11396
11634
  "identityIcon": "r_slHG_identityIcon",
11397
11635
  "identitySummary": "r_slHG_identitySummary",
11636
+ "inviteNotice": "r_slHG_inviteNotice",
11398
11637
  "linkButton": "r_slHG_linkButton",
11399
11638
  "notice": "r_slHG_notice",
11400
11639
  "primary": "r_slHG_primary",
@@ -11426,11 +11665,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11426
11665
  ...props.initialFactorContext === void 0 ? {} : { initialFactorContext: props.initialFactorContext },
11427
11666
  ...props.fixedHandle === void 0 ? {} : { fixedHandle: props.fixedHandle },
11428
11667
  ...props.requestTitle === void 0 ? {} : { requestTitle: props.requestTitle },
11429
- ...props.requestDescription === void 0 ? {} : { requestDescription: props.requestDescription }
11668
+ ...props.requestDescription === void 0 ? {} : { requestDescription: props.requestDescription },
11669
+ retryAt: props.recoveryOtpRetryAt
11430
11670
  }, props.recoveryOperationId ?? props.fixedHandle ?? "new");
11431
11671
  }
11432
11672
  /** Keep phone and OTP values in private browser memory for the duration of this explicit user flow. */
11433
11673
  function AwikiIdentityAccess(props) {
11674
+ const [registrationConfirmation, setRegistrationConfirmation] = (0, react.useState)(null);
11675
+ const registrationInFlight = (0, react.useRef)(false);
11676
+ const [registrationSubmitting, setRegistrationSubmitting] = (0, react.useState)(false);
11677
+ const [shortHandleInviteNotice, setShortHandleInviteNotice] = useDraftState("identity:shortHandleInviteNotice", false, false);
11434
11678
  const recoveryCooldown = useRecoveryOtpCooldown();
11435
11679
  const [phone, setPhone] = useDraftState("identity:phone", "");
11436
11680
  const [handle, setHandle] = useDraftState("identity:handle", "");
@@ -11446,6 +11690,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11446
11690
  const [loginFailed, setLoginFailed] = useDraftState("identity:loginFailed", false, false);
11447
11691
  const [joinContext, setJoinContext] = useDraftState("identity:joinContext", null, false);
11448
11692
  const [recoveryChoice, setRecoveryChoice] = useDraftState("identity:recoveryChoice", null, false);
11693
+ const [recoveryRiskConfirmed, setRecoveryRiskConfirmed] = useDraftState("identity:recoveryRiskConfirmed", false, false);
11694
+ const [recoveryEntryOpen, setRecoveryEntryOpen] = useDraftState("identity:recoveryEntryOpen", false, false);
11695
+ const validRecoveryEntryOpen = recoveryEntryOpen && props.sessionStatus === "recovery-required";
11696
+ const recoveryConfirmationInFlight = (0, react.useRef)(false);
11697
+ const [recoveryConfirming, setRecoveryConfirming] = (0, react.useState)(false);
11449
11698
  const [joinCheck, setJoinCheck] = (0, react.useState)("loading");
11450
11699
  const [joinProgress, setJoinProgress] = (0, react.useState)(null);
11451
11700
  const [deviceRejoinHandle, setDeviceRejoinHandle] = useDraftState("identity:deviceRejoinHandle", null, false);
@@ -11462,11 +11711,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11462
11711
  clearInterval(timer);
11463
11712
  };
11464
11713
  }, [retryDeadline]);
11714
+ (0, react.useEffect)(() => {
11715
+ if (recoveryEntryOpen && props.sessionStatus !== "recovery-required") setRecoveryEntryOpen(false);
11716
+ }, [
11717
+ props.sessionStatus,
11718
+ recoveryEntryOpen,
11719
+ setRecoveryEntryOpen
11720
+ ]);
11465
11721
  const resetIdentityEntry = () => {
11722
+ setRegistrationConfirmation(null);
11723
+ setShortHandleInviteNotice(false);
11466
11724
  setOtp("");
11467
11725
  setRegistrationOtpSent(false);
11468
11726
  setRecoveryFactorContext(null);
11469
11727
  setRecoveryChoice(null);
11728
+ setRecoveryRiskConfirmed(false);
11729
+ setRecoveryEntryOpen(false);
11470
11730
  setNotice(null);
11471
11731
  setError(null);
11472
11732
  setRetryDeadline(null);
@@ -11489,6 +11749,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11489
11749
  phone: phone.trim()
11490
11750
  });
11491
11751
  if (!result.ok) {
11752
+ if (result.failureCode === "short-handle-invite-required") {
11753
+ setNotice(null);
11754
+ setShortHandleInviteNotice(true);
11755
+ return;
11756
+ }
11492
11757
  setError(result.error);
11493
11758
  return;
11494
11759
  }
@@ -11503,32 +11768,46 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11503
11768
  const result = await props.continueRecoveryForHandle?.(handle.trim());
11504
11769
  if (result !== void 0 && !result.ok) return setError(result.error);
11505
11770
  if (result?.ok && result.value) return;
11771
+ setShortHandleInviteNotice(false);
11506
11772
  await requestRegistrationOtp();
11507
11773
  };
11508
11774
  const completeRegistration = async () => {
11509
- if (!registrationOtpSent) return;
11775
+ if (!registrationOtpSent || registrationConfirmation === null || registrationInFlight.current || props.pending) return;
11776
+ registrationInFlight.current = true;
11777
+ setRegistrationSubmitting(true);
11510
11778
  setError(null);
11511
- const result = await props.registerIdentity({
11512
- phone: phone.trim(),
11513
- handle: handle.trim(),
11514
- otp: otp.trim()
11515
- });
11516
- if (!result.ok) {
11517
- setError(result.error);
11518
- return;
11519
- }
11520
- if (result.value.status === "join-required") {
11521
- setOtp("");
11522
- setJoinContext({
11523
- fullHandle: result.value.fullHandle,
11524
- phone: phone.trim()
11525
- });
11526
- return;
11779
+ try {
11780
+ const result = await props.registerIdentity(registrationConfirmation);
11781
+ setRegistrationConfirmation(null);
11782
+ if (!result.ok) {
11783
+ if (result.failureCode === "short-handle-invite-required") {
11784
+ resetIdentityEntry();
11785
+ setNotice(null);
11786
+ setShortHandleInviteNotice(true);
11787
+ return;
11788
+ }
11789
+ setError(result.error);
11790
+ return;
11791
+ }
11792
+ if (result.value.status === "join-required") {
11793
+ setOtp("");
11794
+ setJoinContext({
11795
+ fullHandle: result.value.fullHandle,
11796
+ phone: phone.trim()
11797
+ });
11798
+ return;
11799
+ }
11800
+ setPhone("");
11801
+ setHandle("");
11802
+ setDeviceRejoinHandle(null);
11803
+ resetIdentityEntry();
11804
+ } catch {
11805
+ setRegistrationConfirmation(null);
11806
+ setError("暂时无法完成身份注册,请重试。");
11807
+ } finally {
11808
+ registrationInFlight.current = false;
11809
+ setRegistrationSubmitting(false);
11527
11810
  }
11528
- setPhone("");
11529
- setHandle("");
11530
- setDeviceRejoinHandle(null);
11531
- resetIdentityEntry();
11532
11811
  };
11533
11812
  (0, react.useEffect)(() => {
11534
11813
  if (props.access === void 0 || props.access === null) return;
@@ -11557,32 +11836,69 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11557
11836
  setJoinProgress(null);
11558
11837
  resetIdentityEntry();
11559
11838
  };
11560
- const chooseRecovery = async () => {
11561
- if (joinContext === null || !props.handleRecoveryPhoneEnabled) return;
11839
+ const chooseRecovery = () => {
11840
+ if (joinContext === null) return;
11562
11841
  setError(null);
11563
- const discarded = await props.cancelDeviceJoin();
11564
- if (!discarded.ok) return setError(discarded.error);
11565
11842
  setRecoveryChoice(joinContext.fullHandle);
11566
11843
  setRecoveryFactorContext({
11567
11844
  fullHandle: joinContext.fullHandle,
11568
11845
  phone: joinContext.phone
11569
11846
  });
11570
- setJoinContext(null);
11571
- const continued = await props.continueRecoveryForHandle?.(joinContext.fullHandle);
11572
- if (continued !== void 0 && !continued.ok) return setError(continued.error);
11573
- if (continued?.ok && continued.value) return;
11574
- if (joinContext.phone === "") return;
11575
- const recovery = await props.sendRecoveryOtp({
11576
- fullHandle: joinContext.fullHandle,
11577
- phone: joinContext.phone
11578
- });
11579
- if (!recovery.ok) return setError(recovery.error);
11580
- recoveryCooldown.start(recovery.value.retryAfterSeconds);
11581
- setRecoveryFactorContext({
11582
- fullHandle: recovery.value.fullHandle,
11583
- phone: joinContext.phone
11584
- });
11585
- setJoinContext(null);
11847
+ setRecoveryRiskConfirmed(false);
11848
+ };
11849
+ const cancelRecoveryChoice = () => {
11850
+ setRecoveryChoice(null);
11851
+ setRecoveryFactorContext(null);
11852
+ setRecoveryRiskConfirmed(false);
11853
+ setError(null);
11854
+ };
11855
+ const confirmRecoveryChoice = async () => {
11856
+ if (recoveryChoice === null || recoveryConfirmationInFlight.current) return;
11857
+ recoveryConfirmationInFlight.current = true;
11858
+ setRecoveryConfirming(true);
11859
+ setError(null);
11860
+ try {
11861
+ const factor = recoveryFactorContext ?? {
11862
+ fullHandle: recoveryChoice,
11863
+ phone: ""
11864
+ };
11865
+ if (joinContext !== null) {
11866
+ const continued = await props.continueRecoveryForHandle?.(factor.fullHandle);
11867
+ if (continued !== void 0 && !continued.ok) return setError(continued.error);
11868
+ if (continued?.ok && continued.value) {
11869
+ setJoinContext(null);
11870
+ setRecoveryRiskConfirmed(true);
11871
+ return;
11872
+ }
11873
+ const recovery = await props.beginRecoveryFromDeviceJoin(factor);
11874
+ if (!recovery.ok) {
11875
+ cancelRecoveryChoice();
11876
+ props.refreshIdentityAccess?.();
11877
+ return setError(recovery.error);
11878
+ }
11879
+ setJoinContext(null);
11880
+ setRecoveryRiskConfirmed(true);
11881
+ if (recovery.value === null) return;
11882
+ recoveryCooldown.start(recovery.value.retryAfterSeconds);
11883
+ setRecoveryFactorContext({
11884
+ fullHandle: recovery.value.fullHandle,
11885
+ phone: factor.phone
11886
+ });
11887
+ } else {
11888
+ setRecoveryRiskConfirmed(true);
11889
+ if (factor.phone === "") return;
11890
+ const recovery = await props.sendRecoveryOtp(factor);
11891
+ if (!recovery.ok) return setError(recovery.error);
11892
+ recoveryCooldown.start(recovery.value.retryAfterSeconds);
11893
+ setRecoveryFactorContext({
11894
+ fullHandle: recovery.value.fullHandle,
11895
+ phone: factor.phone
11896
+ });
11897
+ }
11898
+ } finally {
11899
+ recoveryConfirmationInFlight.current = false;
11900
+ setRecoveryConfirming(false);
11901
+ }
11586
11902
  };
11587
11903
  (0, react.useEffect)(() => {
11588
11904
  if (props.sessionStatus !== "unregistered" || joinContext !== null || joinProgress !== null || props.access !== void 0 && props.access?.joining !== true || typeof props.getDeviceJoinStatus !== "function") {
@@ -11667,30 +11983,104 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11667
11983
  setDeviceRejoinHandle(currentHandle);
11668
11984
  resetIdentityEntry();
11669
11985
  };
11670
- const recoveryOpen = props.recoveryOperationId !== null || recoveryChoice !== null || signedOutAlternative === "recover";
11671
- if (!recoveryOpen && (props.access === null && props.accessLoading || props.access === null && props.accessError)) return (0, react_jsx_runtime.jsxs)(AwikiIdentityPage, { children: [(0, react_jsx_runtime.jsx)("p", {
11986
+ const signedOutRecoveryOpen = props.sessionStatus === "signed-out" && signedOutAlternative === "recover";
11987
+ const revokedHandle = props.sessionStatus === "recovery-required" ? props.identity?.handle : void 0;
11988
+ if (props.recoveryOperationId !== null && !signedOutRecoveryOpen) return (0, react_jsx_runtime.jsx)(Recovery, {
11989
+ ...props,
11990
+ onExit: exitRecovery,
11991
+ onExitLabel: props.sessionStatus === "signed-out" ? "返回本机身份" : "返回身份入口",
11992
+ ...recoveryFactorContext === null ? {} : { initialFactorContext: recoveryFactorContext },
11993
+ ...revokedHandle === void 0 ? {} : {
11994
+ fixedHandle: revokedHandle,
11995
+ requestTitle: "需要重新恢复身份",
11996
+ requestDescription: "这个 Handle 已在另一台设备完成了更新恢复,当前设备的旧凭证因此失效。验证绑定手机号后即可继续使用本机数据。"
11997
+ }
11998
+ });
11999
+ if (!validRecoveryEntryOpen && (props.access === null && props.accessLoading || props.access === null && props.accessError)) return (0, react_jsx_runtime.jsxs)(AwikiIdentityPage, { children: [(0, react_jsx_runtime.jsx)("p", {
11672
12000
  role: "status",
11673
12001
  children: props.accessError ?? "正在确认本机身份操作…"
11674
- }), props.accessError && (0, react_jsx_runtime.jsx)("button", {
12002
+ }), props.accessError && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [props.sessionStatus === "recovery-required" && (0, react_jsx_runtime.jsx)("button", {
11675
12003
  type: "button",
11676
12004
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.primary,
11677
12005
  disabled: props.accessLoading,
11678
12006
  onClick: () => {
11679
- props.refreshIdentityAccess?.();
12007
+ setRecoveryEntryOpen(true);
11680
12008
  },
11681
- children: "重新检查身份状态"
11682
- })] });
11683
- if (props.accessError && !recoveryOpen) return (0, react_jsx_runtime.jsxs)(AwikiIdentityPage, { children: [(0, react_jsx_runtime.jsx)("p", {
11684
- role: "alert",
11685
- children: props.accessError
12009
+ children: "恢复身份"
11686
12010
  }), (0, react_jsx_runtime.jsx)("button", {
11687
12011
  type: "button",
11688
- className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.primary,
12012
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.secondary,
12013
+ disabled: props.accessLoading,
11689
12014
  onClick: () => {
11690
12015
  props.refreshIdentityAccess?.();
11691
12016
  },
11692
12017
  children: "重新检查身份状态"
11693
- })] });
12018
+ })] })] });
12019
+ if (!validRecoveryEntryOpen && props.accessError && props.recoveryOperationId === null) return (0, react_jsx_runtime.jsxs)(AwikiIdentityPage, { children: [
12020
+ (0, react_jsx_runtime.jsx)("p", {
12021
+ role: "alert",
12022
+ children: props.accessError
12023
+ }),
12024
+ props.sessionStatus === "recovery-required" && (0, react_jsx_runtime.jsx)("button", {
12025
+ type: "button",
12026
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.primary,
12027
+ onClick: () => {
12028
+ setRecoveryEntryOpen(true);
12029
+ },
12030
+ children: "恢复身份"
12031
+ }),
12032
+ (0, react_jsx_runtime.jsx)("button", {
12033
+ type: "button",
12034
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.secondary,
12035
+ onClick: () => {
12036
+ props.refreshIdentityAccess?.();
12037
+ },
12038
+ children: "重新检查身份状态"
12039
+ })
12040
+ ] });
12041
+ if (props.recoveryOperationId === null && recoveryChoice !== null && !recoveryRiskConfirmed) return (0, react_jsx_runtime.jsx)(AwikiIdentityPage, {
12042
+ onBack: cancelRecoveryChoice,
12043
+ backLabel: "返回设备加入",
12044
+ backDisabled: props.pending || recoveryConfirming,
12045
+ children: (0, react_jsx_runtime.jsxs)("div", {
12046
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.accessFlow,
12047
+ children: [
12048
+ (0, react_jsx_runtime.jsx)("div", {
12049
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.identityIcon,
12050
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 24 })
12051
+ }),
12052
+ (0, react_jsx_runtime.jsxs)("div", {
12053
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.headingGroup,
12054
+ children: [(0, react_jsx_runtime.jsx)("h3", { children: "确认替换此 Handle 的 DID" }), (0, react_jsx_runtime.jsx)("p", { children: "恢复会为这个 Handle 创建新的 DID,使其他设备的旧凭证失效。普通设备加入不会替换 DID,通常应优先使用。" })]
12055
+ }),
12056
+ (0, react_jsx_runtime.jsxs)("div", {
12057
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.dangerPanel,
12058
+ children: [(0, react_jsx_runtime.jsx)("strong", { children: recoveryChoice }), (0, react_jsx_runtime.jsx)("p", { children: "只有在无法通过已有管理设备完成普通加入时,才继续恢复。" })]
12059
+ }),
12060
+ (0, react_jsx_runtime.jsx)("button", {
12061
+ type: "button",
12062
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.dangerButton,
12063
+ disabled: props.pending || recoveryConfirming,
12064
+ onClick: () => {
12065
+ confirmRecoveryChoice();
12066
+ },
12067
+ children: "发送恢复验证码并替换 DID"
12068
+ }),
12069
+ (0, react_jsx_runtime.jsx)("button", {
12070
+ type: "button",
12071
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.secondary,
12072
+ disabled: props.pending || recoveryConfirming,
12073
+ onClick: cancelRecoveryChoice,
12074
+ children: "取消,返回普通加入"
12075
+ }),
12076
+ error !== null && (0, react_jsx_runtime.jsx)("small", {
12077
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.error,
12078
+ role: "alert",
12079
+ children: error
12080
+ })
12081
+ ]
12082
+ })
12083
+ });
11694
12084
  if (props.recoveryOperationId === null && recoveryChoice !== null) return (0, react_jsx_runtime.jsx)(Recovery, {
11695
12085
  ...props,
11696
12086
  requestError: error,
@@ -11718,18 +12108,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11718
12108
  },
11719
12109
  children: "重新检查加入状态"
11720
12110
  })] });
11721
- const signedOutRecoveryOpen = props.sessionStatus === "signed-out" && signedOutAlternative === "recover";
11722
- const revokedHandle = props.sessionStatus === "recovery-required" ? props.identity?.handle : void 0;
11723
- if (props.recoveryOperationId !== null && !signedOutRecoveryOpen) return (0, react_jsx_runtime.jsx)(Recovery, {
12111
+ if (props.sessionStatus === "recovery-required") return (0, react_jsx_runtime.jsx)(Recovery, {
11724
12112
  ...props,
11725
- onExit: exitRecovery,
11726
- onExitLabel: props.sessionStatus === "signed-out" ? "返回本机身份" : "返回身份入口",
11727
- ...recoveryFactorContext === null ? {} : { initialFactorContext: recoveryFactorContext },
11728
- ...revokedHandle === void 0 ? {} : {
11729
- fixedHandle: revokedHandle,
11730
- requestTitle: "需要重新恢复身份",
11731
- requestDescription: "这个 Handle 已在另一台设备完成了更新恢复,当前设备的旧凭证因此失效。验证绑定手机号后即可继续使用本机数据。"
11732
- }
12113
+ ...validRecoveryEntryOpen ? {
12114
+ onExit: () => {
12115
+ setRecoveryEntryOpen(false);
12116
+ },
12117
+ onExitLabel: "返回身份检查"
12118
+ } : {},
12119
+ ...revokedHandle === void 0 ? {} : { fixedHandle: revokedHandle },
12120
+ requestTitle: "需要重新恢复身份",
12121
+ requestDescription: "这个 Handle 已在另一台设备完成了更新恢复,当前设备的旧凭证因此失效。发送验证码会开始一次替换 DID 的恢复;请确认后再继续。"
11733
12122
  });
11734
12123
  if (props.sessionStatus === "device-rejoin-required") return (0, react_jsx_runtime.jsx)(AwikiIdentityPage, { children: (0, react_jsx_runtime.jsxs)("div", {
11735
12124
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.accessFlow,
@@ -11825,13 +12214,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11825
12214
  },
11826
12215
  children: "加入新设备(推荐)"
11827
12216
  }),
11828
- props.handleRecoveryPhoneEnabled && (0, react_jsx_runtime.jsx)("button", {
12217
+ (0, react_jsx_runtime.jsx)("button", {
11829
12218
  type: "button",
11830
12219
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.dangerLink,
11831
12220
  disabled: props.pending,
11832
- onClick: () => {
11833
- chooseRecovery();
11834
- },
12221
+ onClick: chooseRecovery,
11835
12222
  children: "恢复 Handle(会替换 DID)"
11836
12223
  }),
11837
12224
  (0, react_jsx_runtime.jsx)("button", {
@@ -11965,30 +12352,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11965
12352
  backLabel: "修改身份信息"
11966
12353
  } : {},
11967
12354
  backDisabled: props.pending,
11968
- children: [props.sessionStatus === "recovery-required" && !registrationOtpSent && (0, react_jsx_runtime.jsxs)("div", {
11969
- className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.headingGroup,
11970
- children: [
11971
- (0, react_jsx_runtime.jsx)("h3", { children: "需要重新恢复身份" }),
11972
- (0, react_jsx_runtime.jsx)("p", { children: "原身份已在其他设备更新,本机旧凭证已失效。可以恢复原身份,也可以在下方使用其他账号;返回不会清除本机数据。" }),
11973
- revokedHandle !== void 0 && (0, react_jsx_runtime.jsxs)("div", {
11974
- className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.identitySummary,
11975
- children: [(0, react_jsx_runtime.jsx)("span", { children: "原身份" }), (0, react_jsx_runtime.jsx)("strong", { children: revokedHandle })]
11976
- }),
11977
- revokedHandle !== void 0 && props.handleRecoveryPhoneEnabled && (0, react_jsx_runtime.jsx)("button", {
11978
- type: "button",
11979
- className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.secondary,
11980
- disabled: props.pending,
11981
- onClick: () => {
11982
- setRecoveryChoice(revokedHandle);
11983
- },
11984
- children: "恢复本机原有身份"
11985
- })
11986
- ]
11987
- }), (0, react_jsx_runtime.jsxs)("form", {
12355
+ children: [(0, react_jsx_runtime.jsxs)("form", {
11988
12356
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.accessFlow,
11989
12357
  onSubmit: (event) => {
11990
12358
  event.preventDefault();
11991
- registrationOtpSent ? completeRegistration() : requestIdentityOtp();
12359
+ if (props.pending || registrationInFlight.current) return;
12360
+ if (registrationOtpSent) setRegistrationConfirmation({
12361
+ phone: phone.trim(),
12362
+ handle: handle.trim(),
12363
+ otp: otp.trim()
12364
+ });
12365
+ else requestIdentityOtp();
11992
12366
  },
11993
12367
  children: [
11994
12368
  (0, react_jsx_runtime.jsx)("div", {
@@ -12005,6 +12379,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12005
12379
  value: handle,
12006
12380
  onChange: (event) => {
12007
12381
  setHandle(event.target.value);
12382
+ setShortHandleInviteNotice(false);
12008
12383
  },
12009
12384
  readOnly: registrationOtpSent || deviceRejoinHandle !== null,
12010
12385
  autoComplete: "username",
@@ -12051,6 +12426,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12051
12426
  },
12052
12427
  children: retrySeconds > 0 ? `${retrySeconds} 秒后重新获取` : "重新获取注册验证码"
12053
12428
  }),
12429
+ shortHandleInviteNotice && (0, react_jsx_runtime.jsx)("div", {
12430
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.inviteNotice,
12431
+ role: "alert",
12432
+ children: "注册少于5位的handle需要使用邀请码,目前暂不支持自主注册。"
12433
+ }),
12054
12434
  notice !== null && (0, react_jsx_runtime.jsx)("small", {
12055
12435
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.notice,
12056
12436
  role: "status",
@@ -12062,6 +12442,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12062
12442
  children: error
12063
12443
  })
12064
12444
  ]
12445
+ }), (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
12446
+ open: registrationConfirmation !== null,
12447
+ title: "确认创建 AWiki 身份",
12448
+ description: "新 Handle 将通过 ANP Identity 创建身份并注册到 AWiki;如果 Handle 已存在,将继续设备加入流程。",
12449
+ closeLabel: "取消",
12450
+ onClose: () => {
12451
+ if (!registrationInFlight.current) setRegistrationConfirmation(null);
12452
+ },
12453
+ footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
12454
+ type: "button",
12455
+ variant: "outline",
12456
+ disabled: registrationSubmitting || props.pending,
12457
+ onClick: () => {
12458
+ if (!registrationInFlight.current) setRegistrationConfirmation(null);
12459
+ },
12460
+ children: "返回修改"
12461
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
12462
+ type: "button",
12463
+ disabled: registrationSubmitting || props.pending,
12464
+ onClick: () => {
12465
+ completeRegistration();
12466
+ },
12467
+ children: registrationSubmitting ? "正在提交…" : "确认并继续"
12468
+ })] }),
12469
+ children: [(0, react_jsx_runtime.jsxs)("p", { children: ["Handle:", registrationConfirmation?.handle] }), (0, react_jsx_runtime.jsx)("p", { children: "身份密钥由本机 ANP Identity 保管。取消不会提交注册或创建身份。" })]
12065
12470
  })]
12066
12471
  });
12067
12472
  }
@@ -12077,7 +12482,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12077
12482
  this.identity = identity;
12078
12483
  this.IdentityAccess = (props) => (0, react.createElement)(AwikiDraftProvider, {
12079
12484
  store: identity.drafts,
12080
- children: (0, react.createElement)(AwikiIdentityAccess, props)
12485
+ children: (0, react.createElement)(AwikiIdentityAccess, {
12486
+ ...props,
12487
+ inspectIdentityAccess: (request) => identity.inspectIdentityAccess(request)
12488
+ })
12081
12489
  });
12082
12490
  }
12083
12491
  clearLocalIdentity = async () => {
@@ -12423,6 +12831,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12423
12831
  }
12424
12832
  //#endregion
12425
12833
  //#region lib/types/client/controller.js
12834
+ const GENERIC_BUSINESS_FAILURE_MESSAGE = "AWiki 暂时无法完成此操作,请稍后重试。";
12835
+ const GENERIC_CARRIER_FAILURE_MESSAGE = "暂时无法连接 AWiki Host,请稍后重试。";
12836
+ const GENERIC_THROW_FAILURE_MESSAGE = "AWiki 调用暂时失败,请稍后重试。";
12837
+ /** Project only a stable business code into Browser copy; provider messages remain Host-only. */
12838
+ function genericFailureMessage(failure) {
12839
+ switch (failure.code) {
12840
+ case "network": return "无法连接 AWiki 服务,请检查网络后重试。";
12841
+ case "rate-limited": return "AWiki 请求过于频繁,请稍后重试。";
12842
+ case "not-registered": return "请先注册 AWiki 身份后重试。";
12843
+ case "signed-out": return "当前 AWiki 身份已退出,请重新进入后重试。";
12844
+ case "identity-recovery-required": return "当前设备的 AWiki 身份凭证已失效,请重新恢复身份。";
12845
+ case "device-rejoin-required": return "当前设备已被撤销,请重新申请加入。";
12846
+ default: return GENERIC_BUSINESS_FAILURE_MESSAGE;
12847
+ }
12848
+ }
12849
+ /** Carrier diagnostics are not a Browser contract, including for unknown carrier codes. */
12850
+ function genericCarrierFailureMessage(_failure) {
12851
+ return GENERIC_CARRIER_FAILURE_MESSAGE;
12852
+ }
12426
12853
  /** Turn a registration rejection into an actionable message without exposing remote response text. */
12427
12854
  function registrationFailureMessage(failure) {
12428
12855
  switch (failure.code) {
@@ -12431,18 +12858,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12431
12858
  case "invalid-otp": return "验证码不正确,请检查后重试。";
12432
12859
  case "challenge-expired": return "验证码状态已失效,请重新获取验证码后再注册。";
12433
12860
  case "handle-unavailable": return "该 Handle 刚刚已被注册。请返回身份入口,再按恢复流程重新获取验证码。";
12861
+ case "short-handle-invite-required": return SHORT_HANDLE_INVITE_MESSAGE;
12434
12862
  case "conflict": return "注册冲突:服务端可能已收到上次注册请求,或该手机号 / Handle 已绑定其他身份。请保留当前页面并再次提交;若仍失败,请勿清除本机身份数据,联系管理员并提供失败时间。";
12435
12863
  case "rate-limited": return "注册请求过于频繁,请稍后重试。";
12436
12864
  case "network": return "无法连接 AWiki 服务,请检查网络后重试。";
12437
12865
  case "identity-recovery-required": return "这台设备保留了原 AWiki 身份,但本地登录状态已被清除。请先恢复该身份或完整清除这台设备上的 AWiki 身份数据,再重新注册。";
12438
12866
  case "forbidden": return "当前 AWiki 服务未开放公开注册,或该手机号不在注册白名单。请使用已获准的手机号,或联系管理员开通注册权限。";
12439
12867
  case "remote": return "AWiki 服务暂时无法完成注册,请稍后重试;若持续失败,请联系管理员并提供失败时间。";
12440
- default: return `${failure.code}:${failure.message}`;
12868
+ default: return "AWiki 服务暂时无法完成注册,请稍后重试;若持续失败,请联系管理员并提供失败时间。";
12441
12869
  }
12442
12870
  }
12443
12871
  /** Turn a verification-code request failure into a safe next action. */
12444
12872
  function registrationOtpFailureMessage(failure) {
12445
12873
  switch (failure.code) {
12874
+ case "short-handle-invite-required": return SHORT_HANDLE_INVITE_MESSAGE;
12446
12875
  case "rate-limited": return "验证码发送过于频繁,请等待限流解除后再重新获取。";
12447
12876
  case "invalid-request": return "无法发送验证码,请检查手机号和 Handle 后重试。";
12448
12877
  case "forbidden": return "当前 AWiki 服务未向该手机号开放注册,请联系管理员。";
@@ -12459,7 +12888,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12459
12888
  case "rate-limited": return "恢复验证过于频繁,请稍后重试。";
12460
12889
  case "network": return "无法连接 AWiki 服务,请检查网络后重试。";
12461
12890
  case "remote": return "AWiki 服务暂时无法验证恢复信息,请稍后重试。";
12462
- default: return `${failure.code}:${failure.message}`;
12891
+ default: return "AWiki 服务暂时无法验证恢复信息,请稍后重试。";
12463
12892
  }
12464
12893
  }
12465
12894
  function recoveryContinuationFailureMessage(failure, phase) {
@@ -12477,7 +12906,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12477
12906
  case "rate-limited": return "恢复状态检查过于频繁,请稍后继续。";
12478
12907
  case "remote":
12479
12908
  case "forbidden": return "AWiki 服务暂时未能完成恢复。可以重新检查结果,或返回入口稍后继续。";
12480
- default: return `${failure.code}:${failure.message}`;
12909
+ default: return "身份恢复暂未完成。请保留当前恢复操作并重新检查状态,不要重新获取验证码或创建新身份。";
12481
12910
  }
12482
12911
  }
12483
12912
  function identityAccessInspectionFailureMessage(failure) {
@@ -12485,9 +12914,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12485
12914
  case "invalid-request": return "Handle 格式不正确,请检查后重试。";
12486
12915
  case "network": return "无法连接 AWiki 服务,暂时不能确认该 Handle 是否已经存在。";
12487
12916
  case "remote": return "AWiki 服务暂时无法确认该 Handle 的状态,请稍后重试。";
12488
- default: return `${failure.code}:${failure.message}`;
12917
+ default: return "AWiki 服务暂时无法确认该 Handle 的状态,请稍后重试。";
12489
12918
  }
12490
12919
  }
12920
+ const IDENTITY_ACCESS_FAILURE_MESSAGE = "暂时无法读取本机身份状态,请稍后重新检查。";
12491
12921
  const INITIAL_VIEW = Object.freeze({
12492
12922
  status: "cold",
12493
12923
  sessionStatus: "unregistered",
@@ -12514,7 +12944,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12514
12944
  accessLoading: true,
12515
12945
  accessError: null,
12516
12946
  recoveryOperationId: null,
12517
- recoveryProgress: null
12947
+ recoveryProgress: null,
12948
+ recoveryOtpRetryAt: null
12518
12949
  });
12519
12950
  /** Turn a closed Host summary failure into one actionable Chinese message. */
12520
12951
  function summaryFailureMessage(failure) {
@@ -12524,7 +12955,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12524
12955
  case "summary-cancelled": return "AI 总结已取消,请重新生成。";
12525
12956
  case "summary-invalid-output": return "模型没有返回有效的结构化摘要,请重新生成。";
12526
12957
  case "summary-failed": return "暂时无法生成 AI 总结,请检查模型连接后重试。";
12527
- default: return `${failure.code}:${failure.message}`;
12958
+ default: return "暂时无法生成 AI 总结,请检查模型连接后重试。";
12528
12959
  }
12529
12960
  }
12530
12961
  /** Turn closed mail failures into safe, actionable browser messages. */
@@ -12552,7 +12983,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12552
12983
  case "network": return "无法连接 AWiki 服务,请检查网络后重试。";
12553
12984
  case "conflict": return "群聊创建状态发生冲突,请刷新群聊列表后确认是否已经创建。";
12554
12985
  case "remote": return "AWiki 服务暂时无法创建群聊,请稍后重试。";
12555
- default: return `${failure.code}:${failure.message}`;
12986
+ default: return "AWiki 服务暂时无法创建群聊,请稍后重试。";
12556
12987
  }
12557
12988
  }
12558
12989
  /** Keep group authorization failures actionable without exposing raw service text. */
@@ -12564,7 +12995,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12564
12995
  case "forbidden": return "当前身份没有访问这个群聊的权限。";
12565
12996
  case "network": return "无法连接 AWiki 群聊服务,请检查网络后重试。";
12566
12997
  case "remote": return "AWiki 暂时无法读取这个群聊,请稍后重试。";
12567
- default: return `${failure.code}:${failure.message}`;
12998
+ default: return "AWiki 暂时无法读取这个群聊,请稍后重试。";
12568
12999
  }
12569
13000
  }
12570
13001
  function conversationPreferenceFailureMessage(_failure) {
@@ -12605,12 +13036,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12605
13036
  }
12606
13037
  }
12607
13038
  /** Flatten the carrier and business result once for every controller caller. */
12608
- async function call(operation, failureMessage = (failure) => `${failure.code}:${failure.message}`, carrierFailureMessage = (message) => `连接 AWiki Host 失败:${message}`) {
13039
+ async function call(operation, failureMessage = genericFailureMessage, carrierFailureMessage = genericCarrierFailureMessage) {
12609
13040
  try {
12610
13041
  const carried = await operation();
12611
13042
  if (!carried.ok) return {
12612
13043
  ok: false,
12613
- error: carrierFailureMessage(carried.error.message)
13044
+ error: carrierFailureMessage(carried.error)
12614
13045
  };
12615
13046
  if (!carried.value.ok) return {
12616
13047
  ok: false,
@@ -12620,10 +13051,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12620
13051
  ok: true,
12621
13052
  value: carried.value.value
12622
13053
  };
12623
- } catch (error) {
13054
+ } catch {
12624
13055
  return {
12625
13056
  ok: false,
12626
- error: error instanceof Error ? `AWiki 调用失败:${error.message}` : "AWiki 调用失败"
13057
+ error: GENERIC_THROW_FAILURE_MESSAGE
12627
13058
  };
12628
13059
  }
12629
13060
  }
@@ -12633,12 +13064,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12633
13064
  const carried = await operation();
12634
13065
  if (!carried.ok) return {
12635
13066
  ok: false,
12636
- error: `连接 AWiki Host 失败:${carried.error.message}`
12637
- };
12638
- if (!carried.value.ok) return {
12639
- ok: false,
12640
- error: carried.value.error.message
13067
+ error: genericCarrierFailureMessage(carried.error)
12641
13068
  };
13069
+ if (!carried.value.ok) {
13070
+ const failure = carried.value.error;
13071
+ return {
13072
+ ok: false,
13073
+ error: failure.code === "not-found" ? "尚未创建 Integration。" : failure.code === "conflict" ? "Integration 已在其他位置更新,请重新加载后再试。" : failure.code === "invalid-request" ? "Integration 信息不完整或格式不正确。" : failure.code === "unauthorized" || failure.code === "forbidden" ? "当前 AWiki 身份无权管理此 Integration。" : failure.code === "rate-limited" ? "Integration 操作过于频繁,请稍后重试。" : "临时消息服务暂时不可用,请稍后重试。",
13074
+ failureCode: failure.code
13075
+ };
13076
+ }
12642
13077
  return {
12643
13078
  ok: true,
12644
13079
  value: carried.value.value
@@ -12651,31 +13086,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12651
13086
  }
12652
13087
  }
12653
13088
  /** Preserve only the stable business code for controller-level state transitions. */
12654
- async function callWithFailureCode(operation) {
13089
+ async function callWithFailureCode(operation, failureMessage = genericFailureMessage) {
12655
13090
  try {
12656
13091
  const carried = await operation();
12657
13092
  if (!carried.ok) return {
12658
13093
  ok: false,
12659
- error: `连接 AWiki Host 失败:${carried.error.message}`
13094
+ error: genericCarrierFailureMessage(carried.error)
12660
13095
  };
12661
13096
  if (!carried.value.ok) return {
12662
13097
  ok: false,
12663
- error: `${carried.value.error.code}:${carried.value.error.message}`,
13098
+ error: failureMessage(carried.value.error),
12664
13099
  failureCode: carried.value.error.code
12665
13100
  };
12666
13101
  return {
12667
13102
  ok: true,
12668
13103
  value: carried.value.value
12669
13104
  };
12670
- } catch (error) {
13105
+ } catch {
12671
13106
  return {
12672
13107
  ok: false,
12673
- error: error instanceof Error ? `AWiki 调用失败:${error.message}` : "AWiki 调用失败"
13108
+ error: GENERIC_THROW_FAILURE_MESSAGE
12674
13109
  };
12675
13110
  }
12676
13111
  }
12677
- function recoveryCarrierFailureMessage(message) {
12678
- return message.includes("business result failed boundary validation") ? "恢复信息已验证,但暂时无法读取恢复状态。请稍后重试。" : `连接 AWiki Host 失败:${message}`;
13112
+ function recoveryCarrierFailureMessage(failure) {
13113
+ return failure.code === "invalid-response" ? "恢复信息已验证,但暂时无法读取恢复状态。请稍后重试。" : "暂时无法连接 AWiki Host,无法完成身份恢复。请稍后重试。";
12679
13114
  }
12680
13115
  /** Append unique values while retaining existing references. */
12681
13116
  function appendUnique(current, incoming, id) {
@@ -12771,9 +13206,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12771
13206
  /** Runtime-only decoded-byte budget that prevents repeat Host calls while browsing. */
12772
13207
  const BROWSER_IMAGE_ATTACHMENT_CACHE_MAX_BYTES = 33554432;
12773
13208
  const RECOVERY_OPERATION_STORAGE_KEY = "awiki.handle-recovery.operation.v1";
13209
+ const RECOVERY_OTP_RETRY_STORAGE_KEY = "awiki.handle-recovery.retry-at.v1";
12774
13210
  function recoveryOperationStorageKey(tenantId) {
12775
13211
  return tenantId === void 0 || tenantId === "" ? RECOVERY_OPERATION_STORAGE_KEY : `${RECOVERY_OPERATION_STORAGE_KEY}.${encodeURIComponent(tenantId)}`;
12776
13212
  }
13213
+ function recoveryTenantKey(tenantId) {
13214
+ return tenantId === void 0 || tenantId === "" ? "default" : tenantId;
13215
+ }
12777
13216
  function storeRecoveryOperation(operationId, tenantId) {
12778
13217
  try {
12779
13218
  const key = recoveryOperationStorageKey(tenantId);
@@ -12781,6 +13220,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12781
13220
  else globalThis.localStorage?.setItem(key, operationId);
12782
13221
  } catch {}
12783
13222
  }
13223
+ function recoveryOtpRetryStorageKey(operationId, tenantId) {
13224
+ return `${RECOVERY_OTP_RETRY_STORAGE_KEY}.${encodeURIComponent(recoveryTenantKey(tenantId))}.${encodeURIComponent(operationId)}`;
13225
+ }
13226
+ function recoveryOtpRetryAt(result) {
13227
+ const advertised = Date.parse(result.retryAt);
13228
+ const deadline = Number.isFinite(advertised) ? advertised : Date.now() + Math.max(0, result.retryAfterSeconds) * 1e3;
13229
+ return new Date(deadline).toISOString();
13230
+ }
13231
+ function storedRecoveryOtpRetryAt(operationId, tenantId) {
13232
+ if (operationId === null) return null;
13233
+ try {
13234
+ const key = recoveryOtpRetryStorageKey(operationId, tenantId);
13235
+ const value = globalThis.localStorage?.getItem(key);
13236
+ if (value === null || value === void 0) return null;
13237
+ const deadline = Date.parse(value);
13238
+ if (!Number.isFinite(deadline) || deadline <= Date.now()) {
13239
+ globalThis.localStorage?.removeItem(key);
13240
+ return null;
13241
+ }
13242
+ return new Date(deadline).toISOString();
13243
+ } catch {
13244
+ return null;
13245
+ }
13246
+ }
13247
+ function storeRecoveryOtpRetryAt(operationId, retryAt, tenantId) {
13248
+ try {
13249
+ globalThis.localStorage?.setItem(recoveryOtpRetryStorageKey(operationId, tenantId), retryAt);
13250
+ } catch {}
13251
+ }
13252
+ function clearRecoveryOtpRetryAt(operationId, tenantId) {
13253
+ if (operationId === null) return;
13254
+ try {
13255
+ globalThis.localStorage?.removeItem(recoveryOtpRetryStorageKey(operationId, tenantId));
13256
+ } catch {}
13257
+ }
12784
13258
  /** Wait between group-history readiness probes without retaining controller state. */
12785
13259
  function delay(milliseconds) {
12786
13260
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
@@ -12833,6 +13307,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12833
13307
  drafts = new AwikiDraftStore();
12834
13308
  view = INITIAL_VIEW;
12835
13309
  listeners = /* @__PURE__ */ new Set();
13310
+ /** Runtime-only selected operations survive tenant round trips without reopening stale browser hints after reload. */
13311
+ recoveryOperationsByTenant = /* @__PURE__ */ new Map();
12836
13312
  config = null;
12837
13313
  conversationsCursor;
12838
13314
  historyCursor;
@@ -12924,6 +13400,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12924
13400
  const sameOwner = preserveView && previousTenant === config.value.tenantId && previous.sessionStatus === session.value.status && previous.identity?.did === identity?.did;
12925
13401
  this.drafts.setScope(config.value.tenantId ?? "default", identity?.did ?? session.value.status);
12926
13402
  this.activatePresentationCache(identity);
13403
+ const selectedRecovery = previousTenant === config.value.tenantId ? previous.recoveryOperationId : this.recoveryOperationsByTenant.get(recoveryTenantKey(config.value.tenantId)) ?? null;
12927
13404
  this.publish({
12928
13405
  ...sameOwner ? this.view : INITIAL_VIEW,
12929
13406
  status: "ready",
@@ -12932,7 +13409,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12932
13409
  error: null,
12933
13410
  attachmentMaxBytes: config.value.attachmentMaxBytes,
12934
13411
  handleRecoveryPhoneEnabled: config.value.handleRecoveryPhoneEnabled,
12935
- recoveryOperationId: previousTenant === config.value.tenantId ? previous.recoveryOperationId : null
13412
+ recoveryOperationId: selectedRecovery,
13413
+ recoveryOtpRetryAt: storedRecoveryOtpRetryAt(selectedRecovery, config.value.tenantId)
12936
13414
  });
12937
13415
  await this.refreshIdentityAccess();
12938
13416
  if (!this.current(generation)) return {
@@ -13095,7 +13573,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13095
13573
  * @returns challenge retry metadata or one display-safe failure.
13096
13574
  */
13097
13575
  async sendRegistrationOtp(request) {
13098
- return this.withPending("发送验证码", () => call(() => this.remote.sendRegistrationOtp(request), registrationOtpFailureMessage));
13576
+ const result = await this.withPending("发送验证码", () => callWithFailureCode(() => this.remote.sendRegistrationOtp(request), registrationOtpFailureMessage));
13577
+ return !result.ok && result.failureCode !== "short-handle-invite-required" ? {
13578
+ ok: false,
13579
+ error: result.error
13580
+ } : result;
13099
13581
  }
13100
13582
  /** Discover Core-owned work without selecting an account or activating a session. */
13101
13583
  refreshIdentityAccess() {
@@ -13122,42 +13604,56 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13122
13604
  this.publish({
13123
13605
  ...this.view,
13124
13606
  accessLoading: false,
13125
- accessError: result.error
13607
+ accessError: IDENTITY_ACCESS_FAILURE_MESSAGE
13126
13608
  });
13127
- return result;
13609
+ return {
13610
+ ok: false,
13611
+ error: IDENTITY_ACCESS_FAILURE_MESSAGE
13612
+ };
13128
13613
  }
13129
13614
  const candidates = result.value.recoveries;
13130
13615
  const selected = this.view.recoveryOperationId;
13131
13616
  this.publish({
13132
13617
  ...this.view,
13133
- identityAccess: result.value
13618
+ identityAccess: result.value,
13619
+ recoveryOperationId: selected,
13620
+ recoveryProgress: selected === this.view.recoveryOperationId ? this.view.recoveryProgress : null,
13621
+ recoveryOtpRetryAt: storedRecoveryOtpRetryAt(selected, this.config?.tenantId)
13134
13622
  });
13135
13623
  if (selected !== null) {
13136
13624
  const status = await callWithFailureCode(() => this.remote.getRecoveryStatus({ operationId: selected }));
13137
13625
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13138
13626
  if (!status.ok) {
13139
13627
  if (status.failureCode === "not-found" && candidates.length === 0) {
13140
- storeRecoveryOperation(null, this.config?.tenantId);
13628
+ clearRecoveryOtpRetryAt(selected, this.config?.tenantId);
13629
+ this.rememberRecoveryOperation(null, this.config?.tenantId);
13141
13630
  this.publish({
13142
13631
  ...this.view,
13143
13632
  recoveryOperationId: null,
13144
- recoveryProgress: null
13633
+ recoveryProgress: null,
13634
+ recoveryOtpRetryAt: null
13145
13635
  });
13146
13636
  } else {
13147
13637
  this.publish({
13148
13638
  ...this.view,
13149
13639
  accessLoading: false,
13150
- accessError: status.error
13640
+ accessError: IDENTITY_ACCESS_FAILURE_MESSAGE
13151
13641
  });
13152
13642
  return {
13153
13643
  ok: false,
13154
- error: status.error
13644
+ error: IDENTITY_ACCESS_FAILURE_MESSAGE
13155
13645
  };
13156
13646
  }
13157
- } else this.publish({
13158
- ...this.view,
13159
- recoveryProgress: status.value
13160
- });
13647
+ } else {
13648
+ const complete = status.value.phase === "applied";
13649
+ if (complete) clearRecoveryOtpRetryAt(selected, this.config?.tenantId);
13650
+ this.publish({
13651
+ ...this.view,
13652
+ recoveryProgress: status.value,
13653
+ recoveryOtpRetryAt: complete ? null : storedRecoveryOtpRetryAt(selected, this.config?.tenantId),
13654
+ identityAccess: result.value
13655
+ });
13656
+ }
13161
13657
  }
13162
13658
  this.publish({
13163
13659
  ...this.view,
@@ -13176,10 +13672,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13176
13672
  };
13177
13673
  if (this.view.recoveryOperationId !== null) this.leaveRecovery();
13178
13674
  else this.recoveryRevision++;
13675
+ this.rememberRecoveryOperation(operationId, this.config?.tenantId);
13179
13676
  this.publish({
13180
13677
  ...this.view,
13181
13678
  recoveryOperationId: operationId,
13182
- recoveryProgress: null
13679
+ recoveryProgress: null,
13680
+ recoveryOtpRetryAt: storedRecoveryOtpRetryAt(operationId, this.config?.tenantId)
13183
13681
  });
13184
13682
  const result = await this.refreshRecoveryStatus();
13185
13683
  return result.ok ? {
@@ -13198,6 +13696,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13198
13696
  error: "已离开此恢复流程;进度保留在本机。"
13199
13697
  };
13200
13698
  }
13699
+ rememberRecoveryOperation(operationId, tenantId) {
13700
+ const key = recoveryTenantKey(tenantId);
13701
+ if (operationId === null) {
13702
+ this.recoveryOperationsByTenant.delete(key);
13703
+ storeRecoveryOperation(null, tenantId);
13704
+ } else this.recoveryOperationsByTenant.set(key, operationId);
13705
+ }
13201
13706
  /** Navigation only. Never cancel or delete the Core-owned operation. */
13202
13707
  leaveRecovery() {
13203
13708
  this.recoveryRevision++;
@@ -13206,7 +13711,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13206
13711
  if (wasPending) this.pendingRequest = void 0;
13207
13712
  this.pendingRecovery = false;
13208
13713
  this.drafts.clearFlow();
13209
- storeRecoveryOperation(null, this.config?.tenantId);
13714
+ this.rememberRecoveryOperation(null, this.config?.tenantId);
13210
13715
  this.publish({
13211
13716
  ...this.view,
13212
13717
  recoveryOperationId: null,
@@ -13248,9 +13753,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13248
13753
  */
13249
13754
  async registerIdentity(request) {
13250
13755
  const generation = this.generation;
13251
- const result = await this.withPending("注册身份", () => call(() => this.remote.registerIdentity(request), registrationFailureMessage));
13756
+ const classified = await this.withPending("注册身份", () => callWithFailureCode(() => this.remote.registerIdentity(request), registrationFailureMessage));
13757
+ const result = !classified.ok && classified.failureCode !== "short-handle-invite-required" ? {
13758
+ ok: false,
13759
+ error: classified.error
13760
+ } : classified;
13252
13761
  if (!result.ok) {
13253
13762
  if (this.current(generation)) await this.refreshIdentityAccess();
13763
+ if (this.current(generation) && result.failureCode === "short-handle-invite-required") this.publish({
13764
+ ...this.view,
13765
+ error: null
13766
+ });
13254
13767
  return result;
13255
13768
  }
13256
13769
  if (!this.current(generation)) return result;
@@ -13320,6 +13833,77 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13320
13833
  } : result;
13321
13834
  });
13322
13835
  }
13836
+ /** Cancel one exact Join choice and send Recovery OTP only while its original browser scope remains current. */
13837
+ async beginRecoveryFromDeviceJoin(request) {
13838
+ const generation = this.generation;
13839
+ const tenantId = this.config?.tenantId;
13840
+ const flowScope = this.drafts.getScope("recovery:retryDeadline");
13841
+ const flowEpoch = this.drafts.epoch(flowScope);
13842
+ const changed = () => ({
13843
+ ok: false,
13844
+ error: "恢复能力或身份环境已改变,请重新检查后再选择。"
13845
+ });
13846
+ const scopeCurrent = () => this.current(generation) && this.config?.tenantId === tenantId && this.drafts.getScope("recovery:retryDeadline") === flowScope && this.drafts.epoch(flowScope) === flowEpoch;
13847
+ if (!scopeCurrent()) return changed();
13848
+ const latest = await call(() => this.remote.getConfig());
13849
+ if (!scopeCurrent()) return changed();
13850
+ if (!latest.ok) return {
13851
+ ok: false,
13852
+ error: "暂时无法确认服务器的恢复能力,请稍后重试。"
13853
+ };
13854
+ if (latest.value.tenantId !== tenantId) return changed();
13855
+ this.config = latest.value;
13856
+ this.publish({
13857
+ ...this.view,
13858
+ handleRecoveryPhoneEnabled: latest.value.handleRecoveryPhoneEnabled
13859
+ });
13860
+ if (latest.value.tenantOnline === false) return {
13861
+ ok: false,
13862
+ error: "暂时无法确认服务器的恢复能力,请稍后重试。"
13863
+ };
13864
+ if (!latest.value.handleRecoveryPhoneEnabled) return {
13865
+ ok: false,
13866
+ error: "当前服务器未启用手机号恢复,请加入新设备或联系管理员。"
13867
+ };
13868
+ const current = () => scopeCurrent() && this.config?.handleRecoveryPhoneEnabled === true;
13869
+ const result = await this.withPending("开始恢复身份", async () => {
13870
+ const discarded = await call(() => this.remote.cancelDeviceJoin());
13871
+ if (!discarded.ok) return discarded;
13872
+ if (!current()) return changed();
13873
+ this.publish({
13874
+ ...this.view,
13875
+ identityAccess: {
13876
+ choice: null,
13877
+ joining: false,
13878
+ recoveries: []
13879
+ }
13880
+ });
13881
+ if (request.phone === "") return {
13882
+ ok: true,
13883
+ value: null
13884
+ };
13885
+ return call(() => this.remote.sendRecoveryOtp(request), registrationOtpFailureMessage);
13886
+ }, {
13887
+ publishFailure: false,
13888
+ recovery: true
13889
+ });
13890
+ if (!result.ok) {
13891
+ if (current()) await this.continueRecoveryForHandle(request.fullHandle);
13892
+ return result;
13893
+ }
13894
+ if (result.value === null) return result;
13895
+ this.recordRecoveryOtp(result.value, tenantId);
13896
+ if (!(this.config?.tenantId === tenantId && this.drafts.getScope("recovery:retryDeadline") === flowScope && this.drafts.epoch(flowScope) === flowEpoch)) return result;
13897
+ const retryAt = recoveryOtpRetryAt(result.value);
13898
+ this.publish({
13899
+ ...this.view,
13900
+ recoveryOperationId: result.value.operationId,
13901
+ recoveryProgress: null,
13902
+ recoveryOtpRetryAt: retryAt
13903
+ });
13904
+ await this.refreshRecoveryStatus();
13905
+ return result;
13906
+ }
13323
13907
  retireDeviceIdentityForRejoin() {
13324
13908
  return this.withPending("准备重新加入设备", async () => {
13325
13909
  const result = await call(() => this.remote.retireDeviceIdentityForRejoin());
@@ -13408,23 +13992,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13408
13992
  async sendRecoveryOtp(request) {
13409
13993
  const generation = this.generation;
13410
13994
  const revision = this.recoveryRevision;
13995
+ const tenantId = this.config?.tenantId;
13996
+ const flowScope = this.drafts.getScope("recovery:retryDeadline");
13411
13997
  const result = await this.withPending("发送恢复验证码", () => call(() => this.remote.sendRecoveryOtp(request), registrationOtpFailureMessage), {
13412
13998
  publishFailure: false,
13413
13999
  recovery: true
13414
14000
  });
13415
- if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13416
14001
  if (!result.ok) {
14002
+ if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13417
14003
  await this.continueRecoveryForHandle(request.fullHandle);
13418
14004
  return result;
13419
14005
  }
14006
+ this.recordRecoveryOtp(result.value, tenantId);
14007
+ if (!this.recoveryCurrent(generation, revision) || this.config?.tenantId !== tenantId || this.drafts.getScope("recovery:retryDeadline") !== flowScope) return result;
13420
14008
  this.publish({
13421
14009
  ...this.view,
13422
14010
  recoveryOperationId: result.value.operationId,
13423
- recoveryProgress: null
14011
+ recoveryProgress: null,
14012
+ recoveryOtpRetryAt: recoveryOtpRetryAt(result.value)
13424
14013
  });
13425
14014
  await this.refreshRecoveryStatus();
13426
14015
  return this.recoveryCurrent(generation, revision) ? result : this.recoveryLeft();
13427
14016
  }
14017
+ recordRecoveryOtp(result, tenantId) {
14018
+ this.rememberRecoveryOperation(result.operationId, tenantId);
14019
+ storeRecoveryOtpRetryAt(result.operationId, recoveryOtpRetryAt(result), tenantId);
14020
+ }
13428
14021
  /** Publish results only into the exact selected flow; Core work survives navigation. */
13429
14022
  async runRecovery(label, operation, enterWhenApplied = false) {
13430
14023
  const generation = this.generation;
@@ -13440,12 +14033,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13440
14033
  });
13441
14034
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13442
14035
  if (!result.ok) {
13443
- const status = await call(() => this.remote.getRecoveryStatus({ operationId }));
14036
+ const status = await call(() => this.remote.getRecoveryStatus({ operationId }), void 0, recoveryCarrierFailureMessage);
13444
14037
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13445
14038
  this.publish({
13446
14039
  ...this.view,
13447
14040
  recoveryProgress: status.ok ? status.value : this.view.recoveryProgress,
13448
- accessError: status.ok ? null : status.error
14041
+ accessError: status.ok ? null : IDENTITY_ACCESS_FAILURE_MESSAGE
13449
14042
  });
13450
14043
  return result;
13451
14044
  }
@@ -13454,6 +14047,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13454
14047
  recoveryProgress: result.value,
13455
14048
  accessError: null
13456
14049
  });
14050
+ if (result.value.phase === "applied") clearRecoveryOtpRetryAt(operationId, this.config?.tenantId);
13457
14051
  if (enterWhenApplied && result.value.phase === "applied") return this.enterRecoveredSession();
13458
14052
  return result;
13459
14053
  }
@@ -13477,7 +14071,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13477
14071
  }
13478
14072
  /** Read-only even for applied operations. Entering the identity is a separate action. */
13479
14073
  async refreshRecoveryStatus() {
13480
- return this.runRecovery("刷新恢复状态", (operationId) => call(() => this.remote.getRecoveryStatus({ operationId }), void 0, recoveryCarrierFailureMessage));
14074
+ const generation = this.generation;
14075
+ const revision = this.recoveryRevision;
14076
+ const operationId = this.view.recoveryOperationId;
14077
+ if (operationId === null) return {
14078
+ ok: false,
14079
+ error: "没有可查询的身份恢复操作"
14080
+ };
14081
+ const result = await this.withPending("刷新恢复状态", async () => {
14082
+ const status = await call(() => this.remote.getRecoveryStatus({ operationId }), void 0, recoveryCarrierFailureMessage);
14083
+ return status.ok ? status : {
14084
+ ok: false,
14085
+ error: IDENTITY_ACCESS_FAILURE_MESSAGE
14086
+ };
14087
+ }, {
14088
+ publishFailure: false,
14089
+ recovery: true
14090
+ });
14091
+ if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
14092
+ if (!result.ok) {
14093
+ this.publish({
14094
+ ...this.view,
14095
+ accessError: IDENTITY_ACCESS_FAILURE_MESSAGE
14096
+ });
14097
+ return result;
14098
+ }
14099
+ this.publish({
14100
+ ...this.view,
14101
+ recoveryProgress: result.value,
14102
+ accessError: null
14103
+ });
14104
+ if (result.value.phase === "applied") clearRecoveryOtpRetryAt(operationId, this.config?.tenantId);
14105
+ return result;
13481
14106
  }
13482
14107
  async resumeRecovery() {
13483
14108
  const progress = this.view.recoveryProgress;
@@ -13501,6 +14126,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13501
14126
  });
13502
14127
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13503
14128
  if (!result.ok) return result;
14129
+ clearRecoveryOtpRetryAt(progress.operationId, this.config?.tenantId);
13504
14130
  this.leaveRecovery();
13505
14131
  const opened = await this.open();
13506
14132
  return opened.ok ? result : opened;
@@ -13524,6 +14150,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13524
14150
  });
13525
14151
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13526
14152
  if (!result.ok) return result;
14153
+ clearRecoveryOtpRetryAt(operationId, this.config?.tenantId);
13527
14154
  this.leaveRecovery();
13528
14155
  this.refreshIdentityAccess();
13529
14156
  return {
@@ -13531,6 +14158,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13531
14158
  value: void 0
13532
14159
  };
13533
14160
  }
14161
+ /** Return cached browser-safe runtime policy, or load it once on demand. */
14162
+ async getConfig() {
14163
+ if (this.config !== null) return {
14164
+ ok: true,
14165
+ value: this.config
14166
+ };
14167
+ const generation = this.generation;
14168
+ const result = await call(() => this.remote.getConfig(), mailFailureMessage);
14169
+ if (!this.current(generation)) return {
14170
+ ok: false,
14171
+ error: "AWiki 会话已切换"
14172
+ };
14173
+ if (result.ok) this.config = result.value;
14174
+ return result;
14175
+ }
13534
14176
  /** Read the active deployment identity's public mailbox state. */
13535
14177
  getMailAccount() {
13536
14178
  return call(() => this.remote.getMailAccount(), mailFailureMessage);
@@ -13551,6 +14193,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13551
14193
  sendMail(request) {
13552
14194
  return call(() => this.remote.sendMail(request), mailFailureMessage);
13553
14195
  }
14196
+ /** Download one explicitly selected mail attachment without retaining its bytes. */
14197
+ async downloadMailAttachment(request) {
14198
+ if (this.disposed) return {
14199
+ ok: false,
14200
+ error: "AWiki 插件已卸载"
14201
+ };
14202
+ const generation = this.generation;
14203
+ const result = await call(() => this.remote.downloadMailAttachment(request), mailFailureMessage);
14204
+ if (!this.current(generation)) return {
14205
+ ok: false,
14206
+ error: "AWiki 已关闭"
14207
+ };
14208
+ return result;
14209
+ }
13554
14210
  /**
13555
14211
  * Load another page of the conversation roster.
13556
14212
  * @returns successful pagination or one display-safe failure.
@@ -13677,8 +14333,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13677
14333
  return this.selectConversation(existing.id);
13678
14334
  }
13679
14335
  const generation = this.generation;
13680
- const resolved = await this.withPending("查找用户", () => call(() => this.remote.resolvePeer({ peer })));
13681
- if (!resolved.ok) return resolved.error.startsWith("not-found") ? this.fail("该 Handle 不存在") : resolved;
14336
+ const resolved = await this.withPending("查找用户", async () => {
14337
+ const result = await callWithFailureCode(() => this.remote.resolvePeer({ peer }));
14338
+ if (!result.ok) return {
14339
+ ok: false,
14340
+ error: result.failureCode === "not-found" ? "该 Handle 不存在" : result.error
14341
+ };
14342
+ return result;
14343
+ });
14344
+ if (!resolved.ok) return resolved;
13682
14345
  if (!this.current(generation)) return {
13683
14346
  ok: true,
13684
14347
  value: void 0
@@ -14355,11 +15018,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14355
15018
  clearMailBrowserCache(globalThis.localStorage, owner);
14356
15019
  } catch {}
14357
15020
  }
14358
- storeRecoveryOperation(null, tenantId);
15021
+ clearRecoveryOtpRetryAt(this.view.recoveryOperationId, tenantId);
15022
+ this.rememberRecoveryOperation(null, tenantId);
14359
15023
  if (!this.current(generation)) return result;
14360
15024
  this.drafts.clearScope();
14361
15025
  this.close();
14362
- this.config = null;
14363
15026
  this.conversationsCursor = void 0;
14364
15027
  this.historyCursor = void 0;
14365
15028
  this.unreadAtOpen.clear();
@@ -14369,6 +15032,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14369
15032
  ...INITIAL_VIEW,
14370
15033
  status: "ready",
14371
15034
  accessLoading: false,
15035
+ attachmentMaxBytes: this.config?.attachmentMaxBytes ?? INITIAL_VIEW.attachmentMaxBytes,
15036
+ handleRecoveryPhoneEnabled: this.config?.handleRecoveryPhoneEnabled ?? false,
14372
15037
  identityAccess: {
14373
15038
  choice: null,
14374
15039
  joining: false,
@@ -14982,8 +15647,157 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14982
15647
  URL.revokeObjectURL(url);
14983
15648
  }
14984
15649
  //#endregion
15650
+ //#region lib/types/base64.js
15651
+ /** Linear-time standard Base64 syntax validation for bounded binary payloads. */
15652
+ function base64Character(code) {
15653
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code >= 48 && code <= 57 || code === 43 || code === 47;
15654
+ }
15655
+ /** Reject misplaced padding and non-Base64 bytes without recursive regexp matching. */
15656
+ function standardBase64Syntax(value) {
15657
+ if (value.length % 4 !== 0) return false;
15658
+ let dataEnd = value.length;
15659
+ if (dataEnd > 0 && value.charCodeAt(dataEnd - 1) === 61) dataEnd -= 1;
15660
+ if (dataEnd > 0 && value.charCodeAt(dataEnd - 1) === 61) dataEnd -= 1;
15661
+ for (let index = 0; index < dataEnd; index += 1) if (!base64Character(value.charCodeAt(index))) return false;
15662
+ for (let index = dataEnd; index < value.length; index += 1) if (value.charCodeAt(index) !== 61) return false;
15663
+ return true;
15664
+ }
15665
+ //#endregion
15666
+ //#region lib/types/client/mail-attachment.js
15667
+ /** Browser-only mail attachment selection, encoding, integrity, and download helpers. */
15668
+ function invalid(message) {
15669
+ throw new TypeError(message);
15670
+ }
15671
+ function fileName(value) {
15672
+ if (value.length === 0 || value.trim() !== value || value.replace(/[. ]+$/u, "") !== value || value === "." || value === ".." || new TextEncoder().encode(value).byteLength > 255 || /[\\/\p{C}]/u.test(value)) invalid("附件文件名无效。");
15673
+ return value;
15674
+ }
15675
+ function contentType(value) {
15676
+ if (value === "") return "application/octet-stream";
15677
+ if (!/^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+$/u.test(value)) invalid("附件 MIME 类型无效。");
15678
+ return value;
15679
+ }
15680
+ function assertLimits(limits) {
15681
+ if (!Number.isSafeInteger(limits.maxCount) || limits.maxCount < 0 || !Number.isSafeInteger(limits.maxBytes) || limits.maxBytes < 1 || !Number.isSafeInteger(limits.totalMaxBytes) || limits.totalMaxBytes < limits.maxBytes) invalid("邮件附件限制暂不可用。");
15682
+ }
15683
+ function base64(bytes) {
15684
+ let binary = "";
15685
+ const chunkSize = 32768;
15686
+ for (let offset = 0; offset < bytes.length; offset += chunkSize) binary += String.fromCharCode(...bytes.subarray(offset, offset + chunkSize));
15687
+ return btoa(binary);
15688
+ }
15689
+ /** Append browser File references after enforcing the exact Host-owned limits. */
15690
+ function selectMailAttachments(current, selected, limits, createId) {
15691
+ assertLimits(limits);
15692
+ const additions = Array.from(selected, (file) => ({
15693
+ id: createId(),
15694
+ file,
15695
+ fileName: fileName(file.name),
15696
+ contentType: contentType(file.type),
15697
+ sizeBytes: file.size,
15698
+ lastModified: file.lastModified
15699
+ }));
15700
+ const combined = [...current, ...additions];
15701
+ if (combined.length > limits.maxCount) invalid(`邮件最多选择 ${limits.maxCount} 个附件。`);
15702
+ for (const attachment of combined) {
15703
+ if (!Number.isSafeInteger(attachment.sizeBytes) || attachment.sizeBytes < 0) invalid("附件大小无效。");
15704
+ if (attachment.sizeBytes > limits.maxBytes) invalid(`单个附件不能超过 ${limits.maxBytes} bytes。`);
15705
+ }
15706
+ const total = combined.reduce((sum, attachment) => sum + attachment.sizeBytes, 0);
15707
+ if (!Number.isSafeInteger(total) || total > limits.totalMaxBytes) invalid(`附件总大小不能超过 ${limits.totalMaxBytes} bytes。`);
15708
+ return combined;
15709
+ }
15710
+ /** Re-read the same approved File objects and return JSON-safe Remote attachments. */
15711
+ async function encodeMailAttachments(attachments, limits) {
15712
+ selectMailAttachments([], attachments.map((value) => value.file), limits, () => "validation-only");
15713
+ const encoded = [];
15714
+ for (const attachment of attachments) {
15715
+ if (attachment.file.name !== attachment.fileName || contentType(attachment.file.type) !== attachment.contentType || attachment.file.size !== attachment.sizeBytes || attachment.file.lastModified !== attachment.lastModified) invalid(`附件 ${attachment.fileName} 已发生变化,请重新选择。`);
15716
+ let buffer;
15717
+ try {
15718
+ buffer = await attachment.file.arrayBuffer();
15719
+ } catch {
15720
+ invalid(`无法读取附件 ${attachment.fileName},请重新选择。`);
15721
+ }
15722
+ const bytes = new Uint8Array(buffer);
15723
+ if (bytes.byteLength !== attachment.sizeBytes) invalid(`附件 ${attachment.fileName} 的大小已发生变化,请重新选择。`);
15724
+ encoded.push({
15725
+ fileName: attachment.fileName,
15726
+ contentType: attachment.contentType,
15727
+ sizeBytes: bytes.byteLength,
15728
+ bytesBase64: base64(bytes)
15729
+ });
15730
+ }
15731
+ return encoded;
15732
+ }
15733
+ /** Return canonical download metadata only when the service supplied every required field. */
15734
+ function downloadableMailAttachment(value, maxBytes) {
15735
+ if (!Number.isSafeInteger(value.index) || value.index < 0 || value.index > 4294967295) return void 0;
15736
+ if (value.fileName === void 0 || value.contentType === void 0 || value.sizeBytes === void 0) return void 0;
15737
+ if (!/^(?:0|[1-9][0-9]*)$/u.test(value.sizeBytes)) return void 0;
15738
+ const sizeBytes = Number(value.sizeBytes);
15739
+ if (!Number.isSafeInteger(sizeBytes) || sizeBytes < 0 || sizeBytes > maxBytes) return void 0;
15740
+ try {
15741
+ return {
15742
+ index: value.index,
15743
+ fileName: fileName(value.fileName),
15744
+ contentType: contentType(value.contentType),
15745
+ sizeBytes
15746
+ };
15747
+ } catch {
15748
+ return;
15749
+ }
15750
+ }
15751
+ /** Validate exact metadata, canonical Base64, byte length, and SHA-256 before download. */
15752
+ async function prepareMailAttachmentDownload(value, expected, maxBytes) {
15753
+ if (fileName(value.fileName) !== expected.fileName || contentType(value.contentType) !== expected.contentType || value.sizeBytes !== expected.sizeBytes || value.sizeBytes > maxBytes) invalid("下载附件与邮件元数据不一致。");
15754
+ if (!/^[a-f0-9]{64}$/u.test(value.sha256)) invalid("下载附件完整性信息无效。");
15755
+ const expectedEncodedLength = Math.ceil(value.sizeBytes / 3) * 4;
15756
+ if (value.bytesBase64.length !== expectedEncodedLength || value.bytesBase64.length % 4 !== 0 || !standardBase64Syntax(value.bytesBase64)) invalid("下载附件编码无效。");
15757
+ let binary;
15758
+ try {
15759
+ binary = atob(value.bytesBase64);
15760
+ } catch {
15761
+ invalid("下载附件编码无效。");
15762
+ }
15763
+ const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
15764
+ if (bytes.byteLength !== value.sizeBytes || base64(bytes) !== value.bytesBase64) invalid("下载附件大小或编码不一致。");
15765
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
15766
+ if (Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join("") !== value.sha256) invalid("下载附件完整性校验失败。");
15767
+ return {
15768
+ fileName: expected.fileName,
15769
+ contentType: expected.contentType,
15770
+ bytes
15771
+ };
15772
+ }
15773
+ /** Trigger one download and always revoke the temporary object URL immediately. */
15774
+ function savePreparedMailAttachment(value) {
15775
+ const url = URL.createObjectURL(new Blob([value.bytes], { type: value.contentType }));
15776
+ const anchor = document.createElement("a");
15777
+ try {
15778
+ anchor.href = url;
15779
+ anchor.download = value.fileName;
15780
+ anchor.hidden = true;
15781
+ document.body.append(anchor);
15782
+ anchor.click();
15783
+ } finally {
15784
+ anchor.remove();
15785
+ URL.revokeObjectURL(url);
15786
+ }
15787
+ }
15788
+ /** Execute the exact Browser UI download path: Remote, integrity check, Blob, and save click. */
15789
+ async function downloadAndSaveMailAttachment(download, request, expected, maxBytes, active = () => true) {
15790
+ const result = await download(request);
15791
+ if (!active()) return false;
15792
+ if (!result.ok) invalid(result.error);
15793
+ const prepared = await prepareMailAttachmentDownload(result.value, expected, maxBytes);
15794
+ if (!active()) return false;
15795
+ savePreparedMailAttachment(prepared);
15796
+ return true;
15797
+ }
15798
+ //#endregion
14985
15799
  //#region \0dsh-awiki-css:AwikiMail.module.css.mjs
14986
- const css$3 = ".eMUW5a_mail{background:var(--dsw-alias-bg-layer-1);flex:1;grid-template-columns:240px 320px minmax(420px,1fr);min-height:0;display:grid;position:relative}.eMUW5a_sidebar,.eMUW5a_mailList,.eMUW5a_mailDetail{min-width:0;min-height:0}.eMUW5a_sidebar{border-right:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);flex-direction:column;display:flex}.eMUW5a_accountCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:10px;gap:3px;margin:0 14px 12px;padding:10px 12px;display:grid}.eMUW5a_accountCard small,.eMUW5a_accountCard span{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_accountCard strong{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.eMUW5a_accountCard .eMUW5a_accountStatus{color:var(--dsw-alias-state-success-primary)}.eMUW5a_folderNav{gap:4px;padding:0 10px;display:grid}.eMUW5a_folderNav button{min-height:38px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:9px;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:9px;padding:0 10px;display:grid}.eMUW5a_folderNav button:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_folderNav button[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.eMUW5a_folderNav small{min-width:20px;color:var(--dsw-alias-brand-primary);text-align:right}.eMUW5a_folderRow{color:var(--dsw-alias-label-secondary);border-radius:9px;grid-template-columns:minmax(0,1fr) 38px;display:grid}.eMUW5a_folderRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_folderRow[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.eMUW5a_folderRow>button{color:inherit;background:0 0;border-radius:0}.eMUW5a_folderRow>button:hover{background:0 0}.eMUW5a_folderRow>.eMUW5a_composeIconButton{border-radius:8px;grid-template-columns:1fr;place-items:center;gap:0;width:38px;padding:0}.eMUW5a_folderRow>.eMUW5a_composeIconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailList{border-right:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);flex-direction:column;display:flex;position:relative}.eMUW5a_listHeader,.eMUW5a_detailHeader{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:9px;min-height:56px;padding:0 12px;display:flex}.eMUW5a_listHeader>div,.eMUW5a_detailHeader>div{flex-direction:column;flex:1;min-width:0;display:flex}.eMUW5a_listHeader strong,.eMUW5a_detailHeader strong,.eMUW5a_listHeader small,.eMUW5a_detailHeader small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.eMUW5a_listHeader strong,.eMUW5a_detailHeader strong{font-size:13px;line-height:20px}.eMUW5a_listHeader small,.eMUW5a_detailHeader small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_listHeader>button,.eMUW5a_detailBack{width:30px;height:30px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:8px;flex:none;place-items:center;padding:0;display:grid}.eMUW5a_listHeader>button:hover,.eMUW5a_detailBack:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.eMUW5a_listHeader>button:disabled{opacity:.5;cursor:default}.eMUW5a_detailBack{display:none}.eMUW5a_listHeader svg,.eMUW5a_loadingState svg{animation:none}.eMUW5a_listHeader button:disabled svg,.eMUW5a_loadingState svg{animation:1s linear infinite eMUW5a_mail-spin}@keyframes eMUW5a_mail-spin{to{transform:rotate(360deg)}}.eMUW5a_rows{flex:1;min-height:0;padding:6px;overflow:auto}.eMUW5a_mailRow{width:100%;min-height:82px;color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:10px;grid-template-columns:7px minmax(0,1fr) auto;gap:7px;padding:10px 9px;display:grid;position:relative}.eMUW5a_mailRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailRow[data-active]{background:var(--dsw-alias-interactive-bg-active)}.eMUW5a_unreadDot{background:0 0;border-radius:50%;align-self:start;width:6px;height:6px;margin-top:7px}.eMUW5a_mailRow[data-unread] .eMUW5a_unreadDot{background:var(--dsw-alias-brand-primary)}.eMUW5a_rowContent{flex-direction:column;gap:2px;min-width:0;display:flex}.eMUW5a_rowTop{align-items:center;gap:8px;display:flex}.eMUW5a_rowTop strong{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12px;line-height:18px;overflow:hidden}.eMUW5a_mailRow[data-unread] .eMUW5a_rowTop strong,.eMUW5a_mailRow[data-unread] .eMUW5a_rowSubject{font-weight:600}.eMUW5a_rowTop time{color:var(--dsw-alias-label-tertiary);flex:none;font-size:10px;line-height:15px}.eMUW5a_rowSubject,.eMUW5a_rowPreview{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.eMUW5a_rowSubject{color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px}.eMUW5a_rowPreview{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_rowAttachment{color:var(--dsw-alias-label-tertiary);align-self:end;align-items:center;gap:2px;display:flex}.eMUW5a_rowAttachment small{font-size:10px}.eMUW5a_inlineError,.eMUW5a_detailError{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:8px;padding:8px 12px;font-size:11px;line-height:16px;display:flex}.eMUW5a_inlineError button{color:inherit;cursor:pointer;background:0 0;border:0;flex:none;text-decoration:underline}.eMUW5a_loadingState,.eMUW5a_emptyState,.eMUW5a_detailEmpty{color:var(--dsw-alias-label-tertiary);justify-content:center;align-items:center;gap:8px;font-size:12px;display:flex}.eMUW5a_loadingState{pointer-events:none;position:absolute;inset:56px 0 0}.eMUW5a_emptyState{flex-direction:column;min-height:180px}.eMUW5a_emptyState p,.eMUW5a_detailEmpty p{margin:0}.eMUW5a_loadMore{background:var(--dsw-alias-button-elevated-fill);min-height:34px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;border:0;border-radius:9px;margin:7px}.eMUW5a_loadMore:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailDetail{background:var(--dsw-alias-bg-layer-1);flex-direction:column;display:flex;position:relative}.eMUW5a_detailEmpty{flex-direction:column;flex:1}.eMUW5a_detailEmpty button{background:var(--dsw-alias-button-primary-fill);min-height:34px;color:var(--dsw-alias-label-primary-inverted);cursor:pointer;border:0;border-radius:9px;padding:0 14px}.eMUW5a_markReadButton{border:1px solid var(--dsw-alias-border-l2);min-height:30px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;background:0 0;border-radius:8px;flex:none;padding:0 9px;font-size:11px}.eMUW5a_markReadButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_markReadButton:disabled{opacity:.5;cursor:default}.eMUW5a_messageBody{flex:1;min-height:0;padding:22px 24px;overflow:auto}.eMUW5a_messageMeta{border-bottom:1px solid var(--dsw-alias-border-l1);padding-bottom:18px}.eMUW5a_messageMeta h3{overflow-wrap:anywhere;margin:0 0 5px;font-size:18px;line-height:27px}.eMUW5a_messageMeta>time{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_messageMeta dl{gap:3px;margin:14px 0 0;display:grid}.eMUW5a_messageMeta dl>div{grid-template-columns:48px minmax(0,1fr);gap:8px;font-size:11px;line-height:17px;display:grid}.eMUW5a_messageMeta dt{color:var(--dsw-alias-label-tertiary)}.eMUW5a_messageMeta dd{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0}.eMUW5a_untrustedNotice{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);border-radius:8px;align-items:center;gap:7px;margin:16px 0;padding:8px 10px;font-size:11px;line-height:16px;display:flex}.eMUW5a_plainBody{min-height:120px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;font-size:13px;line-height:22px}.eMUW5a_truncatedNotice{color:var(--dsw-alias-state-warn-label);margin:14px 0 0;font-size:11px}.eMUW5a_attachments{border-top:1px solid var(--dsw-alias-border-l1);gap:8px;margin-top:22px;padding-top:16px;display:grid}.eMUW5a_attachments h4{margin:0;font-size:12px;line-height:18px}.eMUW5a_attachments>div{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:9px;align-items:center;gap:9px;padding:9px 10px;display:flex}.eMUW5a_attachments>div>span{flex-direction:column;min-width:0;display:flex}.eMUW5a_attachments strong{text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_attachments small{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.eMUW5a_notice{z-index:6;box-sizing:border-box;background:var(--dsw-alias-button-primary-fill);max-width:min(360px,100% - 32px);color:var(--dsw-alias-label-primary-inverted);box-shadow:var(--dsw-shadow-lv2);overflow-wrap:anywhere;pointer-events:none;text-align:center;border-radius:9px;padding:10px 14px;font-size:12px;line-height:18px;animation:2.4s both eMUW5a_mail-notice;position:absolute;top:16px;left:50%;transform:translate(-50%)}@keyframes eMUW5a_mail-notice{0%{opacity:0;transform:translate(-50%,-6px)}8%,88%{opacity:1;transform:translate(-50%)}to{opacity:0;transform:translate(-50%,-4px)}}.eMUW5a_composer{flex-direction:column;flex:1;min-height:0;display:flex}.eMUW5a_composeFields{flex-direction:column;flex:1;gap:11px;min-height:0;padding:18px 20px;display:flex;overflow:auto}.eMUW5a_composeFields label{color:var(--dsw-alias-label-secondary);grid-template-rows:max-content max-content;gap:5px;font-size:11px;line-height:16px;display:grid}.eMUW5a_composeFields input,.eMUW5a_composeFields textarea{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);width:100%;color:var(--dsw-alias-label-primary);font:inherit;resize:vertical;border-radius:9px;padding:8px 10px}.eMUW5a_composeFields input{height:38px}.eMUW5a_composeFields .eMUW5a_bodyField{flex:1;grid-template-rows:max-content minmax(160px,1fr);min-height:160px}.eMUW5a_bodyField textarea{resize:none;min-height:160px}.eMUW5a_composeError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:11px;line-height:16px}.eMUW5a_composeFooter{border-top:1px solid var(--dsw-alias-border-l1);flex:none;justify-content:flex-end;gap:8px;padding:10px 14px;display:flex}.eMUW5a_cancelButton,.eMUW5a_sendButton{cursor:pointer;min-height:34px;font:inherit;border-radius:9px;justify-content:center;align-items:center;gap:6px;padding:0 13px;display:flex}.eMUW5a_cancelButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.eMUW5a_sendButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-inverted);border:0}.eMUW5a_cancelButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_sendButton:hover{background:var(--dsw-alias-button-primary-hover)}.eMUW5a_confirmSummary{color:var(--dsw-alias-label-secondary);gap:6px;display:grid}.eMUW5a_confirmSummary p,.eMUW5a_discardText{overflow-wrap:anywhere;margin:0}@media (width<=1119px){.eMUW5a_mail{grid-template-columns:220px minmax(0,1fr)}.eMUW5a_mailList,.eMUW5a_mailDetail{grid-area:1/2}.eMUW5a_mailDetail,.eMUW5a_mail[data-detail-active] .eMUW5a_mailList{display:none}.eMUW5a_mail[data-detail-active] .eMUW5a_mailDetail{display:flex}.eMUW5a_detailBack{display:grid}}@media (width<=719px){.eMUW5a_mail{grid-template-columns:1fr}.eMUW5a_sidebar,.eMUW5a_mailList,.eMUW5a_mailDetail{grid-area:1/1}.eMUW5a_mailList,.eMUW5a_mailDetail,.eMUW5a_mail[data-pane=list] .eMUW5a_sidebar,.eMUW5a_mail[data-pane=detail] .eMUW5a_sidebar{display:none}.eMUW5a_mail[data-pane=list] .eMUW5a_mailList,.eMUW5a_mail[data-pane=detail] .eMUW5a_mailDetail{display:flex}.eMUW5a_messageBody{padding:18px}}@media (prefers-reduced-motion:reduce){.eMUW5a_listHeader button:disabled svg,.eMUW5a_loadingState svg,.eMUW5a_notice{animation:none}}";
15800
+ const css$3 = ".eMUW5a_mail{background:var(--dsw-alias-bg-layer-1);flex:1;grid-template-columns:240px 320px minmax(420px,1fr);min-height:0;display:grid;position:relative}.eMUW5a_sidebar,.eMUW5a_mailList,.eMUW5a_mailDetail{min-width:0;min-height:0}.eMUW5a_sidebar{border-right:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);flex-direction:column;display:flex}.eMUW5a_accountCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:10px;gap:3px;margin:0 14px 12px;padding:10px 12px;display:grid}.eMUW5a_accountCard small,.eMUW5a_accountCard span{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_accountCard strong{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.eMUW5a_accountCard .eMUW5a_accountStatus{color:var(--dsw-alias-state-success-primary)}.eMUW5a_folderNav{gap:4px;padding:0 10px;display:grid}.eMUW5a_folderNav button{min-height:38px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:9px;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:9px;padding:0 10px;display:grid}.eMUW5a_folderNav button:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_folderNav button[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.eMUW5a_folderNav small{min-width:20px;color:var(--dsw-alias-brand-primary);text-align:right}.eMUW5a_folderRow{color:var(--dsw-alias-label-secondary);border-radius:9px;grid-template-columns:minmax(0,1fr) 38px;display:grid}.eMUW5a_folderRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_folderRow[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.eMUW5a_folderRow>button{color:inherit;background:0 0;border-radius:0}.eMUW5a_folderRow>button:hover{background:0 0}.eMUW5a_folderRow>.eMUW5a_composeIconButton{border-radius:8px;grid-template-columns:1fr;place-items:center;gap:0;width:38px;padding:0}.eMUW5a_folderRow>.eMUW5a_composeIconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailList{border-right:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);flex-direction:column;display:flex;position:relative}.eMUW5a_listHeader,.eMUW5a_detailHeader{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:9px;min-height:56px;padding:0 12px;display:flex}.eMUW5a_listHeader>div,.eMUW5a_detailHeader>div{flex-direction:column;flex:1;min-width:0;display:flex}.eMUW5a_listHeader strong,.eMUW5a_detailHeader strong,.eMUW5a_listHeader small,.eMUW5a_detailHeader small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.eMUW5a_listHeader strong,.eMUW5a_detailHeader strong{font-size:13px;line-height:20px}.eMUW5a_listHeader small,.eMUW5a_detailHeader small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_listHeader>button,.eMUW5a_detailBack{width:30px;height:30px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:8px;flex:none;place-items:center;padding:0;display:grid}.eMUW5a_listHeader>button:hover,.eMUW5a_detailBack:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.eMUW5a_listHeader>button:disabled{opacity:.5;cursor:default}.eMUW5a_detailBack{display:none}.eMUW5a_listHeader svg,.eMUW5a_loadingState svg{animation:none}.eMUW5a_listHeader button:disabled svg,.eMUW5a_loadingState svg{animation:1s linear infinite eMUW5a_mail-spin}.eMUW5a_listHeader>.eMUW5a_listBack{display:none}@keyframes eMUW5a_mail-spin{to{transform:rotate(360deg)}}.eMUW5a_rows{flex:1;min-height:0;padding:6px;overflow:auto}.eMUW5a_mailRow{width:100%;min-height:82px;color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:10px;grid-template-columns:7px minmax(0,1fr) auto;gap:7px;padding:10px 9px;display:grid;position:relative}.eMUW5a_mailRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailRow[data-active]{background:var(--dsw-alias-interactive-bg-active)}.eMUW5a_unreadDot{background:0 0;border-radius:50%;align-self:start;width:6px;height:6px;margin-top:7px}.eMUW5a_mailRow[data-unread] .eMUW5a_unreadDot{background:var(--dsw-alias-brand-primary)}.eMUW5a_rowContent{flex-direction:column;gap:2px;min-width:0;display:flex}.eMUW5a_rowTop{align-items:center;gap:8px;display:flex}.eMUW5a_rowTop strong{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12px;line-height:18px;overflow:hidden}.eMUW5a_mailRow[data-unread] .eMUW5a_rowTop strong,.eMUW5a_mailRow[data-unread] .eMUW5a_rowSubject{font-weight:600}.eMUW5a_rowTop time{color:var(--dsw-alias-label-tertiary);flex:none;font-size:10px;line-height:15px}.eMUW5a_rowSubject,.eMUW5a_rowPreview{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.eMUW5a_rowSubject{color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px}.eMUW5a_rowPreview{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_rowAttachment{color:var(--dsw-alias-label-tertiary);align-self:end;align-items:center;gap:2px;display:flex}.eMUW5a_rowAttachment small{font-size:10px}.eMUW5a_inlineError,.eMUW5a_detailError{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:8px;padding:8px 12px;font-size:11px;line-height:16px;display:flex}.eMUW5a_inlineError button{color:inherit;cursor:pointer;background:0 0;border:0;flex:none;text-decoration:underline}.eMUW5a_loadingState,.eMUW5a_emptyState,.eMUW5a_detailEmpty{color:var(--dsw-alias-label-tertiary);justify-content:center;align-items:center;gap:8px;font-size:12px;display:flex}.eMUW5a_loadingState{pointer-events:none;position:absolute;inset:56px 0 0}.eMUW5a_emptyState{flex-direction:column;min-height:180px}.eMUW5a_emptyState p,.eMUW5a_detailEmpty p{margin:0}.eMUW5a_loadMore{background:var(--dsw-alias-button-elevated-fill);min-height:34px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;border:0;border-radius:9px;margin:7px}.eMUW5a_loadMore:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailDetail{background:var(--dsw-alias-bg-layer-1);flex-direction:column;display:flex;position:relative}.eMUW5a_detailEmpty{flex-direction:column;flex:1}.eMUW5a_detailEmpty button{background:var(--dsw-alias-button-primary-fill);min-height:34px;color:var(--dsw-alias-label-primary-inverted);cursor:pointer;border:0;border-radius:9px;padding:0 14px}.eMUW5a_markReadButton{border:1px solid var(--dsw-alias-border-l2);min-height:30px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;background:0 0;border-radius:8px;flex:none;padding:0 9px;font-size:11px}.eMUW5a_markReadButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_markReadButton:disabled{opacity:.5;cursor:default}.eMUW5a_messageBody{flex:1;min-height:0;padding:22px 24px;overflow:auto}.eMUW5a_messageMeta{border-bottom:1px solid var(--dsw-alias-border-l1);padding-bottom:18px}.eMUW5a_messageMeta h3{overflow-wrap:anywhere;margin:0 0 5px;font-size:18px;line-height:27px}.eMUW5a_messageMeta>time{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_messageMeta dl{gap:3px;margin:14px 0 0;display:grid}.eMUW5a_messageMeta dl>div{grid-template-columns:48px minmax(0,1fr);gap:8px;font-size:11px;line-height:17px;display:grid}.eMUW5a_messageMeta dt{color:var(--dsw-alias-label-tertiary)}.eMUW5a_messageMeta dd{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0}.eMUW5a_untrustedNotice{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);border-radius:8px;align-items:center;gap:7px;margin:16px 0;padding:8px 10px;font-size:11px;line-height:16px;display:flex}.eMUW5a_plainBody{min-height:120px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;font-size:13px;line-height:22px}.eMUW5a_truncatedNotice{color:var(--dsw-alias-state-warn-label);margin:14px 0 0;font-size:11px}.eMUW5a_attachments{border-top:1px solid var(--dsw-alias-border-l1);gap:8px;min-width:0;margin-top:22px;padding-top:16px;display:grid}.eMUW5a_attachments h4{margin:0;font-size:12px;line-height:18px}.eMUW5a_attachments>div{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:9px;align-items:center;gap:9px;min-width:0;max-width:100%;padding:9px 10px;display:flex}.eMUW5a_attachments>div>span{flex-direction:column;flex:1;min-width:0;display:flex}.eMUW5a_attachments strong{text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_attachments small{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.eMUW5a_attachments button,.eMUW5a_selectedAttachments button{border:1px solid var(--dsw-alias-border-l2);min-height:30px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;background:0 0;border-radius:8px;flex:none;padding:0 10px;font-size:11px}.eMUW5a_attachments button:hover,.eMUW5a_selectedAttachments button:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_attachments button:disabled,.eMUW5a_selectedAttachments button:disabled{opacity:.5;cursor:default}.eMUW5a_attachments .eMUW5a_attachmentDownloadError{color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere}.eMUW5a_notice{z-index:6;box-sizing:border-box;background:var(--dsw-alias-button-primary-fill);max-width:min(360px,100% - 32px);color:var(--dsw-alias-label-primary-inverted);box-shadow:var(--dsw-shadow-lv2);overflow-wrap:anywhere;pointer-events:none;text-align:center;border-radius:9px;padding:10px 14px;font-size:12px;line-height:18px;animation:2.4s both eMUW5a_mail-notice;position:absolute;top:16px;left:50%;transform:translate(-50%)}@keyframes eMUW5a_mail-notice{0%{opacity:0;transform:translate(-50%,-6px)}8%,88%{opacity:1;transform:translate(-50%)}to{opacity:0;transform:translate(-50%,-4px)}}.eMUW5a_composer{flex-direction:column;flex:1;min-height:0;display:flex}.eMUW5a_composeFields{flex-direction:column;flex:1;gap:11px;min-height:0;padding:18px 20px;display:flex;overflow:auto}.eMUW5a_composeFields label{color:var(--dsw-alias-label-secondary);grid-template-rows:max-content max-content;gap:5px;font-size:11px;line-height:16px;display:grid}.eMUW5a_composeFields input,.eMUW5a_composeFields textarea{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);width:100%;color:var(--dsw-alias-label-primary);font:inherit;resize:vertical;border-radius:9px;padding:8px 10px}.eMUW5a_composeFields input{height:38px}.eMUW5a_composeFields .eMUW5a_bodyField{flex:1;grid-template-rows:max-content minmax(160px,1fr);min-height:160px}.eMUW5a_bodyField textarea{resize:none;min-height:160px}.eMUW5a_composeAttachments{gap:9px;display:grid}.eMUW5a_attachmentPickerRow{align-items:center;gap:10px;display:flex}.eMUW5a_attachmentPickerRow>small{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.eMUW5a_attachmentPicker{border:1px solid var(--dsw-alias-border-l2);min-height:32px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;flex:none;justify-content:center;align-items:center;padding:0 11px;display:inline-flex;position:relative;overflow:hidden}.eMUW5a_attachmentPicker:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_attachmentPicker:focus-within{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.eMUW5a_attachmentPicker input{opacity:0;width:1px;height:1px;padding:0;position:absolute}.eMUW5a_attachmentPicker:has(input:disabled){opacity:.5;cursor:default}.eMUW5a_selectedAttachments{gap:7px;display:grid}.eMUW5a_selectedAttachments>div{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:9px;align-items:center;gap:9px;padding:8px 9px;display:flex}.eMUW5a_selectedAttachments>div>span{flex-direction:column;flex:1;min-width:0;display:flex}.eMUW5a_selectedAttachments strong{text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_selectedAttachments small{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.eMUW5a_selectedAttachments>p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:10px;line-height:15px}.eMUW5a_composeError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:11px;line-height:16px}.eMUW5a_composeFooter{border-top:1px solid var(--dsw-alias-border-l1);flex:none;justify-content:flex-end;gap:8px;padding:10px 14px;display:flex}.eMUW5a_cancelButton,.eMUW5a_sendButton{cursor:pointer;min-height:34px;font:inherit;border-radius:9px;justify-content:center;align-items:center;gap:6px;padding:0 13px;display:flex}.eMUW5a_cancelButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.eMUW5a_sendButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-inverted);border:0}.eMUW5a_cancelButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_sendButton:hover{background:var(--dsw-alias-button-primary-hover)}.eMUW5a_confirmSummary{color:var(--dsw-alias-label-secondary);gap:6px;display:grid}.eMUW5a_confirmSummary p,.eMUW5a_discardText{overflow-wrap:anywhere;margin:0}@media (width<=1119px){.eMUW5a_mail{grid-template-columns:220px minmax(0,1fr)}.eMUW5a_mailList,.eMUW5a_mailDetail{grid-area:1/2}.eMUW5a_mailDetail,.eMUW5a_mail[data-detail-active] .eMUW5a_mailList{display:none}.eMUW5a_mail[data-detail-active] .eMUW5a_mailDetail{display:flex}.eMUW5a_detailBack{display:grid}}@media (width<=719px){.eMUW5a_mail{grid-template-columns:1fr}.eMUW5a_sidebar,.eMUW5a_mailList,.eMUW5a_mailDetail{grid-area:1/1}.eMUW5a_mailList,.eMUW5a_mailDetail,.eMUW5a_mail[data-pane=list] .eMUW5a_sidebar,.eMUW5a_mail[data-pane=detail] .eMUW5a_sidebar{display:none}.eMUW5a_mail[data-pane=list] .eMUW5a_mailList,.eMUW5a_mail[data-pane=detail] .eMUW5a_mailDetail{display:flex}.eMUW5a_listHeader>.eMUW5a_listBack{display:grid}.eMUW5a_messageBody{padding:18px}}@media (prefers-reduced-motion:reduce){.eMUW5a_listHeader button:disabled svg,.eMUW5a_loadingState svg,.eMUW5a_notice{animation:none}}";
14987
15801
  const tagId$3 = "@awiki/dsh-plugin/AwikiMail.module.css";
14988
15802
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
14989
15803
  const tag = document.createElement("style");
@@ -14995,9 +15809,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14995
15809
  var _dsh_awiki_css_AwikiMail_module_css_default = {
14996
15810
  "accountCard": "eMUW5a_accountCard",
14997
15811
  "accountStatus": "eMUW5a_accountStatus",
15812
+ "attachmentDownloadError": "eMUW5a_attachmentDownloadError",
15813
+ "attachmentPicker": "eMUW5a_attachmentPicker",
15814
+ "attachmentPickerRow": "eMUW5a_attachmentPickerRow",
14998
15815
  "attachments": "eMUW5a_attachments",
14999
15816
  "bodyField": "eMUW5a_bodyField",
15000
15817
  "cancelButton": "eMUW5a_cancelButton",
15818
+ "composeAttachments": "eMUW5a_composeAttachments",
15001
15819
  "composeError": "eMUW5a_composeError",
15002
15820
  "composeFields": "eMUW5a_composeFields",
15003
15821
  "composeFooter": "eMUW5a_composeFooter",
@@ -15013,6 +15831,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15013
15831
  "folderNav": "eMUW5a_folderNav",
15014
15832
  "folderRow": "eMUW5a_folderRow",
15015
15833
  "inlineError": "eMUW5a_inlineError",
15834
+ "listBack": "eMUW5a_listBack",
15016
15835
  "listHeader": "eMUW5a_listHeader",
15017
15836
  "loadingState": "eMUW5a_loadingState",
15018
15837
  "loadMore": "eMUW5a_loadMore",
@@ -15033,6 +15852,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15033
15852
  "rows": "eMUW5a_rows",
15034
15853
  "rowSubject": "eMUW5a_rowSubject",
15035
15854
  "rowTop": "eMUW5a_rowTop",
15855
+ "selectedAttachments": "eMUW5a_selectedAttachments",
15036
15856
  "sendButton": "eMUW5a_sendButton",
15037
15857
  "sidebar": "eMUW5a_sidebar",
15038
15858
  "truncatedNotice": "eMUW5a_truncatedNotice",
@@ -15043,6 +15863,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15043
15863
  //#region lib/types/client/AwikiMail.js
15044
15864
  /** On-demand AWiki mailbox UI. Mail content is always rendered as untrusted text. */
15045
15865
  const MAIL_NOTICE_AUTO_DISMISS_MS = 2400;
15866
+ const EMPTY_MAIL_ATTACHMENTS = Object.freeze([]);
15046
15867
  const MAIL_FOLDER_COPY = {
15047
15868
  inbox: {
15048
15869
  title: "收件箱",
@@ -15078,6 +15899,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15078
15899
  function utf8Bytes(value) {
15079
15900
  return new TextEncoder().encode(value).byteLength;
15080
15901
  }
15902
+ function displayBytes(value) {
15903
+ if (value < 1024) return `${value} bytes`;
15904
+ if (value < 1048576) return `${(value / 1024).toFixed(value < 10240 ? 1 : 0)} KiB`;
15905
+ return `${(value / 1048576).toFixed(value < 10485760 ? 1 : 0)} MiB`;
15906
+ }
15081
15907
  function browserLocalStorage() {
15082
15908
  try {
15083
15909
  return window.localStorage;
@@ -15215,6 +16041,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15215
16041
  const [subject, setSubject] = useDraftState("mail:subject", "");
15216
16042
  const [bodyText, setBodyText] = useDraftState("mail:bodyText", "");
15217
16043
  const [composeError, setComposeError] = useDraftState("mail:composeError", null, false);
16044
+ const [downloadMaxBytes, setDownloadMaxBytes] = (0, react.useState)(0);
16045
+ const [attachmentLimits, setAttachmentLimits] = (0, react.useState)(null);
16046
+ const [attachments, setAttachments] = useDraftState("mail:attachments", EMPTY_MAIL_ATTACHMENTS);
16047
+ const [attachmentError, setAttachmentError] = (0, react.useState)(null);
16048
+ const [downloadStates, setDownloadStates] = (0, react.useState)({});
15218
16049
  const [confirmOpen, setConfirmOpen] = (0, react.useState)(false);
15219
16050
  const [discardOpen, setDiscardOpen] = (0, react.useState)(false);
15220
16051
  const [sending, setSending] = useDraftState("mail:sending", false, false);
@@ -15224,6 +16055,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15224
16055
  const loadGeneration = (0, react.useRef)(0);
15225
16056
  const detailGeneration = (0, react.useRef)(0);
15226
16057
  const noticeRevision = (0, react.useRef)(0);
16058
+ const fileInput = (0, react.useRef)(null);
15227
16059
  (0, react.useEffect)(() => () => {
15228
16060
  loadGeneration.current += 1;
15229
16061
  detailGeneration.current += 1;
@@ -15276,6 +16108,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15276
16108
  setListError(null);
15277
16109
  setNotice(null);
15278
16110
  const cacheVisible = hydrateListCache(requestedFolder);
16111
+ const configRequest = props.getConfig();
15279
16112
  const accountRequest = props.getMailAccount();
15280
16113
  const inboxRequest = props.listMailInbox({
15281
16114
  folder: requestedFolder,
@@ -15283,6 +16116,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15283
16116
  limit: 20,
15284
16117
  offset: 0
15285
16118
  });
16119
+ const configResult = await configRequest;
16120
+ if (generation !== loadGeneration.current) return;
16121
+ setDownloadMaxBytes(configResult.ok ? configResult.value.mailAttachmentDownloadMaxBytes : 0);
16122
+ setAttachmentLimits(configResult.ok ? {
16123
+ maxCount: configResult.value.mailAttachmentMaxCount,
16124
+ maxBytes: configResult.value.mailAttachmentMaxBytes,
16125
+ totalMaxBytes: configResult.value.mailAttachmentTotalMaxBytes
16126
+ } : null);
15286
16127
  const accountResult = await accountRequest;
15287
16128
  if (generation !== loadGeneration.current) return;
15288
16129
  if (accountResult.ok) setAccount(accountResult.value);
@@ -15327,6 +16168,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15327
16168
  setSelectedId(null);
15328
16169
  setMessage(null);
15329
16170
  setDetailError(null);
16171
+ setDownloadStates({});
15330
16172
  if (!hydrateListCache(nextFolder)) applyListPage(nextFolder, {
15331
16173
  items: [],
15332
16174
  hasMore: false
@@ -15339,6 +16181,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15339
16181
  setCompose(false);
15340
16182
  setSelectedId(summary.id);
15341
16183
  setMessage(null);
16184
+ setDownloadStates({});
15342
16185
  setDetailLoading(true);
15343
16186
  setDetailError(null);
15344
16187
  setNotice(null);
@@ -15418,6 +16261,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15418
16261
  showNotice(result.value.updated > 0 ? "已标为已读。" : "该邮件已经是已读状态。");
15419
16262
  };
15420
16263
  const requestSend = () => {
16264
+ if (attachmentError !== null) {
16265
+ setComposeError(attachmentError);
16266
+ return;
16267
+ }
16268
+ if (attachments.length > 0 && attachmentLimits === null) {
16269
+ setComposeError("邮件附件限制暂不可用,请稍后刷新邮箱再试。");
16270
+ return;
16271
+ }
15421
16272
  const validated = validateDraft$1(to, cc, subject, bodyText);
15422
16273
  if (!validated.ok) {
15423
16274
  setComposeError(validated.error);
@@ -15431,6 +16282,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15431
16282
  setCc("");
15432
16283
  setSubject("");
15433
16284
  setBodyText("");
16285
+ setAttachments(EMPTY_MAIL_ATTACHMENTS);
16286
+ setAttachmentError(null);
16287
+ if (fileInput.current !== null) fileInput.current.value = "";
16288
+ setComposeError(null);
16289
+ };
16290
+ const chooseAttachments = (files) => {
16291
+ if (files === null || files.length === 0) return;
16292
+ if (attachmentLimits === null) {
16293
+ setAttachmentError("邮件附件限制暂不可用,请稍后刷新邮箱再试。");
16294
+ return;
16295
+ }
16296
+ try {
16297
+ const next = selectMailAttachments(attachments, files, attachmentLimits, () => crypto.randomUUID());
16298
+ setAttachments(next);
16299
+ setAttachmentError(null);
16300
+ setComposeError(null);
16301
+ } catch (error) {
16302
+ setAttachmentError(error instanceof TypeError ? error.message : "无法选择这些附件。");
16303
+ }
16304
+ };
16305
+ const removeAttachment = (id) => {
16306
+ setAttachments((current) => {
16307
+ const next = current.filter((attachment) => attachment.id !== id);
16308
+ return next.length === 0 ? EMPTY_MAIL_ATTACHMENTS : next;
16309
+ });
16310
+ setAttachmentError(null);
15434
16311
  setComposeError(null);
15435
16312
  };
15436
16313
  const confirmSend = async () => {
@@ -15440,15 +16317,36 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15440
16317
  setComposeError(validated.error);
15441
16318
  return;
15442
16319
  }
16320
+ if (attachmentError !== null || attachments.length > 0 && attachmentLimits === null) {
16321
+ setConfirmOpen(false);
16322
+ setComposeError(attachmentError ?? "邮件附件限制暂不可用,请稍后刷新邮箱再试。");
16323
+ return;
16324
+ }
16325
+ const generation = detailGeneration.current;
15443
16326
  setSending(true);
16327
+ let encodedAttachments = [];
16328
+ try {
16329
+ if (attachments.length > 0) encodedAttachments = await encodeMailAttachments(attachments, attachmentLimits);
16330
+ } catch (error) {
16331
+ setSending(false);
16332
+ setConfirmOpen(false);
16333
+ setComposeError(error instanceof TypeError ? error.message : "无法读取附件,请重新选择后再试。");
16334
+ return;
16335
+ }
16336
+ if (generation !== detailGeneration.current) {
16337
+ setSending(false);
16338
+ return;
16339
+ }
15444
16340
  const request = {
15445
16341
  to: validated.value.to,
15446
16342
  cc: validated.value.cc,
15447
16343
  subject: validated.value.subject,
15448
- bodyText: validated.value.bodyText
16344
+ bodyText: validated.value.bodyText,
16345
+ ...encodedAttachments.length === 0 ? {} : { attachments: encodedAttachments }
15449
16346
  };
15450
16347
  const result = await props.sendMail(request);
15451
16348
  setSending(false);
16349
+ if (generation !== detailGeneration.current) return;
15452
16350
  setConfirmOpen(false);
15453
16351
  if (!result.ok) {
15454
16352
  setComposeError(result.error);
@@ -15458,7 +16356,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15458
16356
  setComposeError("邮件服务没有接受本次发送,请检查内容后重试。");
15459
16357
  return;
15460
16358
  }
15461
- const warningText = result.value.warnings.length === 0 ? "" : `,服务返回 ${result.value.warnings.length} 条提示`;
16359
+ const acceptedWithWarning = result.value.warnings.length > 0;
15462
16360
  clearDraft();
15463
16361
  setFolder("sent");
15464
16362
  const storage = browserLocalStorage();
@@ -15471,9 +16369,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15471
16369
  setCompose(false);
15472
16370
  setPane("list");
15473
16371
  refresh("sent");
15474
- showNotice(`邮件已发送${warningText}。`);
16372
+ showNotice(acceptedWithWarning ? `邮件已被服务接受,但返回 ${result.value.warnings.length} 条本地记录提示,请勿立即重复发送。` : "邮件已发送。");
15475
16373
  };
15476
- const dirty = to.trim() !== "" || cc.trim() !== "" || subject.trim() !== "" || bodyText.trim() !== "";
16374
+ const dirty = to.trim() !== "" || cc.trim() !== "" || subject.trim() !== "" || bodyText.trim() !== "" || attachments.length > 0;
15477
16375
  const cancelCompose = () => {
15478
16376
  if (dirty) {
15479
16377
  setDiscardOpen(true);
@@ -15483,6 +16381,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15483
16381
  setPane("list");
15484
16382
  };
15485
16383
  const selectedSummary = items.find((item) => item.id === selectedId);
16384
+ const attachmentTotalBytes = attachments.reduce((sum, attachment) => sum + attachment.sizeBytes, 0);
16385
+ const downloadAttachment = async (attachment) => {
16386
+ if (message === null || attachmentLimits === null) return;
16387
+ const expected = downloadableMailAttachment(attachment, downloadMaxBytes);
16388
+ if (expected === void 0 || downloadStates[attachment.index]?.status === "loading") return;
16389
+ const generation = detailGeneration.current;
16390
+ const localMessageId = message.summary.id;
16391
+ setDownloadStates((current) => ({
16392
+ ...current,
16393
+ [attachment.index]: { status: "loading" }
16394
+ }));
16395
+ try {
16396
+ if (!await downloadAndSaveMailAttachment(props.downloadMailAttachment, {
16397
+ localMessageId,
16398
+ attachmentIndex: attachment.index
16399
+ }, expected, downloadMaxBytes, () => generation === detailGeneration.current && message.summary.id === localMessageId)) return;
16400
+ setDownloadStates((current) => {
16401
+ const next = { ...current };
16402
+ delete next[attachment.index];
16403
+ return next;
16404
+ });
16405
+ showNotice(`已开始下载 ${expected.fileName}。`);
16406
+ } catch (error) {
16407
+ if (generation !== detailGeneration.current || message.summary.id !== localMessageId) return;
16408
+ setDownloadStates((current) => ({
16409
+ ...current,
16410
+ [attachment.index]: {
16411
+ status: "error",
16412
+ error: error instanceof TypeError ? error.message : "无法保存附件,请重试。"
16413
+ }
16414
+ }));
16415
+ }
16416
+ };
15486
16417
  return (0, react_jsx_runtime.jsxs)("div", {
15487
16418
  className: _dsh_awiki_css_AwikiMail_module_css_default.mail,
15488
16419
  "data-pane": pane,
@@ -15548,19 +16479,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15548
16479
  children: [
15549
16480
  (0, react_jsx_runtime.jsxs)("header", {
15550
16481
  className: _dsh_awiki_css_AwikiMail_module_css_default.listHeader,
15551
- children: [(0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("strong", { children: MAIL_FOLDER_COPY[folder].title }), (0, react_jsx_runtime.jsxs)("small", { children: [
15552
- items.length,
15553
- " 封邮件",
15554
- folder === "inbox" && visibleUnreadCount > 0 ? ` · ${visibleUnreadCount} 封未读` : ""
15555
- ] })] }), (0, react_jsx_runtime.jsx)("button", {
15556
- type: "button",
15557
- "aria-label": `刷新${MAIL_FOLDER_COPY[folder].title}`,
15558
- disabled: listLoading,
15559
- onClick: () => {
15560
- refresh();
15561
- },
15562
- children: listLoading ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLoadingOutline16, { size: 15 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline14, { size: 15 })
15563
- })]
16482
+ children: [
16483
+ (0, react_jsx_runtime.jsx)("button", {
16484
+ type: "button",
16485
+ className: _dsh_awiki_css_AwikiMail_module_css_default.listBack,
16486
+ "aria-label": "返回邮箱导航",
16487
+ onClick: () => {
16488
+ setPane("folders");
16489
+ },
16490
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutline14, { size: 14 })
16491
+ }),
16492
+ (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("strong", { children: MAIL_FOLDER_COPY[folder].title }), (0, react_jsx_runtime.jsxs)("small", { children: [
16493
+ items.length,
16494
+ " 封邮件",
16495
+ folder === "inbox" && visibleUnreadCount > 0 ? ` · ${visibleUnreadCount} 封未读` : ""
16496
+ ] })] }),
16497
+ (0, react_jsx_runtime.jsx)("button", {
16498
+ type: "button",
16499
+ "aria-label": `刷新${MAIL_FOLDER_COPY[folder].title}`,
16500
+ disabled: listLoading,
16501
+ onClick: () => {
16502
+ refresh();
16503
+ },
16504
+ children: listLoading ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLoadingOutline16, { size: 15 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline14, { size: 15 })
16505
+ })
16506
+ ]
15564
16507
  }),
15565
16508
  listError !== null && (0, react_jsx_runtime.jsxs)("div", {
15566
16509
  className: _dsh_awiki_css_AwikiMail_module_css_default.inlineError,
@@ -15621,7 +16564,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15621
16564
  "aria-label": `返回${MAIL_FOLDER_COPY[folder].title}`,
15622
16565
  onClick: cancelCompose,
15623
16566
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutline14, { size: 14 })
15624
- }), (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("strong", { children: "写邮件" }), (0, react_jsx_runtime.jsx)("small", { children: "发送纯文本邮件" })] })]
16567
+ }), (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("strong", { children: "写邮件" }), (0, react_jsx_runtime.jsx)("small", { children: "发送纯文本邮件,可添加附件" })] })]
15625
16568
  }),
15626
16569
  (0, react_jsx_runtime.jsxs)("div", {
15627
16570
  className: _dsh_awiki_css_AwikiMail_module_css_default.composeFields,
@@ -15629,6 +16572,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15629
16572
  (0, react_jsx_runtime.jsxs)("label", { children: ["收件人", (0, react_jsx_runtime.jsx)("textarea", {
15630
16573
  value: to,
15631
16574
  rows: 1,
16575
+ disabled: sending,
15632
16576
  autoFocus: true,
15633
16577
  placeholder: "alice@example.com,可用逗号或换行分隔",
15634
16578
  onChange: (event) => {
@@ -15639,6 +16583,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15639
16583
  (0, react_jsx_runtime.jsxs)("label", { children: ["抄送", (0, react_jsx_runtime.jsx)("textarea", {
15640
16584
  value: cc,
15641
16585
  rows: 1,
16586
+ disabled: sending,
15642
16587
  placeholder: "选填",
15643
16588
  onChange: (event) => {
15644
16589
  setCc(event.target.value);
@@ -15647,6 +16592,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15647
16592
  })] }),
15648
16593
  (0, react_jsx_runtime.jsxs)("label", { children: ["主题", (0, react_jsx_runtime.jsx)("input", {
15649
16594
  value: subject,
16595
+ disabled: sending,
15650
16596
  placeholder: "邮件主题",
15651
16597
  onChange: (event) => {
15652
16598
  setSubject(event.target.value);
@@ -15657,6 +16603,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15657
16603
  className: _dsh_awiki_css_AwikiMail_module_css_default.bodyField,
15658
16604
  children: ["正文", (0, react_jsx_runtime.jsx)("textarea", {
15659
16605
  value: bodyText,
16606
+ disabled: sending,
15660
16607
  placeholder: "输入纯文本邮件正文",
15661
16608
  onChange: (event) => {
15662
16609
  setBodyText(event.target.value);
@@ -15664,6 +16611,54 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15664
16611
  }
15665
16612
  })]
15666
16613
  }),
16614
+ (0, react_jsx_runtime.jsxs)("section", {
16615
+ className: _dsh_awiki_css_AwikiMail_module_css_default.composeAttachments,
16616
+ "aria-label": "邮件附件",
16617
+ children: [(0, react_jsx_runtime.jsxs)("div", {
16618
+ className: _dsh_awiki_css_AwikiMail_module_css_default.attachmentPickerRow,
16619
+ children: [(0, react_jsx_runtime.jsxs)("label", {
16620
+ className: _dsh_awiki_css_AwikiMail_module_css_default.attachmentPicker,
16621
+ children: ["添加附件", (0, react_jsx_runtime.jsx)("input", {
16622
+ ref: fileInput,
16623
+ type: "file",
16624
+ multiple: true,
16625
+ disabled: sending || attachmentLimits === null || attachmentLimits.maxCount === 0,
16626
+ onChange: (event) => {
16627
+ chooseAttachments(event.currentTarget.files);
16628
+ event.currentTarget.value = "";
16629
+ }
16630
+ })]
16631
+ }), (0, react_jsx_runtime.jsx)("small", { children: attachmentLimits === null ? "附件限制暂不可用" : `最多 ${attachmentLimits.maxCount} 个 · 单个 ${displayBytes(attachmentLimits.maxBytes)} · 总计 ${displayBytes(attachmentLimits.totalMaxBytes)}` })]
16632
+ }), attachments.length > 0 && (0, react_jsx_runtime.jsxs)("div", {
16633
+ className: _dsh_awiki_css_AwikiMail_module_css_default.selectedAttachments,
16634
+ children: [attachments.map((attachment) => (0, react_jsx_runtime.jsxs)("div", { children: [
16635
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, { size: 15 }),
16636
+ (0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("strong", { children: attachment.fileName }), (0, react_jsx_runtime.jsxs)("small", { children: [
16637
+ attachment.contentType,
16638
+ " · ",
16639
+ displayBytes(attachment.sizeBytes)
16640
+ ] })] }),
16641
+ (0, react_jsx_runtime.jsx)("button", {
16642
+ type: "button",
16643
+ disabled: sending,
16644
+ "aria-label": `移除附件 ${attachment.fileName}`,
16645
+ onClick: () => {
16646
+ removeAttachment(attachment.id);
16647
+ },
16648
+ children: "移除"
16649
+ })
16650
+ ] }, attachment.id)), (0, react_jsx_runtime.jsxs)("p", { children: [
16651
+ attachments.length,
16652
+ " 个附件 · 共 ",
16653
+ displayBytes(attachmentTotalBytes)
16654
+ ] })]
16655
+ })]
16656
+ }),
16657
+ attachmentError !== null && (0, react_jsx_runtime.jsx)("p", {
16658
+ className: _dsh_awiki_css_AwikiMail_module_css_default.composeError,
16659
+ role: "alert",
16660
+ children: attachmentError
16661
+ }),
15667
16662
  composeError !== null && (0, react_jsx_runtime.jsx)("p", {
15668
16663
  className: _dsh_awiki_css_AwikiMail_module_css_default.composeError,
15669
16664
  role: "alert",
@@ -15682,7 +16677,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15682
16677
  }), (0, react_jsx_runtime.jsxs)("button", {
15683
16678
  type: "submit",
15684
16679
  className: _dsh_awiki_css_AwikiMail_module_css_default.sendButton,
15685
- disabled: sending,
16680
+ disabled: sending || attachmentError !== null,
15686
16681
  children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSendOutline16, { size: 15 }), "发送"]
15687
16682
  })]
15688
16683
  })
@@ -15707,8 +16702,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15707
16702
  className: _dsh_awiki_css_AwikiMail_module_css_default.detailBack,
15708
16703
  "aria-label": `返回${MAIL_FOLDER_COPY[folder].title}`,
15709
16704
  onClick: () => {
16705
+ detailGeneration.current += 1;
15710
16706
  setSelectedId(null);
15711
16707
  setMessage(null);
16708
+ setDownloadStates({});
15712
16709
  setPane("list");
15713
16710
  },
15714
16711
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutline14, { size: 14 })
@@ -15764,8 +16761,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15764
16761
  }),
15765
16762
  message.attachments.length > 0 && (0, react_jsx_runtime.jsxs)("section", {
15766
16763
  className: _dsh_awiki_css_AwikiMail_module_css_default.attachments,
15767
- "aria-label": "附件元数据",
15768
- children: [(0, react_jsx_runtime.jsx)("h4", { children: "附件(仅元数据)" }), message.attachments.map((attachment) => (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, { size: 15 }), (0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("strong", { children: attachment.fileName ?? `附件 ${attachment.index + 1}` }), (0, react_jsx_runtime.jsx)("small", { children: [attachment.contentType, attachment.sizeBytes === void 0 ? void 0 : `${attachment.sizeBytes} bytes`].filter(Boolean).join(" · ") || "暂无更多信息" })] })] }, attachment.index))]
16764
+ "aria-label": "邮件附件",
16765
+ children: [(0, react_jsx_runtime.jsx)("h4", { children: "附件" }), message.attachments.map((attachment) => {
16766
+ const downloadable = attachmentLimits === null ? void 0 : downloadableMailAttachment(attachment, downloadMaxBytes);
16767
+ const state = downloadStates[attachment.index];
16768
+ return (0, react_jsx_runtime.jsxs)("div", { children: [
16769
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, { size: 15 }),
16770
+ (0, react_jsx_runtime.jsxs)("span", { children: [
16771
+ (0, react_jsx_runtime.jsx)("strong", { children: attachment.fileName ?? `附件 ${attachment.index + 1}` }),
16772
+ (0, react_jsx_runtime.jsx)("small", { children: [attachment.contentType, attachment.sizeBytes === void 0 ? void 0 : `${attachment.sizeBytes} bytes`].filter(Boolean).join(" · ") || "暂无更多信息" }),
16773
+ downloadable === void 0 && (0, react_jsx_runtime.jsx)("small", { children: "当前记录缺少完整、可验证的下载元数据。" }),
16774
+ state?.status === "error" && (0, react_jsx_runtime.jsx)("small", {
16775
+ className: _dsh_awiki_css_AwikiMail_module_css_default.attachmentDownloadError,
16776
+ role: "alert",
16777
+ children: state.error
16778
+ })
16779
+ ] }),
16780
+ downloadable !== void 0 && (0, react_jsx_runtime.jsx)("button", {
16781
+ type: "button",
16782
+ disabled: state?.status === "loading",
16783
+ "aria-label": `${state?.status === "error" ? "重试下载" : "下载附件"} ${downloadable.fileName}`,
16784
+ onClick: () => {
16785
+ downloadAttachment(attachment);
16786
+ },
16787
+ children: state?.status === "loading" ? "下载中…" : state?.status === "error" ? "重试" : "下载"
16788
+ })
16789
+ ] }, attachment.index);
16790
+ })]
15769
16791
  })
15770
16792
  ]
15771
16793
  })
@@ -15818,7 +16840,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15818
16840
  splitAddresses(cc).length,
15819
16841
  " 人"
15820
16842
  ] }),
15821
- (0, react_jsx_runtime.jsxs)("p", { children: ["主题:", subject.trim()] })
16843
+ (0, react_jsx_runtime.jsxs)("p", { children: ["主题:", subject.trim()] }),
16844
+ (0, react_jsx_runtime.jsxs)("p", { children: [
16845
+ "附件:",
16846
+ attachments.length,
16847
+ " 个 · 共 ",
16848
+ displayBytes(attachmentTotalBytes)
16849
+ ] }),
16850
+ attachments.map((attachment) => (0, react_jsx_runtime.jsxs)("p", { children: [
16851
+ attachment.fileName,
16852
+ " · ",
16853
+ attachment.contentType,
16854
+ " · ",
16855
+ displayBytes(attachment.sizeBytes)
16856
+ ] }, attachment.id))
15822
16857
  ]
15823
16858
  })
15824
16859
  }),
@@ -15829,7 +16864,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15829
16864
  },
15830
16865
  title: "放弃这封邮件?",
15831
16866
  closeLabel: "继续编辑",
15832
- description: "放弃后当前内容将被清空。关闭面板会暂存内容,退出应用不会保存。",
16867
+ description: "放弃后当前文字和附件选择将被清空。关闭面板会暂存内容,退出应用不会保存。",
15833
16868
  footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
15834
16869
  type: "button",
15835
16870
  variant: "outline",
@@ -15850,7 +16885,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15850
16885
  })] }),
15851
16886
  children: (0, react_jsx_runtime.jsx)("p", {
15852
16887
  className: _dsh_awiki_css_AwikiMail_module_css_default.discardText,
15853
- children: "收件人、主题和正文中的未发送内容都会丢失。"
16888
+ children: "收件人、主题、正文和已选择的附件都会丢失。"
15854
16889
  })
15855
16890
  })
15856
16891
  ]
@@ -19379,15 +20414,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19379
20414
  className: _dsh_awiki_css_AwikiOverlay_module_css_default.identityAccess,
19380
20415
  children: (0, react_jsx_runtime.jsx)(AwikiIdentityAccess, {
19381
20416
  ...props,
19382
- sessionStatus: view.sessionStatus === "active" ? "recovery-required" : view.sessionStatus,
20417
+ sessionStatus: view.sessionStatus,
19383
20418
  access: view.identityAccess,
19384
20419
  accessLoading: view.accessLoading,
19385
20420
  accessError: view.accessError,
19386
20421
  identity: view.identity,
19387
20422
  recoveryOperationId: view.recoveryOperationId,
19388
20423
  recoveryProgress: view.recoveryProgress,
19389
- pending: view.pending !== null,
19390
- handleRecoveryPhoneEnabled: view.handleRecoveryPhoneEnabled
20424
+ recoveryOtpRetryAt: view.recoveryOtpRetryAt,
20425
+ pending: view.pending !== null
19391
20426
  })
19392
20427
  }),
19393
20428
  view.status === "ready" && view.sessionStatus === "active" && view.identity !== null && view.recoveryOperationId === null && view.identityAccess !== null && view.accessError === null && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {
@@ -19466,12 +20501,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19466
20501
  onChange: setMode
19467
20502
  }),
19468
20503
  onUnreadCountChange: setMailUnreadCount,
20504
+ getConfig: props.getConfig,
19469
20505
  getMailAccount: props.getMailAccount,
19470
20506
  listMailInbox: props.listMailInbox,
19471
20507
  readMail: props.readMail,
19472
20508
  markMailRead: props.markMailRead,
19473
- sendMail: props.sendMail
19474
- }, view.identity.did)
20509
+ sendMail: props.sendMail,
20510
+ downloadMailAttachment: props.downloadMailAttachment
20511
+ }, `${props.drafts?.getScope("mail:attachments") ?? ""}:${view.identity.did}`)
19475
20512
  })] }),
19476
20513
  composeDirect && (0, react_jsx_runtime.jsx)("div", {
19477
20514
  className: _dsh_awiki_css_AwikiOverlay_module_css_default.composeBackdrop,
@@ -19912,7 +20949,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19912
20949
  }),
19913
20950
  (0, react_jsx_runtime.jsx)("p", {
19914
20951
  className: _dsh_awiki_css_AwikiSettingsSection_module_css_default.description,
19915
- children: t("updateCurrent", { version: update?.currentPluginVersion ?? "0.3.10" })
20952
+ children: t("updateCurrent", { version: update?.currentPluginVersion ?? "0.3.11-rc.2" })
19916
20953
  }),
19917
20954
  update !== void 0 && (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: update.currentModelProxyVersion !== void 0 && (0, react_jsx_runtime.jsx)("p", {
19918
20955
  className: _dsh_awiki_css_AwikiSettingsSection_module_css_default.description,
@@ -20847,6 +21884,752 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20847
21884
  ]) target.removeItem(key(kind));
20848
21885
  }
20849
21886
  //#endregion
21887
+ //#region node_modules/.pnpm/zustand@4.4.7_@types+react@18.3.31_immer@10.2.0_react@18.3.1/node_modules/zustand/esm/vanilla.mjs
21888
+ const createStoreImpl = (createState) => {
21889
+ let state;
21890
+ const listeners = /* @__PURE__ */ new Set();
21891
+ const setState = (partial, replace) => {
21892
+ const nextState = typeof partial === "function" ? partial(state) : partial;
21893
+ if (!Object.is(nextState, state)) {
21894
+ const previousState = state;
21895
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
21896
+ listeners.forEach((listener) => listener(state, previousState));
21897
+ }
21898
+ };
21899
+ const getState = () => state;
21900
+ const subscribe = (listener) => {
21901
+ listeners.add(listener);
21902
+ return () => listeners.delete(listener);
21903
+ };
21904
+ const destroy = () => {
21905
+ listeners.clear();
21906
+ };
21907
+ const api = {
21908
+ setState,
21909
+ getState,
21910
+ subscribe,
21911
+ destroy
21912
+ };
21913
+ state = createState(setState, getState, api);
21914
+ return api;
21915
+ };
21916
+ const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
21917
+ //#endregion
21918
+ //#region node_modules/.pnpm/zustand@4.4.7_@types+react@18.3.31_immer@10.2.0_react@18.3.1/node_modules/zustand/esm/middleware.mjs
21919
+ const subscribeWithSelectorImpl = (fn) => (set, get, api) => {
21920
+ const origSubscribe = api.subscribe;
21921
+ api.subscribe = (selector, optListener, options) => {
21922
+ let listener = selector;
21923
+ if (optListener) {
21924
+ const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;
21925
+ let currentSlice = selector(api.getState());
21926
+ listener = (state) => {
21927
+ const nextSlice = selector(state);
21928
+ if (!equalityFn(currentSlice, nextSlice)) {
21929
+ const previousSlice = currentSlice;
21930
+ optListener(currentSlice = nextSlice, previousSlice);
21931
+ }
21932
+ };
21933
+ if (options == null ? void 0 : options.fireImmediately) optListener(currentSlice, currentSlice);
21934
+ }
21935
+ return origSubscribe(listener);
21936
+ };
21937
+ return fn(set, get, api);
21938
+ };
21939
+ const subscribeWithSelector = subscribeWithSelectorImpl;
21940
+ //#endregion
21941
+ //#region node_modules/.pnpm/immer@10.2.0/node_modules/immer/dist/immer.mjs
21942
+ var NOTHING = Symbol.for("immer-nothing");
21943
+ var DRAFTABLE = Symbol.for("immer-draftable");
21944
+ var DRAFT_STATE = Symbol.for("immer-state");
21945
+ function die(error, ...args) {
21946
+ throw new Error(`[Immer] minified error nr: ${error}. Full error at: https://bit.ly/3cXEKWf`);
21947
+ }
21948
+ var getPrototypeOf = Object.getPrototypeOf;
21949
+ function isDraft(value) {
21950
+ return !!value && !!value[DRAFT_STATE];
21951
+ }
21952
+ function isDraftable(value) {
21953
+ if (!value) return false;
21954
+ return isPlainObject(value) || Array.isArray(value) || !!value[DRAFTABLE] || !!value.constructor?.[DRAFTABLE] || isMap(value) || isSet(value);
21955
+ }
21956
+ var objectCtorString = Object.prototype.constructor.toString();
21957
+ var cachedCtorStrings = /* @__PURE__ */ new WeakMap();
21958
+ function isPlainObject(value) {
21959
+ if (!value || typeof value !== "object") return false;
21960
+ const proto = Object.getPrototypeOf(value);
21961
+ if (proto === null || proto === Object.prototype) return true;
21962
+ const Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
21963
+ if (Ctor === Object) return true;
21964
+ if (typeof Ctor !== "function") return false;
21965
+ let ctorString = cachedCtorStrings.get(Ctor);
21966
+ if (ctorString === void 0) {
21967
+ ctorString = Function.toString.call(Ctor);
21968
+ cachedCtorStrings.set(Ctor, ctorString);
21969
+ }
21970
+ return ctorString === objectCtorString;
21971
+ }
21972
+ function each(obj, iter, strict = true) {
21973
+ if (getArchtype(obj) === 0) (strict ? Reflect.ownKeys(obj) : Object.keys(obj)).forEach((key) => {
21974
+ iter(key, obj[key], obj);
21975
+ });
21976
+ else obj.forEach((entry, index) => iter(index, entry, obj));
21977
+ }
21978
+ function getArchtype(thing) {
21979
+ const state = thing[DRAFT_STATE];
21980
+ return state ? state.type_ : Array.isArray(thing) ? 1 : isMap(thing) ? 2 : isSet(thing) ? 3 : 0;
21981
+ }
21982
+ function has(thing, prop) {
21983
+ return getArchtype(thing) === 2 ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
21984
+ }
21985
+ function set(thing, propOrOldValue, value) {
21986
+ const t = getArchtype(thing);
21987
+ if (t === 2) thing.set(propOrOldValue, value);
21988
+ else if (t === 3) thing.add(value);
21989
+ else thing[propOrOldValue] = value;
21990
+ }
21991
+ function is(x, y) {
21992
+ if (x === y) return x !== 0 || 1 / x === 1 / y;
21993
+ else return x !== x && y !== y;
21994
+ }
21995
+ function isMap(target) {
21996
+ return target instanceof Map;
21997
+ }
21998
+ function isSet(target) {
21999
+ return target instanceof Set;
22000
+ }
22001
+ function latest(state) {
22002
+ return state.copy_ || state.base_;
22003
+ }
22004
+ function shallowCopy(base, strict) {
22005
+ if (isMap(base)) return new Map(base);
22006
+ if (isSet(base)) return new Set(base);
22007
+ if (Array.isArray(base)) return Array.prototype.slice.call(base);
22008
+ const isPlain = isPlainObject(base);
22009
+ if (strict === true || strict === "class_only" && !isPlain) {
22010
+ const descriptors = Object.getOwnPropertyDescriptors(base);
22011
+ delete descriptors[DRAFT_STATE];
22012
+ let keys = Reflect.ownKeys(descriptors);
22013
+ for (let i = 0; i < keys.length; i++) {
22014
+ const key = keys[i];
22015
+ const desc = descriptors[key];
22016
+ if (desc.writable === false) {
22017
+ desc.writable = true;
22018
+ desc.configurable = true;
22019
+ }
22020
+ if (desc.get || desc.set) descriptors[key] = {
22021
+ configurable: true,
22022
+ writable: true,
22023
+ enumerable: desc.enumerable,
22024
+ value: base[key]
22025
+ };
22026
+ }
22027
+ return Object.create(getPrototypeOf(base), descriptors);
22028
+ } else {
22029
+ const proto = getPrototypeOf(base);
22030
+ if (proto !== null && isPlain) return { ...base };
22031
+ const obj = Object.create(proto);
22032
+ return Object.assign(obj, base);
22033
+ }
22034
+ }
22035
+ function freeze(obj, deep = false) {
22036
+ if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj)) return obj;
22037
+ if (getArchtype(obj) > 1) Object.defineProperties(obj, {
22038
+ set: dontMutateMethodOverride,
22039
+ add: dontMutateMethodOverride,
22040
+ clear: dontMutateMethodOverride,
22041
+ delete: dontMutateMethodOverride
22042
+ });
22043
+ Object.freeze(obj);
22044
+ if (deep) Object.values(obj).forEach((value) => freeze(value, true));
22045
+ return obj;
22046
+ }
22047
+ function dontMutateFrozenCollections() {
22048
+ die(2);
22049
+ }
22050
+ var dontMutateMethodOverride = { value: dontMutateFrozenCollections };
22051
+ function isFrozen(obj) {
22052
+ if (obj === null || typeof obj !== "object") return true;
22053
+ return Object.isFrozen(obj);
22054
+ }
22055
+ var plugins = {};
22056
+ function getPlugin(pluginKey) {
22057
+ const plugin = plugins[pluginKey];
22058
+ if (!plugin) die(0, pluginKey);
22059
+ return plugin;
22060
+ }
22061
+ var currentScope;
22062
+ function getCurrentScope() {
22063
+ return currentScope;
22064
+ }
22065
+ function createScope(parent_, immer_) {
22066
+ return {
22067
+ drafts_: [],
22068
+ parent_,
22069
+ immer_,
22070
+ canAutoFreeze_: true,
22071
+ unfinalizedDrafts_: 0
22072
+ };
22073
+ }
22074
+ function usePatchesInScope(scope, patchListener) {
22075
+ if (patchListener) {
22076
+ getPlugin("Patches");
22077
+ scope.patches_ = [];
22078
+ scope.inversePatches_ = [];
22079
+ scope.patchListener_ = patchListener;
22080
+ }
22081
+ }
22082
+ function revokeScope(scope) {
22083
+ leaveScope(scope);
22084
+ scope.drafts_.forEach(revokeDraft);
22085
+ scope.drafts_ = null;
22086
+ }
22087
+ function leaveScope(scope) {
22088
+ if (scope === currentScope) currentScope = scope.parent_;
22089
+ }
22090
+ function enterScope(immer2) {
22091
+ return currentScope = createScope(currentScope, immer2);
22092
+ }
22093
+ function revokeDraft(draft) {
22094
+ const state = draft[DRAFT_STATE];
22095
+ if (state.type_ === 0 || state.type_ === 1) state.revoke_();
22096
+ else state.revoked_ = true;
22097
+ }
22098
+ function processResult(result, scope) {
22099
+ scope.unfinalizedDrafts_ = scope.drafts_.length;
22100
+ const baseDraft = scope.drafts_[0];
22101
+ if (result !== void 0 && result !== baseDraft) {
22102
+ if (baseDraft[DRAFT_STATE].modified_) {
22103
+ revokeScope(scope);
22104
+ die(4);
22105
+ }
22106
+ if (isDraftable(result)) {
22107
+ result = finalize(scope, result);
22108
+ if (!scope.parent_) maybeFreeze(scope, result);
22109
+ }
22110
+ if (scope.patches_) getPlugin("Patches").generateReplacementPatches_(baseDraft[DRAFT_STATE].base_, result, scope.patches_, scope.inversePatches_);
22111
+ } else result = finalize(scope, baseDraft, []);
22112
+ revokeScope(scope);
22113
+ if (scope.patches_) scope.patchListener_(scope.patches_, scope.inversePatches_);
22114
+ return result !== NOTHING ? result : void 0;
22115
+ }
22116
+ function finalize(rootScope, value, path) {
22117
+ if (isFrozen(value)) return value;
22118
+ const useStrictIteration = rootScope.immer_.shouldUseStrictIteration();
22119
+ const state = value[DRAFT_STATE];
22120
+ if (!state) {
22121
+ each(value, (key, childValue) => finalizeProperty(rootScope, state, value, key, childValue, path), useStrictIteration);
22122
+ return value;
22123
+ }
22124
+ if (state.scope_ !== rootScope) return value;
22125
+ if (!state.modified_) {
22126
+ maybeFreeze(rootScope, state.base_, true);
22127
+ return state.base_;
22128
+ }
22129
+ if (!state.finalized_) {
22130
+ state.finalized_ = true;
22131
+ state.scope_.unfinalizedDrafts_--;
22132
+ const result = state.copy_;
22133
+ let resultEach = result;
22134
+ let isSet2 = false;
22135
+ if (state.type_ === 3) {
22136
+ resultEach = new Set(result);
22137
+ result.clear();
22138
+ isSet2 = true;
22139
+ }
22140
+ each(resultEach, (key, childValue) => finalizeProperty(rootScope, state, result, key, childValue, path, isSet2), useStrictIteration);
22141
+ maybeFreeze(rootScope, result, false);
22142
+ if (path && rootScope.patches_) getPlugin("Patches").generatePatches_(state, path, rootScope.patches_, rootScope.inversePatches_);
22143
+ }
22144
+ return state.copy_;
22145
+ }
22146
+ function finalizeProperty(rootScope, parentState, targetObject, prop, childValue, rootPath, targetIsSet) {
22147
+ if (childValue == null) return;
22148
+ if (typeof childValue !== "object" && !targetIsSet) return;
22149
+ const childIsFrozen = isFrozen(childValue);
22150
+ if (childIsFrozen && !targetIsSet) return;
22151
+ if (isDraft(childValue)) {
22152
+ const res = finalize(rootScope, childValue, rootPath && parentState && parentState.type_ !== 3 && !has(parentState.assigned_, prop) ? rootPath.concat(prop) : void 0);
22153
+ set(targetObject, prop, res);
22154
+ if (isDraft(res)) rootScope.canAutoFreeze_ = false;
22155
+ else return;
22156
+ } else if (targetIsSet) targetObject.add(childValue);
22157
+ if (isDraftable(childValue) && !childIsFrozen) {
22158
+ if (!rootScope.immer_.autoFreeze_ && rootScope.unfinalizedDrafts_ < 1) return;
22159
+ if (parentState && parentState.base_ && parentState.base_[prop] === childValue && childIsFrozen) return;
22160
+ finalize(rootScope, childValue);
22161
+ if ((!parentState || !parentState.scope_.parent_) && typeof prop !== "symbol" && (isMap(targetObject) ? targetObject.has(prop) : Object.prototype.propertyIsEnumerable.call(targetObject, prop))) maybeFreeze(rootScope, childValue);
22162
+ }
22163
+ }
22164
+ function maybeFreeze(scope, value, deep = false) {
22165
+ if (!scope.parent_ && scope.immer_.autoFreeze_ && scope.canAutoFreeze_) freeze(value, deep);
22166
+ }
22167
+ function createProxyProxy(base, parent) {
22168
+ const isArray = Array.isArray(base);
22169
+ const state = {
22170
+ type_: isArray ? 1 : 0,
22171
+ scope_: parent ? parent.scope_ : getCurrentScope(),
22172
+ modified_: false,
22173
+ finalized_: false,
22174
+ assigned_: {},
22175
+ parent_: parent,
22176
+ base_: base,
22177
+ draft_: null,
22178
+ copy_: null,
22179
+ revoke_: null,
22180
+ isManual_: false
22181
+ };
22182
+ let target = state;
22183
+ let traps = objectTraps;
22184
+ if (isArray) {
22185
+ target = [state];
22186
+ traps = arrayTraps;
22187
+ }
22188
+ const { revoke, proxy } = Proxy.revocable(target, traps);
22189
+ state.draft_ = proxy;
22190
+ state.revoke_ = revoke;
22191
+ return proxy;
22192
+ }
22193
+ var objectTraps = {
22194
+ get(state, prop) {
22195
+ if (prop === DRAFT_STATE) return state;
22196
+ const source = latest(state);
22197
+ if (!has(source, prop)) return readPropFromProto(state, source, prop);
22198
+ const value = source[prop];
22199
+ if (state.finalized_ || !isDraftable(value)) return value;
22200
+ if (value === peek(state.base_, prop)) {
22201
+ prepareCopy(state);
22202
+ return state.copy_[prop] = createProxy(value, state);
22203
+ }
22204
+ return value;
22205
+ },
22206
+ has(state, prop) {
22207
+ return prop in latest(state);
22208
+ },
22209
+ ownKeys(state) {
22210
+ return Reflect.ownKeys(latest(state));
22211
+ },
22212
+ set(state, prop, value) {
22213
+ const desc = getDescriptorFromProto(latest(state), prop);
22214
+ if (desc?.set) {
22215
+ desc.set.call(state.draft_, value);
22216
+ return true;
22217
+ }
22218
+ if (!state.modified_) {
22219
+ const current2 = peek(latest(state), prop);
22220
+ const currentState = current2?.[DRAFT_STATE];
22221
+ if (currentState && currentState.base_ === value) {
22222
+ state.copy_[prop] = value;
22223
+ state.assigned_[prop] = false;
22224
+ return true;
22225
+ }
22226
+ if (is(value, current2) && (value !== void 0 || has(state.base_, prop))) return true;
22227
+ prepareCopy(state);
22228
+ markChanged(state);
22229
+ }
22230
+ if (state.copy_[prop] === value && (value !== void 0 || prop in state.copy_) || Number.isNaN(value) && Number.isNaN(state.copy_[prop])) return true;
22231
+ state.copy_[prop] = value;
22232
+ state.assigned_[prop] = true;
22233
+ return true;
22234
+ },
22235
+ deleteProperty(state, prop) {
22236
+ if (peek(state.base_, prop) !== void 0 || prop in state.base_) {
22237
+ state.assigned_[prop] = false;
22238
+ prepareCopy(state);
22239
+ markChanged(state);
22240
+ } else delete state.assigned_[prop];
22241
+ if (state.copy_) delete state.copy_[prop];
22242
+ return true;
22243
+ },
22244
+ getOwnPropertyDescriptor(state, prop) {
22245
+ const owner = latest(state);
22246
+ const desc = Reflect.getOwnPropertyDescriptor(owner, prop);
22247
+ if (!desc) return desc;
22248
+ return {
22249
+ writable: true,
22250
+ configurable: state.type_ !== 1 || prop !== "length",
22251
+ enumerable: desc.enumerable,
22252
+ value: owner[prop]
22253
+ };
22254
+ },
22255
+ defineProperty() {
22256
+ die(11);
22257
+ },
22258
+ getPrototypeOf(state) {
22259
+ return getPrototypeOf(state.base_);
22260
+ },
22261
+ setPrototypeOf() {
22262
+ die(12);
22263
+ }
22264
+ };
22265
+ var arrayTraps = {};
22266
+ each(objectTraps, (key, fn) => {
22267
+ arrayTraps[key] = function() {
22268
+ arguments[0] = arguments[0][0];
22269
+ return fn.apply(this, arguments);
22270
+ };
22271
+ });
22272
+ arrayTraps.deleteProperty = function(state, prop) {
22273
+ return arrayTraps.set.call(this, state, prop, void 0);
22274
+ };
22275
+ arrayTraps.set = function(state, prop, value) {
22276
+ return objectTraps.set.call(this, state[0], prop, value, state[0]);
22277
+ };
22278
+ function peek(draft, prop) {
22279
+ const state = draft[DRAFT_STATE];
22280
+ return (state ? latest(state) : draft)[prop];
22281
+ }
22282
+ function readPropFromProto(state, source, prop) {
22283
+ const desc = getDescriptorFromProto(source, prop);
22284
+ return desc ? `value` in desc ? desc.value : desc.get?.call(state.draft_) : void 0;
22285
+ }
22286
+ function getDescriptorFromProto(source, prop) {
22287
+ if (!(prop in source)) return void 0;
22288
+ let proto = getPrototypeOf(source);
22289
+ while (proto) {
22290
+ const desc = Object.getOwnPropertyDescriptor(proto, prop);
22291
+ if (desc) return desc;
22292
+ proto = getPrototypeOf(proto);
22293
+ }
22294
+ }
22295
+ function markChanged(state) {
22296
+ if (!state.modified_) {
22297
+ state.modified_ = true;
22298
+ if (state.parent_) markChanged(state.parent_);
22299
+ }
22300
+ }
22301
+ function prepareCopy(state) {
22302
+ if (!state.copy_) state.copy_ = shallowCopy(state.base_, state.scope_.immer_.useStrictShallowCopy_);
22303
+ }
22304
+ var Immer2 = class {
22305
+ constructor(config) {
22306
+ this.autoFreeze_ = true;
22307
+ this.useStrictShallowCopy_ = false;
22308
+ this.useStrictIteration_ = true;
22309
+ /**
22310
+ * The `produce` function takes a value and a "recipe function" (whose
22311
+ * return value often depends on the base state). The recipe function is
22312
+ * free to mutate its first argument however it wants. All mutations are
22313
+ * only ever applied to a __copy__ of the base state.
22314
+ *
22315
+ * Pass only a function to create a "curried producer" which relieves you
22316
+ * from passing the recipe function every time.
22317
+ *
22318
+ * Only plain objects and arrays are made mutable. All other objects are
22319
+ * considered uncopyable.
22320
+ *
22321
+ * Note: This function is __bound__ to its `Immer` instance.
22322
+ *
22323
+ * @param {any} base - the initial state
22324
+ * @param {Function} recipe - function that receives a proxy of the base state as first argument and which can be freely modified
22325
+ * @param {Function} patchListener - optional function that will be called with all the patches produced here
22326
+ * @returns {any} a new state, or the initial state if nothing was modified
22327
+ */
22328
+ this.produce = (base, recipe, patchListener) => {
22329
+ if (typeof base === "function" && typeof recipe !== "function") {
22330
+ const defaultBase = recipe;
22331
+ recipe = base;
22332
+ const self = this;
22333
+ return function curriedProduce(base2 = defaultBase, ...args) {
22334
+ return self.produce(base2, (draft) => recipe.call(this, draft, ...args));
22335
+ };
22336
+ }
22337
+ if (typeof recipe !== "function") die(6);
22338
+ if (patchListener !== void 0 && typeof patchListener !== "function") die(7);
22339
+ let result;
22340
+ if (isDraftable(base)) {
22341
+ const scope = enterScope(this);
22342
+ const proxy = createProxy(base, void 0);
22343
+ let hasError = true;
22344
+ try {
22345
+ result = recipe(proxy);
22346
+ hasError = false;
22347
+ } finally {
22348
+ if (hasError) revokeScope(scope);
22349
+ else leaveScope(scope);
22350
+ }
22351
+ usePatchesInScope(scope, patchListener);
22352
+ return processResult(result, scope);
22353
+ } else if (!base || typeof base !== "object") {
22354
+ result = recipe(base);
22355
+ if (result === void 0) result = base;
22356
+ if (result === NOTHING) result = void 0;
22357
+ if (this.autoFreeze_) freeze(result, true);
22358
+ if (patchListener) {
22359
+ const p = [];
22360
+ const ip = [];
22361
+ getPlugin("Patches").generateReplacementPatches_(base, result, p, ip);
22362
+ patchListener(p, ip);
22363
+ }
22364
+ return result;
22365
+ } else die(1, base);
22366
+ };
22367
+ this.produceWithPatches = (base, recipe) => {
22368
+ if (typeof base === "function") return (state, ...args) => this.produceWithPatches(state, (draft) => base(draft, ...args));
22369
+ let patches, inversePatches;
22370
+ return [
22371
+ this.produce(base, recipe, (p, ip) => {
22372
+ patches = p;
22373
+ inversePatches = ip;
22374
+ }),
22375
+ patches,
22376
+ inversePatches
22377
+ ];
22378
+ };
22379
+ if (typeof config?.autoFreeze === "boolean") this.setAutoFreeze(config.autoFreeze);
22380
+ if (typeof config?.useStrictShallowCopy === "boolean") this.setUseStrictShallowCopy(config.useStrictShallowCopy);
22381
+ if (typeof config?.useStrictIteration === "boolean") this.setUseStrictIteration(config.useStrictIteration);
22382
+ }
22383
+ createDraft(base) {
22384
+ if (!isDraftable(base)) die(8);
22385
+ if (isDraft(base)) base = current(base);
22386
+ const scope = enterScope(this);
22387
+ const proxy = createProxy(base, void 0);
22388
+ proxy[DRAFT_STATE].isManual_ = true;
22389
+ leaveScope(scope);
22390
+ return proxy;
22391
+ }
22392
+ finishDraft(draft, patchListener) {
22393
+ const state = draft && draft[DRAFT_STATE];
22394
+ if (!state || !state.isManual_) die(9);
22395
+ const { scope_: scope } = state;
22396
+ usePatchesInScope(scope, patchListener);
22397
+ return processResult(void 0, scope);
22398
+ }
22399
+ /**
22400
+ * Pass true to automatically freeze all copies created by Immer.
22401
+ *
22402
+ * By default, auto-freezing is enabled.
22403
+ */
22404
+ setAutoFreeze(value) {
22405
+ this.autoFreeze_ = value;
22406
+ }
22407
+ /**
22408
+ * Pass true to enable strict shallow copy.
22409
+ *
22410
+ * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
22411
+ */
22412
+ setUseStrictShallowCopy(value) {
22413
+ this.useStrictShallowCopy_ = value;
22414
+ }
22415
+ /**
22416
+ * Pass false to use faster iteration that skips non-enumerable properties
22417
+ * but still handles symbols for compatibility.
22418
+ *
22419
+ * By default, strict iteration is enabled (includes all own properties).
22420
+ */
22421
+ setUseStrictIteration(value) {
22422
+ this.useStrictIteration_ = value;
22423
+ }
22424
+ shouldUseStrictIteration() {
22425
+ return this.useStrictIteration_;
22426
+ }
22427
+ applyPatches(base, patches) {
22428
+ let i;
22429
+ for (i = patches.length - 1; i >= 0; i--) {
22430
+ const patch = patches[i];
22431
+ if (patch.path.length === 0 && patch.op === "replace") {
22432
+ base = patch.value;
22433
+ break;
22434
+ }
22435
+ }
22436
+ if (i > -1) patches = patches.slice(i + 1);
22437
+ const applyPatchesImpl = getPlugin("Patches").applyPatches_;
22438
+ if (isDraft(base)) return applyPatchesImpl(base, patches);
22439
+ return this.produce(base, (draft) => applyPatchesImpl(draft, patches));
22440
+ }
22441
+ };
22442
+ function createProxy(value, parent) {
22443
+ const draft = isMap(value) ? getPlugin("MapSet").proxyMap_(value, parent) : isSet(value) ? getPlugin("MapSet").proxySet_(value, parent) : createProxyProxy(value, parent);
22444
+ (parent ? parent.scope_ : getCurrentScope()).drafts_.push(draft);
22445
+ return draft;
22446
+ }
22447
+ function current(value) {
22448
+ if (!isDraft(value)) die(10, value);
22449
+ return currentImpl(value);
22450
+ }
22451
+ function currentImpl(value) {
22452
+ if (!isDraftable(value) || isFrozen(value)) return value;
22453
+ const state = value[DRAFT_STATE];
22454
+ let copy;
22455
+ let strict = true;
22456
+ if (state) {
22457
+ if (!state.modified_) return state.base_;
22458
+ state.finalized_ = true;
22459
+ copy = shallowCopy(value, state.scope_.immer_.useStrictShallowCopy_);
22460
+ strict = state.scope_.immer_.shouldUseStrictIteration();
22461
+ } else copy = shallowCopy(value, true);
22462
+ each(copy, (key, childValue) => {
22463
+ set(copy, key, currentImpl(childValue));
22464
+ }, strict);
22465
+ if (state) state.finalized_ = false;
22466
+ return copy;
22467
+ }
22468
+ var produce = new Immer2().produce;
22469
+ //#endregion
22470
+ //#region node_modules/.pnpm/@deepseek-ai+dsh-client-store@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-client-store/lib/index.js
22471
+ /**
22472
+ * React-free snapshot store engine (zustand vanilla + immer + subscribeWithSelector +
22473
+ * rafFlush middleware + opt-in persist + dev freeze) plus the declarative
22474
+ * shell over it: {@link defineStore} bakes an init/persist/actions literal
22475
+ * into a {@link StoreHandle}, the registration-side store seat of slot
22476
+ * terminals. Engine products are bare observables — subscribe/getSnapshot/
22477
+ * update/set, NO selector hook. Hook synthesis is ui-renderer's (the one
22478
+ * uSES bridge, cached per source at the binding site).
22479
+ */
22480
+ /**
22481
+ * Notify an observer set without allowing one callback to starve the rest.
22482
+ * @param listeners - current observer callbacks; copied before dispatch.
22483
+ * @param label - diagnostic owner prefix.
22484
+ * @param args - callback arguments.
22485
+ */
22486
+ function notifySubscribers(listeners, label, ...args) {
22487
+ for (const listener of [...listeners]) try {
22488
+ listener(...args);
22489
+ } catch (error) {
22490
+ console.error(`${label} subscriber failed:`, error);
22491
+ }
22492
+ }
22493
+ /** Batches subscriber notification into one flush per animation frame. */
22494
+ function rafBatch(notify) {
22495
+ const schedule = typeof requestAnimationFrame === "function" ? (fn) => {
22496
+ requestAnimationFrame(() => {
22497
+ fn();
22498
+ });
22499
+ } : (fn) => {
22500
+ queueMicrotask(fn);
22501
+ };
22502
+ let scheduled = false;
22503
+ return () => {
22504
+ if (scheduled) return;
22505
+ scheduled = true;
22506
+ schedule(() => {
22507
+ scheduled = false;
22508
+ notify();
22509
+ });
22510
+ };
22511
+ }
22512
+ /**
22513
+ * Create a snapshot store.
22514
+ *
22515
+ * Flush default is 'sync' (controlled inputs need same-tick echo); frame-driven
22516
+ * stores opt into 'raf', where a frame's worth of updates coalesces into one
22517
+ * notification. Known raf-mode tradeoff: a component mounting mid-frame reads
22518
+ * fresh state while existing subscribers hear it next flush — transient
22519
+ * frame-level skew, same nature as the object layer's microtask batching.
22520
+ *
22521
+ * @param init - initial state.
22522
+ * @param opts - flush mode and opt-in persistence (localStorage, keyed by name).
22523
+ * @returns the store.
22524
+ */
22525
+ function createSnapshotStore(init, opts) {
22526
+ const withSelector = subscribeWithSelector(() => init);
22527
+ const api = createStore()(withSelector);
22528
+ if (opts?.persist) attachPersistence(api, opts.persist.name);
22529
+ let subscribe = (fn) => api.subscribe(() => {
22530
+ notifySubscribers([fn], "[client-store]");
22531
+ });
22532
+ if (opts?.flush === "raf") {
22533
+ const listeners = /* @__PURE__ */ new Set();
22534
+ const flush = rafBatch(() => {
22535
+ notifySubscribers(listeners, "[client-store]");
22536
+ });
22537
+ api.subscribe(flush);
22538
+ subscribe = (fn) => {
22539
+ listeners.add(fn);
22540
+ return () => {
22541
+ listeners.delete(fn);
22542
+ };
22543
+ };
22544
+ }
22545
+ return {
22546
+ getSnapshot: () => api.getState(),
22547
+ subscribe: (fn) => subscribe(fn),
22548
+ update: (mutator) => {
22549
+ api.setState(produce(api.getState(), (draft) => {
22550
+ mutator(draft);
22551
+ }), true);
22552
+ },
22553
+ set: (next) => {
22554
+ api.setState(devFreeze(next), true);
22555
+ }
22556
+ };
22557
+ }
22558
+ /**
22559
+ * Whole-value JSON persistence to localStorage. Hand-rolled instead of the
22560
+ * zustand persist middleware: its write path spreads state into an object
22561
+ * (`partialize({ ...get() })`), exploding primitive state (a persisted string
22562
+ * draft becomes {0:'h',1:'e',...}) — not fixable via merge/deserialize options
22563
+ * because the corruption happens before serialization. Storage failures
22564
+ * (quota, private mode) only disable persistence, never break the store.
22565
+ */
22566
+ function attachPersistence(api, name) {
22567
+ if (typeof localStorage === "undefined") return;
22568
+ try {
22569
+ const raw = localStorage.getItem(name);
22570
+ if (raw !== null) api.setState(devFreeze(JSON.parse(raw)), true);
22571
+ } catch (error) {
22572
+ console.error(`snapshot store '${name}' rehydration failed:`, error);
22573
+ }
22574
+ api.subscribe((state) => {
22575
+ try {
22576
+ localStorage.setItem(name, JSON.stringify(state));
22577
+ } catch (error) {
22578
+ console.error(`snapshot store '${name}' persistence failed:`, error);
22579
+ }
22580
+ });
22581
+ }
22582
+ /** Deep-freeze draftable wholesale-set state outside production: set() bypasses immer's freeze. */
22583
+ function devFreeze(value) {
22584
+ return freeze(value, true);
22585
+ }
22586
+ /**
22587
+ * Declare a store: initial state, optional persistence, and the full write
22588
+ * set as pure draft mutators. The returned handle is the registration
22589
+ * currency of the store seat — its identity keys instance sharing. Satisfies
22590
+ * ui-slots' DefineStore contract (the handle/instance are the engine-extended
22591
+ * subtypes).
22592
+ *
22593
+ * The `A & ActionsDecl<T>` actions position is load-bearing: T resolves from
22594
+ * `init` in the first inference round, and the intersection then contextually
22595
+ * types each mutator's draft parameter (context-sensitive functions defer),
22596
+ * so call sites write `(d, x: X) => { ... }` with no draft annotation. If a
22597
+ * future TS version breaks this single-literal inference, the design's
22598
+ * documented fallback is currying (`defineStore(init).actions({...})`).
22599
+ * @param decl - init lambda (fresh state per instance), optional persist key, actions table.
22600
+ * @returns the store handle.
22601
+ */
22602
+ function defineStore(decl) {
22603
+ return {
22604
+ spec: decl,
22605
+ create(scopeKey) {
22606
+ const persistKey = decl.persist === void 0 ? void 0 : scopeKey === void 0 ? decl.persist : `${decl.persist}.${scopeKey}`;
22607
+ const store = createSnapshotStore(decl.init(), persistKey !== void 0 ? { persist: { name: persistKey } } : void 0);
22608
+ const actions = {};
22609
+ for (const key of Object.keys(decl.actions)) {
22610
+ const mutate = decl.actions[key];
22611
+ actions[key] = (...params) => {
22612
+ store.update((draft) => {
22613
+ mutate(draft, ...params);
22614
+ });
22615
+ };
22616
+ }
22617
+ return {
22618
+ actions,
22619
+ getSnapshot: () => store.getSnapshot(),
22620
+ subscribe: (fn) => store.subscribe(fn),
22621
+ store,
22622
+ clearPersisted: () => {
22623
+ if (persistKey === void 0 || typeof localStorage === "undefined") return;
22624
+ try {
22625
+ localStorage.removeItem(persistKey);
22626
+ } catch {}
22627
+ }
22628
+ };
22629
+ }
22630
+ };
22631
+ }
22632
+ //#endregion
20850
22633
  //#region lib/types/client/store.js
20851
22634
  /** Root-scoped interaction state for the AWiki overlay. */
20852
22635
  /**
@@ -20854,7 +22637,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20854
22637
  * @returns a fresh framework store handle.
20855
22638
  */
20856
22639
  function createAwikiOverlayStore() {
20857
- return (0, _deepseek_ai_dsh_client_runtime_client.defineStore)({
22640
+ return defineStore({
20858
22641
  init: () => ({ open: false }),
20859
22642
  actions: {
20860
22643
  open: (draft) => {
@@ -21168,22 +22951,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21168
22951
  //#endregion
21169
22952
  //#region lib/types/settings-rpc-contract.js
21170
22953
  /** Client-safe contract for AWiki's plugin-owned settings transport. */
21171
- /** Dedicated Connection channel; the Host registers it with loopback authority. */
21172
- const AWIKI_SETTINGS_RPC_CHANNEL = "/awiki-settings";
22954
+ /** Shared Connection carrier with plugin-owned exact loopback routes. */
22955
+ const AWIKI_SETTINGS_RPC_CHANNEL = "/api";
21173
22956
  /** Supported channel-relative operations. */
21174
22957
  const AWIKI_SETTINGS_RPC_ENDPOINTS = {
21175
- describe: "describe",
21176
- setDomain: "set-domain",
21177
- resetDomain: "reset-domain",
21178
- describeTenants: "describe-tenants",
21179
- createTenant: "create-tenant",
21180
- renameTenant: "rename-tenant",
21181
- switchTenant: "switch-tenant",
21182
- archiveTenant: "archive-tenant",
21183
- describeUpdatePolicy: "describe-update-policy",
21184
- refreshUpdatePolicy: "refresh-update-policy",
21185
- describeDesktopUpdate: "describe-desktop-update",
21186
- refreshDesktopUpdate: "refresh-desktop-update"
22958
+ describe: "awiki-settings/describe",
22959
+ setDomain: "awiki-settings/set-domain",
22960
+ resetDomain: "awiki-settings/reset-domain",
22961
+ describeTenants: "awiki-settings/describe-tenants",
22962
+ createTenant: "awiki-settings/create-tenant",
22963
+ renameTenant: "awiki-settings/rename-tenant",
22964
+ switchTenant: "awiki-settings/switch-tenant",
22965
+ archiveTenant: "awiki-settings/archive-tenant",
22966
+ describeUpdatePolicy: "awiki-settings/describe-update-policy",
22967
+ refreshUpdatePolicy: "awiki-settings/refresh-update-policy",
22968
+ describeDesktopUpdate: "awiki-settings/describe-desktop-update",
22969
+ refreshDesktopUpdate: "awiki-settings/refresh-desktop-update"
21187
22970
  };
21188
22971
  function isRecord(value) {
21189
22972
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -21311,7 +23094,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21311
23094
  tenantSnapshot;
21312
23095
  tenantListeners = /* @__PURE__ */ new Set();
21313
23096
  abort = new AbortController();
21314
- disposeHostDescription;
23097
+ disposeGeneration;
21315
23098
  writeTail = Promise.resolve();
21316
23099
  requestVersion = 0;
21317
23100
  disposed = false;
@@ -21327,7 +23110,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21327
23110
  value: INITIAL_TENANTS,
21328
23111
  updateStatus: connection.isLoopback ? "loading" : "unavailable"
21329
23112
  };
21330
- this.disposeHostDescription = connection.isLoopback ? connection.hostDescription.subscribe(() => {
23113
+ this.disposeGeneration = connection.isLoopback ? connection.generation.subscribe(() => {
21331
23114
  this.load();
21332
23115
  }) : () => {};
21333
23116
  }
@@ -21506,6 +23289,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21506
23289
  if (field !== "domain") return Promise.reject(/* @__PURE__ */ new TypeError("AWiki settings only supports the domain field"));
21507
23290
  return this.enqueue(AWIKI_SETTINGS_RPC_ENDPOINTS.resetDomain, {});
21508
23291
  }
23292
+ /** Apply domain edits atomically through the existing revision-fenced Host operation. */
23293
+ mutate(ops, expectedRevision) {
23294
+ if (ops.length === 0) return Promise.resolve();
23295
+ for (const operation of ops) if (operation.path.length !== 1 || operation.path[0] !== "domain" || operation.op !== "set" && operation.op !== "unset" || operation.op === "set" && typeof operation.value !== "string") return Promise.reject(/* @__PURE__ */ new TypeError("AWiki settings only supports domain mutations"));
23296
+ const last = ops[ops.length - 1];
23297
+ const endpoint = last.op === "set" ? AWIKI_SETTINGS_RPC_ENDPOINTS.setDomain : AWIKI_SETTINGS_RPC_ENDPOINTS.resetDomain;
23298
+ const payload = last.op === "set" ? { domain: normalizeAwikiDomain(last.value) } : {};
23299
+ return this.enqueue(endpoint, payload, expectedRevision);
23300
+ }
21509
23301
  /** Stop reconnect reads and cancel outstanding transport calls. */
21510
23302
  dispose() {
21511
23303
  if (this.disposed) return;
@@ -21513,17 +23305,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21513
23305
  if (this.updatePolling !== void 0) clearInterval(this.updatePolling);
21514
23306
  this.requestVersion += 1;
21515
23307
  this.abort.abort();
21516
- this.disposeHostDescription();
23308
+ this.disposeGeneration();
21517
23309
  this.listeners.clear();
21518
23310
  this.tenantListeners.clear();
21519
23311
  }
21520
- enqueue(endpoint, payload) {
21521
- const run = this.writeTail.catch(() => void 0).then(() => this.write(endpoint, payload));
23312
+ enqueue(endpoint, payload, expectedRevision) {
23313
+ const run = this.writeTail.catch(() => void 0).then(() => this.write(endpoint, payload, expectedRevision));
21522
23314
  this.writeTail = run;
21523
23315
  return run;
21524
23316
  }
21525
- async write(endpoint, payload) {
21526
- const revision = this.snapshot.revision;
23317
+ async write(endpoint, payload, expectedRevision) {
23318
+ const revision = expectedRevision ?? this.snapshot.revision;
21527
23319
  if (this.disposed || !this.connection.isLoopback || this.snapshot.status !== "ready" || !this.snapshot.writable || revision === void 0) throw new Error("AWiki settings are not writable");
21528
23320
  const version = ++this.requestVersion;
21529
23321
  try {
@@ -21672,6 +23464,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21672
23464
  beginDeviceJoin: () => awiki.beginDeviceJoin(),
21673
23465
  getDeviceJoinStatus: () => awiki.getDeviceJoinStatus(),
21674
23466
  cancelDeviceJoin: () => awiki.cancelDeviceJoin(),
23467
+ beginRecoveryFromDeviceJoin: (request) => awiki.beginRecoveryFromDeviceJoin(request),
21675
23468
  retireDeviceIdentityForRejoin: () => awiki.retireDeviceIdentityForRejoin(),
21676
23469
  refreshDeviceManagement: () => awiki.refreshDeviceManagement(),
21677
23470
  startDeviceJoinVerification: (request) => awiki.startDeviceJoinVerification(request),
@@ -21718,11 +23511,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21718
23511
  value: void 0
21719
23512
  } : result;
21720
23513
  },
23514
+ getConfig: () => awiki.getConfig(),
21721
23515
  getMailAccount: () => awiki.getMailAccount(),
21722
23516
  listMailInbox: (request) => awiki.listMailInbox(request),
21723
23517
  readMail: (request) => awiki.readMail(request),
21724
23518
  markMailRead: (request) => awiki.markMailRead(request),
21725
- sendMail: (request) => awiki.sendMail(request)
23519
+ sendMail: (request) => awiki.sendMail(request),
23520
+ downloadMailAttachment: (request) => awiki.downloadMailAttachment(request)
21726
23521
  })
21727
23522
  }, AwikiOverlay);
21728
23523
  });
@@ -21757,7 +23552,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21757
23552
  confirmRootTransfer: (request) => awiki.confirmRootTransfer(request),
21758
23553
  loadIntegration: async () => {
21759
23554
  const result = await awiki.getIntegration();
21760
- if (!result.ok && result.error === "尚未创建 Integration。") {
23555
+ if (!result.ok && result.failureCode === "not-found") {
21761
23556
  clearIntegrationOperations();
21762
23557
  return {
21763
23558
  ok: true,