@awiki/dsh-plugin 0.3.10 → 0.3.11-rc.1

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 (81) hide show
  1. package/README.md +4 -3
  2. package/README.zh.md +4 -3
  3. package/lib/client.js +1351 -158
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +172 -93
  6. package/lib/model-proxy-contract.js +8 -8
  7. package/lib/typert.host.js +56 -56
  8. package/lib/typert.remote-client.js +56 -56
  9. package/lib/types/client/AwikiIdentityAccess.d.ts +6 -4
  10. package/lib/types/client/AwikiIdentityAccess.d.ts.map +1 -1
  11. package/lib/types/client/AwikiIdentityAccess.js +111 -43
  12. package/lib/types/client/AwikiIdentityAccess.js.map +1 -1
  13. package/lib/types/client/AwikiOverlay.js +1 -1
  14. package/lib/types/client/AwikiOverlay.js.map +1 -1
  15. package/lib/types/client/AwikiRecoveryForm.d.ts +1 -0
  16. package/lib/types/client/AwikiRecoveryForm.d.ts.map +1 -1
  17. package/lib/types/client/AwikiRecoveryForm.js +3 -2
  18. package/lib/types/client/AwikiRecoveryForm.js.map +1 -1
  19. package/lib/types/client/AwikiSettingsSection.d.ts +1 -1
  20. package/lib/types/client/AwikiSettingsSection.d.ts.map +1 -1
  21. package/lib/types/client/awiki-client-bridge.d.ts +1 -1
  22. package/lib/types/client/awiki-client-bridge.d.ts.map +1 -1
  23. package/lib/types/client/awiki-client-bridge.js +1 -1
  24. package/lib/types/client/awiki-client-bridge.js.map +1 -1
  25. package/lib/types/client/controller.d.ts +8 -0
  26. package/lib/types/client/controller.d.ts.map +1 -1
  27. package/lib/types/client/controller.js +274 -53
  28. package/lib/types/client/controller.js.map +1 -1
  29. package/lib/types/client/index.d.ts +1 -1
  30. package/lib/types/client/index.d.ts.map +1 -1
  31. package/lib/types/client/index.js +2 -1
  32. package/lib/types/client/index.js.map +1 -1
  33. package/lib/types/client/otp-cooldown.d.ts +1 -0
  34. package/lib/types/client/otp-cooldown.d.ts.map +1 -1
  35. package/lib/types/client/otp-cooldown.js +12 -1
  36. package/lib/types/client/otp-cooldown.js.map +1 -1
  37. package/lib/types/client/settings-controller.d.ts +4 -2
  38. package/lib/types/client/settings-controller.d.ts.map +1 -1
  39. package/lib/types/client/settings-controller.js +24 -8
  40. package/lib/types/client/settings-controller.js.map +1 -1
  41. package/lib/types/client/slots.d.ts +1 -0
  42. package/lib/types/client/slots.d.ts.map +1 -1
  43. package/lib/types/client/store.d.ts +1 -1
  44. package/lib/types/client/store.d.ts.map +1 -1
  45. package/lib/types/client/store.js +1 -1
  46. package/lib/types/client/store.js.map +1 -1
  47. package/lib/types/index.d.ts +1 -0
  48. package/lib/types/index.d.ts.map +1 -1
  49. package/lib/types/index.js +35 -9
  50. package/lib/types/index.js.map +1 -1
  51. package/lib/types/listener.d.ts.map +1 -1
  52. package/lib/types/listener.js +2 -1
  53. package/lib/types/listener.js.map +1 -1
  54. package/lib/types/model-proxy-contract.d.ts +8 -8
  55. package/lib/types/model-proxy-contract.d.ts.map +1 -1
  56. package/lib/types/model-proxy-contract.js +8 -8
  57. package/lib/types/model-proxy-contract.js.map +1 -1
  58. package/lib/types/package-version.generated.d.ts +2 -2
  59. package/lib/types/package-version.generated.d.ts.map +1 -1
  60. package/lib/types/package-version.generated.js +2 -2
  61. package/lib/types/package-version.generated.js.map +1 -1
  62. package/lib/types/registration-policy.d.ts +7 -0
  63. package/lib/types/registration-policy.d.ts.map +1 -0
  64. package/lib/types/registration-policy.js +21 -0
  65. package/lib/types/registration-policy.js.map +1 -0
  66. package/lib/types/settings-rpc-contract.d.ts +14 -14
  67. package/lib/types/settings-rpc-contract.d.ts.map +1 -1
  68. package/lib/types/settings-rpc-contract.js +14 -14
  69. package/lib/types/settings-rpc-contract.js.map +1 -1
  70. package/lib/types/settings-rpc.d.ts.map +1 -1
  71. package/lib/types/settings-rpc.js +2 -2
  72. package/lib/types/settings-rpc.js.map +1 -1
  73. package/lib/types/settings-transport.d.ts +7 -0
  74. package/lib/types/settings-transport.d.ts.map +1 -0
  75. package/lib/types/settings-transport.js +52 -0
  76. package/lib/types/settings-transport.js.map +1 -0
  77. package/lib/types/types.d.ts +1 -1
  78. package/lib/types/types.d.ts.map +1 -1
  79. package/lib/types/update-policy.d.ts +2 -2
  80. package/lib/types/update-policy.d.ts.map +1 -1
  81. package/package.json +82 -73
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,
@@ -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,6 +4108,7 @@ 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"),
@@ -4232,6 +4232,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4232
4232
  literal("invalid-otp"),
4233
4233
  literal("challenge-expired"),
4234
4234
  literal("handle-unavailable"),
4235
+ literal("short-handle-invite-required"),
4235
4236
  literal("not-found"),
4236
4237
  literal("forbidden"),
4237
4238
  literal("device-rejoin-required"),
@@ -4303,6 +4304,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4303
4304
  literal("invalid-otp"),
4304
4305
  literal("challenge-expired"),
4305
4306
  literal("handle-unavailable"),
4307
+ literal("short-handle-invite-required"),
4306
4308
  literal("not-found"),
4307
4309
  literal("forbidden"),
4308
4310
  literal("device-rejoin-required"),
@@ -4379,6 +4381,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4379
4381
  literal("invalid-otp"),
4380
4382
  literal("challenge-expired"),
4381
4383
  literal("handle-unavailable"),
4384
+ literal("short-handle-invite-required"),
4382
4385
  literal("not-found"),
4383
4386
  literal("forbidden"),
4384
4387
  literal("device-rejoin-required"),
@@ -4455,6 +4458,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4455
4458
  literal("invalid-otp"),
4456
4459
  literal("challenge-expired"),
4457
4460
  literal("handle-unavailable"),
4461
+ literal("short-handle-invite-required"),
4458
4462
  literal("not-found"),
4459
4463
  literal("forbidden"),
4460
4464
  literal("device-rejoin-required"),
@@ -4519,6 +4523,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4519
4523
  literal("invalid-otp"),
4520
4524
  literal("challenge-expired"),
4521
4525
  literal("handle-unavailable"),
4526
+ literal("short-handle-invite-required"),
4522
4527
  literal("not-found"),
4523
4528
  literal("forbidden"),
4524
4529
  literal("device-rejoin-required"),
@@ -4645,6 +4650,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4645
4650
  literal("invalid-otp"),
4646
4651
  literal("challenge-expired"),
4647
4652
  literal("handle-unavailable"),
4653
+ literal("short-handle-invite-required"),
4648
4654
  literal("not-found"),
4649
4655
  literal("forbidden"),
4650
4656
  literal("device-rejoin-required"),
@@ -4715,6 +4721,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4715
4721
  literal("invalid-otp"),
4716
4722
  literal("challenge-expired"),
4717
4723
  literal("handle-unavailable"),
4724
+ literal("short-handle-invite-required"),
4718
4725
  literal("not-found"),
4719
4726
  literal("forbidden"),
4720
4727
  literal("device-rejoin-required"),
@@ -4790,6 +4797,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4790
4797
  literal("invalid-otp"),
4791
4798
  literal("challenge-expired"),
4792
4799
  literal("handle-unavailable"),
4800
+ literal("short-handle-invite-required"),
4793
4801
  literal("not-found"),
4794
4802
  literal("forbidden"),
4795
4803
  literal("device-rejoin-required"),
@@ -4920,6 +4928,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4920
4928
  literal("invalid-otp"),
4921
4929
  literal("challenge-expired"),
4922
4930
  literal("handle-unavailable"),
4931
+ literal("short-handle-invite-required"),
4923
4932
  literal("not-found"),
4924
4933
  literal("forbidden"),
4925
4934
  literal("device-rejoin-required"),
@@ -4987,6 +4996,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4987
4996
  literal("invalid-otp"),
4988
4997
  literal("challenge-expired"),
4989
4998
  literal("handle-unavailable"),
4999
+ literal("short-handle-invite-required"),
4990
5000
  literal("not-found"),
4991
5001
  literal("forbidden"),
4992
5002
  literal("device-rejoin-required"),
@@ -5060,6 +5070,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5060
5070
  literal("invalid-otp"),
5061
5071
  literal("challenge-expired"),
5062
5072
  literal("handle-unavailable"),
5073
+ literal("short-handle-invite-required"),
5063
5074
  literal("not-found"),
5064
5075
  literal("forbidden"),
5065
5076
  literal("device-rejoin-required"),
@@ -5178,6 +5189,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5178
5189
  literal("invalid-otp"),
5179
5190
  literal("challenge-expired"),
5180
5191
  literal("handle-unavailable"),
5192
+ literal("short-handle-invite-required"),
5181
5193
  literal("not-found"),
5182
5194
  literal("forbidden"),
5183
5195
  literal("device-rejoin-required"),
@@ -5253,6 +5265,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5253
5265
  literal("invalid-otp"),
5254
5266
  literal("challenge-expired"),
5255
5267
  literal("handle-unavailable"),
5268
+ literal("short-handle-invite-required"),
5256
5269
  literal("not-found"),
5257
5270
  literal("forbidden"),
5258
5271
  literal("device-rejoin-required"),
@@ -5337,6 +5350,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5337
5350
  literal("invalid-otp"),
5338
5351
  literal("challenge-expired"),
5339
5352
  literal("handle-unavailable"),
5353
+ literal("short-handle-invite-required"),
5340
5354
  literal("not-found"),
5341
5355
  literal("forbidden"),
5342
5356
  literal("device-rejoin-required"),
@@ -5414,6 +5428,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5414
5428
  literal("invalid-otp"),
5415
5429
  literal("challenge-expired"),
5416
5430
  literal("handle-unavailable"),
5431
+ literal("short-handle-invite-required"),
5417
5432
  literal("not-found"),
5418
5433
  literal("forbidden"),
5419
5434
  literal("device-rejoin-required"),
@@ -5483,6 +5498,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5483
5498
  literal("invalid-otp"),
5484
5499
  literal("challenge-expired"),
5485
5500
  literal("handle-unavailable"),
5501
+ literal("short-handle-invite-required"),
5486
5502
  literal("not-found"),
5487
5503
  literal("forbidden"),
5488
5504
  literal("device-rejoin-required"),
@@ -5559,6 +5575,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5559
5575
  literal("invalid-otp"),
5560
5576
  literal("challenge-expired"),
5561
5577
  literal("handle-unavailable"),
5578
+ literal("short-handle-invite-required"),
5562
5579
  literal("not-found"),
5563
5580
  literal("forbidden"),
5564
5581
  literal("device-rejoin-required"),
@@ -5656,6 +5673,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5656
5673
  literal("invalid-otp"),
5657
5674
  literal("challenge-expired"),
5658
5675
  literal("handle-unavailable"),
5676
+ literal("short-handle-invite-required"),
5659
5677
  literal("not-found"),
5660
5678
  literal("forbidden"),
5661
5679
  literal("device-rejoin-required"),
@@ -5724,6 +5742,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5724
5742
  literal("invalid-otp"),
5725
5743
  literal("challenge-expired"),
5726
5744
  literal("handle-unavailable"),
5745
+ literal("short-handle-invite-required"),
5727
5746
  literal("not-found"),
5728
5747
  literal("forbidden"),
5729
5748
  literal("device-rejoin-required"),
@@ -5859,6 +5878,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5859
5878
  literal("invalid-otp"),
5860
5879
  literal("challenge-expired"),
5861
5880
  literal("handle-unavailable"),
5881
+ literal("short-handle-invite-required"),
5862
5882
  literal("not-found"),
5863
5883
  literal("forbidden"),
5864
5884
  literal("device-rejoin-required"),
@@ -5956,6 +5976,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5956
5976
  literal("invalid-otp"),
5957
5977
  literal("challenge-expired"),
5958
5978
  literal("handle-unavailable"),
5979
+ literal("short-handle-invite-required"),
5959
5980
  literal("not-found"),
5960
5981
  literal("forbidden"),
5961
5982
  literal("device-rejoin-required"),
@@ -6023,6 +6044,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6023
6044
  literal("invalid-otp"),
6024
6045
  literal("challenge-expired"),
6025
6046
  literal("handle-unavailable"),
6047
+ literal("short-handle-invite-required"),
6026
6048
  literal("not-found"),
6027
6049
  literal("forbidden"),
6028
6050
  literal("device-rejoin-required"),
@@ -6094,6 +6116,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6094
6116
  literal("invalid-otp"),
6095
6117
  literal("challenge-expired"),
6096
6118
  literal("handle-unavailable"),
6119
+ literal("short-handle-invite-required"),
6097
6120
  literal("not-found"),
6098
6121
  literal("forbidden"),
6099
6122
  literal("device-rejoin-required"),
@@ -6212,6 +6235,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6212
6235
  literal("invalid-otp"),
6213
6236
  literal("challenge-expired"),
6214
6237
  literal("handle-unavailable"),
6238
+ literal("short-handle-invite-required"),
6215
6239
  literal("not-found"),
6216
6240
  literal("forbidden"),
6217
6241
  literal("device-rejoin-required"),
@@ -6288,6 +6312,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6288
6312
  literal("invalid-otp"),
6289
6313
  literal("challenge-expired"),
6290
6314
  literal("handle-unavailable"),
6315
+ literal("short-handle-invite-required"),
6291
6316
  literal("not-found"),
6292
6317
  literal("forbidden"),
6293
6318
  literal("device-rejoin-required"),
@@ -6355,6 +6380,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6355
6380
  literal("invalid-otp"),
6356
6381
  literal("challenge-expired"),
6357
6382
  literal("handle-unavailable"),
6383
+ literal("short-handle-invite-required"),
6358
6384
  literal("not-found"),
6359
6385
  literal("forbidden"),
6360
6386
  literal("device-rejoin-required"),
@@ -6427,6 +6453,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6427
6453
  literal("invalid-otp"),
6428
6454
  literal("challenge-expired"),
6429
6455
  literal("handle-unavailable"),
6456
+ literal("short-handle-invite-required"),
6430
6457
  literal("not-found"),
6431
6458
  literal("forbidden"),
6432
6459
  literal("device-rejoin-required"),
@@ -6494,6 +6521,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6494
6521
  literal("invalid-otp"),
6495
6522
  literal("challenge-expired"),
6496
6523
  literal("handle-unavailable"),
6524
+ literal("short-handle-invite-required"),
6497
6525
  literal("not-found"),
6498
6526
  literal("forbidden"),
6499
6527
  literal("device-rejoin-required"),
@@ -6584,6 +6612,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6584
6612
  literal("invalid-otp"),
6585
6613
  literal("challenge-expired"),
6586
6614
  literal("handle-unavailable"),
6615
+ literal("short-handle-invite-required"),
6587
6616
  literal("not-found"),
6588
6617
  literal("forbidden"),
6589
6618
  literal("device-rejoin-required"),
