@senguoyun/dsh-arkme 0.1.78 → 0.1.79

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 (52) hide show
  1. package/lib/client.js +912 -108
  2. package/lib/client.js.map +1 -1
  3. package/lib/harness-model-client.js +11 -3
  4. package/lib/harness-native-selection-client.js +11 -3
  5. package/lib/index.js +29 -1
  6. package/lib/persistent-extension.js +1 -1
  7. package/lib/{persistent-runtime-aiHgSAmj.js → persistent-runtime-CB7mEj3E.js} +404 -107
  8. package/lib/types/arkme-service.d.ts +9 -0
  9. package/lib/types/arkme-service.d.ts.map +1 -1
  10. package/lib/types/client/ArkmeAccountCancellation.d.ts +8 -0
  11. package/lib/types/client/ArkmeAccountCancellation.d.ts.map +1 -0
  12. package/lib/types/client/ArkmeLogin.d.ts +3 -0
  13. package/lib/types/client/ArkmeLogin.d.ts.map +1 -1
  14. package/lib/types/client/ArkmeRecordingSurface.d.ts +2 -1
  15. package/lib/types/client/ArkmeRecordingSurface.d.ts.map +1 -1
  16. package/lib/types/client/ArkmeSearchSurface.d.ts.map +1 -1
  17. package/lib/types/client/ArkmeSettingsSurface.d.ts +5 -0
  18. package/lib/types/client/ArkmeSettingsSurface.d.ts.map +1 -1
  19. package/lib/types/client/arkme-auth-flow.d.ts.map +1 -1
  20. package/lib/types/client/arkme-login-locales.d.ts +6 -0
  21. package/lib/types/client/arkme-login-locales.d.ts.map +1 -1
  22. package/lib/types/client/auth-store.d.ts.map +1 -1
  23. package/lib/types/client/locales/actions-en.d.ts.map +1 -1
  24. package/lib/types/client/recordings/RecordingSearchRow.d.ts +5 -0
  25. package/lib/types/client/recordings/RecordingSearchRow.d.ts.map +1 -0
  26. package/lib/types/client/recordings/recording-search-target.d.ts +4 -0
  27. package/lib/types/client/recordings/recording-search-target.d.ts.map +1 -0
  28. package/lib/types/client/ui-controller.d.ts +3 -5
  29. package/lib/types/client/ui-controller.d.ts.map +1 -1
  30. package/lib/types/host-api.d.ts.map +1 -1
  31. package/lib/types/index.d.ts +1 -1
  32. package/lib/types/index.d.ts.map +1 -1
  33. package/lib/types/local-database.d.ts +2 -0
  34. package/lib/types/local-database.d.ts.map +1 -1
  35. package/lib/types/recording-presentation.d.ts +1 -0
  36. package/lib/types/recording-presentation.d.ts.map +1 -1
  37. package/lib/types/recording-search-result.d.ts +3 -0
  38. package/lib/types/recording-search-result.d.ts.map +1 -0
  39. package/lib/types/recording-search-version.d.ts +17 -0
  40. package/lib/types/recording-search-version.d.ts.map +1 -0
  41. package/lib/types/services/auth-service.d.ts +20 -1
  42. package/lib/types/services/auth-service.d.ts.map +1 -1
  43. package/lib/types/services/recording-service.d.ts.map +1 -1
  44. package/lib/types/services/search-service.d.ts +3 -1
  45. package/lib/types/services/search-service.d.ts.map +1 -1
  46. package/lib/types/services/service.d.ts +3 -0
  47. package/lib/types/services/service.d.ts.map +1 -1
  48. package/lib/types/state-store.d.ts +7 -0
  49. package/lib/types/state-store.d.ts.map +1 -1
  50. package/lib/types/types.d.ts +45 -2
  51. package/lib/types/types.d.ts.map +1 -1
  52. package/package.json +5 -5
