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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +12 -4
  2. package/README.zh.md +9 -3
  3. package/lib/client.js +748 -146
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +391 -101
  6. package/lib/provider.js +32 -2
  7. package/lib/{sdk-adapter-CYcJH7sM.mjs → sdk-adapter-DpqT2en9.mjs} +17 -7
  8. package/lib/typert.host.js +181 -117
  9. package/lib/typert.remote-client.d.ts +3 -1
  10. package/lib/typert.remote-client.d.ts.map +1 -1
  11. package/lib/typert.remote-client.js +181 -117
  12. package/lib/types/base64.d.ts +4 -0
  13. package/lib/types/base64.d.ts.map +1 -0
  14. package/lib/types/base64.js +28 -0
  15. package/lib/types/base64.js.map +1 -0
  16. package/lib/types/client/AwikiIdentityAccess.d.ts.map +1 -1
  17. package/lib/types/client/AwikiIdentityAccess.js +55 -34
  18. package/lib/types/client/AwikiIdentityAccess.js.map +1 -1
  19. package/lib/types/client/AwikiMail.d.ts +1 -1
  20. package/lib/types/client/AwikiMail.d.ts.map +1 -1
  21. package/lib/types/client/AwikiMail.js +139 -6
  22. package/lib/types/client/AwikiMail.js.map +1 -1
  23. package/lib/types/client/AwikiOverlay.js +1 -1
  24. package/lib/types/client/AwikiOverlay.js.map +1 -1
  25. package/lib/types/client/controller.d.ts +7 -1
  26. package/lib/types/client/controller.d.ts.map +1 -1
  27. package/lib/types/client/controller.js +29 -1
  28. package/lib/types/client/controller.js.map +1 -1
  29. package/lib/types/client/index.d.ts.map +1 -1
  30. package/lib/types/client/index.js +2 -0
  31. package/lib/types/client/index.js.map +1 -1
  32. package/lib/types/client/mail-attachment.d.ts +40 -0
  33. package/lib/types/client/mail-attachment.d.ts.map +1 -0
  34. package/lib/types/client/mail-attachment.js +187 -0
  35. package/lib/types/client/mail-attachment.js.map +1 -0
  36. package/lib/types/client/slots.d.ts +5 -1
  37. package/lib/types/client/slots.d.ts.map +1 -1
  38. package/lib/types/external-http-auth.d.ts +3 -1
  39. package/lib/types/external-http-auth.d.ts.map +1 -1
  40. package/lib/types/external-http-auth.js +2 -2
  41. package/lib/types/external-http-auth.js.map +1 -1
  42. package/lib/types/identity-handle.d.ts +5 -0
  43. package/lib/types/identity-handle.d.ts.map +1 -0
  44. package/lib/types/identity-handle.js +33 -0
  45. package/lib/types/identity-handle.js.map +1 -0
  46. package/lib/types/index.d.ts +10 -2
  47. package/lib/types/index.d.ts.map +1 -1
  48. package/lib/types/index.js +81 -26
  49. package/lib/types/index.js.map +1 -1
  50. package/lib/types/mail-attachment-client.d.ts +14 -0
  51. package/lib/types/mail-attachment-client.d.ts.map +1 -0
  52. package/lib/types/mail-attachment-client.js +173 -0
  53. package/lib/types/mail-attachment-client.js.map +1 -0
  54. package/lib/types/mail.d.ts +28 -2
  55. package/lib/types/mail.d.ts.map +1 -1
  56. package/lib/types/mail.js +79 -2
  57. package/lib/types/mail.js.map +1 -1
  58. package/lib/types/package-version.generated.d.ts +1 -1
  59. package/lib/types/package-version.generated.js +1 -1
  60. package/lib/types/provider.d.ts +1 -1
  61. package/lib/types/provider.d.ts.map +1 -1
  62. package/lib/types/provider.js +12 -1
  63. package/lib/types/provider.js.map +1 -1
  64. package/lib/types/registration-policy.d.ts +1 -3
  65. package/lib/types/registration-policy.d.ts.map +1 -1
  66. package/lib/types/registration-policy.js +1 -9
  67. package/lib/types/registration-policy.js.map +1 -1
  68. package/lib/types/sdk-adapter.d.ts +2 -1
  69. package/lib/types/sdk-adapter.d.ts.map +1 -1
  70. package/lib/types/sdk-adapter.js +13 -4
  71. package/lib/types/sdk-adapter.js.map +1 -1
  72. package/lib/types/tools.d.ts +1 -1
  73. package/lib/types/tools.d.ts.map +1 -1
  74. package/lib/types/tools.js +20 -4
  75. package/lib/types/tools.js.map +1 -1
  76. package/lib/types/types.d.ts +39 -2
  77. package/lib/types/types.d.ts.map +1 -1
  78. package/lib/types/types.js.map +1 -1
  79. package/lib/types/update-policy.d.ts +1 -1
  80. package/package.json +4 -4