@@ -6672,6 +6701,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6672
6701
  literal("invalid-otp"),
6673
6702
  literal("challenge-expired"),
6674
6703
  literal("handle-unavailable"),
6704
+ literal("short-handle-invite-required"),
6675
6705
  literal("not-found"),
6676
6706
  literal("forbidden"),
6677
6707
  literal("device-rejoin-required"),
@@ -6754,6 +6784,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6754
6784
  literal("invalid-otp"),
6755
6785
  literal("challenge-expired"),
6756
6786
  literal("handle-unavailable"),
6787
+ literal("short-handle-invite-required"),
6757
6788
  literal("not-found"),
6758
6789
  literal("forbidden"),
6759
6790
  literal("device-rejoin-required"),
@@ -6830,6 +6861,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6830
6861
  literal("invalid-otp"),
6831
6862
  literal("challenge-expired"),
6832
6863
  literal("handle-unavailable"),
6864
+ literal("short-handle-invite-required"),
6833
6865
  literal("not-found"),
6834
6866
  literal("forbidden"),
6835
6867
  literal("device-rejoin-required"),
@@ -6906,6 +6938,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6906
6938
  literal("invalid-otp"),
6907
6939
  literal("challenge-expired"),
6908
6940
  literal("handle-unavailable"),
6941
+ literal("short-handle-invite-required"),
6909
6942
  literal("not-found"),
6910
6943
  literal("forbidden"),
6911
6944
  literal("device-rejoin-required"),
@@ -6970,6 +7003,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6970
7003
  literal("invalid-otp"),
6971
7004
  literal("challenge-expired"),
6972
7005
  literal("handle-unavailable"),
7006
+ literal("short-handle-invite-required"),
6973
7007
  literal("not-found"),
6974
7008
  literal("forbidden"),
6975
7009
  literal("device-rejoin-required"),
@@ -7038,6 +7072,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7038
7072
  literal("invalid-otp"),
7039
7073
  literal("challenge-expired"),
7040
7074
  literal("handle-unavailable"),
7075
+ literal("short-handle-invite-required"),
7041
7076
  literal("not-found"),
7042
7077
  literal("forbidden"),
7043
7078
  literal("device-rejoin-required"),
@@ -7157,6 +7192,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7157
7192
  literal("invalid-otp"),
7158
7193
  literal("challenge-expired"),
7159
7194
  literal("handle-unavailable"),
7195
+ literal("short-handle-invite-required"),
7160
7196
  literal("not-found"),
7161
7197
  literal("forbidden"),
7162
7198
  literal("device-rejoin-required"),
@@ -7225,6 +7261,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7225
7261
  literal("invalid-otp"),
7226
7262
  literal("challenge-expired"),
7227
7263
  literal("handle-unavailable"),
7264
+ literal("short-handle-invite-required"),
7228
7265
  literal("not-found"),
7229
7266
  literal("forbidden"),
7230
7267
  literal("device-rejoin-required"),
@@ -7314,6 +7351,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7314
7351
  literal("invalid-otp"),
7315
7352
  literal("challenge-expired"),
7316
7353
  literal("handle-unavailable"),
7354
+ literal("short-handle-invite-required"),
7317
7355
  literal("not-found"),
7318
7356
  literal("forbidden"),
7319
7357
  literal("device-rejoin-required"),
@@ -7419,6 +7457,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7419
7457
  literal("invalid-otp"),
7420
7458
  literal("challenge-expired"),
7421
7459
  literal("handle-unavailable"),
7460
+ literal("short-handle-invite-required"),
7422
7461
  literal("not-found"),
7423
7462
  literal("forbidden"),
7424
7463
  literal("device-rejoin-required"),
@@ -7499,6 +7538,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7499
7538
  literal("invalid-otp"),
7500
7539
  literal("challenge-expired"),
7501
7540
  literal("handle-unavailable"),
7541
+ literal("short-handle-invite-required"),
7502
7542
  literal("not-found"),
7503
7543
  literal("forbidden"),
7504
7544
  literal("device-rejoin-required"),
@@ -7579,6 +7619,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7579
7619
  literal("invalid-otp"),
7580
7620
  literal("challenge-expired"),
7581
7621
  literal("handle-unavailable"),
7622
+ literal("short-handle-invite-required"),
7582
7623
  literal("not-found"),
7583
7624
  literal("forbidden"),
7584
7625
  literal("device-rejoin-required"),
@@ -7714,6 +7755,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7714
7755
  literal("invalid-otp"),
7715
7756
  literal("challenge-expired"),
7716
7757
  literal("handle-unavailable"),
7758
+ literal("short-handle-invite-required"),
7717
7759
  literal("not-found"),
7718
7760
  literal("forbidden"),
7719
7761
  literal("device-rejoin-required"),
@@ -7783,6 +7825,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7783
7825
  literal("invalid-otp"),
7784
7826
  literal("challenge-expired"),
7785
7827
  literal("handle-unavailable"),
7828
+ literal("short-handle-invite-required"),
7786
7829
  literal("not-found"),
7787
7830
  literal("forbidden"),
7788
7831
  literal("device-rejoin-required"),
@@ -7901,6 +7944,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7901
7944
  literal("invalid-otp"),
7902
7945
  literal("challenge-expired"),
7903
7946
  literal("handle-unavailable"),
7947
+ literal("short-handle-invite-required"),
7904
7948
  literal("not-found"),
7905
7949
  literal("forbidden"),
7906
7950
  literal("device-rejoin-required"),
@@ -7968,6 +8012,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7968
8012
  literal("invalid-otp"),
7969
8013
  literal("challenge-expired"),
7970
8014
  literal("handle-unavailable"),
8015
+ literal("short-handle-invite-required"),
7971
8016
  literal("not-found"),
7972
8017
  literal("forbidden"),
7973
8018
  literal("device-rejoin-required"),
@@ -8141,6 +8186,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8141
8186
  literal("invalid-otp"),
8142
8187
  literal("challenge-expired"),
8143
8188
  literal("handle-unavailable"),
8189
+ literal("short-handle-invite-required"),
8144
8190
  literal("not-found"),
8145
8191
  literal("forbidden"),
8146
8192
  literal("device-rejoin-required"),
@@ -8240,6 +8286,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8240
8286
  literal("invalid-otp"),
8241
8287
  literal("challenge-expired"),
8242
8288
  literal("handle-unavailable"),
8289
+ literal("short-handle-invite-required"),
8243
8290
  literal("not-found"),
8244
8291
  literal("forbidden"),
8245
8292
  literal("device-rejoin-required"),
@@ -8311,6 +8358,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8311
8358
  literal("invalid-otp"),
8312
8359
  literal("challenge-expired"),
8313
8360
  literal("handle-unavailable"),
8361
+ literal("short-handle-invite-required"),
8314
8362
  literal("not-found"),
8315
8363
  literal("forbidden"),
8316
8364
  literal("device-rejoin-required"),
@@ -8383,6 +8431,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8383
8431
  literal("invalid-otp"),
8384
8432
  literal("challenge-expired"),
8385
8433
  literal("handle-unavailable"),
8434
+ literal("short-handle-invite-required"),
8386
8435
  literal("not-found"),
8387
8436
  literal("forbidden"),
8388
8437
  literal("device-rejoin-required"),
@@ -8467,6 +8516,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8467
8516
  literal("invalid-otp"),
8468
8517
  literal("challenge-expired"),
8469
8518
  literal("handle-unavailable"),
8519
+ literal("short-handle-invite-required"),
8470
8520
  literal("not-found"),
8471
8521
  literal("forbidden"),
8472
8522
  literal("device-rejoin-required"),
@@ -8561,6 +8611,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8561
8611
  literal("invalid-otp"),
8562
8612
  literal("challenge-expired"),
8563
8613
  literal("handle-unavailable"),
8614
+ literal("short-handle-invite-required"),
8564
8615
  literal("not-found"),
8565
8616
  literal("forbidden"),
8566
8617
  literal("device-rejoin-required"),
@@ -8641,6 +8692,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8641
8692
  literal("invalid-otp"),
8642
8693
  literal("challenge-expired"),
8643
8694
  literal("handle-unavailable"),
8695
+ literal("short-handle-invite-required"),
8644
8696
  literal("not-found"),
8645
8697
  literal("forbidden"),
8646
8698
  literal("device-rejoin-required"),
@@ -8745,6 +8797,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8745
8797
  literal("invalid-otp"),
8746
8798
  literal("challenge-expired"),
8747
8799
  literal("handle-unavailable"),
8800
+ literal("short-handle-invite-required"),
8748
8801
  literal("not-found"),
8749
8802
  literal("forbidden"),
8750
8803
  literal("device-rejoin-required"),
@@ -8830,6 +8883,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8830
8883
  literal("invalid-otp"),
8831
8884
  literal("challenge-expired"),
8832
8885
  literal("handle-unavailable"),
8886
+ literal("short-handle-invite-required"),
8833
8887
  literal("not-found"),
8834
8888
  literal("forbidden"),
8835
8889
  literal("device-rejoin-required"),
@@ -8971,6 +9025,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8971
9025
  literal("invalid-otp"),
8972
9026
  literal("challenge-expired"),
8973
9027
  literal("handle-unavailable"),
9028
+ literal("short-handle-invite-required"),
8974
9029
  literal("not-found"),
8975
9030
  literal("forbidden"),
8976
9031
  literal("device-rejoin-required"),
@@ -10739,6 +10794,26 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10739
10794
  return [store === void 0 ? local : store.read(scope, key, initial, dirty), set];
10740
10795
  }
10741
10796
  //#endregion
10797
+ //#region lib/types/registration-policy.js
10798
+ /** Product registration policy for invite-only short Handles. */
10799
+ const SHORT_HANDLE_INVITE_MESSAGE = "注册少于5位的handle需要使用邀请码,目前暂不支持自主注册。";
10800
+ const HANDLE_LOCAL_PART = /^(?!-)(?!.*--)[a-z0-9-]{1,63}(?<!-)$/u;
10801
+ /** Return the canonical local part when the input has valid WNS local-part syntax. */
10802
+ function registrationHandleLocalPart(value) {
10803
+ let normalized = value.trim().toLowerCase();
10804
+ if (normalized.startsWith("wba://")) normalized = normalized.slice(6);
10805
+ const dot = normalized.indexOf(".");
10806
+ const localPart = (dot < 0 ? normalized : normalized.slice(0, dot)).trim();
10807
+ return HANDLE_LOCAL_PART.test(localPart) ? localPart : void 0;
10808
+ }
10809
+ /** One- through four-character Handle registrations require the unavailable invitation flow. */
10810
+ function shortHandleInviteRequired(value) {
10811
+ const localPart = registrationHandleLocalPart(value);
10812
+ if (localPart === void 0) return false;
10813
+ const length = Array.from(localPart).length;
10814
+ return length >= 1 && length <= 4;
10815
+ }
10816
+ //#endregion
10742
10817
  //#region lib/types/client/otp-cooldown.js
10743
10818
  /** Retain the server cooldown across panel remounts, without persisting OTPs. */
10744
10819
  function useRecoveryOtpCooldown() {
@@ -10753,13 +10828,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10753
10828
  clearInterval(timer);
10754
10829
  };
10755
10830
  }, [deadline]);
10831
+ const restore = (0, react.useCallback)((retryAt) => {
10832
+ if (retryAt === null || retryAt === void 0) return;
10833
+ const parsed = Date.parse(retryAt);
10834
+ if (!Number.isFinite(parsed) || parsed <= Date.now()) return;
10835
+ setNow(Date.now());
10836
+ setDeadline((deadline) => Math.max(deadline, parsed));
10837
+ }, [setDeadline]);
10756
10838
  return {
10757
10839
  seconds: Math.max(0, Math.ceil((deadline - now) / 1e3)),
10758
10840
  start: (seconds) => {
10759
10841
  const now = Date.now();
10760
10842
  setNow(now);
10761
10843
  setDeadline(now + Math.max(0, seconds) * 1e3);
10762
- }
10844
+ },
10845
+ restore
10763
10846
  };
10764
10847
  }
10765
10848
  //#endregion
@@ -11016,6 +11099,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11016
11099
  setNotice(null);
11017
11100
  setError(null);
11018
11101
  }, [props.operationId]);
11102
+ (0, react.useEffect)(() => {
11103
+ cooldown.restore(props.retryAt);
11104
+ }, [cooldown.restore, props.retryAt]);
11019
11105
  (0, react.useEffect)(() => {
11020
11106
  const progress = props.progress;
11021
11107
  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 +11220,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11134
11220
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 24 })
11135
11221
  }),
11136
11222
  (0, react_jsx_runtime.jsx)("h3", { children: props.requestTitle ?? "恢复已有身份" }),
11137
- (0, react_jsx_runtime.jsx)("p", { children: props.requestDescription ?? "输入原来的完整 Handle 和绑定手机号,我们会发送验证码来确认身份归属。" }),
11223
+ (0, react_jsx_runtime.jsx)("p", { children: props.requestDescription ?? "输入原来的完整 Handle 和绑定手机号。发送验证码会开始一次替换 DID 的恢复,使其他设备的旧凭证失效。" }),
11138
11224
  props.fixedHandle === void 0 ? (0, react_jsx_runtime.jsxs)("label", { children: ["完整 Handle", (0, react_jsx_runtime.jsx)("input", {
11139
11225
  ref: handle,
11140
11226
  value: handleDraft,
@@ -11162,7 +11248,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11162
11248
  type: "submit",
11163
11249
  className: _dsh_awiki_css_AwikiOverlay_module_css_default.primary,
11164
11250
  disabled: props.pending || cooldown.seconds > 0 || phoneDraft.trim() === "",
11165
- children: "获取恢复验证码"
11251
+ children: "发送恢复验证码并替换 DID"
11166
11252
  }),
11167
11253
  (error ?? props.requestError) && (0, react_jsx_runtime.jsx)("small", {
11168
11254
  className: _dsh_awiki_css_AwikiOverlay_module_css_default.inlineError,
@@ -11372,7 +11458,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11372
11458
  }
11373
11459
  //#endregion
11374
11460
  //#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}}";
11461
+ 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
11462
  const tagId$4 = "@awiki/dsh-plugin/AwikiIdentityAccess.module.css";
11377
11463
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
11378
11464
  const tag = document.createElement("style");
@@ -11395,6 +11481,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11395
11481
  "identity-spin": "r_slHG_identity-spin",
11396
11482
  "identityIcon": "r_slHG_identityIcon",
11397
11483
  "identitySummary": "r_slHG_identitySummary",
11484
+ "inviteNotice": "r_slHG_inviteNotice",
11398
11485
  "linkButton": "r_slHG_linkButton",
11399
11486
  "notice": "r_slHG_notice",
11400
11487
  "primary": "r_slHG_primary",
@@ -11426,11 +11513,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11426
11513
  ...props.initialFactorContext === void 0 ? {} : { initialFactorContext: props.initialFactorContext },
11427
11514
  ...props.fixedHandle === void 0 ? {} : { fixedHandle: props.fixedHandle },
11428
11515
  ...props.requestTitle === void 0 ? {} : { requestTitle: props.requestTitle },
11429
- ...props.requestDescription === void 0 ? {} : { requestDescription: props.requestDescription }
11516
+ ...props.requestDescription === void 0 ? {} : { requestDescription: props.requestDescription },
11517
+ retryAt: props.recoveryOtpRetryAt
11430
11518
  }, props.recoveryOperationId ?? props.fixedHandle ?? "new");
11431
11519
  }
11432
11520
  /** Keep phone and OTP values in private browser memory for the duration of this explicit user flow. */
11433
11521
  function AwikiIdentityAccess(props) {
11522
+ const [shortHandleInviteNotice, setShortHandleInviteNotice] = useDraftState("identity:shortHandleInviteNotice", false, false);
11434
11523
  const recoveryCooldown = useRecoveryOtpCooldown();
11435
11524
  const [phone, setPhone] = useDraftState("identity:phone", "");
11436
11525
  const [handle, setHandle] = useDraftState("identity:handle", "");
@@ -11446,6 +11535,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11446
11535
  const [loginFailed, setLoginFailed] = useDraftState("identity:loginFailed", false, false);
11447
11536
  const [joinContext, setJoinContext] = useDraftState("identity:joinContext", null, false);
11448
11537
  const [recoveryChoice, setRecoveryChoice] = useDraftState("identity:recoveryChoice", null, false);
11538
+ const [recoveryRiskConfirmed, setRecoveryRiskConfirmed] = useDraftState("identity:recoveryRiskConfirmed", false, false);
11539
+ const [recoveryEntryOpen, setRecoveryEntryOpen] = useDraftState("identity:recoveryEntryOpen", false, false);
11540
+ const validRecoveryEntryOpen = recoveryEntryOpen && props.sessionStatus === "recovery-required";
11541
+ const recoveryConfirmationInFlight = (0, react.useRef)(false);
11542
+ const [recoveryConfirming, setRecoveryConfirming] = (0, react.useState)(false);
11449
11543
  const [joinCheck, setJoinCheck] = (0, react.useState)("loading");
11450
11544
  const [joinProgress, setJoinProgress] = (0, react.useState)(null);
11451
11545
  const [deviceRejoinHandle, setDeviceRejoinHandle] = useDraftState("identity:deviceRejoinHandle", null, false);
@@ -11462,11 +11556,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11462
11556
  clearInterval(timer);
11463
11557
  };
11464
11558
  }, [retryDeadline]);