@@ -1296,6 +1296,9 @@ var ServiceRuntime = class {
1296
1296
  async deleteSession() {
1297
1297
  await this.accountSessions.delete();
1298
1298
  }
1299
+ async deleteSessionIfCurrent(expected) {
1300
+ return await this.accountSessions.deleteIfCurrent(expected);
1301
+ }
1299
1302
  async moveSessionToPendingBinding(expected) {
1300
1303
  return await this.accountSessions.deleteIfCurrent(expected, async (current) => {
1301
1304
  await this.writePendingBindingSession(current);
@@ -3863,7 +3866,7 @@ var ArkmeDesktopScreenshot = class {
3863
3866
  };
3864
3867
  //#endregion
3865
3868
  //#region src/services/record-edit-history-service.ts
3866
- function invalid$9() {
3869
+ function invalid$10() {
3867
3870
  throw new ArkmePluginError("record-edit-history-invalid", "编辑记录暂不可用,请刷新后重试", true, 502);
3868
3871
  }
3869
3872
  var RecordEditHistoryService = class {
@@ -3874,9 +3877,9 @@ var RecordEditHistoryService = class {
3874
3877
  this.projector = projector;
3875
3878
  }
3876
3879
  async page(target, cursorEditAt = 0, signal) {
3877
- if (!Number.isSafeInteger(cursorEditAt) || cursorEditAt < 0 || target.recordUid.trim() === "") invalid$9();
3880
+ if (!Number.isSafeInteger(cursorEditAt) || cursorEditAt < 0 || target.recordUid.trim() === "") invalid$10();
3878
3881
  const session = await this.runtime.requireSession();
3879
- if (session.userId !== target.viewerUserId) invalid$9();
3882
+ if (session.userId !== target.viewerUserId) invalid$10();
3880
3883
  const window = {
3881
3884
  limit: 50,
3882
3885
  ...cursorEditAt === 0 ? {} : { cursor_edit_at: cursorEditAt }
@@ -3889,22 +3892,22 @@ var RecordEditHistoryService = class {
3889
3892
  rel_uid: target.relationUid,
3890
3893
  ...window
3891
3894
  }, session, signal));
3892
- if (signal?.aborted || (await this.runtime.requireSession()).userId !== session.userId) invalid$9();
3893
- if (!Array.isArray(data.items) || typeof data.has_more !== "boolean") invalid$9();
3895
+ if (signal?.aborted || (await this.runtime.requireSession()).userId !== session.userId) invalid$10();
3896
+ if (!Array.isArray(data.items) || typeof data.has_more !== "boolean") invalid$10();
3894
3897
  const next = data.next_cursor_edit_at;
3895
- if (data.has_more && (typeof next !== "number" || !Number.isSafeInteger(next) || next <= 0 || cursorEditAt > 0 && next >= cursorEditAt)) invalid$9();
3898
+ if (data.has_more && (typeof next !== "number" || !Number.isSafeInteger(next) || next <= 0 || cursorEditAt > 0 && next >= cursorEditAt)) invalid$10();
3896
3899
  const seen = /* @__PURE__ */ new Set();
3897
3900
  const snapshots = data.items.flatMap((raw) => {
3898
3901
  const revision = objectValue$2(raw);
3899
- if (revision.record_uid !== target.recordUid || typeof revision.revision_uid !== "string" || revision.revision_uid.trim() === "") invalid$9();
3902
+ if (revision.record_uid !== target.recordUid || typeof revision.revision_uid !== "string" || revision.revision_uid.trim() === "") invalid$10();
3900
3903
  if (revision.revision_type !== 1 && revision.revision_type !== 5) return [];
3901
- if (typeof revision.edit_at !== "number" || !Number.isSafeInteger(revision.edit_at) || revision.edit_at <= 0 || !Number.isFinite(new Date(revision.edit_at).getTime()) || typeof revision.text_content !== "string") invalid$9();
3904
+ if (typeof revision.edit_at !== "number" || !Number.isSafeInteger(revision.edit_at) || revision.edit_at <= 0 || !Number.isFinite(new Date(revision.edit_at).getTime()) || typeof revision.text_content !== "string") invalid$10();
3902
3905
  if (seen.has(revision.revision_uid)) return [];
3903
3906
  seen.add(revision.revision_uid);
3904
3907
  return [revision];
3905
3908
  });
3906
3909
  const contents = snapshots.length === 0 ? [] : await this.projector.projectPage(snapshots, target, signal);
3907
- if (signal?.aborted || (await this.runtime.requireSession()).userId !== session.userId || contents.length !== snapshots.length) invalid$9();
3910
+ if (signal?.aborted || (await this.runtime.requireSession()).userId !== session.userId || contents.length !== snapshots.length) invalid$10();
3908
3911
  const items = snapshots.map((revision, index) => ({
3909
3912
  revisionUid: revision.revision_uid,
3910
3913
  kind: revision.revision_type === 5 ? "original" : "manual",
@@ -22457,7 +22460,7 @@ function arkmeArticleImageReference(value) {
22457
22460
  }
22458
22461
  //#endregion
22459
22462
  //#region src/services/archive-service.ts
22460
- const invalid$8 = () => new ArkmePluginError("archive-contract-invalid", "归档数据无效,请刷新后重试", false, 502);
22463
+ const invalid$9 = () => new ArkmePluginError("archive-contract-invalid", "归档数据无效,请刷新后重试", false, 502);
22461
22464
  /** One Host owner for UI, Tools and SDK. Raw topic identities stay here. */
22462
22465
  var ArchiveService = class {
22463
22466
  runtime;
@@ -22481,17 +22484,17 @@ var ArchiveService = class {
22481
22484
  limit: 50,
22482
22485
  ...cursor === void 0 ? {} : { cursor }
22483
22486
  }, session, readSignal, { lane: "interactive-read" });
22484
- if (!Array.isArray(data.items) || typeof data.has_more !== "boolean") throw invalid$8();
22487
+ if (!Array.isArray(data.items) || typeof data.has_more !== "boolean") throw invalid$9();
22485
22488
  const items = [];
22486
22489
  for (const value of data.items) {
22487
22490
  const raw = objectValue$2(value);
22488
- if (typeof raw.title !== "string" || typeof raw.privacy_locked !== "boolean") throw invalid$8();
22491
+ if (typeof raw.title !== "string" || typeof raw.privacy_locked !== "boolean") throw invalid$9();
22489
22492
  const title = raw.privacy_locked ? "隐私主题" : raw.title;
22490
22493
  const state = await this.state(session, raw, title);
22491
- if (!state.ownerAvailable || !state.effectiveArchived) throw invalid$8();
22494
+ if (!state.ownerAvailable || !state.effectiveArchived) throw invalid$9();
22492
22495
  const inherited = raw.inherited_from_summary === void 0 ? void 0 : objectValue$2(raw.inherited_from_summary);
22493
- if (state.inheritedFrom !== void 0 !== (inherited !== void 0)) throw invalid$8();
22494
- if (inherited !== void 0 && (typeof inherited.title !== "string" || typeof inherited.privacy_locked !== "boolean")) throw invalid$8();
22496
+ if (state.inheritedFrom !== void 0 !== (inherited !== void 0)) throw invalid$9();
22497
+ if (inherited !== void 0 && (typeof inherited.title !== "string" || typeof inherited.privacy_locked !== "boolean")) throw invalid$9();
22495
22498
  items.push({
22496
22499
  ...state,
22497
22500
  privacyLocked: raw.privacy_locked,
@@ -22510,7 +22513,7 @@ var ArchiveService = class {
22510
22513
  }
22511
22514
  });
22512
22515
  }
22513
- if (data.has_more && (typeof data.next_cursor !== "string" || data.next_cursor === "" || data.next_cursor === cursor)) throw invalid$8();
22516
+ if (data.has_more && (typeof data.next_cursor !== "string" || data.next_cursor === "" || data.next_cursor === cursor)) throw invalid$9();
22514
22517
  await this.assertSession(session);
22515
22518
  return {
22516
22519
  items,
@@ -22520,7 +22523,7 @@ var ArchiveService = class {
22520
22523
  }, signal);
22521
22524
  }
22522
22525
  async states(sourceRefs, signal) {
22523
- if (sourceRefs.length === 0 || sourceRefs.length > 200 || new Set(sourceRefs).size !== sourceRefs.length) throw invalid$8();
22526
+ if (sourceRefs.length === 0 || sourceRefs.length > 200 || new Set(sourceRefs).size !== sourceRefs.length) throw invalid$9();
22524
22527
  return this.runtime.runOwnerRead("archives", {
22525
22528
  operation: "states",
22526
22529
  sourceRefs
@@ -22533,12 +22536,12 @@ var ArchiveService = class {
22533
22536
  entity_type: 1,
22534
22537
  entity_uid: ref.ownerRef
22535
22538
  })) }, session, readSignal, { lane: "interactive-read" });
22536
- if (!Array.isArray(data.items) || data.items.length !== refs.length) throw invalid$8();
22539
+ if (!Array.isArray(data.items) || data.items.length !== refs.length) throw invalid$9();
22537
22540
  const byUID = new Map(data.items.map((value) => {
22538
22541
  const raw = objectValue$2(value);
22539
22542
  return [raw.entity_uid, raw];
22540
22543
  }));
22541
- if (byUID.size !== refs.length) throw invalid$8();
22544
+ if (byUID.size !== refs.length) throw invalid$9();
22542
22545
  const states = await Promise.all(refs.map(async (ref, i) => ({
22543
22546
  ...await this.state(session, byUID.get(ref.ownerRef), ""),
22544
22547
  sourceRef: sourceRefs[i]
@@ -22548,7 +22551,7 @@ var ArchiveService = class {
22548
22551
  }, signal);
22549
22552
  }
22550
22553
  async set(input, signal) {
22551
- if (typeof input.selfArchived !== "boolean" || !Number.isSafeInteger(input.expectedRevision) || input.expectedRevision < 0) throw invalid$8();
22554
+ if (typeof input.selfArchived !== "boolean" || !Number.isSafeInteger(input.expectedRevision) || input.expectedRevision < 0) throw invalid$9();
22552
22555
  const session = await this.runtime.requireSession();
22553
22556
  const ref = await this.sources.openSourceRef(input.sourceRef, session.userId);
22554
22557
  if (ref.kind !== "topic") throw new ArkmePluginError("archive-target-invalid", "仅支持个人主题归档", false, 400);
@@ -22562,7 +22565,7 @@ var ArchiveService = class {
22562
22565
  self_status: input.selfArchived ? 2 : 1,
22563
22566
  expected_revision: input.expectedRevision
22564
22567
  }, session, signal, { trackWriteOutcome: true });
22565
- if (data.entity_uid !== ref.ownerRef || data.self_status !== (input.selfArchived ? 2 : 1) || typeof data.state_changed !== "boolean" || !Number.isSafeInteger(data.effective_changed_count) || Number(data.effective_changed_count) < 0) throw invalid$8();
22568
+ if (data.entity_uid !== ref.ownerRef || data.self_status !== (input.selfArchived ? 2 : 1) || typeof data.state_changed !== "boolean" || !Number.isSafeInteger(data.effective_changed_count) || Number(data.effective_changed_count) < 0) throw invalid$9();
22566
22569
  const state = await this.state(session, data, "");
22567
22570
  await this.assertSession(session);
22568
22571
  return {
@@ -22578,9 +22581,9 @@ var ArchiveService = class {
22578
22581
  }
22579
22582
  async state(session, value, title) {
22580
22583
  const raw = objectValue$2(value);
22581
- if (raw.entity_type !== 1 || typeof raw.entity_uid !== "string" || raw.entity_uid.trim() === "" || raw.self_status !== 1 && raw.self_status !== 2 || raw.effective_status !== 1 && raw.effective_status !== 2 || typeof raw.owner_available !== "boolean" || !Number.isSafeInteger(raw.revision) || Number(raw.revision) < 0 || !Number.isSafeInteger(raw.display_archive_at)) throw invalid$8();
22584
+ if (raw.entity_type !== 1 || typeof raw.entity_uid !== "string" || raw.entity_uid.trim() === "" || raw.self_status !== 1 && raw.self_status !== 2 || raw.effective_status !== 1 && raw.effective_status !== 2 || typeof raw.owner_available !== "boolean" || !Number.isSafeInteger(raw.revision) || Number(raw.revision) < 0 || !Number.isSafeInteger(raw.display_archive_at)) throw invalid$9();
22582
22585
  const parent = raw.inherited_from === void 0 ? void 0 : objectValue$2(raw.inherited_from);
22583
- if (parent !== void 0 && (parent.entity_type !== 1 || typeof parent.entity_uid !== "string" || parent.entity_uid === "")) throw invalid$8();
22586
+ if (parent !== void 0 && (parent.entity_type !== 1 || typeof parent.entity_uid !== "string" || parent.entity_uid === "")) throw invalid$9();
22584
22587
  return {
22585
22588
  entityType: "topic",
22586
22589
  sourceRef: await this.sources.sealSourceRef(session.userId, "topic", raw.entity_uid, title),
@@ -22599,23 +22602,23 @@ var ArchiveService = class {
22599
22602
  //#endregion
22600
22603
  //#region src/record-deletion-ref.ts
22601
22604
  const prefix$1 = "arkme-record-delete-v1";
22602
- const invalid$7 = () => new ArkmePluginError("record-delete-reference-invalid", "删除引用已失效,请刷新后重新选择", false, 409);
22605
+ const invalid$8 = () => new ArkmePluginError("record-delete-reference-invalid", "删除引用已失效,请刷新后重新选择", false, 409);
22603
22606
  function sealRecordDeletionRef(ref, key) {
22604
22607
  const payload = Buffer.from(JSON.stringify(ref)).toString("base64url");
22605
22608
  return `${prefix$1}.${payload}.${createHmac("sha256", key).update(`${prefix$1}.${payload}`).digest("base64url")}`;
22606
22609
  }
22607
22610
  function openRecordDeletionRef(value, key) {
22608
- if (typeof value !== "string" || value.length > 2048) throw invalid$7();
22611
+ if (typeof value !== "string" || value.length > 2048) throw invalid$8();
22609
22612
  const [kind, payload, signature, extra] = value.split(".");
22610
- if (kind !== prefix$1 || !payload || !signature || extra !== void 0) throw invalid$7();
22613
+ if (kind !== prefix$1 || !payload || !signature || extra !== void 0) throw invalid$8();
22611
22614
  const actual = Buffer.from(signature, "base64url");
22612
22615
  const expected = createHmac("sha256", key).update(`${prefix$1}.${payload}`).digest();
22613
- if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) throw invalid$7();
22616
+ if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) throw invalid$8();
22614
22617
  let ref;
22615
22618
  try {
22616
22619
  ref = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
22617
22620
  } catch {
22618
- throw invalid$7();
22621
+ throw invalid$8();
22619
22622
  }
22620
22623
  if (!ref || !Number.isSafeInteger(ref.userId) || ref.userId <= 0 || !Number.isSafeInteger(ref.recordVersion) || ref.recordVersion <= 0 || ![
22621
22624
  "private_chat",
@@ -22623,7 +22626,7 @@ function openRecordDeletionRef(value, key) {
22623
22626
  "send_to_self",
22624
22627
  "default_category",
22625
22628
  "topic"
22626
- ].includes(ref.sourceKind) || typeof ref.sourceOwnerRef !== "string" || !ref.sourceOwnerRef.trim() || typeof ref.recordUid !== "string" || !ref.recordUid.trim()) throw invalid$7();
22629
+ ].includes(ref.sourceKind) || typeof ref.sourceOwnerRef !== "string" || !ref.sourceOwnerRef.trim() || typeof ref.recordUid !== "string" || !ref.recordUid.trim()) throw invalid$8();
22627
22630
  return ref;
22628
22631
  }
22629
22632
  /** Only authoritative Record snapshots can grant deletion; missing versions never fall back to a relation version. */
@@ -22736,31 +22739,31 @@ var RecordDeletionService = class {
22736
22739
  };
22737
22740
  //#endregion
22738
22741
  //#region src/record-topic-assignment-ref.ts
22739
- const invalid$6 = () => new ArkmePluginError("record-topic-reference-invalid", "快记归属引用已失效,请刷新后重新选择", false, 409);
22742
+ const invalid$7 = () => new ArkmePluginError("record-topic-reference-invalid", "快记归属引用已失效,请刷新后重新选择", false, 409);
22740
22743
  const prefix = "arkme-record-topic-v1";
22741
22744
  function sealRecordTopicAssignmentRef(reference, key) {
22742
22745
  const payload = Buffer.from(JSON.stringify(reference)).toString("base64url");
22743
22746
  return `${prefix}.${payload}.${createHmac("sha256", key).update(`${prefix}.${payload}`).digest("base64url")}`;
22744
22747
  }
22745
22748
  function openRecordTopicAssignmentRef(value, key) {
22746
- if (typeof value !== "string" || value.length > 2048) throw invalid$6();
22749
+ if (typeof value !== "string" || value.length > 2048) throw invalid$7();
22747
22750
  const parts = value.split(".");
22748
- if (parts.length !== 3 || parts[0] !== prefix) throw invalid$6();
22751
+ if (parts.length !== 3 || parts[0] !== prefix) throw invalid$7();
22749
22752
  const payload = parts[1];
22750
22753
  const signature = Buffer.from(parts[2], "base64url");
22751
22754
  const expected = createHmac("sha256", key).update(`${prefix}.${payload}`).digest();
22752
- if (signature.length !== expected.length || !timingSafeEqual(signature, expected)) throw invalid$6();
22755
+ if (signature.length !== expected.length || !timingSafeEqual(signature, expected)) throw invalid$7();
22753
22756
  let parsed;
22754
22757
  try {
22755
22758
  parsed = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
22756
22759
  } catch {
22757
- throw invalid$6();
22760
+ throw invalid$7();
22758
22761
  }
22759
22762
  if (!parsed || !Number.isSafeInteger(parsed.userId) || parsed.userId <= 0 || ![
22760
22763
  "send_to_self",
22761
22764
  "default_category",
22762
22765
  "topic"
22763
- ].includes(parsed.sourceKind) || typeof parsed.sourceOwnerRef !== "string" || parsed.sourceOwnerRef.trim() === "" || typeof parsed.recordUid !== "string" || parsed.recordUid.trim() === "" || typeof parsed.sourceTopicUid !== "string") throw invalid$6();
22766
+ ].includes(parsed.sourceKind) || typeof parsed.sourceOwnerRef !== "string" || parsed.sourceOwnerRef.trim() === "" || typeof parsed.recordUid !== "string" || parsed.recordUid.trim() === "" || typeof parsed.sourceTopicUid !== "string") throw invalid$7();
22764
22767
  return parsed;
22765
22768
  }
22766
22769
  //#endregion
@@ -36846,6 +36849,10 @@ var AuthService = class {
36846
36849
  runtime;
36847
36850
  profile;
36848
36851
  lifecycle;
36852
+ cancellationNotice;
36853
+ pendingCancellationLogin;
36854
+ pendingCancellationCleanup;
36855
+ cancellationTask;
36849
36856
  pendingPhoneUnbindSession;
36850
36857
  attempts = /* @__PURE__ */ new Map();
36851
36858
  jiwoAttemptGeneration = 0;
@@ -36860,6 +36867,7 @@ var AuthService = class {
36860
36867
  for (const [attemptId, attempt] of this.attempts) if (attempt.kind === "wechat") this.attempts.delete(attemptId);
36861
36868
  }
36862
36869
  async logout() {
36870
+ this.pendingCancellationLogin = void 0;
36863
36871
  this.pendingPhoneUnbindSession = void 0;
36864
36872
  const activeSession = await this.runtime.sessionStore.read();
36865
36873
  const pendingSession = await this.runtime.readPendingBindingSession();
@@ -36882,7 +36890,24 @@ var AuthService = class {
36882
36890
  };
36883
36891
  }
36884
36892
  async authStatus() {
36893
+ if (this.pendingCancellationLogin !== void 0) return this.cancellationLoginSnapshot();
36885
36894
  const activeSession = await this.runtime.sessionStore.read();
36895
+ const completion = await this.runtime.stateStore.readCancellationCompletion?.();
36896
+ if (completion !== void 0) {
36897
+ if (activeSession === void 0) this.cancellationNotice = completion.result.status === "done" ? "done" : "waiting";
36898
+ else if (completion.userId === activeSession.userId && completion.sessionHash === this.cancellationSessionHash(activeSession)) {
36899
+ this.pendingCancellationCleanup = {
36900
+ session: activeSession,
36901
+ result: completion.result
36902
+ };
36903
+ await this.submitCancellation(activeSession.userId, completion.result.mode);
36904
+ return {
36905
+ status: "logged-out",
36906
+ environment: this.runtime.config.environment,
36907
+ cancellationNotice: completion.result.status === "done" ? "done" : "waiting"
36908
+ };
36909
+ }
36910
+ }
36886
36911
  if (activeSession !== void 0) {
36887
36912
  const cachedProfile = await this.runtime.stateStore.cachedProfile(activeSession.userId);
36888
36913
  const snapshot = cachedProfile.profile === null ? await this.authSnapshotForSession(activeSession) : {
@@ -36900,7 +36925,8 @@ var AuthService = class {
36900
36925
  const pendingSession = await this.runtime.readPendingBindingSession();
36901
36926
  return pendingSession === void 0 ? {
36902
36927
  status: "logged-out",
36903
- environment: this.runtime.config.environment
36928
+ environment: this.runtime.config.environment,
36929
+ ...this.cancellationNotice === void 0 ? {} : { cancellationNotice: this.cancellationNotice }
36904
36930
  } : {
36905
36931
  status: "binding-required",
36906
36932
  environment: this.runtime.config.environment,
@@ -36908,6 +36934,7 @@ var AuthService = class {
36908
36934
  };
36909
36935
  }
36910
36936
  async beginWechatLogin() {
36937
+ this.pendingCancellationLogin = void 0;
36911
36938
  this.jiwoAttemptGeneration += 1;
36912
36939
  await this.cancelAllJiwoLoginAttempts();
36913
36940
  const data = await this.runtime.post(this.runtime.config.authBaseUrl, "/api/public/v1/auth/wechat-oauth-login-qrcode", {}, void 0, [200]);
@@ -36970,10 +36997,11 @@ var AuthService = class {
36970
36997
  userId
36971
36998
  };
36972
36999
  this.attempts.delete(attemptId);
36973
- return await this.acceptLoginSession(session);
37000
+ return await this.acceptLoginSession(session, numberValue$27(data.rest_days_cancel));
36974
37001
  }
36975
37002
  async beginJiwoLogin() {
36976
37003
  if (!jiwoScanLoginAvailable(this.runtime.config)) throw new ArkmePluginError("jiwo-scan-login-disabled", "即我扫码登录当前未启用", false, 403);
37004
+ this.pendingCancellationLogin = void 0;
36977
37005
  const attemptGeneration = ++this.jiwoAttemptGeneration;
36978
37006
  await this.cancelAllJiwoLoginAttempts();
36979
37007
  const data = await this.runtime.post(this.runtime.config.authBaseUrl, "/api/public/v1/auth/app-scan-login/start", {
@@ -37042,7 +37070,7 @@ var AuthService = class {
37042
37070
  accessToken,
37043
37071
  refreshToken,
37044
37072
  userId
37045
- });
37073
+ }, numberValue$27(data.rest_days_cancel));
37046
37074
  }
37047
37075
  async cancelJiwoLogin(attemptId) {
37048
37076
  if (attemptId.trim() === "") return { canceled: true };
@@ -37080,6 +37108,7 @@ var AuthService = class {
37080
37108
  async testLogin(userId) {
37081
37109
  if (this.runtime.config.environment !== "test") throw new ArkmePluginError("test-login-disabled", "测试账号登录仅允许测试环境使用", false, 403);
37082
37110
  if (!Number.isSafeInteger(userId) || userId <= 0) throw new ArkmePluginError("test-user-id-invalid", "请输入有效的测试账号 user_id", false);
37111
+ this.pendingCancellationLogin = void 0;
37083
37112
  const data = await this.runtime.post(this.runtime.config.authBaseUrl, "/api/public/v1/auth/the-best-api-for-testing", {
37084
37113
  user_id: userId,
37085
37114
  unique_code: await this.runtime.stateStore.uniqueCode(),
@@ -37095,7 +37124,30 @@ var AuthService = class {
37095
37124
  userId
37096
37125
  };
37097
37126
  this.attempts.clear();
37098
- return await this.acceptLoginSession(session);
37127
+ return await this.acceptLoginSession(session, numberValue$27(data.rest_days_cancel));
37128
+ }
37129
+ async emailBindingRequest(expectedUserId, email, code) {
37130
+ const session = await this.runtime.requireSession();
37131
+ if (session.userId !== expectedUserId) throw new ArkmePluginError("email-session-changed", "账号已切换,请重新打开账号设置", false);
37132
+ const normalizedEmail = email.trim();
37133
+ if (normalizedEmail.length > 254 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalizedEmail)) throw new ArkmePluginError("email-invalid", "请输入有效的邮箱地址", false);
37134
+ if (code !== void 0 && !/^[0-9]{4}$/.test(code.trim())) throw new ArkmePluginError("email-code-invalid", "请输入4位邮箱验证码", false);
37135
+ const data = await this.runtime.post(this.runtime.config.authBaseUrl, code === void 0 ? "/api/v1/auth/email-bind-send-code" : "/api/v1/auth/email-bind", {
37136
+ email: normalizedEmail,
37137
+ ...code === void 0 ? {} : { code: code.trim() }
37138
+ }, session.accessToken, [200]);
37139
+ const current = await this.runtime.requireSession();
37140
+ if (current.userId !== session.userId || current.refreshToken !== session.refreshToken) throw new ArkmePluginError("email-session-changed", "账号已切换,请重新打开账号设置", false);
37141
+ if (data.result !== 1) throw new ArkmePluginError("email-bind-rejected", data.result === 2 ? "该邮箱已绑定其他账号" : data.result === 3 ? "当前账号已绑定邮箱,请刷新账号信息" : code !== void 0 && data.result === 4 ? "邮箱或验证码错误" : "邮箱绑定响应异常,请重试", false);
37142
+ if (code !== void 0) this.profile.invalidate(session.userId);
37143
+ }
37144
+ async sendEmailBindCode(expectedUserId, email) {
37145
+ await this.emailBindingRequest(expectedUserId, email);
37146
+ return { sent: true };
37147
+ }
37148
+ async bindEmail(expectedUserId, email, code) {
37149
+ await this.emailBindingRequest(expectedUserId, email, code);
37150
+ return { bound: true };
37099
37151
  }
37100
37152
  async sendPhoneCode(phone, captcha) {
37101
37153
  const normalizedPhone = this.normalizedPhone(phone);
@@ -37122,6 +37174,7 @@ var AuthService = class {
37122
37174
  const normalizedPhone = this.normalizedPhone(phone);
37123
37175
  const normalizedCode = code.trim();
37124
37176
  if (!/^[0-9]{6}$/.test(normalizedCode)) throw new ArkmePluginError("phone-code-invalid", "请输入有效的短信验证码", false);
37177
+ this.pendingCancellationLogin = void 0;
37125
37178
  const session = await this.runtime.sessionStore.read() ?? await this.runtime.readPendingBindingSession();
37126
37179
  if (session !== void 0) {
37127
37180
  const result = numberValue$27((await this.runtime.post(this.runtime.config.authBaseUrl, "/api/v1/auth/verify-bind-phone", {
@@ -37155,7 +37208,7 @@ var AuthService = class {
37155
37208
  userId
37156
37209
  };
37157
37210
  this.attempts.clear();
37158
- return await this.acceptLoginSession(sessionAfterPhoneLogin);
37211
+ return await this.acceptLoginSession(sessionAfterPhoneLogin, numberValue$27(data.rest_days_cancel));
37159
37212
  }
37160
37213
  async checkPhoneUnbindEligibility(expectedUserId) {
37161
37214
  const session = await this.runtime.requireSession();
@@ -37250,21 +37303,144 @@ var AuthService = class {
37250
37303
  profileHasBoundPhone(snapshot) {
37251
37304
  return (snapshot.profile?.contact.phoneMasked?.trim() ?? "") !== "";
37252
37305
  }
37253
- async acceptLoginSession(session) {
37306
+ async acceptLoginSession(session, restDaysCancel = 0, assertCurrent) {
37307
+ if (assertCurrent === void 0) this.pendingCancellationLogin = void 0;
37308
+ if (restDaysCancel > 0) {
37309
+ this.pendingCancellationLogin = {
37310
+ session,
37311
+ days: restDaysCancel
37312
+ };
37313
+ return this.cancellationLoginSnapshot();
37314
+ }
37315
+ await this.runtime.stateStore.writeCancellationCompletion?.(void 0);
37316
+ this.cancellationNotice = void 0;
37254
37317
  this.runtime.invalidateScope(this.runtime.requestScope(session.userId));
37255
37318
  this.profile.invalidate(session.userId);
37256
37319
  const snapshot = await this.authSnapshotForSession(session, { forceProfile: true });
37320
+ assertCurrent?.();
37257
37321
  if (snapshot.status === "authenticated") {
37258
37322
  await this.runtime.clearPendingBindingSession();
37323
+ assertCurrent?.();
37259
37324
  await this.runtime.writeSession(session);
37325
+ assertCurrent?.();
37260
37326
  this.lifecycle.reconnectChatRealtime();
37261
37327
  return snapshot;
37262
37328
  }
37263
37329
  await this.runtime.writePendingBindingSession(session);
37330
+ assertCurrent?.();
37264
37331
  await this.runtime.deleteSession();
37332
+ assertCurrent?.();
37265
37333
  this.lifecycle.reconnectChatRealtime();
37266
37334
  return snapshot;
37267
37335
  }
37336
+ cancellationLoginSnapshot() {
37337
+ return {
37338
+ status: "cancellation-pending",
37339
+ environment: this.runtime.config.environment,
37340
+ restDaysCancel: this.pendingCancellationLogin.days
37341
+ };
37342
+ }
37343
+ async resolveCancellationLogin(continueLogin) {
37344
+ const pending = this.pendingCancellationLogin;
37345
+ if (pending === void 0) throw new ArkmePluginError("cancellation-login-expired", "登录确认已失效,请重新登录", false);
37346
+ if (!continueLogin) {
37347
+ this.pendingCancellationLogin = void 0;
37348
+ return {
37349
+ status: "logged-out",
37350
+ environment: this.runtime.config.environment
37351
+ };
37352
+ }
37353
+ await this.runtime.post(this.runtime.config.authBaseUrl, "/api/v1/auth/abort-cancel", {}, pending.session.accessToken, [200]);
37354
+ if (this.pendingCancellationLogin !== pending) throw new ArkmePluginError("cancellation-login-expired", "登录确认已失效,请重新登录", false);
37355
+ const snapshot = await this.acceptLoginSession(pending.session, 0, () => {
37356
+ if (this.pendingCancellationLogin !== pending) throw new ArkmePluginError("cancellation-login-expired", "登录确认已失效,请重新登录", false);
37357
+ });
37358
+ if (this.pendingCancellationLogin === pending) this.pendingCancellationLogin = void 0;
37359
+ return snapshot;
37360
+ }
37361
+ async cancellationSession(expectedUserId) {
37362
+ const session = await this.runtime.requireSession();
37363
+ if (session.userId !== expectedUserId) throw new ArkmePluginError("cancellation-session-changed", "账号已切换,请重新打开账号设置", false);
37364
+ return session;
37365
+ }
37366
+ cancellationResult(data) {
37367
+ if (!data || !["immediate", "waiting"].includes(data.mode) || ![
37368
+ "eligible",
37369
+ "waiting",
37370
+ "done"
37371
+ ].includes(data.status) || !Number.isSafeInteger(data.cancel_at) || data.cancel_at < 0 || typeof data.has_phone !== "boolean") throw new ArkmePluginError("cancellation-contract-invalid", "注销状态未确认,请稍后重试", true, 502);
37372
+ return data;
37373
+ }
37374
+ async previewCancellation(expectedUserId) {
37375
+ const session = await this.cancellationSession(expectedUserId);
37376
+ const data = await this.runtime.post(this.runtime.config.authBaseUrl, "/api/v1/auth/cancellation/preview", {}, session.accessToken, [200]);
37377
+ if ((await this.cancellationSession(expectedUserId)).refreshToken !== session.refreshToken) throw new ArkmePluginError("cancellation-session-changed", "登录状态已变化,请重试", false);
37378
+ return this.cancellationResult(data);
37379
+ }
37380
+ async submitCancellation(expectedUserId, expectedMode) {
37381
+ if (expectedMode !== "immediate" && expectedMode !== "waiting") throw new ArkmePluginError("cancellation-mode-invalid", "请重新确认注销方式", false);
37382
+ if (this.cancellationTask !== void 0) throw new ArkmePluginError("cancellation-busy", "正在处理注销,请稍候", true);
37383
+ const task = this.performCancellation(expectedUserId, expectedMode);
37384
+ this.cancellationTask = task;
37385
+ try {
37386
+ return await task;
37387
+ } finally {
37388
+ if (this.cancellationTask === task) this.cancellationTask = void 0;
37389
+ }
37390
+ }
37391
+ async performCancellation(expectedUserId, expectedMode) {
37392
+ let cleanup = this.pendingCancellationCleanup;
37393
+ if (cleanup === void 0) {
37394
+ const completion = await this.runtime.stateStore.readCancellationCompletion?.();
37395
+ const active = await this.runtime.sessionStore.read();
37396
+ if (completion?.userId === expectedUserId && active === void 0) return completion.result;
37397
+ if (completion?.userId === expectedUserId && active !== void 0 && completion.sessionHash === this.cancellationSessionHash(active)) {
37398
+ cleanup = {
37399
+ session: active,
37400
+ result: completion.result
37401
+ };
37402
+ this.pendingCancellationCleanup = cleanup;
37403
+ }
37404
+ }
37405
+ if (cleanup === void 0 || cleanup.session.userId !== expectedUserId) {
37406
+ const session = await this.cancellationSession(expectedUserId);
37407
+ const result = this.cancellationResult(await this.runtime.post(this.runtime.config.authBaseUrl, "/api/v1/auth/cancellation/submit", { expected_mode: expectedMode }, session.accessToken, [200], void 0, false, this.runtime.authenticatedRequestOptions(session, "auth", "write", { trackWriteOutcome: true })));
37408
+ if (result.changed === true && result.status === "eligible") return result;
37409
+ if (result.status !== "done" && result.status !== "waiting") throw new ArkmePluginError("cancellation-contract-invalid", "注销状态未确认,请稍后重试", true);
37410
+ cleanup = {
37411
+ session,
37412
+ result
37413
+ };
37414
+ this.pendingCancellationCleanup = cleanup;
37415
+ }
37416
+ const current = await this.runtime.sessionStore.read();
37417
+ if (current !== void 0 && (current.userId !== cleanup.session.userId || current.refreshToken !== cleanup.session.refreshToken)) {
37418
+ await this.runtime.stateStore.writeCancellationCompletion?.(void 0);
37419
+ this.pendingCancellationCleanup = void 0;
37420
+ throw new ArkmePluginError("cancellation-session-changed", "账号已切换,原账号注销已处理", false);
37421
+ }
37422
+ await this.runtime.stateStore.writeCancellationCompletion?.({
37423
+ userId: cleanup.session.userId,
37424
+ sessionHash: this.cancellationSessionHash(cleanup.session),
37425
+ result: cleanup.result
37426
+ });
37427
+ this.runtime.invalidateScope(this.runtime.requestScope(cleanup.session.userId));
37428
+ this.runtime.clearRefreshForUser(cleanup.session.userId);
37429
+ if (!await this.runtime.deleteSessionIfCurrent(cleanup.session) && await this.runtime.sessionStore.read() !== void 0) {
37430
+ await this.runtime.stateStore.writeCancellationCompletion?.(void 0);
37431
+ this.pendingCancellationCleanup = void 0;
37432
+ throw new ArkmePluginError("cancellation-session-changed", "账号已切换,原账号注销已处理", false);
37433
+ }
37434
+ this.profile.invalidate(cleanup.session.userId);
37435
+ this.lifecycle.clearAccountState([cleanup.session.userId]);
37436
+ this.lifecycle.reconnectChatRealtime();
37437
+ this.cancellationNotice = cleanup.result.status === "done" ? "done" : "waiting";
37438
+ this.pendingCancellationCleanup = void 0;
37439
+ return cleanup.result;
37440
+ }
37441
+ cancellationSessionHash(session) {
37442
+ return createHash("sha256").update(session.refreshToken).digest("hex");
37443
+ }
37268
37444
  normalizedPhone(phone) {
37269
37445
  const normalized = phone.replace(/[\s-]/g, "");
37270
37446
  if (!/^1[3-9][0-9]{9}$/.test(normalized)) throw new ArkmePluginError("phone-invalid", "请输入有效的中国大陆手机号", false);
@@ -37321,23 +37497,23 @@ var BackgroundSoundMembershipService = class {
37321
37497
  };
37322
37498
  //#endregion
37323
37499
  //#region src/services/membership-service.ts
37324
- function invalid$5() {
37500
+ function invalid$6() {
37325
37501
  throw new ArkmePluginError("membership-contract-invalid", "会员信息暂时无法确认,请稍后重试", true, 502);
37326
37502
  }
37327
37503
  function integer$3(value) {
37328
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) return invalid$5();
37504
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) return invalid$6();
37329
37505
  return value;
37330
37506
  }
37331
37507
  function timestamp(value) {
37332
37508
  if (value === void 0 || value === null || value === 0) return null;
37333
37509
  const micros = integer$3(value);
37334
37510
  const millis = Math.floor(micros / 1e3);
37335
- if (millis < Date.UTC(2e3, 0) || millis > Date.UTC(3e3, 0)) return invalid$5();
37511
+ if (millis < Date.UTC(2e3, 0) || millis > Date.UTC(3e3, 0)) return invalid$6();
37336
37512
  return millis;
37337
37513
  }
37338
37514
  function parseMembership(raw, userId, now = Date.now()) {
37339
37515
  const memberType = integer$3(raw.member_type);
37340
- if (memberType > 2) return invalid$5();
37516
+ if (memberType > 2) return invalid$6();
37341
37517
  const expireAtMillis = timestamp(raw.expire_at);
37342
37518
  return {
37343
37519
  userId,
@@ -37348,16 +37524,16 @@ function parseMembership(raw, userId, now = Date.now()) {
37348
37524
  };
37349
37525
  }
37350
37526
  function parseMembershipProducts(raw) {
37351
- if (!Array.isArray(raw.data_ls)) return invalid$5();
37527
+ if (!Array.isArray(raw.data_ls)) return invalid$6();
37352
37528
  const products = raw.data_ls.map((entry) => {
37353
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) return invalid$5();
37529
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return invalid$6();
37354
37530
  const row = entry;
37355
37531
  const memberType = integer$3(row.spu_code);
37356
- if (memberType !== 1 && memberType !== 2) return invalid$5();
37357
- if (typeof row.name !== "string" || !row.name.trim() || typeof row.is_period !== "boolean") return invalid$5();
37532
+ if (memberType !== 1 && memberType !== 2) return invalid$6();
37533
+ if (typeof row.name !== "string" || !row.name.trim() || typeof row.is_period !== "boolean") return invalid$6();
37358
37534
  const alipayId = integer$3(row.alipay_product_id);
37359
37535
  const wechatId = integer$3(row.wechat_product_id);
37360
- if (alipayId === 0 && wechatId === 0) return invalid$5();
37536
+ if (alipayId === 0 && wechatId === 0) return invalid$6();
37361
37537
  return {
37362
37538
  id: `${memberType}:${alipayId}:${wechatId}:${row.is_period ? "recurring" : "once"}`,
37363
37539
  memberType,
@@ -37368,7 +37544,7 @@ function parseMembershipProducts(raw) {
37368
37544
  monthCount: integer$3(row.month_count)
37369
37545
  };
37370
37546
  });
37371
- if (new Set(products.map((p) => p.id)).size !== products.length) return invalid$5();
37547
+ if (new Set(products.map((p) => p.id)).size !== products.length) return invalid$6();
37372
37548
  return products.sort((a, b) => a.memberType - b.memberType || a.monthCount - b.monthCount || a.priceMinor - b.priceMinor);
37373
37549
  }
37374
37550
  /** Membership is distinct from managed-AI balance billing. Only read endpoints are exposed. */
@@ -37384,7 +37560,7 @@ var MembershipService = class {
37384
37560
  return parseMembership(raw, userId);
37385
37561
  }
37386
37562
  async catalog(expectedUserId) {
37387
- if (!Number.isSafeInteger(expectedUserId) || expectedUserId <= 0) return invalid$5();
37563
+ if (!Number.isSafeInteger(expectedUserId) || expectedUserId <= 0) return invalid$6();
37388
37564
  const session = await this.runtime.requireSession();
37389
37565
  if (session.userId !== expectedUserId) throw new ArkmePluginError("membership-account-changed", "账号已切换,请重新打开会员页面", false, 409);
37390
37566
  const raw = await this.runtime.authenticatedAuthReadPost("/api/v1/payment/get/sale-product", {}, session);
@@ -37499,19 +37675,19 @@ var AccountUsageService = class {
37499
37675
  //#endregion
37500
37676
  //#region src/services/account-usage-details-service.ts
37501
37677
  const monthPattern = /^\d{4}-(0[1-9]|1[0-2])$/;
37502
- function invalid$4() {
37678
+ function invalid$5() {
37503
37679
  return new ArkmePluginError("account-usage-details-invalid", "用量明细暂时无法确认,请重试", true, 502);
37504
37680
  }
37505
37681
  function object$5(value) {
37506
- if (!value || typeof value !== "object" || Array.isArray(value)) throw invalid$4();
37682
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw invalid$5();
37507
37683
  return value;
37508
37684
  }
37509
37685
  function count(value) {
37510
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw invalid$4();
37686
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw invalid$5();
37511
37687
  return value;
37512
37688
  }
37513
37689
  function text$4(value, max = 16384) {
37514
- if (typeof value !== "string" || value.length > max) throw invalid$4();
37690
+ if (typeof value !== "string" || value.length > max) throw invalid$5();
37515
37691
  return value;
37516
37692
  }
37517
37693
  function tokens(value) {
@@ -37540,17 +37716,17 @@ function status(value) {
37540
37716
  }
37541
37717
  function parseTokenSummary(value, accountScope) {
37542
37718
  const raw = object$5(value), monthKey = text$4(raw.month_key, 7);
37543
- if (!monthPattern.test(monthKey) || !Array.isArray(raw.available_months)) throw invalid$4();
37719
+ if (!monthPattern.test(monthKey) || !Array.isArray(raw.available_months)) throw invalid$5();
37544
37720
  const availableMonths = [...new Set(raw.available_months.map((value) => {
37545
37721
  const month = text$4(value, 7);
37546
- if (!monthPattern.test(month)) throw invalid$4();
37722
+ if (!monthPattern.test(month)) throw invalid$5();
37547
37723
  return month;
37548
37724
  }))].sort().reverse();
37549
37725
  const timezone = text$4(raw.timezone, 100);
37550
37726
  try {
37551
37727
  new Intl.DateTimeFormat("en", { timeZone: timezone });
37552
37728
  } catch {
37553
- throw invalid$4();
37729
+ throw invalid$5();
37554
37730
  }
37555
37731
  return {
37556
37732
  accountScope,
@@ -37567,7 +37743,7 @@ function parseTokenSummary(value, accountScope) {
37567
37743
  }
37568
37744
  function parseTokenPage(value, accountScope, kind) {
37569
37745
  const raw = object$5(value);
37570
- if (!Array.isArray(raw.items) || raw.items.length > 100) throw invalid$4();
37746
+ if (!Array.isArray(raw.items) || raw.items.length > 100) throw invalid$5();
37571
37747
  return {
37572
37748
  accountScope,
37573
37749
  items: raw.items.map((value) => {
@@ -37583,7 +37759,7 @@ function parseTokenPage(value, accountScope, kind) {
37583
37759
  usageStatus: status(item.usage_status)
37584
37760
  };
37585
37761
  const operationUid = text$4(item.operation_uid, 256), displayName = text$4(item.display_name, 2048);
37586
- if (!operationUid.trim() || !displayName.trim() || !Array.isArray(item.models)) throw invalid$4();
37762
+ if (!operationUid.trim() || !displayName.trim() || !Array.isArray(item.models)) throw invalid$5();
37587
37763
  return {
37588
37764
  ...common,
37589
37765
  operationUid,
@@ -37610,11 +37786,11 @@ var AccountUsageDetailsService = class {
37610
37786
  async read(scope, kind, query, signal) {
37611
37787
  const session = await this.session(scope);
37612
37788
  const month = text$4(query.monthKey, 7), timezone = text$4(query.timezone, 100) || "Asia/Shanghai";
37613
- if (month && !monthPattern.test(month)) throw invalid$4();
37789
+ if (month && !monthPattern.test(month)) throw invalid$5();
37614
37790
  try {
37615
37791
  new Intl.DateTimeFormat("en", { timeZone: timezone });
37616
37792
  } catch {
37617
- throw invalid$4();
37793
+ throw invalid$5();
37618
37794
  }
37619
37795
  const body = {
37620
37796
  month_key: month,
@@ -37626,7 +37802,7 @@ var AccountUsageDetailsService = class {
37626
37802
  }
37627
37803
  if (kind === "calls") {
37628
37804
  const uid = text$4(query.operationUid, 256), biz = count(query.bizCode);
37629
- if (!uid.trim() || biz > 32767) throw invalid$4();
37805
+ if (!uid.trim() || biz > 32767) throw invalid$5();
37630
37806
  body.operation_uid = uid;
37631
37807
  body.biz_code = biz;
37632
37808
  }
@@ -37636,7 +37812,7 @@ var AccountUsageDetailsService = class {
37636
37812
  }
37637
37813
  async summary(scope, query, signal) {
37638
37814
  const result = parseTokenSummary(await this.read(scope, "summary", query, signal), scope);
37639
- if (query.monthKey && result.monthKey !== query.monthKey) throw invalid$4();
37815
+ if (query.monthKey && result.monthKey !== query.monthKey) throw invalid$5();
37640
37816
  return result;
37641
37817
  }
37642
37818
  async operations(scope, query, signal) {
@@ -37649,17 +37825,17 @@ var AccountUsageDetailsService = class {
37649
37825
  //#endregion
37650
37826
  //#region src/services/data-management-service.ts
37651
37827
  function object$4(value) {
37652
- if (!value || typeof value !== "object" || Array.isArray(value)) throw invalid$3();
37828
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw invalid$4();
37653
37829
  return value;
37654
37830
  }
37655
- function invalid$3() {
37831
+ function invalid$4() {
37656
37832
  return new ArkmePluginError("data-management-contract-invalid", "数据格式暂时无法确认,请重试", true, 502);
37657
37833
  }
37658
37834
  function text$3(value) {
37659
37835
  return typeof value === "string" ? value : "";
37660
37836
  }
37661
37837
  function integer$1(value) {
37662
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw invalid$3();
37838
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw invalid$4();
37663
37839
  return value;
37664
37840
  }
37665
37841
  const DELETED_RETENTION_MILLIS = 720 * 60 * 60 * 1e3;
@@ -37682,7 +37858,7 @@ function lifecycle(value) {
37682
37858
  function parseDeletedRecords(raw, accountScope, nowMillis = Date.now()) {
37683
37859
  const envelope = object$4(raw);
37684
37860
  const rows = envelope.items ?? envelope.records ?? envelope.list ?? envelope.data;
37685
- if (!Array.isArray(rows)) throw invalid$3();
37861
+ if (!Array.isArray(rows)) throw invalid$4();
37686
37862
  let unverifiedCount = 0;
37687
37863
  return {
37688
37864
  accountScope,
@@ -37690,7 +37866,7 @@ function parseDeletedRecords(raw, accountScope, nowMillis = Date.now()) {
37690
37866
  const row = object$4(value);
37691
37867
  const core = object$4(row.record_core ?? row.record ?? row);
37692
37868
  const recordUid = text$3(core.record_uid).trim();
37693
- if (!recordUid) throw invalid$3();
37869
+ if (!recordUid) throw invalid$4();
37694
37870
  const status = lifecycle(core.status);
37695
37871
  if (status === "excluded") return [];
37696
37872
  if (status === "unknown") {
@@ -37753,7 +37929,7 @@ var DataManagementService = class {
37753
37929
  }, session, signal, { lane: "interactive-read" }), this.runtime.authenticatedPost("/api/v1/records/export/session/latest", {}, session, signal, { lane: "interactive-read" })]);
37754
37930
  await this.session(scope);
37755
37931
  const raw = object$4(preflightResponse), latest = object$4(latestResponse);
37756
- if (typeof raw.can_export !== "boolean") throw invalid$3();
37932
+ if (typeof raw.can_export !== "boolean") throw invalid$4();
37757
37933
  return {
37758
37934
  accountScope: scope,
37759
37935
  canExport: raw.can_export,
@@ -37765,7 +37941,7 @@ var DataManagementService = class {
37765
37941
  };
37766
37942
  }
37767
37943
  async recover(scope, recordUid, version) {
37768
- if (!recordUid.trim() || integer$1(version) <= 0) throw invalid$3();
37944
+ if (!recordUid.trim() || integer$1(version) <= 0) throw invalid$4();
37769
37945
  const record = (await this.deleted(scope)).items.find((item) => item.recordUid === recordUid);
37770
37946
  if (!record || record.version !== version || record.recoverableUntilMillis === void 0 || record.recoverableUntilMillis <= Date.now()) throw new ArkmePluginError("data-management-record-changed", "记录状态已变化或无法确认可恢复,请刷新最近删除列表。", false, 409);
37771
37947
  const session = await this.session(scope);
@@ -37775,7 +37951,7 @@ var DataManagementService = class {
37775
37951
  }, session);
37776
37952
  await this.session(scope);
37777
37953
  const envelope = object$4(raw);
37778
- if (object$4(envelope.record_core ?? envelope.record ?? envelope).record_uid !== recordUid) throw invalid$3();
37954
+ if (object$4(envelope.record_core ?? envelope.record ?? envelope).record_uid !== recordUid) throw invalid$4();
37779
37955
  return {
37780
37956
  accountScope: scope,
37781
37957
  recordUid
@@ -46119,7 +46295,7 @@ var RecordReeditSubmissions = class {
46119
46295
  };
46120
46296
  //#endregion
46121
46297
  //#region src/services/record-reedit-attachments.ts
46122
- const invalid$2 = () => new ArkmePluginError("record-reedit-attachment-invalid", "附件引用无效或不属于这条快记,请重新读取后选择", false, 409);
46298
+ const invalid$3 = () => new ArkmePluginError("record-reedit-attachment-invalid", "附件引用无效或不属于这条快记,请重新读取后选择", false, 409);
46123
46299
  const refs = (payload) => Array.isArray(payload?.media_refs) ? payload.media_refs.map(objectValue$2) : [];
46124
46300
  function recordReeditIsBackgroundSound(ref) {
46125
46301
  return ref.content_file_role === 4;
@@ -46141,14 +46317,14 @@ function recordReeditAttachmentSelection(value, payload) {
46141
46317
  try {
46142
46318
  selection = parseArkmeRecordReeditAttachments(value);
46143
46319
  } catch {
46144
- throw invalid$2();
46320
+ throw invalid$3();
46145
46321
  }
46146
46322
  const groups = recordReeditMediaGroups(payload);
46147
46323
  const supported = new Set(groups.map((group) => group.fileAssetUid));
46148
- if (selection.some((item) => item.fileAssetUid !== void 0 && !supported.has(item.fileAssetUid))) throw invalid$2();
46324
+ if (selection.some((item) => item.fileAssetUid !== void 0 && !supported.has(item.fileAssetUid))) throw invalid$3();
46149
46325
  const grouped = new Set(groups.flatMap((group) => group.refs));
46150
- if (refs(payload).some((ref) => !recordReeditIsBackgroundSound(ref) && ref.render_role === 4 && !groups.some((group) => group.refs.some((item) => item.file_asset_uid === ref.file_asset_uid)))) throw invalid$2();
46151
- if (groups.some((group) => group.fileAssetUid === "") || grouped.size !== groups.reduce((sum, group) => sum + group.refs.length, 0)) throw invalid$2();
46326
+ if (refs(payload).some((ref) => !recordReeditIsBackgroundSound(ref) && ref.render_role === 4 && !groups.some((group) => group.refs.some((item) => item.file_asset_uid === ref.file_asset_uid)))) throw invalid$3();
46327
+ if (groups.some((group) => group.fileAssetUid === "") || grouped.size !== groups.reduce((sum, group) => sum + group.refs.length, 0)) throw invalid$3();
46152
46328
  return selection;
46153
46329
  }
46154
46330
  function recordReeditAttachmentChanges(payload, selection) {
@@ -46170,11 +46346,11 @@ function recordReeditWithAttachments(payload, selection, uploads) {
46170
46346
  const media = selection.flatMap((item) => {
46171
46347
  if (item.fileAssetUid !== void 0) {
46172
46348
  const group = groups.find((value) => value.fileAssetUid === item.fileAssetUid);
46173
- if (group === void 0) throw invalid$2();
46349
+ if (group === void 0) throw invalid$3();
46174
46350
  return group.refs.map((ref) => structuredClone(ref));
46175
46351
  }
46176
46352
  const asset = uploads.get(item.fileRef);
46177
- if (asset === void 0 || asset.fileAssetUid.trim() === "") throw invalid$2();
46353
+ if (asset === void 0 || asset.fileAssetUid.trim() === "") throw invalid$3();
46178
46354
  return [{
46179
46355
  file_asset_uid: asset.fileAssetUid,
46180
46356
  render_role: 1,
@@ -47701,21 +47877,21 @@ var RecordService = class {
47701
47877
  const LOCAL_FILE_REF = /^arkme-file-v1\.[0-9a-f-]{36}$/;
47702
47878
  const ASSET_REF = /^[A-Za-z0-9._:-]{8,256}$/;
47703
47879
  const MAX_AMPLITUDES = 4096;
47704
- function invalid$1(message) {
47880
+ function invalid$2(message) {
47705
47881
  return new ArkmePluginError("background-sound-invalid", message, false, 400);
47706
47882
  }
47707
47883
  function invalidFile(message) {
47708
47884
  return new ArkmePluginError("background-sound-file-invalid", message, false, 400);
47709
47885
  }
47710
47886
  function arkmeBackgroundSoundAmplitudes(values) {
47711
- if (!Array.isArray(values) || values.length > MAX_AMPLITUDES || values.some((value) => typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1)) throw invalid$1("背景音振幅数量不能超过 4096,且每项必须是 0 到 1 之间的有限数字");
47887
+ if (!Array.isArray(values) || values.length > MAX_AMPLITUDES || values.some((value) => typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1)) throw invalid$2("背景音振幅数量不能超过 4096,且每项必须是 0 到 1 之间的有限数字");
47712
47888
  return [...values];
47713
47889
  }
47714
47890
  function arkmeFileBackgroundSound(value, allFileRefs) {
47715
47891
  if (value === void 0) return void 0;
47716
- if (!Array.isArray(value.fileRefs) || value.fileRefs.length === 0 || value.fileRefs.some((ref) => typeof ref !== "string" || !LOCAL_FILE_REF.test(ref)) || new Set(value.fileRefs).size !== value.fileRefs.length) throw invalid$1("背景音文件引用为空、重复或无效");
47892
+ if (!Array.isArray(value.fileRefs) || value.fileRefs.length === 0 || value.fileRefs.some((ref) => typeof ref !== "string" || !LOCAL_FILE_REF.test(ref)) || new Set(value.fileRefs).size !== value.fileRefs.length) throw invalid$2("背景音文件引用为空、重复或无效");
47717
47893
  const allowed = new Set(allFileRefs);
47718
- if (value.fileRefs.some((ref) => !allowed.has(ref))) throw invalid$1("背景音文件必须属于同一发送任务");
47894
+ if (value.fileRefs.some((ref) => !allowed.has(ref))) throw invalid$2("背景音文件必须属于同一发送任务");
47719
47895
  return {
47720
47896
  fileRefs: [...value.fileRefs],
47721
47897
  amplitudes: arkmeBackgroundSoundAmplitudes(value.amplitudes)
@@ -47745,10 +47921,10 @@ function normalizedBackgroundAsset(asset) {
47745
47921
  }
47746
47922
  function arkmeRichBackgroundSound(value) {
47747
47923
  if (value === void 0) return void 0;
47748
- if (!Array.isArray(value.assets) || value.assets.length === 0 || value.assets.length > 20) throw invalid$1("背景音资产为空或数量超限");
47924
+ if (!Array.isArray(value.assets) || value.assets.length === 0 || value.assets.length > 20) throw invalid$2("背景音资产为空或数量超限");
47749
47925
  const assets = value.assets.map(normalizedBackgroundAsset);
47750
47926
  const identities = assets.map((asset) => asset.fileAssetUid);
47751
- if (new Set(identities).size !== identities.length) throw invalid$1("背景音资产不能重复");
47927
+ if (new Set(identities).size !== identities.length) throw invalid$2("背景音资产不能重复");
47752
47928
  return {
47753
47929
  assets,
47754
47930
  amplitudes: arkmeBackgroundSoundAmplitudes(value.amplitudes)
@@ -83924,13 +84100,13 @@ var GroupService = class {
83924
84100
  };
83925
84101
  //#endregion
83926
84102
  //#region src/services/common-group-service.ts
83927
- const invalid = () => new ArkmePluginError("common-groups-response-invalid", "共同群聊响应不完整,请重试", true, 502);
84103
+ const invalid$1 = () => new ArkmePluginError("common-groups-response-invalid", "共同群聊响应不完整,请重试", true, 502);
83928
84104
  function commonGroupChanges(value, known, after) {
83929
84105
  const raw = objectValue$2(value);
83930
- if (!Array.isArray(raw.items) || !Array.isArray(raw.removed) || typeof raw.has_more !== "boolean" || raw.items.length > 20 || raw.removed.length > 20) throw invalid();
84106
+ if (!Array.isArray(raw.items) || !Array.isArray(raw.removed) || typeof raw.has_more !== "boolean" || raw.items.length > 20 || raw.removed.length > 20) throw invalid$1();
83931
84107
  const items = raw.items.map((value) => {
83932
84108
  const row = objectValue$2(value);
83933
- if (typeof row.chat_session_uid !== "string" || !row.chat_session_uid || row.chat_session_uid.length > 128 || typeof row.title !== "string" || row.title.length > 4096 || !Number.isSafeInteger(row.member_count) || Number(row.member_count) < 0) throw invalid();
84109
+ if (typeof row.chat_session_uid !== "string" || !row.chat_session_uid || row.chat_session_uid.length > 128 || typeof row.title !== "string" || row.title.length > 4096 || !Number.isSafeInteger(row.member_count) || Number(row.member_count) < 0) throw invalid$1();
83934
84110
  return {
83935
84111
  uid: row.chat_session_uid,
83936
84112
  title: row.title,
@@ -83938,14 +84114,14 @@ function commonGroupChanges(value, known, after) {
83938
84114
  };
83939
84115
  });
83940
84116
  const removed = raw.removed;
83941
- if (removed.some((uid) => typeof uid !== "string" || !known.includes(uid))) throw invalid();
84117
+ if (removed.some((uid) => typeof uid !== "string" || !known.includes(uid))) throw invalid$1();
83942
84118
  const identities = [...items.map((row) => row.uid), ...removed];
83943
- if (new Set(identities).size !== identities.length) throw invalid();
84119
+ if (new Set(identities).size !== identities.length) throw invalid$1();
83944
84120
  if (known.length) {
83945
- if (raw.has_more || identities.length !== known.length || identities.some((uid) => !known.includes(String(uid)))) throw invalid();
83946
- } else if (removed.length || items.some((row, i) => row.uid <= (items[i - 1]?.uid ?? after))) throw invalid();
84121
+ if (raw.has_more || identities.length !== known.length || identities.some((uid) => !known.includes(String(uid)))) throw invalid$1();
84122
+ } else if (removed.length || items.some((row, i) => row.uid <= (items[i - 1]?.uid ?? after))) throw invalid$1();
83947
84123
  const next = raw.has_more ? raw.next_after : "";
83948
- if (typeof next !== "string" || raw.has_more && (!items.length || next !== items.at(-1)?.uid || next <= after)) throw invalid();
84124
+ if (typeof next !== "string" || raw.has_more && (!items.length || next !== items.at(-1)?.uid || next <= after)) throw invalid$1();
83949
84125
  return {
83950
84126
  items,
83951
84127
  removed,
@@ -87884,6 +88060,28 @@ var RelatedQuickNoteService = class {
87884
88060
  }
87885
88061
  };
87886
88062
  //#endregion
88063
+ //#region src/recording-search-version.ts
88064
+ /** Public Audio contract: hash raw decrypted text, retaining whitespace and Unicode. */
88065
+ function recordingSearchVersion(item) {
88066
+ return createHash("sha256").update([
88067
+ item.sessionId,
88068
+ item.childId,
88069
+ item.asrItemIndex,
88070
+ item.transcriptSource,
88071
+ item.startAtMillis,
88072
+ item.endAtMillis,
88073
+ item.text
88074
+ ].join("\n"), "utf8").digest("hex");
88075
+ }
88076
+ function recordingSearchIdentityHash(item) {
88077
+ return createHash("sha256").update(JSON.stringify([
88078
+ item.sessionId,
88079
+ item.transcriptSource,
88080
+ item.childId,
88081
+ item.itemIndex
88082
+ ]), "utf8").digest("hex");
88083
+ }
88084
+ //#endregion
87887
88085
  //#region src/recording-import-coordinator.ts
87888
88086
  function importFailure(error) {
87889
88087
  if (error instanceof RecordingImportContractError) return {
@@ -88417,6 +88615,7 @@ function projectRecordingTranscripts(response, speakerResponse, profilesByUserId
88417
88615
  isSelf,
88418
88616
  isBackground,
88419
88617
  text,
88618
+ rawTranscriptText: stringValue(row.t ?? row.text),
88420
88619
  ...generationText === text ? {} : { generationText },
88421
88620
  ...stringValue(row.p).trim() === "" ? {} : { event: stringValue(row.p).trim() },
88422
88621
  sourceIndex,
@@ -89817,6 +90016,18 @@ var RecordingService = class {
89817
90016
  return {
89818
90017
  itemId: item.itemId,
89819
90018
  itemRef: this.sealRecordingRefWithKey("arkme-recording-item-v1", payload, refKey),
90019
+ ...item.transcriptSource !== "system" ? {} : {
90020
+ searchIdentityHash: recordingSearchIdentityHash({
90021
+ sessionId: item.sessionId,
90022
+ childId: item.childId,
90023
+ itemIndex: item.asrItemIndex,
90024
+ transcriptSource: item.transcriptSource
90025
+ }),
90026
+ searchVersion: recordingSearchVersion({
90027
+ ...item,
90028
+ text: item.rawTranscriptText ?? item.text
90029
+ })
90030
+ },
89820
90031
  transcriptSource: item.transcriptSource,
89821
90032
  sessionKey: createHmac("sha256", refKey).update(`recording-session:${String(viewerUserId)}:${item.sessionId}`).digest("base64url"),
89822
90033
  startAtMillis: item.startAtMillis,
@@ -90789,6 +91000,60 @@ var RelatedRecordingService = class {
90789
91000
  }
90790
91001
  };
90791
91002
  //#endregion
91003
+ //#region src/recording-search-result.ts
91004
+ function invalid() {
91005
+ throw new ArkmePluginError("recording-search-invalid", "录音搜索结果已失效,请重试", true);
91006
+ }
91007
+ function segment(raw) {
91008
+ const value = objectValue$2(raw);
91009
+ if (!stringValue$2(value.session_id).trim() || !stringValue$2(value.child_id).trim() || !Number.isSafeInteger(value.item_index) || Number(value.item_index) < 0 || value.transcript_source !== "system" || !stringValue$2(value.transcript_version).trim() || typeof value.text !== "string" || !Number.isSafeInteger(value.start_at) || !Number.isSafeInteger(value.end_at)) invalid();
91010
+ const speaker = objectValue$2(value.speaker);
91011
+ return {
91012
+ sessionId: String(value.session_id),
91013
+ childId: String(value.child_id),
91014
+ itemIndex: Number(value.item_index),
91015
+ transcriptSource: "system",
91016
+ transcriptVersion: String(value.transcript_version),
91017
+ startAtMillis: Number(value.start_at),
91018
+ endAtMillis: Number(value.end_at),
91019
+ text: String(value.text),
91020
+ ...value.speaker === void 0 ? {} : { speaker: {
91021
+ speakerId: stringValue$2(speaker.speaker_id),
91022
+ label: stringValue$2(speaker.label) || "未知说话人",
91023
+ ...typeof speaker.user_id === "number" && speaker.user_id > 0 ? { userId: speaker.user_id } : {},
91024
+ ...typeof speaker.color_index === "number" ? { colorIndex: speaker.color_index } : {}
91025
+ } }
91026
+ };
91027
+ }
91028
+ function parseRecordingSearchItem(raw) {
91029
+ const value = objectValue$2(raw);
91030
+ const match = segment(value.match);
91031
+ const previous = value.previous == null ? void 0 : segment(value.previous);
91032
+ const next = value.next == null ? void 0 : segment(value.next);
91033
+ if (match.sessionId !== value.session_id) invalid();
91034
+ const day = Number(value.date_stamp);
91035
+ if ([previous, next].some((item) => item && item.sessionId !== match.sessionId && (!Number.isSafeInteger(day) || day <= 0 || item.startAtMillis < day || item.startAtMillis >= day + 864e5))) invalid();
91036
+ if (previous && previous.startAtMillis > match.startAtMillis || next && next.startAtMillis < match.startAtMillis) invalid();
91037
+ const ranges = Array.isArray(value.highlight_ranges) ? value.highlight_ranges : [];
91038
+ const length = Array.from(match.text).length;
91039
+ const highlightRanges = ranges.map(objectValue$2).map((range) => ({
91040
+ start: Number(range.start_index),
91041
+ length: Number(range.length)
91042
+ })).filter((range) => Number.isSafeInteger(range.start) && Number.isSafeInteger(range.length) && range.start >= 0 && range.length > 0 && range.start + range.length <= length).sort((a, b) => a.start - b.start).filter((range, index, all) => index === 0 || range.start >= all[index - 1].start + all[index - 1].length);
91043
+ return {
91044
+ sessionId: match.sessionId,
91045
+ dateStamp: Number(value.date_stamp) || 0,
91046
+ startAtMillis: match.startAtMillis,
91047
+ snippet: match.text,
91048
+ score: Number(value.score) || 0,
91049
+ match,
91050
+ highlightRanges,
91051
+ ...stringValue$2(value.record_uid) ? { recordUid: String(value.record_uid) } : {},
91052
+ ...previous ? { previous } : {},
91053
+ ...next ? { next } : {}
91054
+ };
91055
+ }
91056
+ //#endregion
90792
91057
  //#region src/dsh-search-origins.ts
90793
91058
  /** Resolve sync identity using the public index and exact deterministic record IDs. */
90794
91059
  async function resolveDshSearchOrigins(provider, items, signal) {
@@ -91115,13 +91380,15 @@ var SearchService = class {
91115
91380
  media;
91116
91381
  source;
91117
91382
  privacy;
91383
+ profile;
91118
91384
  localDshQuery;
91119
- constructor(runtime, record, media, source, privacy = new ArkmePrivacyVisibilityService(runtime)) {
91385
+ constructor(runtime, record, media, source, privacy = new ArkmePrivacyVisibilityService(runtime), profile) {
91120
91386
  this.runtime = runtime;
91121
91387
  this.record = record;
91122
91388
  this.media = media;
91123
91389
  this.source = source;
91124
91390
  this.privacy = privacy;
91391
+ this.profile = profile;
91125
91392
  }
91126
91393
  async searchRecords(options) {
91127
91394
  const query = options.query.trim();
@@ -91483,22 +91750,37 @@ var SearchService = class {
91483
91750
  const session = await this.runtime.requireSession();
91484
91751
  const data = await this.runtime.authenticatedPost("/api/v1/search/recordings/query", {
91485
91752
  keyword: query,
91753
+ result_mode: "segments",
91486
91754
  limit: Math.min(50, Math.max(1, Math.trunc(options.limit))),
91487
91755
  ...options.cursor?.trim() ? { cursor: options.cursor.trim() } : {}
91488
91756
  }, session, options.signal);
91757
+ const items = listValue$3(data.items).map(parseRecordingSearchItem);
91758
+ const segments = items.flatMap((item) => [
91759
+ item.previous,
91760
+ item.match,
91761
+ item.next
91762
+ ].filter((value) => value !== void 0));
91763
+ const userIds = [...new Set(segments.flatMap((item) => item.speaker?.userId === void 0 ? [] : [item.speaker.userId]))];
91764
+ if (this.profile !== void 0 && userIds.length > 0) try {
91765
+ const profiles = await this.profile.publicProfileSummariesByUserIds(userIds, session, options.signal);
91766
+ const avatars = /* @__PURE__ */ new Map();
91767
+ await Promise.all([...profiles].map(async ([userId, profile]) => {
91768
+ if (profile.avatarUrl !== void 0) avatars.set(userId, await this.profile.sealProfileImageRef(session.userId, userId));
91769
+ }));
91770
+ for (const segment of segments) {
91771
+ const speaker = segment.speaker;
91772
+ if (speaker?.userId === void 0) continue;
91773
+ const profile = profiles.get(speaker.userId);
91774
+ const avatarRef = avatars.get(speaker.userId);
91775
+ if (avatarRef !== void 0) speaker.avatarRef = avatarRef;
91776
+ if (profile && (speaker.userId === session.userId || speaker.label === "未知说话人")) speaker.label = profile.displayName.trim() || profile.nickname.trim() || speaker.label;
91777
+ }
91778
+ } catch (error) {
91779
+ if (options.signal?.aborted) throw error;
91780
+ }
91489
91781
  const guard = objectValue$2(data.query_guard);
91490
91782
  return {
91491
- items: listValue$3(data.items).map((raw) => {
91492
- const item = objectValue$2(raw);
91493
- return {
91494
- sessionId: stringValue$2(item.session_id).trim(),
91495
- ...stringValue$2(item.record_uid).trim() === "" ? {} : { recordUid: stringValue$2(item.record_uid).trim() },
91496
- dateStamp: numberValue$2(item.date_stamp),
91497
- startAtMillis: numberValue$2(item.start_at),
91498
- snippet: clippedText(item.snippet, 1e3),
91499
- score: numberValue$2(item.score)
91500
- };
91501
- }).filter((item) => item.sessionId !== "" && item.snippet !== ""),
91783
+ items,
91502
91784
  hasMore: booleanValue$1(data.has_more),
91503
91785
  ...stringValue$2(data.next_cursor).trim() === "" ? {} : { nextCursor: stringValue$2(data.next_cursor).trim() },
91504
91786
  queryGuard: {
@@ -95342,7 +95624,7 @@ var ArkmeService = class {
95342
95624
  await this.realtime.invalidateRecordProjection();
95343
95625
  }, async (source, text, humans, bots, session, textFormat) => await this.chat.resolveMentions(source, text, text, humans, bots, session, void 0, textFormat));
95344
95626
  this.calendar = new CalendarService(this.runtime, this.privacy, this.media, this.record, this.source, this.callHistory);
95345
- this.search = new SearchService(this.runtime, this.record, this.media, this.source, this.privacy);
95627
+ this.search = new SearchService(this.runtime, this.record, this.media, this.source, this.privacy, this.profile);
95346
95628
  if (localDshQuery !== void 0) this.search.localDshQuery = localDshQuery;
95347
95629
  this.bot = new BotService(this.runtime, this.source);
95348
95630
  this.messageActions = new MessageActionService(new ArkmeMessageActionGateway(this.runtime, this.source, async (target, sequence) => {
@@ -96777,6 +97059,12 @@ var ArkmeService = class {
96777
97059
  async testLogin(userId) {
96778
97060
  return await this.auth.testLogin(userId);
96779
97061
  }
97062
+ async sendEmailBindCode(expectedUserId, email) {
97063
+ return await this.auth.sendEmailBindCode(expectedUserId, email);
97064
+ }
97065
+ async bindEmail(expectedUserId, email, code) {
97066
+ return await this.auth.bindEmail(expectedUserId, email, code);
97067
+ }
96780
97068
  async sendPhoneCode(phone, captcha) {
96781
97069
  return await this.auth.sendPhoneCode(phone, captcha);
96782
97070
  }
@@ -96792,6 +97080,15 @@ var ArkmeService = class {
96792
97080
  async verifyPhoneCode(phone, code) {
96793
97081
  return await this.auth.verifyPhoneCode(phone, code);
96794
97082
  }
97083
+ async previewCancellation(expectedUserId) {
97084
+ return await this.auth.previewCancellation(expectedUserId);
97085
+ }
97086
+ async submitCancellation(expectedUserId, expectedMode) {
97087
+ return await this.auth.submitCancellation(expectedUserId, expectedMode);
97088
+ }
97089
+ async resolveCancellationLogin(continueLogin) {
97090
+ return await this.auth.resolveCancellationLogin(continueLogin);
97091
+ }
96795
97092
  async logout() {
96796
97093
  return await this.auth.logout();
96797
97094
  }