@senguoyun/dsh-arkme 0.1.82 → 0.1.84

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 (108) hide show
  1. package/docs/ai-points-implementation.md +43 -0
  2. package/docs/interwoven-compact-summary-regression-2026-09-28.md +35 -0
  3. package/docs/interwoven-original-read-receipt-regression-2026-09-28.md +50 -0
  4. package/docs/personal-detail-consistency-regression-2026-09-28.md +40 -0
  5. package/docs/recognized-speaker-directory-backend-handoff-2026-09-28.md +157 -0
  6. package/docs/recognized-speaker-entry-and-visits.md +47 -0
  7. package/docs/recognized-speaker-presence-delivery.md +51 -0
  8. package/docs/recognized-speaker-sorting.md +30 -0
  9. package/docs/send-to-self-roles-cross-client-api-handoff-2026-09-27.md +9 -0
  10. package/lib/client.js +3358 -1946
  11. package/lib/client.js.map +1 -1
  12. package/lib/harness-model-client.js +168 -38
  13. package/lib/harness-native-selection-client.js +92 -1
  14. package/lib/harness-sidebar-client.js +31 -0
  15. package/lib/index.js +347 -132
  16. package/lib/persistent-extension.js +1 -1
  17. package/lib/{persistent-runtime-DV9Hme-U.js → persistent-runtime-CuKplHIv.js} +607 -303
  18. package/lib/sdk.js +31 -0
  19. package/lib/types/ai-points.d.ts +61 -0
  20. package/lib/types/ai-points.d.ts.map +1 -0
  21. package/lib/types/arkme-service.d.ts +11 -1
  22. package/lib/types/arkme-service.d.ts.map +1 -1
  23. package/lib/types/billing-gateway.d.ts.map +1 -1
  24. package/lib/types/client/ArkmeAccountUsage.d.ts +1 -3
  25. package/lib/types/client/ArkmeAccountUsage.d.ts.map +1 -1
  26. package/lib/types/client/ArkmeArkoSurface.d.ts.map +1 -1
  27. package/lib/types/client/ArkmeBillingSettings.d.ts +3 -2
  28. package/lib/types/client/ArkmeBillingSettings.d.ts.map +1 -1
  29. package/lib/types/client/ArkmeDataManagementSettings.d.ts.map +1 -1
  30. package/lib/types/client/ArkmeDocumentComposerInput.d.ts.map +1 -1
  31. package/lib/types/client/ArkmeEmojiPicker.d.ts.map +1 -1
  32. package/lib/types/client/ArkmeInterwovenReadReceipt.d.ts +12 -0
  33. package/lib/types/client/ArkmeInterwovenReadReceipt.d.ts.map +1 -0
  34. package/lib/types/client/ArkmeModelPricing.d.ts +9 -0
  35. package/lib/types/client/ArkmeModelPricing.d.ts.map +1 -0
  36. package/lib/types/client/ArkmeModelSelect.d.ts.map +1 -1
  37. package/lib/types/client/ArkmeNoteDetails.d.ts.map +1 -1
  38. package/lib/types/client/ArkmePointsConsumption.d.ts +5 -0
  39. package/lib/types/client/ArkmePointsConsumption.d.ts.map +1 -0
  40. package/lib/types/client/ArkmeRecognizedSpeakersSurface.d.ts +6 -2
  41. package/lib/types/client/ArkmeRecognizedSpeakersSurface.d.ts.map +1 -1
  42. package/lib/types/client/ArkmeRecordingSurface.d.ts.map +1 -1
  43. package/lib/types/client/ArkmeRelatedQuickNotes.d.ts.map +1 -1
  44. package/lib/types/client/ArkmeSidebar.d.ts.map +1 -1
  45. package/lib/types/client/ArkoModelMenu.d.ts.map +1 -1
  46. package/lib/types/client/api.d.ts +1 -1
  47. package/lib/types/client/api.d.ts.map +1 -1
  48. package/lib/types/client/interwoven-moments.d.ts.map +1 -1
  49. package/lib/types/client/interwoven-read-receipt-store.d.ts +32 -0
  50. package/lib/types/client/interwoven-read-receipt-store.d.ts.map +1 -0
  51. package/lib/types/client/locales/actions-en.d.ts.map +1 -1
  52. package/lib/types/client/locales/dynamic-en.d.ts.map +1 -1
  53. package/lib/types/client/locales/en.d.ts.map +1 -1
  54. package/lib/types/client/reaction-preview-store.d.ts +1 -0
  55. package/lib/types/client/reaction-preview-store.d.ts.map +1 -1
  56. package/lib/types/client/recognized-speaker-directory.d.ts +36 -0
  57. package/lib/types/client/recognized-speaker-directory.d.ts.map +1 -0
  58. package/lib/types/client/recognized-speaker-order.d.ts +28 -0
  59. package/lib/types/client/recognized-speaker-order.d.ts.map +1 -0
  60. package/lib/types/client/recognized-speaker-tracker.d.ts +33 -0
  61. package/lib/types/client/recognized-speaker-tracker.d.ts.map +1 -0
  62. package/lib/types/client/recordings/RecognizedSpeakerEntry.d.ts +12 -0
  63. package/lib/types/client/recordings/RecognizedSpeakerEntry.d.ts.map +1 -0
  64. package/lib/types/client/recordings/SpeakerSelfGuide.d.ts +8 -0
  65. package/lib/types/client/recordings/SpeakerSelfGuide.d.ts.map +1 -0
  66. package/lib/types/client/recordings/recording-speaker-options-store.d.ts.map +1 -1
  67. package/lib/types/client/self-role-presentation.d.ts +6 -1
  68. package/lib/types/client/self-role-presentation.d.ts.map +1 -1
  69. package/lib/types/client/use-personal-extension-parents.d.ts +4 -0
  70. package/lib/types/client/use-personal-extension-parents.d.ts.map +1 -0
  71. package/lib/types/host-api.d.ts.map +1 -1
  72. package/lib/types/index.d.ts.map +1 -1
  73. package/lib/types/managed-ai/adapter.d.ts +2 -1
  74. package/lib/types/managed-ai/adapter.d.ts.map +1 -1
  75. package/lib/types/managed-ai/operation.d.ts +17 -0
  76. package/lib/types/managed-ai/operation.d.ts.map +1 -0
  77. package/lib/types/managed-ai/transport.d.ts +1 -0
  78. package/lib/types/managed-ai/transport.d.ts.map +1 -1
  79. package/lib/types/record-extension-tree.d.ts +2 -0
  80. package/lib/types/record-extension-tree.d.ts.map +1 -1
  81. package/lib/types/sdk/index.d.ts +14 -0
  82. package/lib/types/sdk/index.d.ts.map +1 -1
  83. package/lib/types/services/ai-points-service.d.ts +13 -0
  84. package/lib/types/services/ai-points-service.d.ts.map +1 -0
  85. package/lib/types/services/arko-service.d.ts.map +1 -1
  86. package/lib/types/services/chat-service.d.ts +9 -1
  87. package/lib/types/services/chat-service.d.ts.map +1 -1
  88. package/lib/types/services/interwoven-service.d.ts +3 -1
  89. package/lib/types/services/interwoven-service.d.ts.map +1 -1
  90. package/lib/types/services/recording-service.d.ts +2 -5
  91. package/lib/types/services/recording-service.d.ts.map +1 -1
  92. package/lib/types/services/unmarked-speaker-service.d.ts.map +1 -1
  93. package/lib/types/tools/business/account/ai-points.d.ts +4 -0
  94. package/lib/types/tools/business/account/ai-points.d.ts.map +1 -0
  95. package/lib/types/tools/business/account/index.d.ts.map +1 -1
  96. package/lib/types/tools/business/recordings/index.d.ts +1 -1
  97. package/lib/types/tools/business/recordings/index.d.ts.map +1 -1
  98. package/lib/types/tools/business/recordings/speaker-presence.d.ts +2 -0
  99. package/lib/types/tools/business/recordings/speaker-presence.d.ts.map +1 -0
  100. package/lib/types/tools/ports/profile.d.ts +3 -0
  101. package/lib/types/tools/ports/profile.d.ts.map +1 -1
  102. package/lib/types/tools/ports/recordings.d.ts +4 -0
  103. package/lib/types/tools/ports/recordings.d.ts.map +1 -1
  104. package/lib/types/types.d.ts +33 -8
  105. package/lib/types/types.d.ts.map +1 -1
  106. package/package.json +5 -5
  107. package/lib/types/recording-speaker-presence.d.ts +0 -28
  108. package/lib/types/recording-speaker-presence.d.ts.map +0 -1
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as inspectNativeBundleArtifactV3, At as ArkmeRecordReeditDraftConflict, Bt as __require, Ct as isRecentEmojiId, D as bundleSha256, Dt as ArkmePluginError, E as arkmeSandboxEntryId, F as assertExtensionArtifactSize, Ft as registerDSHAgentInputRecordSync, G as validateVoiceprintPcm16Wav, I as canonicalExtensionJson, It as createDesktopLifecycleReader, J as arkmeRequiredLinkMetadataFallback, K as arkmeExtensionShareRefFromLink, L as sha256Hex, Lt as __commonJSMin, M as packLocalNativeBundleDirectoryV3, Mt as parseArkmeRecordReeditMentions, N as readNativeBundleTarballV3, O as canonicalBundleJson, Ot as retryAfterMillis, P as renderArkmeSandboxHostEntry, Pt as parseArrangementBoardCachePages, Q as ARKME_PROVIDER_CONTRACT_VERSION, R as unpackArkmeExtension, Rt as __esmMin, S as ARKME_BUNDLE_ARTIFACT_KIND, St as recordingImportFileNameKey, T as ArkmeBundleArtifactError, Tt as registerManagedAiProvider, U as ARKME_EXTENSION_RUNTIME_UNAVAILABLE_MESSAGE, Vt as __toCommonJS, W as ArkmeService, X as arkmeRichBackgroundSound, Y as arkmeFileBackgroundSound, Z as ARKME_DEFAULT_SHARE_WEBSITE, _ as arkmeClientContentDigest, _t as isRecordingInstantOnOrAfterUnixEpoch, at as cachedMemberItem, b as verifyExtensionResolutionSignature, bt as sameRecordingImportIdentity, c as persistentExtensionBundleDirectory, ct as ARKME_RUNTIME_INSTANCE_ID, d as readPersistentExtensionActivation, dt as arkmeNormalizedFileMimeType, f as refreshPersistentClientWrapper, ft as arkmePickedFileKind, g as activeProfileExtensionOwnerConflicts, gt as ArkmeDirectMessageAdmissionError, h as renderArkmeBundleClientBundle, ht as SecretValue, i as invokePersistentArkmeExtension, it as applyMemberUpdate, j as packBundleFiles, jt as parseArkmeRecordReeditAttachments, k as inspectBundleArtifact, kt as recordOwnerId, l as persistentExtensionPackageIdentity, lt as ARKME_TOOL_FILE_MAX_BYTES, m as writePersistentExtensionActivation, mt as ArkmeOutgoingCallError, nt as ARKME_WORLD_PUBLISH_MAX_IMAGES, o as persistentArkmeExtensionRuntimeState, ot as mergeMemberJoinEvents, p as repairPersistentExtensionInstallation, pt as isArkmeBotAvatarRef, q as arkmeIsGenericLinkMetadataTitle, r as deactivatePersistentArkmeExtension, rt as ARKME_WORLD_PUBLISH_MAX_IMAGE_BYTES, s as materializePersistentExtensionBundle, st as validateMemberUpdate, t as activatePersistentArkmeExtension, u as quarantinePersistentExtension, ut as arkmeCanInlineLocalFile, v as arkmeClientContentDigestFromSource, vt as isUnresolvedRecordingImportJob, w as ARKME_NATIVE_BUNDLE_ARTIFACT_KIND, wt as normalizeRecentEmojiIds, x as verifyNativeBundleResolutionSignature, y as verifyBundleResolutionSignature, yt as recordingImportFileKind, z as ARKME_EXTENSION_FORMAT, zt as __exportAll } from "./persistent-runtime-DV9Hme-U.js";
1
+ import { A as inspectNativeBundleArtifactV3, At as ArkmeRecordReeditDraftConflict, Bt as __require, Ct as isRecentEmojiId, D as bundleSha256, Dt as ArkmePluginError, E as arkmeSandboxEntryId, F as assertExtensionArtifactSize, Ft as registerDSHAgentInputRecordSync, G as validateVoiceprintPcm16Wav, I as canonicalExtensionJson, It as createDesktopLifecycleReader, J as arkmeRequiredLinkMetadataFallback, K as arkmeExtensionShareRefFromLink, L as sha256Hex, Lt as __commonJSMin, M as packLocalNativeBundleDirectoryV3, Mt as parseArkmeRecordReeditMentions, N as readNativeBundleTarballV3, O as canonicalBundleJson, Ot as retryAfterMillis, P as renderArkmeSandboxHostEntry, Pt as parseArrangementBoardCachePages, Q as ARKME_PROVIDER_CONTRACT_VERSION, R as unpackArkmeExtension, Rt as __esmMin, S as ARKME_BUNDLE_ARTIFACT_KIND, St as recordingImportFileNameKey, T as ArkmeBundleArtifactError, Tt as registerManagedAiProvider, U as ARKME_EXTENSION_RUNTIME_UNAVAILABLE_MESSAGE, Vt as __toCommonJS, W as ArkmeService, X as arkmeRichBackgroundSound, Y as arkmeFileBackgroundSound, Z as ARKME_DEFAULT_SHARE_WEBSITE, _ as arkmeClientContentDigest, _t as isRecordingInstantOnOrAfterUnixEpoch, at as cachedMemberItem, b as verifyExtensionResolutionSignature, bt as sameRecordingImportIdentity, c as persistentExtensionBundleDirectory, ct as ARKME_RUNTIME_INSTANCE_ID, d as readPersistentExtensionActivation, dt as arkmeNormalizedFileMimeType, f as refreshPersistentClientWrapper, ft as arkmePickedFileKind, g as activeProfileExtensionOwnerConflicts, gt as ArkmeDirectMessageAdmissionError, h as renderArkmeBundleClientBundle, ht as SecretValue, i as invokePersistentArkmeExtension, it as applyMemberUpdate, j as packBundleFiles, jt as parseArkmeRecordReeditAttachments, k as inspectBundleArtifact, kt as recordOwnerId, l as persistentExtensionPackageIdentity, lt as ARKME_TOOL_FILE_MAX_BYTES, m as writePersistentExtensionActivation, mt as ArkmeOutgoingCallError, nt as ARKME_WORLD_PUBLISH_MAX_IMAGES, o as persistentArkmeExtensionRuntimeState, ot as mergeMemberJoinEvents, p as repairPersistentExtensionInstallation, pt as isArkmeBotAvatarRef, q as arkmeIsGenericLinkMetadataTitle, r as deactivatePersistentArkmeExtension, rt as ARKME_WORLD_PUBLISH_MAX_IMAGE_BYTES, s as materializePersistentExtensionBundle, st as validateMemberUpdate, t as activatePersistentArkmeExtension, u as quarantinePersistentExtension, ut as arkmeCanInlineLocalFile, v as arkmeClientContentDigestFromSource, vt as isUnresolvedRecordingImportJob, w as ARKME_NATIVE_BUNDLE_ARTIFACT_KIND, wt as normalizeRecentEmojiIds, x as verifyNativeBundleResolutionSignature, y as verifyBundleResolutionSignature, yt as recordingImportFileKind, z as ARKME_EXTENSION_FORMAT, zt as __exportAll } from "./persistent-runtime-CuKplHIv.js";
2
2
  import { i as securePrivateFileSync, n as securePrivateDirectorySync, r as securePrivateFile, t as securePrivateDirectory } from "./private-filesystem-CGh4FtyA.js";