11559
+ (0, react.useEffect)(() => {
11560
+ if (recoveryEntryOpen && props.sessionStatus !== "recovery-required") setRecoveryEntryOpen(false);
11561
+ }, [
11562
+ props.sessionStatus,
11563
+ recoveryEntryOpen,
11564
+ setRecoveryEntryOpen
11565
+ ]);
11465
11566
  const resetIdentityEntry = () => {
11567
+ setShortHandleInviteNotice(false);
11466
11568
  setOtp("");
11467
11569
  setRegistrationOtpSent(false);
11468
11570
  setRecoveryFactorContext(null);
11469
11571
  setRecoveryChoice(null);
11572
+ setRecoveryRiskConfirmed(false);
11573
+ setRecoveryEntryOpen(false);
11470
11574
  setNotice(null);
11471
11575
  setError(null);
11472
11576
  setRetryDeadline(null);
@@ -11489,6 +11593,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11489
11593
  phone: phone.trim()
11490
11594
  });
11491
11595
  if (!result.ok) {
11596
+ if (result.failureCode === "short-handle-invite-required") {
11597
+ setNotice(null);
11598
+ setShortHandleInviteNotice(true);
11599
+ return;
11600
+ }
11492
11601
  setError(result.error);
11493
11602
  return;
11494
11603
  }
@@ -11503,6 +11612,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11503
11612
  const result = await props.continueRecoveryForHandle?.(handle.trim());
11504
11613
  if (result !== void 0 && !result.ok) return setError(result.error);
11505
11614
  if (result?.ok && result.value) return;
11615
+ setShortHandleInviteNotice(false);
11616
+ if (shortHandleInviteRequired(handle)) {
11617
+ const inspection = await props.inspectIdentityAccess({ handle: handle.trim() });
11618
+ if (!inspection.ok) return setError(inspection.error);
11619
+ if (inspection.value.status === "available") {
11620
+ setNotice(null);
11621
+ setShortHandleInviteNotice(true);
11622
+ return;
11623
+ }
11624
+ }
11506
11625
  await requestRegistrationOtp();
11507
11626
  };
11508
11627
  const completeRegistration = async () => {
@@ -11557,32 +11676,69 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11557
11676
  setJoinProgress(null);
11558
11677
  resetIdentityEntry();
11559
11678
  };
11560
- const chooseRecovery = async () => {
11561
- if (joinContext === null || !props.handleRecoveryPhoneEnabled) return;
11679
+ const chooseRecovery = () => {
11680
+ if (joinContext === null) return;
11562
11681
  setError(null);
11563
- const discarded = await props.cancelDeviceJoin();
11564
- if (!discarded.ok) return setError(discarded.error);
11565
11682
  setRecoveryChoice(joinContext.fullHandle);
11566
11683
  setRecoveryFactorContext({
11567
11684
  fullHandle: joinContext.fullHandle,
11568
11685
  phone: joinContext.phone
11569
11686
  });
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);
11687
+ setRecoveryRiskConfirmed(false);
11688
+ };
11689
+ const cancelRecoveryChoice = () => {
11690
+ setRecoveryChoice(null);
11691
+ setRecoveryFactorContext(null);
11692
+ setRecoveryRiskConfirmed(false);
11693
+ setError(null);
11694
+ };
11695
+ const confirmRecoveryChoice = async () => {
11696
+ if (recoveryChoice === null || recoveryConfirmationInFlight.current) return;
11697
+ recoveryConfirmationInFlight.current = true;
11698
+ setRecoveryConfirming(true);
11699
+ setError(null);
11700
+ try {
11701
+ const factor = recoveryFactorContext ?? {
11702
+ fullHandle: recoveryChoice,
11703
+ phone: ""
11704
+ };
11705
+ if (joinContext !== null) {
11706
+ const continued = await props.continueRecoveryForHandle?.(factor.fullHandle);
11707
+ if (continued !== void 0 && !continued.ok) return setError(continued.error);
11708
+ if (continued?.ok && continued.value) {
11709
+ setJoinContext(null);
11710
+ setRecoveryRiskConfirmed(true);
11711
+ return;
11712
+ }
11713
+ const recovery = await props.beginRecoveryFromDeviceJoin(factor);
11714
+ if (!recovery.ok) {
11715
+ cancelRecoveryChoice();
11716
+ props.refreshIdentityAccess?.();
11717
+ return setError(recovery.error);
11718
+ }
11719
+ setJoinContext(null);
11720
+ setRecoveryRiskConfirmed(true);
11721
+ if (recovery.value === null) return;
11722
+ recoveryCooldown.start(recovery.value.retryAfterSeconds);
11723
+ setRecoveryFactorContext({
11724
+ fullHandle: recovery.value.fullHandle,
11725
+ phone: factor.phone
11726
+ });
11727
+ } else {
11728
+ setRecoveryRiskConfirmed(true);
11729
+ if (factor.phone === "") return;
11730
+ const recovery = await props.sendRecoveryOtp(factor);
11731
+ if (!recovery.ok) return setError(recovery.error);
11732
+ recoveryCooldown.start(recovery.value.retryAfterSeconds);
11733
+ setRecoveryFactorContext({
11734
+ fullHandle: recovery.value.fullHandle,
11735
+ phone: factor.phone
11736
+ });
11737
+ }
11738
+ } finally {
11739
+ recoveryConfirmationInFlight.current = false;
11740
+ setRecoveryConfirming(false);
11741
+ }
11586
11742
  };
11587
11743
  (0, react.useEffect)(() => {
11588
11744
  if (props.sessionStatus !== "unregistered" || joinContext !== null || joinProgress !== null || props.access !== void 0 && props.access?.joining !== true || typeof props.getDeviceJoinStatus !== "function") {
@@ -11667,30 +11823,104 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11667
11823
  setDeviceRejoinHandle(currentHandle);
11668
11824
  resetIdentityEntry();
11669
11825
  };
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", {
11826
+ const signedOutRecoveryOpen = props.sessionStatus === "signed-out" && signedOutAlternative === "recover";
11827
+ const revokedHandle = props.sessionStatus === "recovery-required" ? props.identity?.handle : void 0;
11828
+ if (props.recoveryOperationId !== null && !signedOutRecoveryOpen) return (0, react_jsx_runtime.jsx)(Recovery, {
11829
+ ...props,
11830
+ onExit: exitRecovery,
11831
+ onExitLabel: props.sessionStatus === "signed-out" ? "返回本机身份" : "返回身份入口",
11832
+ ...recoveryFactorContext === null ? {} : { initialFactorContext: recoveryFactorContext },
11833
+ ...revokedHandle === void 0 ? {} : {
11834
+ fixedHandle: revokedHandle,
11835
+ requestTitle: "需要重新恢复身份",
11836
+ requestDescription: "这个 Handle 已在另一台设备完成了更新恢复,当前设备的旧凭证因此失效。验证绑定手机号后即可继续使用本机数据。"
11837
+ }
11838
+ });
11839
+ 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
11840
  role: "status",
11673
11841
  children: props.accessError ?? "正在确认本机身份操作…"
11674
- }), props.accessError && (0, react_jsx_runtime.jsx)("button", {
11842
+ }), props.accessError && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [props.sessionStatus === "recovery-required" && (0, react_jsx_runtime.jsx)("button", {
11675
11843
  type: "button",
11676
11844
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.primary,
11677
11845
  disabled: props.accessLoading,
11678
11846
  onClick: () => {
11679
- props.refreshIdentityAccess?.();
11847
+ setRecoveryEntryOpen(true);
11680
11848
  },
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
11849
+ children: "恢复身份"
11686
11850
  }), (0, react_jsx_runtime.jsx)("button", {
11687
11851
  type: "button",
11688
- className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.primary,
11852
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.secondary,
11853
+ disabled: props.accessLoading,
11689
11854
  onClick: () => {
11690
11855
  props.refreshIdentityAccess?.();
11691
11856
  },
11692
11857
  children: "重新检查身份状态"
11693
- })] });
11858
+ })] })] });
11859
+ if (!validRecoveryEntryOpen && props.accessError && props.recoveryOperationId === null) return (0, react_jsx_runtime.jsxs)(AwikiIdentityPage, { children: [
11860
+ (0, react_jsx_runtime.jsx)("p", {
11861
+ role: "alert",
11862
+ children: props.accessError
11863
+ }),
11864
+ props.sessionStatus === "recovery-required" && (0, react_jsx_runtime.jsx)("button", {
11865
+ type: "button",
11866
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.primary,
11867
+ onClick: () => {
11868
+ setRecoveryEntryOpen(true);
11869
+ },
11870
+ children: "恢复身份"
11871
+ }),
11872
+ (0, react_jsx_runtime.jsx)("button", {
11873
+ type: "button",
11874
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.secondary,
11875
+ onClick: () => {
11876
+ props.refreshIdentityAccess?.();
11877
+ },
11878
+ children: "重新检查身份状态"
11879
+ })
11880
+ ] });
11881
+ if (props.recoveryOperationId === null && recoveryChoice !== null && !recoveryRiskConfirmed) return (0, react_jsx_runtime.jsx)(AwikiIdentityPage, {
11882
+ onBack: cancelRecoveryChoice,
11883
+ backLabel: "返回设备加入",
11884
+ backDisabled: props.pending || recoveryConfirming,
11885
+ children: (0, react_jsx_runtime.jsxs)("div", {
11886
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.accessFlow,
11887
+ children: [
11888
+ (0, react_jsx_runtime.jsx)("div", {
11889
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.identityIcon,
11890
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 24 })
11891
+ }),
11892
+ (0, react_jsx_runtime.jsxs)("div", {
11893
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.headingGroup,
11894
+ children: [(0, react_jsx_runtime.jsx)("h3", { children: "确认替换此 Handle 的 DID" }), (0, react_jsx_runtime.jsx)("p", { children: "恢复会为这个 Handle 创建新的 DID,使其他设备的旧凭证失效。普通设备加入不会替换 DID,通常应优先使用。" })]
11895
+ }),
11896
+ (0, react_jsx_runtime.jsxs)("div", {
11897
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.dangerPanel,
11898
+ children: [(0, react_jsx_runtime.jsx)("strong", { children: recoveryChoice }), (0, react_jsx_runtime.jsx)("p", { children: "只有在无法通过已有管理设备完成普通加入时,才继续恢复。" })]
11899
+ }),
11900
+ (0, react_jsx_runtime.jsx)("button", {
11901
+ type: "button",
11902
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.dangerButton,
11903
+ disabled: props.pending || recoveryConfirming,
11904
+ onClick: () => {
11905
+ confirmRecoveryChoice();
11906
+ },
11907
+ children: "发送恢复验证码并替换 DID"
11908
+ }),
11909
+ (0, react_jsx_runtime.jsx)("button", {
11910
+ type: "button",
11911
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.secondary,
11912
+ disabled: props.pending || recoveryConfirming,
11913
+ onClick: cancelRecoveryChoice,
11914
+ children: "取消,返回普通加入"
11915
+ }),
11916
+ error !== null && (0, react_jsx_runtime.jsx)("small", {
11917
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.error,
11918
+ role: "alert",
11919
+ children: error
11920
+ })
11921
+ ]
11922
+ })
11923
+ });
11694
11924
  if (props.recoveryOperationId === null && recoveryChoice !== null) return (0, react_jsx_runtime.jsx)(Recovery, {
11695
11925
  ...props,
11696
11926
  requestError: error,
@@ -11718,18 +11948,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11718
11948
  },
11719
11949
  children: "重新检查加入状态"
11720
11950
  })] });
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, {
11951
+ if (props.sessionStatus === "recovery-required") return (0, react_jsx_runtime.jsx)(Recovery, {
11724
11952
  ...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
- }
11953
+ ...validRecoveryEntryOpen ? {
11954
+ onExit: () => {
11955
+ setRecoveryEntryOpen(false);
11956
+ },
11957
+ onExitLabel: "返回身份检查"
11958
+ } : {},
11959
+ ...revokedHandle === void 0 ? {} : { fixedHandle: revokedHandle },
11960
+ requestTitle: "需要重新恢复身份",
11961
+ requestDescription: "这个 Handle 已在另一台设备完成了更新恢复,当前设备的旧凭证因此失效。发送验证码会开始一次替换 DID 的恢复;请确认后再继续。"
11733
11962
  });
11734
11963
  if (props.sessionStatus === "device-rejoin-required") return (0, react_jsx_runtime.jsx)(AwikiIdentityPage, { children: (0, react_jsx_runtime.jsxs)("div", {
11735
11964
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.accessFlow,
@@ -11825,13 +12054,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11825
12054
  },
11826
12055
  children: "加入新设备(推荐)"
11827
12056
  }),
11828
- props.handleRecoveryPhoneEnabled && (0, react_jsx_runtime.jsx)("button", {
12057
+ (0, react_jsx_runtime.jsx)("button", {
11829
12058
  type: "button",
11830
12059
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.dangerLink,
11831
12060
  disabled: props.pending,
11832
- onClick: () => {
11833
- chooseRecovery();
11834
- },
12061
+ onClick: chooseRecovery,
11835
12062
  children: "恢复 Handle(会替换 DID)"
11836
12063
  }),
11837
12064
  (0, react_jsx_runtime.jsx)("button", {
@@ -11959,32 +12186,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11959
12186
  ]
11960
12187
  }) });
11961
12188
  }