@@ -34,7 +34,7 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
34
34
  };
35
35
  export { registerAwikiLoopbackRpc } from "./settings-transport.js";
36
36
  import { registerAwikiSettingsTransport } from "./settings-transport.js";
37
- import { registrationHandleLocalPart, shortHandleInviteRequired } from "./registration-policy.js";
37
+ import { registrationHandleLocalPart } from "./registration-policy.js";
38
38
  import { decodeDesktopDistribution } from "./desktop-distribution.js";
39
39
  /** Unified AWiki identity, messaging, attachment, Remote, and model-tool service. */
40
40
  import { Context } from '@deepseek-ai/cordis';
@@ -49,10 +49,12 @@ import { AwikiExternalHttpAuthError, createAwikiExternalHttpAuth, externalHttpAu
49
49
  import { AwikiIntegrationClient } from "./integration-client.js";
50
50
  import { clearLegacySentMailCache } from "./legacy-sent-mail-cache.js";
51
51
  import { AwikiMailListClient } from "./mail-list-client.js";
52
+ import { AwikiMailAttachmentClient, MAIL_HTTP_UPLOAD_MAX_BYTES } from "./mail-attachment-client.js";
52
53
  import { AwikiSdkError, downloadedAttachment } from "./sdk-adapter.js";
53
54
  import { failedMailRecoveryObservability, fencedMailRecoveryObservability, successfulMailRecoveryObservability, } from "./mail-recovery-observability.js";
55
+ import { standardBase64Syntax } from "./base64.js";
54
56
  import { registerAwikiTools } from "./tools.js";
55
- import { mailInboxRequest, mailMarkReadRequest, mailReadRequest, mailSendRequest, } from "./mail.js";
57
+ import { MAIL_ATTACHMENT_SERVICE_MAX_BYTES, MAIL_ATTACHMENT_SERVICE_MAX_COUNT, MAIL_ATTACHMENT_SERVICE_TOTAL_MAX_BYTES, mailAttachmentDownloadRequest, mailInboxRequest, mailMarkReadRequest, mailReadRequest, mailSendRequest, } from "./mail.js";
56
58
  import { AwikiSettingsSchema, validateAwikiSettings, } from "./settings.js";
57
59
  import { AWIKI_SETTINGS_NAMESPACE, DEFAULT_AWIKI_DOMAIN, normalizeAwikiDomain } from "./domain.js";
58
60
  import { AWIKI_DEFAULT_BUILTIN_TENANT, } from "./builtin-tenant-config.js";
@@ -99,6 +101,9 @@ export const Config = z.object({
99
101
  allowInsecureLoopbackForTesting: z.boolean().default(false),
100
102
  stateRoot: z.string(),
101
103
  attachmentMaxBytes: z.number().default(DEFAULT_ATTACHMENT_MAX_BYTES),
104
+ mailAttachmentMaxCount: z.number().default(MAIL_ATTACHMENT_SERVICE_MAX_COUNT),
105
+ mailAttachmentMaxBytes: z.number().default(MAIL_ATTACHMENT_SERVICE_MAX_BYTES),
106
+ mailAttachmentTotalMaxBytes: z.number().default(MAIL_ATTACHMENT_SERVICE_TOTAL_MAX_BYTES),
102
107
  imageAttachmentCacheMaxBytes: z.number().default(DEFAULT_IMAGE_ATTACHMENT_CACHE_MAX_BYTES),
103
108
  pollIntervalMs: z.number().default(DEFAULT_POLL_INTERVAL_MS),
104
109
  realtimeEnabled: z.boolean().default(true),
@@ -122,6 +127,7 @@ const FAILURE_CODES = new Set([
122
127
  'device-rejoin-required',
123
128
  'identity-recovery-required',
124
129
  'conflict',
130
+ 'state-in-use',
125
131
  'rate-limited',
126
132
  'group-membership-required',
127
133
  'group-identity-stale',
@@ -160,6 +166,7 @@ const FAILURE_MESSAGES = {
160
166
  'device-rejoin-required': 'This device credential was revoked and must join the Handle again.',
161
167
  'identity-recovery-required': 'The local AWiki identity must be recovered before it can be used again.',
162
168
  'conflict': 'The AWiki operation conflicts with current state.',
169
+ 'state-in-use': 'AWiki data is already open in another client.',
163
170
  'rate-limited': 'The AWiki service rate-limited the request.',
164
171
  'group-membership-required': 'The active AWiki identity is not a member of this group.',
165
172
  'group-identity-stale': 'The AWiki group identity binding is still recovering.',
@@ -339,6 +346,24 @@ function resolveConfig(ctx, config) {
339
346
  if (!Number.isSafeInteger(attachmentMaxBytes) || attachmentMaxBytes < 1) {
340
347
  throw new TypeError('awiki: attachmentMaxBytes must be a positive safe integer');
341
348
  }
349
+ const mailAttachmentMaxCount = config.mailAttachmentMaxCount ?? MAIL_ATTACHMENT_SERVICE_MAX_COUNT;
350
+ if (!Number.isSafeInteger(mailAttachmentMaxCount)
351
+ || mailAttachmentMaxCount < 0
352
+ || mailAttachmentMaxCount > MAIL_ATTACHMENT_SERVICE_MAX_COUNT) {
353
+ throw new TypeError('awiki: mailAttachmentMaxCount must be an integer from 0 through 10');
354
+ }
355
+ const mailAttachmentMaxBytes = config.mailAttachmentMaxBytes ?? MAIL_ATTACHMENT_SERVICE_MAX_BYTES;
356
+ if (!Number.isSafeInteger(mailAttachmentMaxBytes)
357
+ || mailAttachmentMaxBytes < 1
358
+ || mailAttachmentMaxBytes > MAIL_ATTACHMENT_SERVICE_MAX_BYTES) {
359
+ throw new TypeError('awiki: mailAttachmentMaxBytes must be a positive safe integer no greater than 10 MiB');
360
+ }
361
+ const mailAttachmentTotalMaxBytes = config.mailAttachmentTotalMaxBytes ?? MAIL_ATTACHMENT_SERVICE_TOTAL_MAX_BYTES;
362
+ if (!Number.isSafeInteger(mailAttachmentTotalMaxBytes)
363
+ || mailAttachmentTotalMaxBytes < mailAttachmentMaxBytes
364
+ || mailAttachmentTotalMaxBytes > MAIL_ATTACHMENT_SERVICE_TOTAL_MAX_BYTES) {
365
+ throw new TypeError('awiki: mailAttachmentTotalMaxBytes must cover one attachment and not exceed 18 MiB');
366
+ }
342
367
  const imageAttachmentCacheMaxBytes = config.imageAttachmentCacheMaxBytes ?? DEFAULT_IMAGE_ATTACHMENT_CACHE_MAX_BYTES;
343
368
  if (!Number.isSafeInteger(imageAttachmentCacheMaxBytes)
344
369
  || imageAttachmentCacheMaxBytes < minimumImageAttachmentCacheMaxBytes(attachmentMaxBytes)) {
@@ -384,6 +409,9 @@ function resolveConfig(ctx, config) {
384
409
  allowInsecureLoopbackForTesting,
385
410
  stateRoot,
386
411
  attachmentMaxBytes,
412
+ mailAttachmentMaxCount,
413
+ mailAttachmentMaxBytes,
414
+ mailAttachmentTotalMaxBytes,
387
415
  imageAttachmentCacheMaxBytes,
388
416
  pollIntervalMs,
389
417
  realtimeEnabled,
@@ -738,7 +766,7 @@ function decodeAttachment(bytesBase64, maxBytes) {
738
766
  const maxEncoded = Math.ceil(maxBytes / 3) * 4;
739
767
  if (bytesBase64.length > maxEncoded)
740
768
  return { ok: false, error: failure('attachment-too-large') };
741
- if (bytesBase64.length % 4 !== 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(bytesBase64)) {
769
+ if (bytesBase64.length % 4 !== 0 || !standardBase64Syntax(bytesBase64)) {
742
770
  return { ok: false, error: failure('invalid-request') };
743
771
  }
744
772
  const bytes = Uint8Array.from(Buffer.from(bytesBase64, 'base64'));
@@ -812,6 +840,7 @@ let AwikiService = (() => {
812
840
  let _readMail_decorators;
813
841
  let _markMailRead_decorators;
814
842
  let _sendMail_decorators;
843
+ let _downloadMailAttachment_decorators;
815
844
  let _clearLocalData_decorators;
816
845
  return class AwikiService extends _classSuper {
817
846
  static {
@@ -876,6 +905,7 @@ let AwikiService = (() => {
876
905
  _readMail_decorators = [Remote];
877
906
  _markMailRead_decorators = [Remote];
878
907
  _sendMail_decorators = [Remote];
908
+ _downloadMailAttachment_decorators = [Remote];
879
909
  _clearLocalData_decorators = [Remote];
880
910
  __esDecorate(this, null, _getConfig_decorators, { kind: "method", name: "getConfig", static: false, private: false, access: { has: obj => "getConfig" in obj, get: obj => obj.getConfig }, metadata: _metadata }, null, _instanceExtraInitializers);
881
911
  __esDecorate(this, null, _getIntegration_decorators, { kind: "method", name: "getIntegration", static: false, private: false, access: { has: obj => "getIntegration" in obj, get: obj => obj.getIntegration }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -937,6 +967,7 @@ let AwikiService = (() => {
937
967
  __esDecorate(this, null, _readMail_decorators, { kind: "method", name: "readMail", static: false, private: false, access: { has: obj => "readMail" in obj, get: obj => obj.readMail }, metadata: _metadata }, null, _instanceExtraInitializers);
938
968
  __esDecorate(this, null, _markMailRead_decorators, { kind: "method", name: "markMailRead", static: false, private: false, access: { has: obj => "markMailRead" in obj, get: obj => obj.markMailRead }, metadata: _metadata }, null, _instanceExtraInitializers);
939
969
  __esDecorate(this, null, _sendMail_decorators, { kind: "method", name: "sendMail", static: false, private: false, access: { has: obj => "sendMail" in obj, get: obj => obj.sendMail }, metadata: _metadata }, null, _instanceExtraInitializers);
970
+ __esDecorate(this, null, _downloadMailAttachment_decorators, { kind: "method", name: "downloadMailAttachment", static: false, private: false, access: { has: obj => "downloadMailAttachment" in obj, get: obj => obj.downloadMailAttachment }, metadata: _metadata }, null, _instanceExtraInitializers);
940
971
  __esDecorate(this, null, _clearLocalData_decorators, { kind: "method", name: "clearLocalData", static: false, private: false, access: { has: obj => "clearLocalData" in obj, get: obj => obj.clearLocalData }, metadata: _metadata }, null, _instanceExtraInitializers);
941
972
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
942
973
  }
@@ -1451,6 +1482,10 @@ let AwikiService = (() => {
1451
1482
  value: {
1452
1483
  pollIntervalMs: this.resolved.pollIntervalMs,
1453
1484
  attachmentMaxBytes: this.resolved.attachmentMaxBytes,
1485
+ mailAttachmentMaxCount: this.resolved.mailAttachmentMaxCount,
1486
+ mailAttachmentMaxBytes: Math.min(this.resolved.mailAttachmentMaxBytes, MAIL_HTTP_UPLOAD_MAX_BYTES),
1487
+ mailAttachmentDownloadMaxBytes: this.resolved.mailAttachmentMaxBytes,
1488
+ mailAttachmentTotalMaxBytes: Math.min(this.resolved.mailAttachmentTotalMaxBytes, MAIL_HTTP_UPLOAD_MAX_BYTES),
1454
1489
  handleRecoveryPhoneEnabled: capabilities.handleRecoveryPhoneEnabled,
1455
1490
  ...capabilities.guestGatewayBaseUrl === undefined
1456
1491
  ? {}
@@ -1716,13 +1751,6 @@ let AwikiService = (() => {
1716
1751
  }
1717
1752
  }
1718
1753
  async sendRegistrationOtp(request) {
1719
- if (shortHandleInviteRequired(request.handle)) {
1720
- const inspection = await this.inspectIdentityAccess({ handle: request.handle });
1721
- if (!inspection.ok)
1722
- return inspection;
1723
- if (inspection.value.status === 'available')
1724
- return { ok: false, error: failure('short-handle-invite-required') };
1725
- }
1726
1754
  this.pendingDeviceJoin = undefined;
1727
1755
  return this.run(async (client) => {
1728
1756
  if (await this.selectDeviceJoinSession(client) !== null) {
@@ -1737,13 +1765,6 @@ let AwikiService = (() => {
1737
1765
  * @returns The new public identity or a closed failure.
1738
1766
  */
1739
1767
  async registerIdentity(request) {
1740
- if (shortHandleInviteRequired(request.handle)) {
1741
- const inspection = await this.inspectIdentityAccess({ handle: request.handle });
1742
- if (!inspection.ok)
1743
- return inspection;
1744
- if (inspection.value.status === 'available')
1745
- return { ok: false, error: failure('short-handle-invite-required') };
1746
- }
1747
1768
  this.pendingDeviceJoin = undefined;
1748
1769
  const result = await this.run(async (client) => {
1749
1770
  if (await this.selectDeviceJoinSession(client) !== null) {
@@ -2444,7 +2465,7 @@ let AwikiService = (() => {
2444
2465
  }
2445
2466
  /** Return the deployment identity's public mailbox state. */
2446
2467
  getMailAccount() {
2447
- return this.run(client => client.getMailAccount());
2468
+ return this.run(client => client.getMailAccount(), { bindMailOwner: true });
2448
2469
  }
2449
2470
  /** List one bounded mailbox page on explicit browser/tool demand. */
2450
2471
  async listMailInbox(request) {
@@ -2463,7 +2484,7 @@ let AwikiService = (() => {
2463
2484
  if (this.sessionRevision !== requestGeneration)
2464
2485
  throw new AwikiSdkError('network');
2465
2486
  return page;
2466
- });
2487
+ }, { bindMailOwner: true });
2467
2488
  }
2468
2489
  /** Read one bounded plain-text mail message. */
2469
2490
  async readMail(request) {
@@ -2474,22 +2495,39 @@ let AwikiService = (() => {
2474
2495
  catch {
2475
2496
  return { ok: false, error: failure('invalid-request') };
2476
2497
  }
2477
- return this.run(client => client.readMail(normalized));
2498
+ return this.run(client => client.readMail(normalized), { bindMailOwner: true });
2478
2499
  }
2479
2500
  /** Mark explicitly selected mail messages read. Browser callers require an explicit click. */
2480
2501
  markMailRead(request) {
2481
- return this.runValidatedMail(() => mailMarkReadRequest(request), (client, normalized) => client.markMailRead(normalized));
2502
+ return this.runValidatedMail(() => mailMarkReadRequest(request), (client, normalized) => client.markMailRead(normalized), { bindMailOwner: true });
2482
2503
  }
2483
- /** Send one plain-text mail once. Browser callers require an explicit confirmation. */
2504
+ /** Send one mail once. Browser callers require an explicit confirmation. */
2484
2505
  async sendMail(request) {
2485
2506
  let normalized;
2486
2507
  try {
2487
- normalized = mailSendRequest(request);
2508
+ normalized = mailSendRequest(request, {
2509
+ maxCount: this.resolved.mailAttachmentMaxCount,
2510
+ maxBytes: Math.min(this.resolved.mailAttachmentMaxBytes, MAIL_HTTP_UPLOAD_MAX_BYTES),
2511
+ totalMaxBytes: Math.min(this.resolved.mailAttachmentTotalMaxBytes, MAIL_HTTP_UPLOAD_MAX_BYTES),
2512
+ });
2488
2513
  }
2489
2514
  catch {
2490
2515
  return { ok: false, error: failure('invalid-request') };
2491
2516
  }
2492
- return this.run(client => client.sendMail(normalized));
2517
+ return this.run(client => normalized.attachments.length === 0
2518
+ ? client.sendMail({ to: normalized.to, cc: normalized.cc, subject: normalized.subject, bodyText: normalized.bodyText })
2519
+ : new AwikiMailAttachmentClient(this.activeClientOptions.mailServiceUrl, this.externalHttpAuth).send(normalized), { bindMailOwner: true });
2520
+ }
2521
+ /** Download one mail attachment only after an explicit browser action. */
2522
+ async downloadMailAttachment(request) {
2523
+ let normalized;
2524
+ try {
2525
+ normalized = mailAttachmentDownloadRequest(request);
2526
+ }
2527
+ catch {
2528
+ return { ok: false, error: failure('invalid-request') };
2529
+ }
2530
+ return this.run(() => new AwikiMailAttachmentClient(this.activeClientOptions.mailServiceUrl, this.externalHttpAuth).download(normalized, this.resolved.mailAttachmentMaxBytes), { bindMailOwner: true });
2493
2531
  }
2494
2532
  /**
2495
2533
  * Permanently remove the exact SDK-owned local state after an explicit browser acknowledgement.
@@ -2844,6 +2882,7 @@ let AwikiService = (() => {
2844
2882
  async run(operation, options = {}) {
2845
2883
  try {
2846
2884
  const generation = this.runtimeGeneration;
2885
+ const revision = this.sessionRevision;
2847
2886
  if (this.getUpdatePolicyStatus().restricted) {
2848
2887
  return { ok: false, error: failure('client-version-unsupported') };
2849
2888
  }
@@ -2853,7 +2892,23 @@ let AwikiService = (() => {
2853
2892
  const provider = this.provider;
2854
2893
  if (provider === undefined)
2855
2894
  throw new ProviderUnavailableError();
2895
+ const owner = options.bindMailOwner === true ? await provider.client.getIdentity() : undefined;
2896
+ const assertMailSession = () => {
2897
+ if (options.bindMailOwner !== true)
2898
+ return;
2899
+ if (this.runtimeGeneration !== generation || this.provider !== provider || this.tenantSwitching) {
2900
+ throw new AwikiSdkError('conflict');
2901
+ }
2902
+ if (this.sessionRevision !== revision || this.signedOut === true)
2903
+ throw new ProviderUnavailableError();
2904
+ if (owner == null)
2905
+ throw new AwikiSdkError('not-registered');
2906
+ if (this.activeIdentityDid !== undefined && this.activeIdentityDid !== owner.did)
2907
+ throw new ProviderUnavailableError();
2908
+ };
2909
+ assertMailSession();
2856
2910
  const value = await operation(provider.client);
2911
+ assertMailSession();
2857
2912
  if (this.runtimeGeneration !== generation || this.provider !== provider) {
2858
2913
  return { ok: false, error: failure('conflict') };
2859
2914
  }
@@ -2872,7 +2927,7 @@ let AwikiService = (() => {
2872
2927
  }
2873
2928
  }
2874
2929
  /** Validate mail input before entering the provider and preserve fixed public failures. */
2875
- runValidatedMail(validate, operation) {
2930
+ runValidatedMail(validate, operation, options = {}) {
2876
2931
  let request;
2877
2932
  try {
2878
2933
  request = validate();
@@ -2880,7 +2935,7 @@ let AwikiService = (() => {
2880
2935
  catch {
2881
2936
  return Promise.resolve({ ok: false, error: failure('invalid-request') });
2882
2937
  }
2883
- return this.run(client => operation(client, request));
2938
+ return this.run(client => operation(client, request), options);
2884
2939
  }
2885
2940
  /** Read and cache the private Host-owned session marker. */
2886
2941
  async isSignedOut() {