3
3
  import { _ as parsePluginUpdateManifest, b as validatePluginUpdateServiceOrigin, d as writePluginUpdateLifecycleLog, f as PluginUpdateInstallStateStore, g as existingCachedPluginArtifactPath, h as downloadAndCachePluginArtifact, m as PluginUpdateArtifactError, n as buildTargetInstallArgs, o as reconcilePluginUpdaterProfilePolicy, p as ARKME_PLUGIN_PACKAGE_NAME$1, t as assertTargetArtifactIntegrity, u as detachManagedProfilePluginLink, v as pluginUpdateEndpointUrl, y as validatePluginUpdateArtifactOrigin } from "./plugin-updater-helper-dNxHpiVg.js";
4
4
  import { i as prepareProfilePackageManager, n as isArkmeProfilePackageName, r as localExtensionPnpmArgs, t as applyArkmeProfileBundlePolicy } from "./profile-bundle-policy-8_y3QfHe.js";
@@ -510,6 +510,84 @@ var DshNativeSocket = class {
510
510
  }
511
511
  };
512
512
  //#endregion
513
+ //#region src/dsh-session-events.ts
514
+ function readSessionEvents(session) {
515
+ if (typeof session.snapshotEvents === "function") return session.snapshotEvents();
516
+ if (Array.isArray(session.events)) return session.events;
517
+ throw new Error("当前 DSH 会话不支持读取事件,无法核验用户输入");
518
+ }
519
+ //#endregion
520
+ //#region src/managed-ai/operation.ts
521
+ /** The durable DSH boundary, never a session-wide credit exemption. */
522
+ function turnOperationId(session, start) {
523
+ return createHash("sha256").update(JSON.stringify([
524
+ session.id,
525
+ start.seq,
526
+ start.time,
527
+ start.data.turn
528
+ ])).digest("hex");
529
+ }
530
+ var ManagedTurnFunding = class {
531
+ session;
532
+ close;
533
+ failed;
534
+ credentials = /* @__PURE__ */ new Map();
535
+ constructor(session, close, failed) {
536
+ this.session = session;
537
+ this.close = close;
538
+ this.failed = failed;
539
+ }
540
+ prepare(request, bearer) {
541
+ if (request.sessionId === void 0 || request.purpose === "session-title") return void 0;
542
+ const session = this.session(request.sessionId);
543
+ if (session === void 0) return void 0;
544
+ const boundary = readSessionEvents(session).findLast((event) => event.type === "turn/start" || event.type === "turn/end");
545
+ if (boundary?.type !== "turn/start") return void 0;
546
+ const uid = turnOperationId(session, boundary);
547
+ const credentials = this.credentials.get(uid) ?? /* @__PURE__ */ new Set();
548
+ credentials.add(bearer);
549
+ this.credentials.set(uid, credentials);
550
+ return uid;
551
+ }
552
+ async ended(session, event) {
553
+ if (event.type !== "turn/end") return;
554
+ const start = readSessionEvents(session).findLast((item) => item.type === "turn/start" && item.data.turn === event.data.turn);
555
+ if (start?.type !== "turn/start") return;
556
+ const uid = turnOperationId(session, start);
557
+ const credentials = this.credentials.get(uid);
558
+ this.credentials.delete(uid);
559
+ if (credentials === void 0) return;
560
+ await Promise.all([...credentials].map(async (bearer) => {
561
+ try {
562
+ await this.close(uid, bearer);
563
+ } catch {
564
+ this.failed();
565
+ }
566
+ }));
567
+ }
568
+ dispose() {
569
+ this.credentials.clear();
570
+ }
571
+ };
572
+ function registerManagedTurnFunding(ctx, intelligentBaseUrl) {
573
+ const funding = new ManagedTurnFunding((id) => ctx.get("sessions")?.get(id), async (operationUid, bearer) => {
574
+ if (!(await fetch(`${intelligentBaseUrl.replace(/\/+$/, "")}/api/v1/managed-ai/operations/close`, {
575
+ method: "POST",
576
+ headers: {
577
+ Authorization: `Bearer ${bearer}`,
578
+ "Content-Type": "application/json"
579
+ },
580
+ body: JSON.stringify({ operation_uid: operationUid }),
581
+ signal: AbortSignal.timeout(5e3)
582
+ })).ok) throw new Error("Could not close AI turn");
583
+ }, () => ctx.logger.warn("Arkme AI turn close failed; server authorization expiry will reclaim it"));
584
+ ctx.on("session/event", (session, event) => {
585
+ funding.ended(session, event).catch(() => ctx.logger.warn("Arkme AI turn boundary could not be read"));
586
+ }, { global: true });
587
+ ctx.effect(() => () => funding.dispose());
588
+ return funding;
589
+ }
590
+ //#endregion
513
591
  //#region src/dsh-remote/native-history-cache.ts