11962
- return (0, react_jsx_runtime.jsxs)(AwikiIdentityPage, {
12189
+ return (0, react_jsx_runtime.jsx)(AwikiIdentityPage, {
11963
12190
  ...registrationOtpSent ? {
11964
12191
  onBack: resetIdentityEntry,
11965
12192
  backLabel: "修改身份信息"
11966
12193
  } : {},
11967
12194
  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", {
12195
+ children: (0, react_jsx_runtime.jsxs)("form", {
11988
12196
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.accessFlow,
11989
12197
  onSubmit: (event) => {
11990
12198
  event.preventDefault();
@@ -12005,6 +12213,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12005
12213
  value: handle,
12006
12214
  onChange: (event) => {
12007
12215
  setHandle(event.target.value);
12216
+ setShortHandleInviteNotice(false);
12008
12217
  },
12009
12218
  readOnly: registrationOtpSent || deviceRejoinHandle !== null,
12010
12219
  autoComplete: "username",
@@ -12051,6 +12260,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12051
12260
  },
12052
12261
  children: retrySeconds > 0 ? `${retrySeconds} 秒后重新获取` : "重新获取注册验证码"
12053
12262
  }),
12263
+ shortHandleInviteNotice && (0, react_jsx_runtime.jsx)("div", {
12264
+ className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.inviteNotice,
12265
+ role: "alert",
12266
+ children: "注册少于5位的handle需要使用邀请码,目前暂不支持自主注册。"
12267
+ }),
12054
12268
  notice !== null && (0, react_jsx_runtime.jsx)("small", {
12055
12269
  className: _dsh_awiki_css_AwikiIdentityAccess_module_css_default.notice,
12056
12270
  role: "status",
@@ -12062,7 +12276,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12062
12276
  children: error
12063
12277
  })
12064
12278
  ]
12065
- })]
12279
+ })
12066
12280
  });
12067
12281
  }
12068
12282
  //#endregion
@@ -12077,7 +12291,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12077
12291
  this.identity = identity;
12078
12292
  this.IdentityAccess = (props) => (0, react.createElement)(AwikiDraftProvider, {
12079
12293
  store: identity.drafts,
12080
- children: (0, react.createElement)(AwikiIdentityAccess, props)
12294
+ children: (0, react.createElement)(AwikiIdentityAccess, {
12295
+ ...props,
12296
+ inspectIdentityAccess: (request) => identity.inspectIdentityAccess(request)
12297
+ })
12081
12298
  });
12082
12299
  }
12083
12300
  clearLocalIdentity = async () => {
@@ -12423,6 +12640,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12423
12640
  }
12424
12641
  //#endregion
12425
12642
  //#region lib/types/client/controller.js
12643
+ const GENERIC_BUSINESS_FAILURE_MESSAGE = "AWiki 暂时无法完成此操作,请稍后重试。";
12644
+ const GENERIC_CARRIER_FAILURE_MESSAGE = "暂时无法连接 AWiki Host,请稍后重试。";
12645
+ const GENERIC_THROW_FAILURE_MESSAGE = "AWiki 调用暂时失败,请稍后重试。";
12646
+ /** Project only a stable business code into Browser copy; provider messages remain Host-only. */
12647
+ function genericFailureMessage(failure) {
12648
+ switch (failure.code) {
12649
+ case "network": return "无法连接 AWiki 服务,请检查网络后重试。";
12650
+ case "rate-limited": return "AWiki 请求过于频繁,请稍后重试。";
12651
+ case "not-registered": return "请先注册 AWiki 身份后重试。";
12652
+ case "signed-out": return "当前 AWiki 身份已退出,请重新进入后重试。";
12653
+ case "identity-recovery-required": return "当前设备的 AWiki 身份凭证已失效,请重新恢复身份。";
12654
+ case "device-rejoin-required": return "当前设备已被撤销,请重新申请加入。";
12655
+ default: return GENERIC_BUSINESS_FAILURE_MESSAGE;
12656
+ }
12657
+ }
12658
+ /** Carrier diagnostics are not a Browser contract, including for unknown carrier codes. */
12659
+ function genericCarrierFailureMessage(_failure) {
12660
+ return GENERIC_CARRIER_FAILURE_MESSAGE;
12661
+ }
12426
12662
  /** Turn a registration rejection into an actionable message without exposing remote response text. */
12427
12663
  function registrationFailureMessage(failure) {
12428
12664
  switch (failure.code) {
@@ -12431,18 +12667,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12431
12667
  case "invalid-otp": return "验证码不正确,请检查后重试。";
12432
12668
  case "challenge-expired": return "验证码状态已失效,请重新获取验证码后再注册。";
12433
12669
  case "handle-unavailable": return "该 Handle 刚刚已被注册。请返回身份入口,再按恢复流程重新获取验证码。";
12670
+ case "short-handle-invite-required": return SHORT_HANDLE_INVITE_MESSAGE;
12434
12671
  case "conflict": return "注册冲突:服务端可能已收到上次注册请求,或该手机号 / Handle 已绑定其他身份。请保留当前页面并再次提交;若仍失败,请勿清除本机身份数据,联系管理员并提供失败时间。";
12435
12672
  case "rate-limited": return "注册请求过于频繁,请稍后重试。";
12436
12673
  case "network": return "无法连接 AWiki 服务,请检查网络后重试。";
12437
12674
  case "identity-recovery-required": return "这台设备保留了原 AWiki 身份,但本地登录状态已被清除。请先恢复该身份或完整清除这台设备上的 AWiki 身份数据,再重新注册。";
12438
12675
  case "forbidden": return "当前 AWiki 服务未开放公开注册,或该手机号不在注册白名单。请使用已获准的手机号,或联系管理员开通注册权限。";
12439
12676
  case "remote": return "AWiki 服务暂时无法完成注册,请稍后重试;若持续失败,请联系管理员并提供失败时间。";
12440
- default: return `${failure.code}:${failure.message}`;
12677
+ default: return "AWiki 服务暂时无法完成注册,请稍后重试;若持续失败,请联系管理员并提供失败时间。";
12441
12678
  }
12442
12679
  }
12443
12680
  /** Turn a verification-code request failure into a safe next action. */
12444
12681
  function registrationOtpFailureMessage(failure) {
12445
12682
  switch (failure.code) {
12683
+ case "short-handle-invite-required": return SHORT_HANDLE_INVITE_MESSAGE;
12446
12684
  case "rate-limited": return "验证码发送过于频繁,请等待限流解除后再重新获取。";
12447
12685
  case "invalid-request": return "无法发送验证码,请检查手机号和 Handle 后重试。";
12448
12686
  case "forbidden": return "当前 AWiki 服务未向该手机号开放注册,请联系管理员。";
@@ -12459,7 +12697,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12459
12697
  case "rate-limited": return "恢复验证过于频繁,请稍后重试。";
12460
12698
  case "network": return "无法连接 AWiki 服务,请检查网络后重试。";
12461
12699
  case "remote": return "AWiki 服务暂时无法验证恢复信息,请稍后重试。";
12462
- default: return `${failure.code}:${failure.message}`;
12700
+ default: return "AWiki 服务暂时无法验证恢复信息,请稍后重试。";
12463
12701
  }
12464
12702
  }
12465
12703
  function recoveryContinuationFailureMessage(failure, phase) {
@@ -12477,7 +12715,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12477
12715
  case "rate-limited": return "恢复状态检查过于频繁,请稍后继续。";
12478
12716
  case "remote":
12479
12717
  case "forbidden": return "AWiki 服务暂时未能完成恢复。可以重新检查结果,或返回入口稍后继续。";
12480
- default: return `${failure.code}:${failure.message}`;
12718
+ default: return "身份恢复暂未完成。请保留当前恢复操作并重新检查状态,不要重新获取验证码或创建新身份。";
12481
12719
  }
12482
12720
  }
12483
12721
  function identityAccessInspectionFailureMessage(failure) {
@@ -12485,9 +12723,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12485
12723
  case "invalid-request": return "Handle 格式不正确,请检查后重试。";
12486
12724
  case "network": return "无法连接 AWiki 服务,暂时不能确认该 Handle 是否已经存在。";
12487
12725
  case "remote": return "AWiki 服务暂时无法确认该 Handle 的状态,请稍后重试。";
12488
- default: return `${failure.code}:${failure.message}`;
12726
+ default: return "AWiki 服务暂时无法确认该 Handle 的状态,请稍后重试。";
12489
12727
  }
12490
12728
  }
12729
+ const IDENTITY_ACCESS_FAILURE_MESSAGE = "暂时无法读取本机身份状态,请稍后重新检查。";
12491
12730
  const INITIAL_VIEW = Object.freeze({
12492
12731
  status: "cold",
12493
12732
  sessionStatus: "unregistered",
@@ -12514,7 +12753,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12514
12753
  accessLoading: true,
12515
12754
  accessError: null,
12516
12755
  recoveryOperationId: null,
12517
- recoveryProgress: null
12756
+ recoveryProgress: null,
12757
+ recoveryOtpRetryAt: null
12518
12758
  });
12519
12759
  /** Turn a closed Host summary failure into one actionable Chinese message. */
12520
12760
  function summaryFailureMessage(failure) {
@@ -12524,7 +12764,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12524
12764
  case "summary-cancelled": return "AI 总结已取消,请重新生成。";
12525
12765
  case "summary-invalid-output": return "模型没有返回有效的结构化摘要,请重新生成。";
12526
12766
  case "summary-failed": return "暂时无法生成 AI 总结,请检查模型连接后重试。";
12527
- default: return `${failure.code}:${failure.message}`;
12767
+ default: return "暂时无法生成 AI 总结,请检查模型连接后重试。";
12528
12768
  }
12529
12769
  }
12530
12770
  /** Turn closed mail failures into safe, actionable browser messages. */
@@ -12552,7 +12792,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12552
12792
  case "network": return "无法连接 AWiki 服务,请检查网络后重试。";
12553
12793
  case "conflict": return "群聊创建状态发生冲突,请刷新群聊列表后确认是否已经创建。";
12554
12794
  case "remote": return "AWiki 服务暂时无法创建群聊,请稍后重试。";
12555
- default: return `${failure.code}:${failure.message}`;
12795
+ default: return "AWiki 服务暂时无法创建群聊,请稍后重试。";
12556
12796
  }
12557
12797
  }
12558
12798
  /** Keep group authorization failures actionable without exposing raw service text. */
@@ -12564,7 +12804,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12564
12804
  case "forbidden": return "当前身份没有访问这个群聊的权限。";
12565
12805
  case "network": return "无法连接 AWiki 群聊服务,请检查网络后重试。";
12566
12806
  case "remote": return "AWiki 暂时无法读取这个群聊,请稍后重试。";
12567
- default: return `${failure.code}:${failure.message}`;
12807
+ default: return "AWiki 暂时无法读取这个群聊,请稍后重试。";
12568
12808
  }
12569
12809
  }
12570
12810
  function conversationPreferenceFailureMessage(_failure) {
@@ -12605,12 +12845,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12605
12845
  }
12606
12846
  }
12607
12847
  /** 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}`) {
12848
+ async function call(operation, failureMessage = genericFailureMessage, carrierFailureMessage = genericCarrierFailureMessage) {
12609
12849
  try {
12610
12850
  const carried = await operation();
12611
12851
  if (!carried.ok) return {
12612
12852
  ok: false,
12613
- error: carrierFailureMessage(carried.error.message)
12853
+ error: carrierFailureMessage(carried.error)
12614
12854
  };
12615
12855
  if (!carried.value.ok) return {
12616
12856
  ok: false,
@@ -12620,10 +12860,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12620
12860
  ok: true,
12621
12861
  value: carried.value.value
12622
12862
  };
12623
- } catch (error) {
12863
+ } catch {
12624
12864
  return {
12625
12865
  ok: false,
12626
- error: error instanceof Error ? `AWiki 调用失败:${error.message}` : "AWiki 调用失败"
12866
+ error: GENERIC_THROW_FAILURE_MESSAGE
12627
12867
  };
12628
12868
  }
12629
12869
  }
@@ -12633,12 +12873,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12633
12873
  const carried = await operation();
12634
12874
  if (!carried.ok) return {
12635
12875
  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
12876
+ error: genericCarrierFailureMessage(carried.error)
12641
12877
  };
12878
+ if (!carried.value.ok) {
12879
+ const failure = carried.value.error;
12880
+ return {
12881
+ ok: false,
12882
+ 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 操作过于频繁,请稍后重试。" : "临时消息服务暂时不可用,请稍后重试。",
12883
+ failureCode: failure.code
12884
+ };
12885
+ }
12642
12886
  return {
12643
12887
  ok: true,
12644
12888
  value: carried.value.value
@@ -12651,31 +12895,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12651
12895
  }
12652
12896
  }
12653
12897
  /** Preserve only the stable business code for controller-level state transitions. */
12654
- async function callWithFailureCode(operation) {
12898
+ async function callWithFailureCode(operation, failureMessage = genericFailureMessage) {
12655
12899
  try {
12656
12900
  const carried = await operation();
12657
12901
  if (!carried.ok) return {
12658
12902
  ok: false,
12659
- error: `连接 AWiki Host 失败:${carried.error.message}`
12903
+ error: genericCarrierFailureMessage(carried.error)
12660
12904
  };
12661
12905
  if (!carried.value.ok) return {
12662
12906
  ok: false,
12663
- error: `${carried.value.error.code}:${carried.value.error.message}`,
12907
+ error: failureMessage(carried.value.error),
12664
12908
  failureCode: carried.value.error.code
12665
12909
  };
12666
12910
  return {
12667
12911
  ok: true,
12668
12912
  value: carried.value.value
12669
12913
  };
12670
- } catch (error) {
12914
+ } catch {
12671
12915
  return {
12672
12916
  ok: false,
12673
- error: error instanceof Error ? `AWiki 调用失败:${error.message}` : "AWiki 调用失败"
12917
+ error: GENERIC_THROW_FAILURE_MESSAGE
12674
12918
  };
12675
12919
  }
12676
12920
  }
12677
- function recoveryCarrierFailureMessage(message) {
12678
- return message.includes("business result failed boundary validation") ? "恢复信息已验证,但暂时无法读取恢复状态。请稍后重试。" : `连接 AWiki Host 失败:${message}`;
12921
+ function recoveryCarrierFailureMessage(failure) {
12922
+ return failure.code === "invalid-response" ? "恢复信息已验证,但暂时无法读取恢复状态。请稍后重试。" : "暂时无法连接 AWiki Host,无法完成身份恢复。请稍后重试。";
12679
12923
  }
12680
12924
  /** Append unique values while retaining existing references. */
12681
12925
  function appendUnique(current, incoming, id) {
@@ -12771,9 +13015,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12771
13015
  /** Runtime-only decoded-byte budget that prevents repeat Host calls while browsing. */
12772
13016
  const BROWSER_IMAGE_ATTACHMENT_CACHE_MAX_BYTES = 33554432;
12773
13017
  const RECOVERY_OPERATION_STORAGE_KEY = "awiki.handle-recovery.operation.v1";
13018
+ const RECOVERY_OTP_RETRY_STORAGE_KEY = "awiki.handle-recovery.retry-at.v1";
12774
13019
  function recoveryOperationStorageKey(tenantId) {
12775
13020
  return tenantId === void 0 || tenantId === "" ? RECOVERY_OPERATION_STORAGE_KEY : `${RECOVERY_OPERATION_STORAGE_KEY}.${encodeURIComponent(tenantId)}`;
12776
13021
  }
13022
+ function recoveryTenantKey(tenantId) {
13023
+ return tenantId === void 0 || tenantId === "" ? "default" : tenantId;
13024
+ }
12777
13025
  function storeRecoveryOperation(operationId, tenantId) {
12778
13026
  try {
12779
13027
  const key = recoveryOperationStorageKey(tenantId);
@@ -12781,6 +13029,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12781
13029
  else globalThis.localStorage?.setItem(key, operationId);
12782
13030
  } catch {}
12783
13031
  }
13032
+ function recoveryOtpRetryStorageKey(operationId, tenantId) {
13033
+ return `${RECOVERY_OTP_RETRY_STORAGE_KEY}.${encodeURIComponent(recoveryTenantKey(tenantId))}.${encodeURIComponent(operationId)}`;
13034
+ }
13035
+ function recoveryOtpRetryAt(result) {
13036
+ const advertised = Date.parse(result.retryAt);
13037
+ const deadline = Number.isFinite(advertised) ? advertised : Date.now() + Math.max(0, result.retryAfterSeconds) * 1e3;
13038
+ return new Date(deadline).toISOString();
13039
+ }
13040
+ function storedRecoveryOtpRetryAt(operationId, tenantId) {
13041
+ if (operationId === null) return null;
13042
+ try {
13043
+ const key = recoveryOtpRetryStorageKey(operationId, tenantId);
13044
+ const value = globalThis.localStorage?.getItem(key);
13045
+ if (value === null || value === void 0) return null;
13046
+ const deadline = Date.parse(value);
13047
+ if (!Number.isFinite(deadline) || deadline <= Date.now()) {
13048
+ globalThis.localStorage?.removeItem(key);
13049
+ return null;
13050
+ }
13051
+ return new Date(deadline).toISOString();
13052
+ } catch {
13053
+ return null;
13054
+ }
13055
+ }
13056
+ function storeRecoveryOtpRetryAt(operationId, retryAt, tenantId) {
13057
+ try {
13058
+ globalThis.localStorage?.setItem(recoveryOtpRetryStorageKey(operationId, tenantId), retryAt);
13059
+ } catch {}
13060
+ }
13061
+ function clearRecoveryOtpRetryAt(operationId, tenantId) {
13062
+ if (operationId === null) return;
13063
+ try {
13064
+ globalThis.localStorage?.removeItem(recoveryOtpRetryStorageKey(operationId, tenantId));
13065
+ } catch {}
13066
+ }
12784
13067
  /** Wait between group-history readiness probes without retaining controller state. */
12785
13068
  function delay(milliseconds) {
12786
13069
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
@@ -12833,6 +13116,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12833
13116
  drafts = new AwikiDraftStore();
12834
13117
  view = INITIAL_VIEW;
12835
13118
  listeners = /* @__PURE__ */ new Set();
13119
+ /** Runtime-only selected operations survive tenant round trips without reopening stale browser hints after reload. */
13120
+ recoveryOperationsByTenant = /* @__PURE__ */ new Map();
12836
13121
  config = null;
12837
13122
  conversationsCursor;
12838
13123
  historyCursor;
@@ -12924,6 +13209,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12924
13209
  const sameOwner = preserveView && previousTenant === config.value.tenantId && previous.sessionStatus === session.value.status && previous.identity?.did === identity?.did;
12925
13210
  this.drafts.setScope(config.value.tenantId ?? "default", identity?.did ?? session.value.status);
12926
13211
  this.activatePresentationCache(identity);
13212
+ const selectedRecovery = previousTenant === config.value.tenantId ? previous.recoveryOperationId : this.recoveryOperationsByTenant.get(recoveryTenantKey(config.value.tenantId)) ?? null;
12927
13213
  this.publish({
12928
13214
  ...sameOwner ? this.view : INITIAL_VIEW,
12929
13215
  status: "ready",
@@ -12932,7 +13218,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12932
13218
  error: null,
12933
13219
  attachmentMaxBytes: config.value.attachmentMaxBytes,
12934
13220
  handleRecoveryPhoneEnabled: config.value.handleRecoveryPhoneEnabled,
12935
- recoveryOperationId: previousTenant === config.value.tenantId ? previous.recoveryOperationId : null
13221
+ recoveryOperationId: selectedRecovery,
13222
+ recoveryOtpRetryAt: storedRecoveryOtpRetryAt(selectedRecovery, config.value.tenantId)
12936
13223
  });
12937
13224
  await this.refreshIdentityAccess();
12938
13225
  if (!this.current(generation)) return {
@@ -13095,7 +13382,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13095
13382
  * @returns challenge retry metadata or one display-safe failure.
13096
13383
  */
13097
13384
  async sendRegistrationOtp(request) {
13098
- return this.withPending("发送验证码", () => call(() => this.remote.sendRegistrationOtp(request), registrationOtpFailureMessage));
13385
+ const result = await this.withPending("发送验证码", () => callWithFailureCode(() => this.remote.sendRegistrationOtp(request), registrationOtpFailureMessage));
13386
+ return !result.ok && result.failureCode !== "short-handle-invite-required" ? {
13387
+ ok: false,
13388
+ error: result.error
13389
+ } : result;
13099
13390
  }
13100
13391
  /** Discover Core-owned work without selecting an account or activating a session. */
13101
13392
  refreshIdentityAccess() {
@@ -13122,42 +13413,56 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13122
13413
  this.publish({
13123
13414
  ...this.view,
13124
13415
  accessLoading: false,
13125
- accessError: result.error
13416
+ accessError: IDENTITY_ACCESS_FAILURE_MESSAGE
13126
13417
  });
13127
- return result;
13418
+ return {
13419
+ ok: false,
13420
+ error: IDENTITY_ACCESS_FAILURE_MESSAGE
13421
+ };
13128
13422
  }
13129
13423
  const candidates = result.value.recoveries;
13130
13424
  const selected = this.view.recoveryOperationId;
13131
13425
  this.publish({
13132
13426
  ...this.view,
13133
- identityAccess: result.value
13427
+ identityAccess: result.value,
13428
+ recoveryOperationId: selected,
13429
+ recoveryProgress: selected === this.view.recoveryOperationId ? this.view.recoveryProgress : null,
13430
+ recoveryOtpRetryAt: storedRecoveryOtpRetryAt(selected, this.config?.tenantId)
13134
13431
  });
13135
13432
  if (selected !== null) {
13136
13433
  const status = await callWithFailureCode(() => this.remote.getRecoveryStatus({ operationId: selected }));
13137
13434
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13138
13435
  if (!status.ok) {
13139
13436
  if (status.failureCode === "not-found" && candidates.length === 0) {
13140
- storeRecoveryOperation(null, this.config?.tenantId);
13437
+ clearRecoveryOtpRetryAt(selected, this.config?.tenantId);
13438
+ this.rememberRecoveryOperation(null, this.config?.tenantId);
13141
13439
  this.publish({
13142
13440
  ...this.view,
13143
13441
  recoveryOperationId: null,
13144
- recoveryProgress: null
13442
+ recoveryProgress: null,
13443
+ recoveryOtpRetryAt: null
13145
13444
  });
13146
13445
  } else {
13147
13446
  this.publish({
13148
13447
  ...this.view,
13149
13448
  accessLoading: false,
13150
- accessError: status.error
13449
+ accessError: IDENTITY_ACCESS_FAILURE_MESSAGE
13151
13450
  });
13152
13451
  return {
13153
13452
  ok: false,
13154
- error: status.error
13453
+ error: IDENTITY_ACCESS_FAILURE_MESSAGE
13155
13454
  };
13156
13455
  }
13157
- } else this.publish({
13158
- ...this.view,
13159
- recoveryProgress: status.value
13160
- });
13456
+ } else {
13457
+ const complete = status.value.phase === "applied";
13458
+ if (complete) clearRecoveryOtpRetryAt(selected, this.config?.tenantId);
13459
+ this.publish({
13460
+ ...this.view,
13461
+ recoveryProgress: status.value,
13462
+ recoveryOtpRetryAt: complete ? null : storedRecoveryOtpRetryAt(selected, this.config?.tenantId),
13463
+ identityAccess: result.value
13464
+ });
13465
+ }
13161
13466
  }
13162
13467
  this.publish({
13163
13468
  ...this.view,
@@ -13176,10 +13481,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13176
13481
  };
13177
13482
  if (this.view.recoveryOperationId !== null) this.leaveRecovery();
13178
13483
  else this.recoveryRevision++;
13484
+ this.rememberRecoveryOperation(operationId, this.config?.tenantId);
13179
13485
  this.publish({
13180
13486
  ...this.view,
13181
13487
  recoveryOperationId: operationId,
13182
- recoveryProgress: null
13488
+ recoveryProgress: null,
13489
+ recoveryOtpRetryAt: storedRecoveryOtpRetryAt(operationId, this.config?.tenantId)
13183
13490
  });
13184
13491
  const result = await this.refreshRecoveryStatus();
13185
13492
  return result.ok ? {
@@ -13198,6 +13505,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13198
13505
  error: "已离开此恢复流程;进度保留在本机。"
13199
13506
  };
13200
13507
  }
13508
+ rememberRecoveryOperation(operationId, tenantId) {
13509
+ const key = recoveryTenantKey(tenantId);
13510
+ if (operationId === null) {
13511
+ this.recoveryOperationsByTenant.delete(key);
13512
+ storeRecoveryOperation(null, tenantId);
13513
+ } else this.recoveryOperationsByTenant.set(key, operationId);
13514
+ }
13201
13515
  /** Navigation only. Never cancel or delete the Core-owned operation. */
13202
13516
  leaveRecovery() {
13203
13517
  this.recoveryRevision++;
@@ -13206,7 +13520,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13206
13520
  if (wasPending) this.pendingRequest = void 0;
13207
13521
  this.pendingRecovery = false;
13208
13522
  this.drafts.clearFlow();
13209
- storeRecoveryOperation(null, this.config?.tenantId);
13523
+ this.rememberRecoveryOperation(null, this.config?.tenantId);
13210
13524
  this.publish({
13211
13525
  ...this.view,
13212
13526
  recoveryOperationId: null,
@@ -13320,6 +13634,77 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13320
13634
  } : result;
13321
13635
  });
13322
13636
  }
13637
+ /** Cancel one exact Join choice and send Recovery OTP only while its original browser scope remains current. */
13638
+ async beginRecoveryFromDeviceJoin(request) {
13639
+ const generation = this.generation;
13640
+ const tenantId = this.config?.tenantId;
13641
+ const flowScope = this.drafts.getScope("recovery:retryDeadline");
13642
+ const flowEpoch = this.drafts.epoch(flowScope);
13643
+ const changed = () => ({
13644
+ ok: false,
13645
+ error: "恢复能力或身份环境已改变,请重新检查后再选择。"
13646
+ });
13647
+ const scopeCurrent = () => this.current(generation) && this.config?.tenantId === tenantId && this.drafts.getScope("recovery:retryDeadline") === flowScope && this.drafts.epoch(flowScope) === flowEpoch;
13648
+ if (!scopeCurrent()) return changed();
13649
+ const latest = await call(() => this.remote.getConfig());
13650
+ if (!scopeCurrent()) return changed();
13651
+ if (!latest.ok) return {
13652
+ ok: false,
13653
+ error: "暂时无法确认服务器的恢复能力,请稍后重试。"
13654
+ };
13655
+ if (latest.value.tenantId !== tenantId) return changed();
13656
+ this.config = latest.value;
13657
+ this.publish({
13658
+ ...this.view,
13659
+ handleRecoveryPhoneEnabled: latest.value.handleRecoveryPhoneEnabled
13660
+ });
13661
+ if (latest.value.tenantOnline === false) return {
13662
+ ok: false,
13663
+ error: "暂时无法确认服务器的恢复能力,请稍后重试。"
13664
+ };
13665
+ if (!latest.value.handleRecoveryPhoneEnabled) return {
13666
+ ok: false,
13667
+ error: "当前服务器未启用手机号恢复,请加入新设备或联系管理员。"
13668
+ };
13669
+ const current = () => scopeCurrent() && this.config?.handleRecoveryPhoneEnabled === true;
13670
+ const result = await this.withPending("开始恢复身份", async () => {
13671
+ const discarded = await call(() => this.remote.cancelDeviceJoin());
13672
+ if (!discarded.ok) return discarded;
13673
+ if (!current()) return changed();
13674
+ this.publish({
13675
+ ...this.view,
13676
+ identityAccess: {
13677
+ choice: null,
13678
+ joining: false,
13679
+ recoveries: []
13680
+ }
13681
+ });
13682
+ if (request.phone === "") return {
13683
+ ok: true,
13684
+ value: null
13685
+ };
13686
+ return call(() => this.remote.sendRecoveryOtp(request), registrationOtpFailureMessage);
13687
+ }, {
13688
+ publishFailure: false,
13689
+ recovery: true
13690
+ });
13691
+ if (!result.ok) {
13692
+ if (current()) await this.continueRecoveryForHandle(request.fullHandle);
13693
+ return result;
13694
+ }
13695
+ if (result.value === null) return result;
13696
+ this.recordRecoveryOtp(result.value, tenantId);
13697
+ if (!(this.config?.tenantId === tenantId && this.drafts.getScope("recovery:retryDeadline") === flowScope && this.drafts.epoch(flowScope) === flowEpoch)) return result;
13698
+ const retryAt = recoveryOtpRetryAt(result.value);
13699
+ this.publish({
13700
+ ...this.view,
13701
+ recoveryOperationId: result.value.operationId,
13702
+ recoveryProgress: null,
13703
+ recoveryOtpRetryAt: retryAt
13704
+ });
13705
+ await this.refreshRecoveryStatus();
13706
+ return result;
13707
+ }
13323
13708
  retireDeviceIdentityForRejoin() {
13324
13709
  return this.withPending("准备重新加入设备", async () => {
13325
13710
  const result = await call(() => this.remote.retireDeviceIdentityForRejoin());
@@ -13408,23 +13793,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13408
13793
  async sendRecoveryOtp(request) {
13409
13794
  const generation = this.generation;
13410
13795
  const revision = this.recoveryRevision;
13796
+ const tenantId = this.config?.tenantId;
13797
+ const flowScope = this.drafts.getScope("recovery:retryDeadline");
13411
13798
  const result = await this.withPending("发送恢复验证码", () => call(() => this.remote.sendRecoveryOtp(request), registrationOtpFailureMessage), {
13412
13799
  publishFailure: false,
13413
13800
  recovery: true
13414
13801
  });
13415
- if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13416
13802
  if (!result.ok) {
13803
+ if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13417
13804
  await this.continueRecoveryForHandle(request.fullHandle);
13418
13805
  return result;
13419
13806
  }
13807
+ this.recordRecoveryOtp(result.value, tenantId);
13808
+ if (!this.recoveryCurrent(generation, revision) || this.config?.tenantId !== tenantId || this.drafts.getScope("recovery:retryDeadline") !== flowScope) return result;
13420
13809
  this.publish({
13421
13810
  ...this.view,
13422
13811
  recoveryOperationId: result.value.operationId,
13423
- recoveryProgress: null
13812
+ recoveryProgress: null,
13813
+ recoveryOtpRetryAt: recoveryOtpRetryAt(result.value)
13424
13814
  });
13425
13815
  await this.refreshRecoveryStatus();
13426
13816
  return this.recoveryCurrent(generation, revision) ? result : this.recoveryLeft();
13427
13817
  }
13818
+ recordRecoveryOtp(result, tenantId) {
13819
+ this.rememberRecoveryOperation(result.operationId, tenantId);
13820
+ storeRecoveryOtpRetryAt(result.operationId, recoveryOtpRetryAt(result), tenantId);
13821
+ }
13428
13822
  /** Publish results only into the exact selected flow; Core work survives navigation. */
13429
13823
  async runRecovery(label, operation, enterWhenApplied = false) {
13430
13824
  const generation = this.generation;
@@ -13440,12 +13834,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13440
13834
  });
13441
13835
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13442
13836
  if (!result.ok) {
13443
- const status = await call(() => this.remote.getRecoveryStatus({ operationId }));
13837
+ const status = await call(() => this.remote.getRecoveryStatus({ operationId }), void 0, recoveryCarrierFailureMessage);
13444
13838
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13445
13839
  this.publish({
13446
13840
  ...this.view,
13447
13841
  recoveryProgress: status.ok ? status.value : this.view.recoveryProgress,
13448
- accessError: status.ok ? null : status.error
13842
+ accessError: status.ok ? null : IDENTITY_ACCESS_FAILURE_MESSAGE
13449
13843
  });
13450
13844
  return result;
13451
13845
  }
@@ -13454,6 +13848,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13454
13848
  recoveryProgress: result.value,
13455
13849
  accessError: null
13456
13850
  });
13851
+ if (result.value.phase === "applied") clearRecoveryOtpRetryAt(operationId, this.config?.tenantId);
13457
13852
  if (enterWhenApplied && result.value.phase === "applied") return this.enterRecoveredSession();
13458
13853
  return result;
13459
13854
  }
@@ -13477,7 +13872,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13477
13872
  }
13478
13873
  /** Read-only even for applied operations. Entering the identity is a separate action. */
13479
13874
  async refreshRecoveryStatus() {
13480
- return this.runRecovery("刷新恢复状态", (operationId) => call(() => this.remote.getRecoveryStatus({ operationId }), void 0, recoveryCarrierFailureMessage));
13875
+ const generation = this.generation;
13876
+ const revision = this.recoveryRevision;
13877
+ const operationId = this.view.recoveryOperationId;
13878
+ if (operationId === null) return {
13879
+ ok: false,
13880
+ error: "没有可查询的身份恢复操作"
13881
+ };
13882
+ const result = await this.withPending("刷新恢复状态", async () => {
13883
+ const status = await call(() => this.remote.getRecoveryStatus({ operationId }), void 0, recoveryCarrierFailureMessage);
13884
+ return status.ok ? status : {
13885
+ ok: false,
13886
+ error: IDENTITY_ACCESS_FAILURE_MESSAGE
13887
+ };
13888
+ }, {
13889
+ publishFailure: false,
13890
+ recovery: true
13891
+ });
13892
+ if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13893
+ if (!result.ok) {
13894
+ this.publish({
13895
+ ...this.view,
13896
+ accessError: IDENTITY_ACCESS_FAILURE_MESSAGE
13897
+ });
13898
+ return result;
13899
+ }
13900
+ this.publish({
13901
+ ...this.view,
13902
+ recoveryProgress: result.value,
13903
+ accessError: null
13904
+ });
13905
+ if (result.value.phase === "applied") clearRecoveryOtpRetryAt(operationId, this.config?.tenantId);
13906
+ return result;
13481
13907
  }
13482
13908
  async resumeRecovery() {
13483
13909
  const progress = this.view.recoveryProgress;
@@ -13501,6 +13927,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13501
13927
  });