514
592
  /** Rebuildable native history, separate from business records and write ledgers. */
515
593
  var DshNativeHistoryCache = class {
@@ -2579,13 +2657,6 @@ function formatArkmeIdMutationResult(result) {
2579
2657
  ].join("\n");
2580
2658
  }
2581
2659
  //#endregion
2582
- //#region src/dsh-session-events.ts
2583
- function readSessionEvents(session) {
2584
- if (typeof session.snapshotEvents === "function") return session.snapshotEvents();
2585
- if (Array.isArray(session.events)) return session.events;
2586
- throw new Error("当前 DSH 会话不支持读取事件,无法核验用户输入");
2587
- }
2588
- //#endregion
2589
2660
  //#region src/tools/shared/conversational-confirmation.ts
2590
2661
  const DEFAULT_CONFIRMATION_TTL_MILLIS$2 = 10 * 6e4;
2591
2662
  const MAX_PENDING_CONFIRMATIONS$1 = 1024;
@@ -14384,6 +14455,11 @@ async function dispatchArkmeHostOperation(service, operation, params, updateMana
14384
14455
  case "billing.products": return await service.billingProducts();
14385
14456
  case "membership.current": return await service.membershipCurrent(numberParam(params, "expectedUserId", NaN));
14386
14457
  case "membership.catalog": return await service.membershipCatalog(numberParam(params, "expectedUserId", NaN));
14458
+ case "account.points.query": return await service.aiPointsAccount(stringParam(params, "expectedAccountScope"), requestSignal);
14459
+ case "account.points.consumption": return await service.aiPointsConsumption({
14460
+ month: stringParam(params, "month"),
14461
+ ...typeof params.beforeId === "string" && params.beforeId ? { beforeId: params.beforeId } : {}
14462
+ }, stringParam(params, "expectedAccountScope"), requestSignal);
14387
14463
  case "account.usage.tokens": return await service.accountTokenUsage(stringParam(params, "expectedAccountScope"));
14388
14464
  case "account.usage.storage": return await service.accountStorageUsage(stringParam(params, "expectedAccountScope"));
14389
14465
  case "account.usage.voice": return await service.accountVoiceUsage(stringParam(params, "expectedAccountScope"));
@@ -14569,7 +14645,7 @@ async function dispatchArkmeHostOperation(service, operation, params, updateMana
14569
14645
  case "recordings.speaker.cached-options": return await service.cachedRecordingSpeakerOptions(requestSignal);
14570
14646
  case "recordings.speaker.options": return await service.recordingSpeakerOptions(requestSignal);
14571
14647
  case "recordings.speaker.presence": return await service.recordingSpeakerPresence(requestSignal);
14572
- case "recordings.speaker.members": return await service.recordingSpeakerMembers(stringParam(params, "speakerRef").trim(), requestSignal);
14648
+ case "recordings.speaker.members": return await service.recordingSpeakerMembers(stringParam(params, "speakerRef").trim(), requestSignal, stringParam(params, "expectedVersion").trim() || void 0);
14573
14649
  case "recordings.speaker.recommendation": return await service.recordingSpeakerRecommendation(stringParam(params, "itemRef").trim(), requestSignal);
14574
14650
  case "recordings.speaker.assign-item": return await service.assignRecordingSpeaker({
14575
14651
  itemRef: stringParam(params, "itemRef").trim(),
@@ -14949,6 +15025,9 @@ async function dispatchArkmeHostOperation(service, operation, params, updateMana
14949
15025
  });
14950
15026
  case "source.interwoven-moments": return await service.interwovenMoments(requiredInterwovenParam(params, "sourceRef"));
14951
15027
  case "source.interwoven-detail": return await service.interwovenMomentDetail(requiredInterwovenParam(params, "sourceRef"), requiredInterwovenParam(params, "momentRef"));
15028
+ case "source.interwoven-read-receipts":
15029
+ if (!Array.isArray(params.momentRefs) || !params.momentRefs.every((ref) => typeof ref === "string")) throw new ArkmePluginError("interwoven-param-invalid", "群互动已读查询参数无效", false, 400);
15030
+ return await service.interwovenReadReceipts(requiredInterwovenParam(params, "sourceRef"), params.momentRefs, requestSignal);
14952
15031
  case "source.related-quick-notes.from-message": return await service.relatedQuickNotesFromMessage(requiredRelatedQuickNoteParam(params, "sourceRef"), requiredRelatedQuickNoteParam(params, "messageActionRef", MAX_MESSAGE_ACTION_REF_CHARS), requestSignal);
14953
15032
  case "source.related-quick-notes.from-moment": return await service.relatedQuickNotesFromMoment(requiredRelatedQuickNoteParam(params, "sourceRef"), requiredRelatedQuickNoteParam(params, "momentRef"), requestSignal);
14954
15033
  case "source.record-edit-history": return await service.recordEditHistoryPage(stringParam(params, "sourceRef"), stringParam(params, "messageActionRef"), numberParam(params, "cursorEditAt", 0), requestSignal);
@@ -14987,6 +15066,7 @@ async function dispatchArkmeHostOperation(service, operation, params, updateMana
14987
15066
  case "message-actions.copy-link": return await service.copyMessageActionsLink(stringParam(params, "conversationRef").trim(), messageActionRefsParam(params), requestSignal === void 0 ? {} : { signal: requestSignal });
14988
15067
  case "source.message-copy-link.resolve": return await service.resolveMessageCopyLink(stringParam(params, "sid"), requestSignal === void 0 ? {} : { signal: requestSignal });
14989
15068
  case "source.message-copy-link.extend": return await service.extendMessageCopyLink(stringParam(params, "sid"), numberParam(params, "itemIndex", 0), stringParam(params, "textContent"), stringParam(params, "recordUid"), requestSignal === void 0 ? {} : { signal: requestSignal });
15069
+ case "source.message-extension.parent": return await service.sourceMessageExtensionParent(stringParam(params, "sourceRef"), stringParam(params, "messageActionRef"), requestSignal === void 0 ? {} : { signal: requestSignal });
14990
15070
  case "source.message-extension.context": return await service.sourceMessageExtensionContext(stringParam(params, "sourceRef"), stringParam(params, "messageActionRef"), requestSignal === void 0 ? {} : { signal: requestSignal });
14991
15071
  case "source.message-extension.extend": return await service.extendSourceMessage(stringParam(params, "sourceRef"), stringParam(params, "messageActionRef"), stringParam(params, "textContent"), stringParam(params, "recordUid"), [...new Set(stringListParam(params, "fileRefs").map((value) => value.trim()).filter((value) => value !== ""))], {
14992
15072
  ...richSendParam(params),
@@ -28114,6 +28194,60 @@ const recordCalendarToolModules = [defineArkmeCoreToolModule({
28114
28194
  });
28115
28195
  }
28116
28196
  })];
28197
+ const aiPointsToolModules = [defineArkmeCoreToolModule({
28198
+ meta: {
28199
+ id: "business.account.ai-points.v1",
28200
+ toolName: "arkme_ai_points",
28201
+ kind: "business",
28202
+ phase: "core",
28203
+ effect: "read",
28204
+ profiles: ["business", "hybrid"]
28205
+ },
28206
+ create: (ports) => defineTool({
28207
+ name: "arkme_ai_points",
28208
+ description: "Read the signed-in Arkme account AI points: available, member grants and purchased points. This read cannot recharge, grant points or call a model.",
28209
+ parameters: {},
28210
+ output: TEXT_OUTPUT$3,
28211
+ isConcurrencySafe: () => true,
28212
+ execute: async (_args, exec) => {
28213
+ const { accountScope: _scope, ...account } = await ports.aiPointsAccount(void 0, exec.signal);
28214
+ return taggedJSON("AI 积分", account);
28215
+ }
28216
+ })
28217
+ }), defineArkmeCoreToolModule({
28218
+ meta: {
28219
+ id: "business.account.ai-points-consumption.v1",
28220
+ toolName: "arkme_ai_points_consumption",
28221
+ kind: "business",
28222
+ phase: "core",
28223
+ effect: "read",
28224
+ profiles: ["business", "hybrid"]
28225
+ },
28226
+ create: (ports) => defineTool({
28227
+ name: "arkme_ai_points_consumption",
28228
+ description: "Read settled AI point consumption for a natural month (Asia/Shanghai). Non-charged background model usage is excluded. Follow nextBeforeId to read another page.",
28229
+ parameters: {
28230
+ month: {
28231
+ type: "string",
28232
+ required: true,
28233
+ description: "Month YYYY-MM"
28234
+ },
28235
+ beforeId: {
28236
+ type: "string",
28237
+ description: "Opaque nextBeforeId returned by the previous page"
28238
+ }
28239
+ },
28240
+ output: TEXT_OUTPUT$3,
28241
+ isConcurrencySafe: () => true,
28242
+ execute: async (args, exec) => {
28243
+ const { accountScope: _scope, ...page } = await ports.aiPointsConsumption({
28244
+ month: args.month,
28245
+ ...args.beforeId ? { beforeId: args.beforeId } : {}
28246
+ }, void 0, exec.signal);
28247
+ return taggedJSON("AI 积分消费", page);
28248
+ }
28249
+ })
28250
+ })];
28117
28251
  //#endregion
28118
28252
  //#region src/tools/business/account/profile.ts
28119
28253
  const userProfileToolModule = defineArkmeCoreToolModule({
@@ -28184,57 +28318,59 @@ function expectedUserId(value) {
28184
28318
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) throw new Error("背景音设置的账号归属无效,请刷新后重试");
28185
28319
  return value;
28186
28320
  }
28321
+ const backgroundSoundPreferenceToolModules = [defineArkmeCoreToolModule({
28322
+ meta: {
28323
+ id: "business.account.background-sound-status.v1",
28324
+ toolName: "arkme_background_sound_status",
28325
+ kind: "business",
28326
+ phase: "core",
28327
+ effect: "read",
28328
+ profiles: ["business", "hybrid"]
28329
+ },
28330
+ create: (ports) => defineTool({
28331
+ name: "arkme_background_sound_status",
28332
+ description: "Read whether text background sound is enabled for the signed-in Arkme account. This does not request microphone permission, record audio, or change the preference.",
28333
+ parameters: {},
28334
+ output: TEXT_OUTPUT$3,
28335
+ isConcurrencySafe: () => true,
28336
+ execute: async (_args, exec) => {
28337
+ return taggedJSON("Arkme 文字背景音设置", safePreference(await ports.backgroundSoundPreference(exec.signal)));
28338
+ }
28339
+ })
28340
+ }), defineArkmeCoreToolModule({
28341
+ meta: {
28342
+ id: "business.account.background-sound-disable.v1",
28343
+ toolName: "arkme_background_sound_disable",
28344
+ kind: "business",
28345
+ phase: "core",
28346
+ effect: "write",
28347
+ grant: "explicit-user-write",
28348
+ profiles: ["business", "hybrid"]
28349
+ },
28350
+ create: (ports) => withArkmeConfirmationContext(defineTool({
28351
+ name: "arkme_background_sound_disable",
28352
+ description: "Only after an explicit current human request: disable text background sound for the signed-in Arkme account. This Tool has no enable parameter and can never request microphone permission or start recording. Enabling is available only from an interactive UI/SDK action by the human.",
28353
+ parameters: {},
28354
+ output: TEXT_OUTPUT$3,
28355
+ execute: async (_args, exec) => {
28356
+ const current = await ports.backgroundSoundPreference(exec.signal);
28357
+ return taggedJSON("Arkme 文字背景音设置", safePreference(await ports.updateBackgroundSoundPreference(false, exec.signal, expectedUserId(current.userId))));
28358
+ }
28359
+ }), {
28360
+ prepare: async (_args, exec) => {
28361
+ return { expectedUserId: expectedUserId((await ports.backgroundSoundPreference(exec.signal)).userId) };
28362
+ },
28363
+ execute: async (_args, exec, prepared) => {
28364
+ return taggedJSON("Arkme 文字背景音设置", safePreference(await ports.updateBackgroundSoundPreference(false, exec.signal, expectedUserId(prepared.expectedUserId))));
28365
+ }
28366
+ })
28367
+ })];
28187
28368
  //#endregion
28188
28369
  //#region src/tools/business/account/index.ts
28189
28370
  const accountBusinessToolModules = [
28190
28371
  userProfileToolModule,
28191
- ...[defineArkmeCoreToolModule({
28192
- meta: {
28193
- id: "business.account.background-sound-status.v1",
28194
- toolName: "arkme_background_sound_status",
28195
- kind: "business",
28196
- phase: "core",
28197
- effect: "read",
28198
- profiles: ["business", "hybrid"]
28199
- },
28200
- create: (ports) => defineTool({
28201
- name: "arkme_background_sound_status",
28202
- description: "Read whether text background sound is enabled for the signed-in Arkme account. This does not request microphone permission, record audio, or change the preference.",
28203
- parameters: {},
28204
- output: TEXT_OUTPUT$3,
28205
- isConcurrencySafe: () => true,
28206
- execute: async (_args, exec) => {
28207
- return taggedJSON("Arkme 文字背景音设置", safePreference(await ports.backgroundSoundPreference(exec.signal)));
28208
- }
28209
- })
28210
- }), defineArkmeCoreToolModule({
28211
- meta: {
28212
- id: "business.account.background-sound-disable.v1",
28213
- toolName: "arkme_background_sound_disable",
28214
- kind: "business",
28215
- phase: "core",
28216
- effect: "write",
28217
- grant: "explicit-user-write",
28218
- profiles: ["business", "hybrid"]
28219
- },
28220
- create: (ports) => withArkmeConfirmationContext(defineTool({
28221
- name: "arkme_background_sound_disable",
28222
- description: "Only after an explicit current human request: disable text background sound for the signed-in Arkme account. This Tool has no enable parameter and can never request microphone permission or start recording. Enabling is available only from an interactive UI/SDK action by the human.",
28223
- parameters: {},
28224
- output: TEXT_OUTPUT$3,
28225
- execute: async (_args, exec) => {
28226
- const current = await ports.backgroundSoundPreference(exec.signal);
28227
- return taggedJSON("Arkme 文字背景音设置", safePreference(await ports.updateBackgroundSoundPreference(false, exec.signal, expectedUserId(current.userId))));
28228
- }
28229
- }), {
28230
- prepare: async (_args, exec) => {
28231
- return { expectedUserId: expectedUserId((await ports.backgroundSoundPreference(exec.signal)).userId) };
28232
- },
28233
- execute: async (_args, exec, prepared) => {
28234
- return taggedJSON("Arkme 文字背景音设置", safePreference(await ports.updateBackgroundSoundPreference(false, exec.signal, expectedUserId(prepared.expectedUserId))));
28235
- }
28236
- })
28237
- })],
28372
+ ...aiPointsToolModules,
28373
+ ...backgroundSoundPreferenceToolModules,
28238
28374
  setArkmeIdToolModule
28239
28375
  ];
28240
28376
  //#endregion
@@ -30286,6 +30422,79 @@ const fileToolModules = [
30286
30422
  })
30287
30423
  ];
30288
30424
  //#endregion
30425
+ //#region src/tools/business/recordings/speaker-presence.ts
30426
+ const speakerPresenceToolModule = defineArkmeCoreToolModule({
30427
+ meta: {
30428
+ id: "business.recordings.speaker-presence.v1",
30429
+ toolName: "arkme_speaker_presence",
30430
+ kind: "business",
30431
+ phase: "core",
30432
+ effect: "read",
30433
+ profiles: ["business", "hybrid"]
30434
+ },
30435
+ create: (ports) => defineTool({
30436
+ name: "arkme_speaker_presence",
30437
+ description: "Read the current account’s all-history confirmed speaker appearance statistics or original voice associations. Counts use transcribed system speech in visible recordings, not voiceprint usage or other people’s recordings. List returns opaque speakerRef values; pass one unchanged to detail. A non-fresh state is incomplete and must never be reported as zero appearances. Do not poll continuously; report that processing is in progress.",
30438
+ parameters: {
30439
+ action: {
30440
+ type: "string",
30441
+ enum: ["list", "detail"],
30442
+ required: true
30443
+ },
30444
+ speaker_ref: {
30445
+ type: "string",
30446
+ description: "Detail only: unchanged speakerRef returned by list."
30447
+ },
30448
+ expected_version: {
30449
+ type: "string",
30450
+ description: "Optional version from list, to avoid mixing snapshots."
30451
+ }
30452
+ },
30453
+ output: TEXT_OUTPUT$3,
30454
+ isConcurrencySafe: () => true,
30455
+ execute: async (args, exec) => {
30456
+ exec.signal?.throwIfAborted();
30457
+ if (args.action === "list") {
30458
+ if (args.speaker_ref !== void 0 || args.expected_version !== void 0) throw new TypeError("列表不接受详情参数");
30459
+ const [candidates, presence] = await Promise.all([ports.recordingSpeakerOptions(exec.signal), ports.recordingSpeakerPresence(exec.signal)]);
30460
+ return taggedJSON("已识别说话人出现统计", {
30461
+ candidates: candidates.filter((item) => item.kind === "speaker").map(({ speakerRef, optionKey, personKey, label }) => ({
30462
+ speakerRef,
30463
+ optionKey,
30464
+ personKey,
30465
+ label
30466
+ })),
30467
+ state: presence.state,
30468
+ version: presence.version,
30469
+ retryAfterMs: presence.retryAfterMs,
30470
+ items: presence.state === "fresh" ? presence.items.map(({ optionKey, dayCount, lastSeenAt }) => ({
30471
+ optionKey,
30472
+ dayCount,
30473
+ lastSeenAt
30474
+ })) : []
30475
+ });
30476
+ }
30477
+ if (args.action !== "detail" || typeof args.speaker_ref !== "string" || args.speaker_ref.trim() === "" || args.speaker_ref.length > 4096) throw new TypeError("详情需要列表返回的 speaker_ref");
30478
+ const result = await ports.recordingSpeakerMembers(args.speaker_ref, exec.signal, args.expected_version);
30479
+ return taggedJSON("说话人原始声音关联", {
30480
+ state: result.state,
30481
+ version: result.version,
30482
+ retryAfterMs: result.retryAfterMs,
30483
+ ...result.state === "fresh" ? {
30484
+ dayCount: result.dayCount,
30485
+ lastSeenAt: result.lastSeenAt
30486
+ } : {},
30487
+ items: result.state === "fresh" ? result.items.map(({ identityKey, token, dayCount, lastSeenAt }) => ({
30488
+ identityKey,
30489
+ token,
30490
+ dayCount,
30491
+ lastSeenAt
30492
+ })) : []
30493
+ });
30494
+ }
30495
+ })
30496
+ });
30497
+ //#endregion
30289
30498
  //#region src/tools/business/recordings/import.ts
30290
30499
  function importResult(job) {
30291
30500
  const failureMessage = job.retryable ? "录音导入失败,可使用最新任务版本重试。" : "录音导入失败,请在录音导入页面查看原因。";
@@ -30453,85 +30662,89 @@ function directoryConfirmation(input, prepared) {
30453
30662
  }
30454
30663
  //#endregion
30455
30664
  //#region src/tools/business/recordings/index.ts
30456
- const recordingToolModules = [recordingImportToolModule, defineArkmeCoreToolModule({
30457
- meta: {
30458
- id: "business.recordings.import-folder.v1",
30459
- toolName: "arkme_recording_import_folder",
30460
- kind: "business",
30461
- phase: "core",
30462
- effect: "write",
30463
- grant: "explicit-user-write",
30464
- profiles: ["business", "hybrid"]
30465
- },
30466
- create: (ports) => withArkmeConfirmationContext(defineTool({
30467
- name: "arkme_recording_import_folder",
30468
- description: "Import WAV, MP3 and M4A recordings from a human-selected local absolute or ~/ directory. Use action=prepare to check or refresh cloud matches without uploading, directly once the directory is known. The preflight returns one final confirmation with upload counts, exceptional file paths and ownership, which defaults to self. Only after a later human confirmation use action=upload with the same directory, scope, ownership and recording times; missing, expired or changed confirmation scope requires a fresh confirmation. Includes subdirectories by default and does not follow symlinks. Filename YYYYMMDD-HHMMSS uses the host local timezone; use start_times for unknown recording times. matched_uploaded means metadata match and upload finalization, not content hash verification. Returns after Audio receives the uploads; transcription is separate.",
30469
- parameters: {
30470
- action: {
30471
- type: "string",
30472
- enum: ["prepare", "upload"],
30473
- required: true,
30474
- description: "Use prepare for read-only preflight or refresh; use upload after the human confirms the returned scope."
30475
- },
30476
- directory_path: {
30477
- type: "string",
30478
- required: true,
30479
- description: "Exact local absolute or ~/ recording directory selected by the human."
30480
- },
30481
- recursive: {
30482
- type: "boolean",
30483
- description: "Include subdirectories; defaults to true."
30484
- },
30485
- ownership: {
30486
- type: "string",
30487
- enum: ["self", "other"],
30488
- description: "Recording ownership; defaults to self."
30489
- },
30490
- start_times: {
30491
- type: "array",
30492
- description: "Actual per-file recording starts when filename time is unknown or needs correction.",
30493
- items: {
30494
- type: "object",
30495
- additionalProperties: false,
30496
- properties: {
30497
- relative_path: {
30498
- type: "string",
30499
- required: true,
30500
- description: "Exact path relative to directory_path."
30501
- },
30502
- start_at_millis: {
30503
- type: "integer",
30504
- required: true,
30505
- description: "Actual recording start in Unix milliseconds."
30665
+ const recordingToolModules = [
30666
+ recordingImportToolModule,
30667
+ defineArkmeCoreToolModule({
30668
+ meta: {
30669
+ id: "business.recordings.import-folder.v1",
30670
+ toolName: "arkme_recording_import_folder",
30671
+ kind: "business",
30672
+ phase: "core",
30673
+ effect: "write",
30674
+ grant: "explicit-user-write",
30675
+ profiles: ["business", "hybrid"]
30676
+ },
30677
+ create: (ports) => withArkmeConfirmationContext(defineTool({
30678
+ name: "arkme_recording_import_folder",
30679
+ description: "Import WAV, MP3 and M4A recordings from a human-selected local absolute or ~/ directory. Use action=prepare to check or refresh cloud matches without uploading, directly once the directory is known. The preflight returns one final confirmation with upload counts, exceptional file paths and ownership, which defaults to self. Only after a later human confirmation use action=upload with the same directory, scope, ownership and recording times; missing, expired or changed confirmation scope requires a fresh confirmation. Includes subdirectories by default and does not follow symlinks. Filename YYYYMMDD-HHMMSS uses the host local timezone; use start_times for unknown recording times. matched_uploaded means metadata match and upload finalization, not content hash verification. Returns after Audio receives the uploads; transcription is separate.",
30680
+ parameters: {
30681
+ action: {
30682
+ type: "string",
30683
+ enum: ["prepare", "upload"],
30684
+ required: true,
30685
+ description: "Use prepare for read-only preflight or refresh; use upload after the human confirms the returned scope."
30686
+ },
30687
+ directory_path: {
30688
+ type: "string",
30689
+ required: true,
30690
+ description: "Exact local absolute or ~/ recording directory selected by the human."
30691
+ },
30692
+ recursive: {
30693
+ type: "boolean",
30694
+ description: "Include subdirectories; defaults to true."
30695
+ },
30696
+ ownership: {
30697
+ type: "string",
30698
+ enum: ["self", "other"],
30699
+ description: "Recording ownership; defaults to self."
30700
+ },
30701
+ start_times: {
30702
+ type: "array",
30703
+ description: "Actual per-file recording starts when filename time is unknown or needs correction.",
30704
+ items: {
30705
+ type: "object",
30706
+ additionalProperties: false,
30707
+ properties: {
30708
+ relative_path: {
30709
+ type: "string",
30710
+ required: true,
30711
+ description: "Exact path relative to directory_path."
30712
+ },
30713
+ start_at_millis: {
30714
+ type: "integer",
30715
+ required: true,
30716
+ description: "Actual recording start in Unix milliseconds."
30717
+ }
30506
30718
  }
30507
30719
  }
30508
30720
  }
30721
+ },
30722
+ output: TEXT_OUTPUT$3,
30723
+ isConcurrencySafe: () => true,
30724
+ execute: async (args, exec) => {
30725
+ exec.signal?.throwIfAborted();
30726
+ const input = directoryInput(args);
30727
+ const prepared = await ports.prepareRecordingDirectory(input, exec.signal);
30728
+ if (args.action === "prepare") return directoryPreviewResult(prepared);
30729
+ return directoryResult(await ports.importRecordingDirectory(input, prepared, exec.signal));
30509
30730
  }
30510
- },
30511
- output: TEXT_OUTPUT$3,
30512
- isConcurrencySafe: () => true,
30513
- execute: async (args, exec) => {
30514
- exec.signal?.throwIfAborted();
30515
- const input = directoryInput(args);
30516
- const prepared = await ports.prepareRecordingDirectory(input, exec.signal);
30517
- if (args.action === "prepare") return directoryPreviewResult(prepared);
30518
- return directoryResult(await ports.importRecordingDirectory(input, prepared, exec.signal));
30519
- }
30520
- }), {
30521
- confirmationRequest: directoryConfirmationRequest,
30522
- question: (args, prepared) => directoryConfirmation(directoryInput(args), prepared),
30523
- prepare: async (args, exec) => {
30524
- exec.signal?.throwIfAborted();
30525
- return await ports.prepareRecordingDirectory(directoryInput(args), exec.signal);
30526
- },
30527
- execute: async (args, exec, prepared) => {
30528
- exec.signal?.throwIfAborted();
30529
- const request = directoryConfirmationRequest(args);
30530
- if (request.forcePrepare) return directoryPreviewResult(prepared);
30531
- return directoryResult(await ports.importRecordingDirectory(request.arguments, prepared, exec.signal));
30532
- }
30533
- })
30534
- })];
30731
+ }), {
30732
+ confirmationRequest: directoryConfirmationRequest,
30733
+ question: (args, prepared) => directoryConfirmation(directoryInput(args), prepared),
30734
+ prepare: async (args, exec) => {
30735
+ exec.signal?.throwIfAborted();
30736
+ return await ports.prepareRecordingDirectory(directoryInput(args), exec.signal);
30737
+ },
30738
+ execute: async (args, exec, prepared) => {
30739
+ exec.signal?.throwIfAborted();
30740
+ const request = directoryConfirmationRequest(args);
30741
+ if (request.forcePrepare) return directoryPreviewResult(prepared);
30742
+ return directoryResult(await ports.importRecordingDirectory(request.arguments, prepared, exec.signal));
30743
+ }
30744
+ })
30745
+ }),
30746
+ speakerPresenceToolModule
30747
+ ];
30535
30748
  //#endregion
30536
30749
  //#region src/tools/business/records/create.ts
30537
30750
  const createRecordToolModule = defineArkmeCoreToolModule({
@@ -39008,10 +39221,12 @@ function apply(ctx, config) {
39008
39221
  return () => void 0;
39009
39222
  }, "dsh-arkme: desktop account scope attestation");
39010
39223
  ctx.inject(["llm"], (modelCtx) => {
39224
+ const funding = registerManagedTurnFunding(modelCtx, config.intelligentBaseUrl);
39011
39225
  registerManagedAiProvider(modelCtx, {
39012
39226
  intelligentBaseUrl: config.intelligentBaseUrl,
39013
39227
  credentialOwner: service,
39014
- resolveAttachmentReader: () => modelCtx.get("attachments")
39228
+ resolveAttachmentReader: () => modelCtx.get("attachments"),
39229
+ prepareOperation: (request, bearer) => funding.prepare(request, bearer)
39015
39230
  });
39016
39231
  });
39017
39232
  registerDSHAgentInputRecordSync(ctx, service);
@@ -1,2 +1,2 @@
1
- import { a as persistentArkmeExtensionActive, i as invokePersistentArkmeExtension, n as applyPersistentArkmeHostExtension, o as persistentArkmeExtensionRuntimeState, r as deactivatePersistentArkmeExtension, t as activatePersistentArkmeExtension } from "./persistent-runtime-DV9Hme-U.js";
1
+ import { a as persistentArkmeExtensionActive, i as invokePersistentArkmeExtension, n as applyPersistentArkmeHostExtension, o as persistentArkmeExtensionRuntimeState, r as deactivatePersistentArkmeExtension, t as activatePersistentArkmeExtension } from "./persistent-runtime-CuKplHIv.js";
2
2
  export { activatePersistentArkmeExtension, applyPersistentArkmeHostExtension, deactivatePersistentArkmeExtension, invokePersistentArkmeExtension, persistentArkmeExtensionActive, persistentArkmeExtensionRuntimeState };