13502
13928
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13503
13929
  if (!result.ok) return result;
13930
+ clearRecoveryOtpRetryAt(progress.operationId, this.config?.tenantId);
13504
13931
  this.leaveRecovery();
13505
13932
  const opened = await this.open();
13506
13933
  return opened.ok ? result : opened;
@@ -13524,6 +13951,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13524
13951
  });
13525
13952
  if (!this.recoveryCurrent(generation, revision)) return this.recoveryLeft();
13526
13953
  if (!result.ok) return result;
13954
+ clearRecoveryOtpRetryAt(operationId, this.config?.tenantId);
13527
13955
  this.leaveRecovery();
13528
13956
  this.refreshIdentityAccess();
13529
13957
  return {
@@ -13677,8 +14105,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13677
14105
  return this.selectConversation(existing.id);
13678
14106
  }
13679
14107
  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;
14108
+ const resolved = await this.withPending("查找用户", async () => {
14109
+ const result = await callWithFailureCode(() => this.remote.resolvePeer({ peer }));
14110
+ if (!result.ok) return {
14111
+ ok: false,
14112
+ error: result.failureCode === "not-found" ? "该 Handle 不存在" : result.error
14113
+ };
14114
+ return result;
14115
+ });
14116
+ if (!resolved.ok) return resolved;
13682
14117
  if (!this.current(generation)) return {
13683
14118
  ok: true,
13684
14119
  value: void 0
@@ -14355,11 +14790,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14355
14790
  clearMailBrowserCache(globalThis.localStorage, owner);
14356
14791
  } catch {}
14357
14792
  }
14358
- storeRecoveryOperation(null, tenantId);
14793
+ clearRecoveryOtpRetryAt(this.view.recoveryOperationId, tenantId);
14794
+ this.rememberRecoveryOperation(null, tenantId);
14359
14795
  if (!this.current(generation)) return result;
14360
14796
  this.drafts.clearScope();
14361
14797
  this.close();
14362
- this.config = null;
14363
14798
  this.conversationsCursor = void 0;
14364
14799
  this.historyCursor = void 0;
14365
14800
  this.unreadAtOpen.clear();
@@ -14369,6 +14804,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14369
14804
  ...INITIAL_VIEW,
14370
14805
  status: "ready",
14371
14806
  accessLoading: false,
14807
+ attachmentMaxBytes: this.config?.attachmentMaxBytes ?? INITIAL_VIEW.attachmentMaxBytes,
14808
+ handleRecoveryPhoneEnabled: this.config?.handleRecoveryPhoneEnabled ?? false,
14372
14809
  identityAccess: {
14373
14810
  choice: null,
14374
14811
  joining: false,
@@ -19379,15 +19816,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19379
19816
  className: _dsh_awiki_css_AwikiOverlay_module_css_default.identityAccess,
19380
19817
  children: (0, react_jsx_runtime.jsx)(AwikiIdentityAccess, {
19381
19818
  ...props,
19382
- sessionStatus: view.sessionStatus === "active" ? "recovery-required" : view.sessionStatus,
19819
+ sessionStatus: view.sessionStatus,
19383
19820
  access: view.identityAccess,
19384
19821
  accessLoading: view.accessLoading,
19385
19822
  accessError: view.accessError,
19386
19823
  identity: view.identity,
19387
19824
  recoveryOperationId: view.recoveryOperationId,
19388
19825
  recoveryProgress: view.recoveryProgress,
19389
- pending: view.pending !== null,
19390
- handleRecoveryPhoneEnabled: view.handleRecoveryPhoneEnabled
19826
+ recoveryOtpRetryAt: view.recoveryOtpRetryAt,
19827
+ pending: view.pending !== null
19391
19828
  })
19392
19829
  }),
19393
19830
  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", {
@@ -19912,7 +20349,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19912
20349
  }),
19913
20350
  (0, react_jsx_runtime.jsx)("p", {
19914
20351
  className: _dsh_awiki_css_AwikiSettingsSection_module_css_default.description,
19915
- children: t("updateCurrent", { version: update?.currentPluginVersion ?? "0.3.10" })
20352
+ children: t("updateCurrent", { version: update?.currentPluginVersion ?? "0.3.11-rc.1" })
19916
20353
  }),
19917
20354
  update !== void 0 && (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: update.currentModelProxyVersion !== void 0 && (0, react_jsx_runtime.jsx)("p", {
19918
20355
  className: _dsh_awiki_css_AwikiSettingsSection_module_css_default.description,
@@ -20847,6 +21284,752 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20847
21284
  ]) target.removeItem(key(kind));
20848
21285
  }
20849
21286
  //#endregion
21287
+ //#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
21288
+ const createStoreImpl = (createState) => {
21289
+ let state;
21290
+ const listeners = /* @__PURE__ */ new Set();
21291
+ const setState = (partial, replace) => {
21292
+ const nextState = typeof partial === "function" ? partial(state) : partial;
21293
+ if (!Object.is(nextState, state)) {
21294
+ const previousState = state;
21295
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
21296
+ listeners.forEach((listener) => listener(state, previousState));
21297
+ }
21298
+ };
21299
+ const getState = () => state;
21300
+ const subscribe = (listener) => {
21301
+ listeners.add(listener);
21302
+ return () => listeners.delete(listener);
21303
+ };
21304
+ const destroy = () => {
21305
+ listeners.clear();
21306
+ };
21307
+ const api = {
21308
+ setState,
21309
+ getState,
21310
+ subscribe,
21311
+ destroy
21312
+ };
21313
+ state = createState(setState, getState, api);
21314
+ return api;
21315
+ };
21316
+ const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
21317
+ //#endregion
21318
+ //#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
21319
+ const subscribeWithSelectorImpl = (fn) => (set, get, api) => {
21320
+ const origSubscribe = api.subscribe;
21321
+ api.subscribe = (selector, optListener, options) => {
21322
+ let listener = selector;
21323
+ if (optListener) {
21324
+ const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;
21325
+ let currentSlice = selector(api.getState());
21326
+ listener = (state) => {
21327
+ const nextSlice = selector(state);
21328
+ if (!equalityFn(currentSlice, nextSlice)) {
21329
+ const previousSlice = currentSlice;
21330
+ optListener(currentSlice = nextSlice, previousSlice);
21331
+ }
21332
+ };
21333
+ if (options == null ? void 0 : options.fireImmediately) optListener(currentSlice, currentSlice);
21334
+ }
21335
+ return origSubscribe(listener);
21336
+ };
21337
+ return fn(set, get, api);
21338
+ };
21339
+ const subscribeWithSelector = subscribeWithSelectorImpl;
21340
+ //#endregion
21341
+ //#region node_modules/.pnpm/immer@10.2.0/node_modules/immer/dist/immer.mjs
21342
+ var NOTHING = Symbol.for("immer-nothing");
21343
+ var DRAFTABLE = Symbol.for("immer-draftable");
21344
+ var DRAFT_STATE = Symbol.for("immer-state");
21345
+ function die(error, ...args) {
21346
+ throw new Error(`[Immer] minified error nr: ${error}. Full error at: https://bit.ly/3cXEKWf`);
21347
+ }
21348
+ var getPrototypeOf = Object.getPrototypeOf;
21349
+ function isDraft(value) {
21350
+ return !!value && !!value[DRAFT_STATE];
21351
+ }
21352
+ function isDraftable(value) {
21353
+ if (!value) return false;
21354
+ return isPlainObject(value) || Array.isArray(value) || !!value[DRAFTABLE] || !!value.constructor?.[DRAFTABLE] || isMap(value) || isSet(value);
21355
+ }
21356
+ var objectCtorString = Object.prototype.constructor.toString();
21357
+ var cachedCtorStrings = /* @__PURE__ */ new WeakMap();
21358
+ function isPlainObject(value) {
21359
+ if (!value || typeof value !== "object") return false;
21360
+ const proto = Object.getPrototypeOf(value);
21361
+ if (proto === null || proto === Object.prototype) return true;
21362
+ const Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
21363
+ if (Ctor === Object) return true;
21364
+ if (typeof Ctor !== "function") return false;
21365
+ let ctorString = cachedCtorStrings.get(Ctor);
21366
+ if (ctorString === void 0) {
21367
+ ctorString = Function.toString.call(Ctor);
21368
+ cachedCtorStrings.set(Ctor, ctorString);
21369
+ }
21370
+ return ctorString === objectCtorString;
21371
+ }
21372
+ function each(obj, iter, strict = true) {
21373
+ if (getArchtype(obj) === 0) (strict ? Reflect.ownKeys(obj) : Object.keys(obj)).forEach((key) => {
21374
+ iter(key, obj[key], obj);
21375
+ });
21376
+ else obj.forEach((entry, index) => iter(index, entry, obj));
21377
+ }
21378
+ function getArchtype(thing) {
21379
+ const state = thing[DRAFT_STATE];
21380
+ return state ? state.type_ : Array.isArray(thing) ? 1 : isMap(thing) ? 2 : isSet(thing) ? 3 : 0;
21381
+ }
21382
+ function has(thing, prop) {
21383
+ return getArchtype(thing) === 2 ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
21384
+ }
21385
+ function set(thing, propOrOldValue, value) {
21386
+ const t = getArchtype(thing);
21387
+ if (t === 2) thing.set(propOrOldValue, value);
21388
+ else if (t === 3) thing.add(value);
21389
+ else thing[propOrOldValue] = value;
21390
+ }
21391
+ function is(x, y) {
21392
+ if (x === y) return x !== 0 || 1 / x === 1 / y;
21393
+ else return x !== x && y !== y;
21394
+ }
21395
+ function isMap(target) {
21396
+ return target instanceof Map;
21397
+ }
21398
+ function isSet(target) {
21399
+ return target instanceof Set;
21400
+ }
21401
+ function latest(state) {
21402
+ return state.copy_ || state.base_;
21403
+ }
21404
+ function shallowCopy(base, strict) {
21405
+ if (isMap(base)) return new Map(base);
21406
+ if (isSet(base)) return new Set(base);
21407
+ if (Array.isArray(base)) return Array.prototype.slice.call(base);
21408
+ const isPlain = isPlainObject(base);
21409
+ if (strict === true || strict === "class_only" && !isPlain) {
21410
+ const descriptors = Object.getOwnPropertyDescriptors(base);
21411
+ delete descriptors[DRAFT_STATE];
21412
+ let keys = Reflect.ownKeys(descriptors);
21413
+ for (let i = 0; i < keys.length; i++) {
21414
+ const key = keys[i];
21415
+ const desc = descriptors[key];
21416
+ if (desc.writable === false) {
21417
+ desc.writable = true;
21418
+ desc.configurable = true;
21419
+ }
21420
+ if (desc.get || desc.set) descriptors[key] = {
21421
+ configurable: true,
21422
+ writable: true,
21423
+ enumerable: desc.enumerable,
21424
+ value: base[key]
21425
+ };
21426
+ }
21427
+ return Object.create(getPrototypeOf(base), descriptors);
21428
+ } else {
21429
+ const proto = getPrototypeOf(base);
21430
+ if (proto !== null && isPlain) return { ...base };
21431
+ const obj = Object.create(proto);
21432
+ return Object.assign(obj, base);
21433
+ }
21434
+ }
21435
+ function freeze(obj, deep = false) {
21436
+ if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj)) return obj;
21437
+ if (getArchtype(obj) > 1) Object.defineProperties(obj, {
21438
+ set: dontMutateMethodOverride,
21439
+ add: dontMutateMethodOverride,
21440
+ clear: dontMutateMethodOverride,
21441
+ delete: dontMutateMethodOverride
21442
+ });
21443
+ Object.freeze(obj);
21444
+ if (deep) Object.values(obj).forEach((value) => freeze(value, true));
21445
+ return obj;
21446
+ }
21447
+ function dontMutateFrozenCollections() {
21448
+ die(2);
21449
+ }
21450
+ var dontMutateMethodOverride = { value: dontMutateFrozenCollections };
21451
+ function isFrozen(obj) {
21452
+ if (obj === null || typeof obj !== "object") return true;
21453
+ return Object.isFrozen(obj);
21454
+ }
21455
+ var plugins = {};
21456
+ function getPlugin(pluginKey) {
21457
+ const plugin = plugins[pluginKey];
21458
+ if (!plugin) die(0, pluginKey);
21459
+ return plugin;
21460
+ }
21461
+ var currentScope;
21462
+ function getCurrentScope() {
21463
+ return currentScope;
21464
+ }
21465
+ function createScope(parent_, immer_) {
21466
+ return {
21467
+ drafts_: [],
21468
+ parent_,
21469
+ immer_,
21470
+ canAutoFreeze_: true,
21471
+ unfinalizedDrafts_: 0
21472
+ };
21473
+ }
21474
+ function usePatchesInScope(scope, patchListener) {
21475
+ if (patchListener) {
21476
+ getPlugin("Patches");
21477
+ scope.patches_ = [];
21478
+ scope.inversePatches_ = [];
21479
+ scope.patchListener_ = patchListener;
21480
+ }
21481
+ }
21482
+ function revokeScope(scope) {
21483
+ leaveScope(scope);
21484
+ scope.drafts_.forEach(revokeDraft);
21485
+ scope.drafts_ = null;
21486
+ }
21487
+ function leaveScope(scope) {
21488
+ if (scope === currentScope) currentScope = scope.parent_;
21489
+ }
21490
+ function enterScope(immer2) {
21491
+ return currentScope = createScope(currentScope, immer2);
21492
+ }
21493
+ function revokeDraft(draft) {
21494
+ const state = draft[DRAFT_STATE];
21495
+ if (state.type_ === 0 || state.type_ === 1) state.revoke_();
21496
+ else state.revoked_ = true;
21497
+ }
21498
+ function processResult(result, scope) {
21499
+ scope.unfinalizedDrafts_ = scope.drafts_.length;
21500
+ const baseDraft = scope.drafts_[0];
21501
+ if (result !== void 0 && result !== baseDraft) {
21502
+ if (baseDraft[DRAFT_STATE].modified_) {
21503
+ revokeScope(scope);
21504
+ die(4);
21505
+ }
21506
+ if (isDraftable(result)) {
21507
+ result = finalize(scope, result);
21508
+ if (!scope.parent_) maybeFreeze(scope, result);
21509
+ }
21510
+ if (scope.patches_) getPlugin("Patches").generateReplacementPatches_(baseDraft[DRAFT_STATE].base_, result, scope.patches_, scope.inversePatches_);
21511
+ } else result = finalize(scope, baseDraft, []);
21512
+ revokeScope(scope);
21513
+ if (scope.patches_) scope.patchListener_(scope.patches_, scope.inversePatches_);
21514
+ return result !== NOTHING ? result : void 0;
21515
+ }
21516
+ function finalize(rootScope, value, path) {
21517
+ if (isFrozen(value)) return value;
21518
+ const useStrictIteration = rootScope.immer_.shouldUseStrictIteration();
21519
+ const state = value[DRAFT_STATE];
21520
+ if (!state) {
21521
+ each(value, (key, childValue) => finalizeProperty(rootScope, state, value, key, childValue, path), useStrictIteration);
21522
+ return value;
21523
+ }
21524
+ if (state.scope_ !== rootScope) return value;
21525
+ if (!state.modified_) {
21526
+ maybeFreeze(rootScope, state.base_, true);
21527
+ return state.base_;
21528
+ }
21529
+ if (!state.finalized_) {
21530
+ state.finalized_ = true;
21531
+ state.scope_.unfinalizedDrafts_--;
21532
+ const result = state.copy_;
21533
+ let resultEach = result;
21534
+ let isSet2 = false;
21535
+ if (state.type_ === 3) {
21536
+ resultEach = new Set(result);
21537
+ result.clear();
21538
+ isSet2 = true;
21539
+ }
21540
+ each(resultEach, (key, childValue) => finalizeProperty(rootScope, state, result, key, childValue, path, isSet2), useStrictIteration);
21541
+ maybeFreeze(rootScope, result, false);
21542
+ if (path && rootScope.patches_) getPlugin("Patches").generatePatches_(state, path, rootScope.patches_, rootScope.inversePatches_);
21543
+ }
21544
+ return state.copy_;
21545
+ }
21546
+ function finalizeProperty(rootScope, parentState, targetObject, prop, childValue, rootPath, targetIsSet) {
21547
+ if (childValue == null) return;
21548
+ if (typeof childValue !== "object" && !targetIsSet) return;
21549
+ const childIsFrozen = isFrozen(childValue);
21550
+ if (childIsFrozen && !targetIsSet) return;
21551
+ if (isDraft(childValue)) {
21552
+ const res = finalize(rootScope, childValue, rootPath && parentState && parentState.type_ !== 3 && !has(parentState.assigned_, prop) ? rootPath.concat(prop) : void 0);
21553
+ set(targetObject, prop, res);
21554
+ if (isDraft(res)) rootScope.canAutoFreeze_ = false;
21555
+ else return;
21556
+ } else if (targetIsSet) targetObject.add(childValue);
21557
+ if (isDraftable(childValue) && !childIsFrozen) {
21558
+ if (!rootScope.immer_.autoFreeze_ && rootScope.unfinalizedDrafts_ < 1) return;
21559
+ if (parentState && parentState.base_ && parentState.base_[prop] === childValue && childIsFrozen) return;
21560
+ finalize(rootScope, childValue);
21561
+ if ((!parentState || !parentState.scope_.parent_) && typeof prop !== "symbol" && (isMap(targetObject) ? targetObject.has(prop) : Object.prototype.propertyIsEnumerable.call(targetObject, prop))) maybeFreeze(rootScope, childValue);
21562
+ }
21563
+ }
21564
+ function maybeFreeze(scope, value, deep = false) {
21565
+ if (!scope.parent_ && scope.immer_.autoFreeze_ && scope.canAutoFreeze_) freeze(value, deep);
21566
+ }
21567
+ function createProxyProxy(base, parent) {
21568
+ const isArray = Array.isArray(base);
21569
+ const state = {
21570
+ type_: isArray ? 1 : 0,
21571
+ scope_: parent ? parent.scope_ : getCurrentScope(),
21572
+ modified_: false,
21573
+ finalized_: false,
21574
+ assigned_: {},
21575
+ parent_: parent,
21576
+ base_: base,
21577
+ draft_: null,
21578
+ copy_: null,
21579
+ revoke_: null,
21580
+ isManual_: false
21581
+ };
21582
+ let target = state;
21583
+ let traps = objectTraps;
21584
+ if (isArray) {
21585
+ target = [state];
21586
+ traps = arrayTraps;
21587
+ }
21588
+ const { revoke, proxy } = Proxy.revocable(target, traps);
21589
+ state.draft_ = proxy;
21590
+ state.revoke_ = revoke;
21591
+ return proxy;
21592
+ }
21593
+ var objectTraps = {
21594
+ get(state, prop) {
21595
+ if (prop === DRAFT_STATE) return state;
21596
+ const source = latest(state);
21597
+ if (!has(source, prop)) return readPropFromProto(state, source, prop);
21598
+ const value = source[prop];
21599
+ if (state.finalized_ || !isDraftable(value)) return value;
21600
+ if (value === peek(state.base_, prop)) {
21601
+ prepareCopy(state);
21602
+ return state.copy_[prop] = createProxy(value, state);
21603
+ }
21604
+ return value;
21605
+ },
21606
+ has(state, prop) {
21607
+ return prop in latest(state);
21608
+ },
21609
+ ownKeys(state) {
21610
+ return Reflect.ownKeys(latest(state));
21611
+ },
21612
+ set(state, prop, value) {
21613
+ const desc = getDescriptorFromProto(latest(state), prop);
21614
+ if (desc?.set) {
21615
+ desc.set.call(state.draft_, value);
21616
+ return true;
21617
+ }
21618
+ if (!state.modified_) {
21619
+ const current2 = peek(latest(state), prop);
21620
+ const currentState = current2?.[DRAFT_STATE];
21621
+ if (currentState && currentState.base_ === value) {
21622
+ state.copy_[prop] = value;
21623
+ state.assigned_[prop] = false;
21624
+ return true;
21625
+ }
21626
+ if (is(value, current2) && (value !== void 0 || has(state.base_, prop))) return true;
21627
+ prepareCopy(state);
21628
+ markChanged(state);
21629
+ }
21630
+ if (state.copy_[prop] === value && (value !== void 0 || prop in state.copy_) || Number.isNaN(value) && Number.isNaN(state.copy_[prop])) return true;
21631
+ state.copy_[prop] = value;
21632
+ state.assigned_[prop] = true;
21633
+ return true;
21634
+ },
21635
+ deleteProperty(state, prop) {
21636
+ if (peek(state.base_, prop) !== void 0 || prop in state.base_) {
21637
+ state.assigned_[prop] = false;
21638
+ prepareCopy(state);
21639
+ markChanged(state);
21640
+ } else delete state.assigned_[prop];
21641
+ if (state.copy_) delete state.copy_[prop];
21642
+ return true;
21643
+ },
21644
+ getOwnPropertyDescriptor(state, prop) {
21645
+ const owner = latest(state);
21646
+ const desc = Reflect.getOwnPropertyDescriptor(owner, prop);
21647
+ if (!desc) return desc;
21648
+ return {
21649
+ writable: true,
21650
+ configurable: state.type_ !== 1 || prop !== "length",
21651
+ enumerable: desc.enumerable,
21652
+ value: owner[prop]
21653
+ };
21654
+ },
21655
+ defineProperty() {
21656
+ die(11);
21657
+ },
21658
+ getPrototypeOf(state) {
21659
+ return getPrototypeOf(state.base_);
21660
+ },
21661
+ setPrototypeOf() {
21662
+ die(12);
21663
+ }
21664
+ };
21665
+ var arrayTraps = {};
21666
+ each(objectTraps, (key, fn) => {
21667
+ arrayTraps[key] = function() {
21668
+ arguments[0] = arguments[0][0];
21669
+ return fn.apply(this, arguments);
21670
+ };
21671
+ });
21672
+ arrayTraps.deleteProperty = function(state, prop) {
21673
+ return arrayTraps.set.call(this, state, prop, void 0);
21674
+ };
21675
+ arrayTraps.set = function(state, prop, value) {
21676
+ return objectTraps.set.call(this, state[0], prop, value, state[0]);
21677
+ };
21678
+ function peek(draft, prop) {
21679
+ const state = draft[DRAFT_STATE];
21680
+ return (state ? latest(state) : draft)[prop];
21681
+ }
21682
+ function readPropFromProto(state, source, prop) {
21683
+ const desc = getDescriptorFromProto(source, prop);
21684
+ return desc ? `value` in desc ? desc.value : desc.get?.call(state.draft_) : void 0;
21685
+ }
21686
+ function getDescriptorFromProto(source, prop) {
21687
+ if (!(prop in source)) return void 0;
21688
+ let proto = getPrototypeOf(source);
21689
+ while (proto) {
21690
+ const desc = Object.getOwnPropertyDescriptor(proto, prop);
21691
+ if (desc) return desc;
21692
+ proto = getPrototypeOf(proto);
21693
+ }
21694
+ }
21695
+ function markChanged(state) {
21696
+ if (!state.modified_) {
21697
+ state.modified_ = true;
21698
+ if (state.parent_) markChanged(state.parent_);
21699
+ }
21700
+ }
21701
+ function prepareCopy(state) {
21702
+ if (!state.copy_) state.copy_ = shallowCopy(state.base_, state.scope_.immer_.useStrictShallowCopy_);
21703
+ }
21704
+ var Immer2 = class {
21705
+ constructor(config) {
21706
+ this.autoFreeze_ = true;
21707
+ this.useStrictShallowCopy_ = false;
21708
+ this.useStrictIteration_ = true;
21709
+ /**
21710
+ * The `produce` function takes a value and a "recipe function" (whose
21711
+ * return value often depends on the base state). The recipe function is
21712
+ * free to mutate its first argument however it wants. All mutations are
21713
+ * only ever applied to a __copy__ of the base state.
21714
+ *
21715
+ * Pass only a function to create a "curried producer" which relieves you
21716
+ * from passing the recipe function every time.
21717
+ *
21718
+ * Only plain objects and arrays are made mutable. All other objects are
21719
+ * considered uncopyable.
21720
+ *
21721
+ * Note: This function is __bound__ to its `Immer` instance.
21722
+ *
21723
+ * @param {any} base - the initial state
21724
+ * @param {Function} recipe - function that receives a proxy of the base state as first argument and which can be freely modified
21725
+ * @param {Function} patchListener - optional function that will be called with all the patches produced here
21726
+ * @returns {any} a new state, or the initial state if nothing was modified
21727
+ */
21728
+ this.produce = (base, recipe, patchListener) => {
21729
+ if (typeof base === "function" && typeof recipe !== "function") {
21730
+ const defaultBase = recipe;
21731
+ recipe = base;
21732
+ const self = this;
21733
+ return function curriedProduce(base2 = defaultBase, ...args) {
21734
+ return self.produce(base2, (draft) => recipe.call(this, draft, ...args));
21735
+ };
21736
+ }
21737
+ if (typeof recipe !== "function") die(6);
21738
+ if (patchListener !== void 0 && typeof patchListener !== "function") die(7);
21739
+ let result;
21740
+ if (isDraftable(base)) {
21741
+ const scope = enterScope(this);
21742
+ const proxy = createProxy(base, void 0);
21743
+ let hasError = true;
21744
+ try {
21745
+ result = recipe(proxy);
21746
+ hasError = false;
21747
+ } finally {
21748
+ if (hasError) revokeScope(scope);
21749
+ else leaveScope(scope);
21750
+ }
21751
+ usePatchesInScope(scope, patchListener);
21752
+ return processResult(result, scope);
21753
+ } else if (!base || typeof base !== "object") {
21754
+ result = recipe(base);
21755
+ if (result === void 0) result = base;
21756
+ if (result === NOTHING) result = void 0;
21757
+ if (this.autoFreeze_) freeze(result, true);
21758
+ if (patchListener) {
21759
+ const p = [];
21760
+ const ip = [];
21761
+ getPlugin("Patches").generateReplacementPatches_(base, result, p, ip);
21762
+ patchListener(p, ip);
21763
+ }
21764
+ return result;
21765
+ } else die(1, base);
21766
+ };
21767
+ this.produceWithPatches = (base, recipe) => {
21768
+ if (typeof base === "function") return (state, ...args) => this.produceWithPatches(state, (draft) => base(draft, ...args));
21769
+ let patches, inversePatches;
21770
+ return [
21771
+ this.produce(base, recipe, (p, ip) => {
21772
+ patches = p;
21773
+ inversePatches = ip;
21774
+ }),
21775
+ patches,
21776
+ inversePatches
21777
+ ];
21778
+ };
21779
+ if (typeof config?.autoFreeze === "boolean") this.setAutoFreeze(config.autoFreeze);
21780
+ if (typeof config?.useStrictShallowCopy === "boolean") this.setUseStrictShallowCopy(config.useStrictShallowCopy);
21781
+ if (typeof config?.useStrictIteration === "boolean") this.setUseStrictIteration(config.useStrictIteration);
21782
+ }
21783
+ createDraft(base) {
21784
+ if (!isDraftable(base)) die(8);
21785
+ if (isDraft(base)) base = current(base);
21786
+ const scope = enterScope(this);
21787
+ const proxy = createProxy(base, void 0);
21788
+ proxy[DRAFT_STATE].isManual_ = true;
21789
+ leaveScope(scope);
21790
+ return proxy;
21791
+ }
21792
+ finishDraft(draft, patchListener) {
21793
+ const state = draft && draft[DRAFT_STATE];
21794
+ if (!state || !state.isManual_) die(9);
21795
+ const { scope_: scope } = state;
21796
+ usePatchesInScope(scope, patchListener);
21797
+ return processResult(void 0, scope);
21798
+ }
21799
+ /**
21800
+ * Pass true to automatically freeze all copies created by Immer.
21801
+ *
21802
+ * By default, auto-freezing is enabled.
21803
+ */
21804
+ setAutoFreeze(value) {
21805
+ this.autoFreeze_ = value;
21806
+ }
21807
+ /**
21808
+ * Pass true to enable strict shallow copy.
21809
+ *
21810
+ * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
21811
+ */
21812
+ setUseStrictShallowCopy(value) {
21813
+ this.useStrictShallowCopy_ = value;
21814
+ }
21815
+ /**
21816
+ * Pass false to use faster iteration that skips non-enumerable properties
21817
+ * but still handles symbols for compatibility.
21818
+ *
21819
+ * By default, strict iteration is enabled (includes all own properties).
21820
+ */
21821
+ setUseStrictIteration(value) {
21822
+ this.useStrictIteration_ = value;
21823
+ }
21824
+ shouldUseStrictIteration() {
21825
+ return this.useStrictIteration_;
21826
+ }
21827
+ applyPatches(base, patches) {
21828
+ let i;
21829
+ for (i = patches.length - 1; i >= 0; i--) {
21830
+ const patch = patches[i];
21831
+ if (patch.path.length === 0 && patch.op === "replace") {
21832
+ base = patch.value;
21833
+ break;
21834
+ }
21835
+ }
21836
+ if (i > -1) patches = patches.slice(i + 1);
21837
+ const applyPatchesImpl = getPlugin("Patches").applyPatches_;
21838
+ if (isDraft(base)) return applyPatchesImpl(base, patches);
21839
+ return this.produce(base, (draft) => applyPatchesImpl(draft, patches));
21840
+ }
21841
+ };
21842
+ function createProxy(value, parent) {
21843
+ const draft = isMap(value) ? getPlugin("MapSet").proxyMap_(value, parent) : isSet(value) ? getPlugin("MapSet").proxySet_(value, parent) : createProxyProxy(value, parent);
21844
+ (parent ? parent.scope_ : getCurrentScope()).drafts_.push(draft);
21845
+ return draft;
21846
+ }
21847
+ function current(value) {
21848
+ if (!isDraft(value)) die(10, value);
21849
+ return currentImpl(value);
21850
+ }
21851
+ function currentImpl(value) {
21852
+ if (!isDraftable(value) || isFrozen(value)) return value;
21853
+ const state = value[DRAFT_STATE];
21854
+ let copy;
21855
+ let strict = true;
21856
+ if (state) {
21857
+ if (!state.modified_) return state.base_;
21858
+ state.finalized_ = true;
21859
+ copy = shallowCopy(value, state.scope_.immer_.useStrictShallowCopy_);
21860
+ strict = state.scope_.immer_.shouldUseStrictIteration();
21861
+ } else copy = shallowCopy(value, true);
21862
+ each(copy, (key, childValue) => {
21863
+ set(copy, key, currentImpl(childValue));
21864
+ }, strict);
21865
+ if (state) state.finalized_ = false;
21866
+ return copy;
21867
+ }
21868
+ var produce = new Immer2().produce;
21869
+ //#endregion
21870
+ //#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
21871
+ /**
21872
+ * React-free snapshot store engine (zustand vanilla + immer + subscribeWithSelector +
21873
+ * rafFlush middleware + opt-in persist + dev freeze) plus the declarative
21874
+ * shell over it: {@link defineStore} bakes an init/persist/actions literal
21875
+ * into a {@link StoreHandle}, the registration-side store seat of slot
21876
+ * terminals. Engine products are bare observables — subscribe/getSnapshot/
21877
+ * update/set, NO selector hook. Hook synthesis is ui-renderer's (the one
21878
+ * uSES bridge, cached per source at the binding site).
21879
+ */
21880
+ /**
21881
+ * Notify an observer set without allowing one callback to starve the rest.
21882
+ * @param listeners - current observer callbacks; copied before dispatch.
21883
+ * @param label - diagnostic owner prefix.
21884
+ * @param args - callback arguments.
21885
+ */
21886
+ function notifySubscribers(listeners, label, ...args) {
21887
+ for (const listener of [...listeners]) try {
21888
+ listener(...args);
21889
+ } catch (error) {
21890
+ console.error(`${label} subscriber failed:`, error);
21891
+ }
21892
+ }
21893
+ /** Batches subscriber notification into one flush per animation frame. */
21894
+ function rafBatch(notify) {
21895
+ const schedule = typeof requestAnimationFrame === "function" ? (fn) => {
21896
+ requestAnimationFrame(() => {
21897
+ fn();
21898
+ });
21899
+ } : (fn) => {
21900
+ queueMicrotask(fn);
21901
+ };
21902
+ let scheduled = false;
21903
+ return () => {
21904
+ if (scheduled) return;
21905
+ scheduled = true;
21906
+ schedule(() => {
21907
+ scheduled = false;
21908
+ notify();
21909
+ });
21910
+ };
21911
+ }
21912
+ /**
21913
+ * Create a snapshot store.
21914
+ *
21915
+ * Flush default is 'sync' (controlled inputs need same-tick echo); frame-driven
21916
+ * stores opt into 'raf', where a frame's worth of updates coalesces into one
21917
+ * notification. Known raf-mode tradeoff: a component mounting mid-frame reads
21918
+ * fresh state while existing subscribers hear it next flush — transient
21919
+ * frame-level skew, same nature as the object layer's microtask batching.
21920
+ *
21921
+ * @param init - initial state.
21922
+ * @param opts - flush mode and opt-in persistence (localStorage, keyed by name).
21923
+ * @returns the store.
21924
+ */
21925
+ function createSnapshotStore(init, opts) {
21926
+ const withSelector = subscribeWithSelector(() => init);
21927
+ const api = createStore()(withSelector);
21928
+ if (opts?.persist) attachPersistence(api, opts.persist.name);
21929
+ let subscribe = (fn) => api.subscribe(() => {
21930
+ notifySubscribers([fn], "[client-store]");
21931
+ });
21932
+ if (opts?.flush === "raf") {
21933
+ const listeners = /* @__PURE__ */ new Set();
21934
+ const flush = rafBatch(() => {
21935
+ notifySubscribers(listeners, "[client-store]");
21936
+ });
21937
+ api.subscribe(flush);
21938
+ subscribe = (fn) => {
21939
+ listeners.add(fn);
21940
+ return () => {
21941
+ listeners.delete(fn);
21942
+ };
21943
+ };
21944
+ }
21945
+ return {
21946
+ getSnapshot: () => api.getState(),
21947
+ subscribe: (fn) => subscribe(fn),
21948
+ update: (mutator) => {
21949
+ api.setState(produce(api.getState(), (draft) => {
21950
+ mutator(draft);
21951
+ }), true);
21952
+ },
21953
+ set: (next) => {
21954
+ api.setState(devFreeze(next), true);
21955
+ }
21956
+ };
21957
+ }
21958
+ /**
21959
+ * Whole-value JSON persistence to localStorage. Hand-rolled instead of the
21960
+ * zustand persist middleware: its write path spreads state into an object
21961
+ * (`partialize({ ...get() })`), exploding primitive state (a persisted string
21962
+ * draft becomes {0:'h',1:'e',...}) — not fixable via merge/deserialize options
21963
+ * because the corruption happens before serialization. Storage failures
21964
+ * (quota, private mode) only disable persistence, never break the store.
21965
+ */
21966
+ function attachPersistence(api, name) {
21967
+ if (typeof localStorage === "undefined") return;
21968
+ try {
21969
+ const raw = localStorage.getItem(name);
21970
+ if (raw !== null) api.setState(devFreeze(JSON.parse(raw)), true);
21971
+ } catch (error) {
21972
+ console.error(`snapshot store '${name}' rehydration failed:`, error);
21973
+ }
21974
+ api.subscribe((state) => {
21975
+ try {
21976
+ localStorage.setItem(name, JSON.stringify(state));
21977
+ } catch (error) {
21978
+ console.error(`snapshot store '${name}' persistence failed:`, error);
21979
+ }
21980
+ });
21981
+ }
21982
+ /** Deep-freeze draftable wholesale-set state outside production: set() bypasses immer's freeze. */
21983
+ function devFreeze(value) {
21984
+ return freeze(value, true);
21985
+ }
21986
+ /**
21987
+ * Declare a store: initial state, optional persistence, and the full write
21988
+ * set as pure draft mutators. The returned handle is the registration
21989
+ * currency of the store seat — its identity keys instance sharing. Satisfies
21990
+ * ui-slots' DefineStore contract (the handle/instance are the engine-extended
21991
+ * subtypes).
21992
+ *
21993
+ * The `A & ActionsDecl<T>` actions position is load-bearing: T resolves from
21994
+ * `init` in the first inference round, and the intersection then contextually
21995
+ * types each mutator's draft parameter (context-sensitive functions defer),
21996
+ * so call sites write `(d, x: X) => { ... }` with no draft annotation. If a
21997
+ * future TS version breaks this single-literal inference, the design's
21998
+ * documented fallback is currying (`defineStore(init).actions({...})`).
21999
+ * @param decl - init lambda (fresh state per instance), optional persist key, actions table.
22000
+ * @returns the store handle.
22001
+ */
22002
+ function defineStore(decl) {
22003
+ return {
22004
+ spec: decl,
22005
+ create(scopeKey) {
22006
+ const persistKey = decl.persist === void 0 ? void 0 : scopeKey === void 0 ? decl.persist : `${decl.persist}.${scopeKey}`;
22007
+ const store = createSnapshotStore(decl.init(), persistKey !== void 0 ? { persist: { name: persistKey } } : void 0);
22008
+ const actions = {};
22009
+ for (const key of Object.keys(decl.actions)) {
22010
+ const mutate = decl.actions[key];
22011
+ actions[key] = (...params) => {
22012
+ store.update((draft) => {
22013
+ mutate(draft, ...params);
22014
+ });
22015
+ };
22016
+ }
22017
+ return {
22018
+ actions,
22019
+ getSnapshot: () => store.getSnapshot(),
22020
+ subscribe: (fn) => store.subscribe(fn),
22021
+ store,
22022
+ clearPersisted: () => {
22023
+ if (persistKey === void 0 || typeof localStorage === "undefined") return;
22024
+ try {
22025
+ localStorage.removeItem(persistKey);
22026
+ } catch {}
22027
+ }
22028
+ };
22029
+ }
22030
+ };
22031
+ }
22032
+ //#endregion
20850
22033
  //#region lib/types/client/store.js
20851
22034
  /** Root-scoped interaction state for the AWiki overlay. */
20852
22035
  /**
@@ -20854,7 +22037,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20854
22037
  * @returns a fresh framework store handle.
20855
22038
  */
20856
22039
  function createAwikiOverlayStore() {
20857
- return (0, _deepseek_ai_dsh_client_runtime_client.defineStore)({
22040
+ return defineStore({
20858
22041
  init: () => ({ open: false }),
20859
22042
  actions: {
20860
22043
  open: (draft) => {
@@ -21168,22 +22351,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21168
22351
  //#endregion
21169
22352
  //#region lib/types/settings-rpc-contract.js
21170
22353
  /** 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";
22354
+ /** Shared Connection carrier with plugin-owned exact loopback routes. */
22355
+ const AWIKI_SETTINGS_RPC_CHANNEL = "/api";
21173
22356
  /** Supported channel-relative operations. */
21174
22357
  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"
22358
+ describe: "awiki-settings/describe",
22359
+ setDomain: "awiki-settings/set-domain",
22360
+ resetDomain: "awiki-settings/reset-domain",
22361
+ describeTenants: "awiki-settings/describe-tenants",
22362
+ createTenant: "awiki-settings/create-tenant",
22363
+ renameTenant: "awiki-settings/rename-tenant",
22364
+ switchTenant: "awiki-settings/switch-tenant",
22365
+ archiveTenant: "awiki-settings/archive-tenant",
22366
+ describeUpdatePolicy: "awiki-settings/describe-update-policy",
22367
+ refreshUpdatePolicy: "awiki-settings/refresh-update-policy",
22368
+ describeDesktopUpdate: "awiki-settings/describe-desktop-update",
22369
+ refreshDesktopUpdate: "awiki-settings/refresh-desktop-update"
21187
22370
  };
21188
22371
  function isRecord(value) {
21189
22372
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -21311,7 +22494,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21311
22494
  tenantSnapshot;
21312
22495
  tenantListeners = /* @__PURE__ */ new Set();
21313
22496
  abort = new AbortController();
21314
- disposeHostDescription;
22497
+ disposeGeneration;
21315
22498
  writeTail = Promise.resolve();
21316
22499
  requestVersion = 0;
21317
22500
  disposed = false;
@@ -21327,7 +22510,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21327
22510
  value: INITIAL_TENANTS,
21328
22511
  updateStatus: connection.isLoopback ? "loading" : "unavailable"
21329
22512
  };
21330
- this.disposeHostDescription = connection.isLoopback ? connection.hostDescription.subscribe(() => {
22513
+ this.disposeGeneration = connection.isLoopback ? connection.generation.subscribe(() => {
21331
22514
  this.load();
21332
22515
  }) : () => {};
21333
22516
  }
@@ -21506,6 +22689,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21506
22689
  if (field !== "domain") return Promise.reject(/* @__PURE__ */ new TypeError("AWiki settings only supports the domain field"));
21507
22690
  return this.enqueue(AWIKI_SETTINGS_RPC_ENDPOINTS.resetDomain, {});
21508
22691
  }
22692
+ /** Apply domain edits atomically through the existing revision-fenced Host operation. */
22693
+ mutate(ops, expectedRevision) {
22694
+ if (ops.length === 0) return Promise.resolve();
22695
+ 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"));
22696
+ const last = ops[ops.length - 1];
22697
+ const endpoint = last.op === "set" ? AWIKI_SETTINGS_RPC_ENDPOINTS.setDomain : AWIKI_SETTINGS_RPC_ENDPOINTS.resetDomain;
22698
+ const payload = last.op === "set" ? { domain: normalizeAwikiDomain(last.value) } : {};
22699
+ return this.enqueue(endpoint, payload, expectedRevision);
22700
+ }
21509
22701
  /** Stop reconnect reads and cancel outstanding transport calls. */
21510
22702
  dispose() {
21511
22703
  if (this.disposed) return;
@@ -21513,17 +22705,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21513
22705
  if (this.updatePolling !== void 0) clearInterval(this.updatePolling);
21514
22706
  this.requestVersion += 1;
21515
22707
  this.abort.abort();
21516
- this.disposeHostDescription();
22708
+ this.disposeGeneration();
21517
22709
  this.listeners.clear();
21518
22710
  this.tenantListeners.clear();
21519
22711
  }
21520
- enqueue(endpoint, payload) {
21521
- const run = this.writeTail.catch(() => void 0).then(() => this.write(endpoint, payload));
22712
+ enqueue(endpoint, payload, expectedRevision) {
22713
+ const run = this.writeTail.catch(() => void 0).then(() => this.write(endpoint, payload, expectedRevision));
21522
22714
  this.writeTail = run;
21523
22715
  return run;
21524
22716
  }
21525
- async write(endpoint, payload) {
21526
- const revision = this.snapshot.revision;
22717
+ async write(endpoint, payload, expectedRevision) {
22718
+ const revision = expectedRevision ?? this.snapshot.revision;
21527
22719
  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
22720
  const version = ++this.requestVersion;
21529
22721
  try {
@@ -21672,6 +22864,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21672
22864
  beginDeviceJoin: () => awiki.beginDeviceJoin(),
21673
22865
  getDeviceJoinStatus: () => awiki.getDeviceJoinStatus(),
21674
22866
  cancelDeviceJoin: () => awiki.cancelDeviceJoin(),
22867
+ beginRecoveryFromDeviceJoin: (request) => awiki.beginRecoveryFromDeviceJoin(request),
21675
22868
  retireDeviceIdentityForRejoin: () => awiki.retireDeviceIdentityForRejoin(),
21676
22869
  refreshDeviceManagement: () => awiki.refreshDeviceManagement(),
21677
22870
  startDeviceJoinVerification: (request) => awiki.startDeviceJoinVerification(request),
@@ -21757,7 +22950,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21757
22950
  confirmRootTransfer: (request) => awiki.confirmRootTransfer(request),
21758
22951
  loadIntegration: async () => {
21759
22952
  const result = await awiki.getIntegration();
21760
- if (!result.ok && result.error === "尚未创建 Integration。") {
22953
+ if (!result.ok && result.failureCode === "not-found") {
21761
22954
  clearIntegrationOperations();
21762
22955
  return {
21763
22956
  ok: true,