@senguoyun/dsh-arkme 0.1.50 → 0.1.52

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 (132) hide show
  1. package/docs/dsh-input-system-topic.md +26 -0
  2. package/lib/client.js +4430 -3115
  3. package/lib/client.js.map +1 -1
  4. package/lib/extension-profile-restart-helper.js +10 -6
  5. package/lib/harness-model-client.js +8 -0
  6. package/lib/index.js +99 -57
  7. package/lib/persistent-extension.js +1 -1
  8. package/lib/{persistent-runtime-YkrM3K7s.js → persistent-runtime-BRy2sNmS.js} +312 -81
  9. package/lib/{plugin-updater-helper-B0yVav4f.js → plugin-updater-helper-n8JrMPum.js} +1 -1
  10. package/lib/{plugin-updater-helper-BbjKUV9T.js → plugin-updater-helper-y7wzJLOx.js} +11 -4
  11. package/lib/plugin-updater-helper.js +1 -1
  12. package/lib/sdk.js +8 -0
  13. package/lib/types/arkme-service.d.ts +3 -0
  14. package/lib/types/arkme-service.d.ts.map +1 -1
  15. package/lib/types/call-record-presentation.d.ts +2 -0
  16. package/lib/types/call-record-presentation.d.ts.map +1 -1
  17. package/lib/types/client/ArkmeArkoSurface.d.ts.map +1 -1
  18. package/lib/types/client/ArkmeBotConversationSurface.d.ts.map +1 -1
  19. package/lib/types/client/ArkmeBotCreateDialog.d.ts.map +1 -1
  20. package/lib/types/client/ArkmeCallDetailContent.d.ts +13 -0
  21. package/lib/types/client/ArkmeCallDetailContent.d.ts.map +1 -0
  22. package/lib/types/client/ArkmeCallDetailDrawer.d.ts +2 -1
  23. package/lib/types/client/ArkmeCallDetailDrawer.d.ts.map +1 -1
  24. package/lib/types/client/ArkmeCallRecordContent.d.ts +4 -2
  25. package/lib/types/client/ArkmeCallRecordContent.d.ts.map +1 -1
  26. package/lib/types/client/ArkmeCallSurface.d.ts.map +1 -1
  27. package/lib/types/client/ArkmeComposerSendButton.d.ts +10 -0
  28. package/lib/types/client/ArkmeComposerSendButton.d.ts.map +1 -0
  29. package/lib/types/client/ArkmeDshAgentInputMarker.d.ts +1 -1
  30. package/lib/types/client/ArkmeDshAgentInputMarker.d.ts.map +1 -1
  31. package/lib/types/client/ArkmeLinkText.d.ts +1 -1
  32. package/lib/types/client/ArkmeLinkText.d.ts.map +1 -1
  33. package/lib/types/client/ArkmeLogin.d.ts.map +1 -1
  34. package/lib/types/client/ArkmeMarketplace.d.ts +1 -0
  35. package/lib/types/client/ArkmeMarketplace.d.ts.map +1 -1
  36. package/lib/types/client/ArkmeMentionSuggestionRow.d.ts +20 -0
  37. package/lib/types/client/ArkmeMentionSuggestionRow.d.ts.map +1 -0
  38. package/lib/types/client/ArkmeMessageActions.d.ts.map +1 -1
  39. package/lib/types/client/ArkmeNoteDetails.d.ts +6 -2
  40. package/lib/types/client/ArkmeNoteDetails.d.ts.map +1 -1
  41. package/lib/types/client/ArkmeOfficialAuthorGuide.d.ts +7 -0
  42. package/lib/types/client/ArkmeOfficialAuthorGuide.d.ts.map +1 -0
  43. package/lib/types/client/ArkmePersistentShell.d.ts +1 -1
  44. package/lib/types/client/ArkmePersistentShell.d.ts.map +1 -1
  45. package/lib/types/client/ArkmeRichContent.d.ts +2 -1
  46. package/lib/types/client/ArkmeRichContent.d.ts.map +1 -1
  47. package/lib/types/client/ArkmeRichText.d.ts +9 -5
  48. package/lib/types/client/ArkmeRichText.d.ts.map +1 -1
  49. package/lib/types/client/ArkmeScanGuide.d.ts +5 -0
  50. package/lib/types/client/ArkmeScanGuide.d.ts.map +1 -0
  51. package/lib/types/client/ArkmeSidebar.d.ts +3 -35
  52. package/lib/types/client/ArkmeSidebar.d.ts.map +1 -1
  53. package/lib/types/client/ArkmeSourceBreadcrumb.d.ts.map +1 -1
  54. package/lib/types/client/ArkmeTopicDirectoryPopover.d.ts +2 -1
  55. package/lib/types/client/ArkmeTopicDirectoryPopover.d.ts.map +1 -1
  56. package/lib/types/client/ArkmeTopicReadOnlyNotice.d.ts +3 -0
  57. package/lib/types/client/ArkmeTopicReadOnlyNotice.d.ts.map +1 -0
  58. package/lib/types/client/ArkmeVirtualWorkspace.d.ts +13 -7
  59. package/lib/types/client/ArkmeVirtualWorkspace.d.ts.map +1 -1
  60. package/lib/types/client/api.d.ts +1 -1
  61. package/lib/types/client/api.d.ts.map +1 -1
  62. package/lib/types/client/arkme-login-locales.d.ts +13 -0
  63. package/lib/types/client/arkme-login-locales.d.ts.map +1 -1
  64. package/lib/types/client/call-detail-presentation.d.ts +13 -0
  65. package/lib/types/client/call-detail-presentation.d.ts.map +1 -0
  66. package/lib/types/client/chat-directory-store.d.ts.map +1 -1
  67. package/lib/types/client/composer-draft-store.d.ts +7 -0
  68. package/lib/types/client/composer-draft-store.d.ts.map +1 -1
  69. package/lib/types/client/conversation-composer-presentation.d.ts +3 -0
  70. package/lib/types/client/conversation-composer-presentation.d.ts.map +1 -1
  71. package/lib/types/client/conversation-resize-anchor.d.ts +1 -1
  72. package/lib/types/client/conversation-resize-anchor.d.ts.map +1 -1
  73. package/lib/types/client/index.d.ts +2 -1
  74. package/lib/types/client/index.d.ts.map +1 -1
  75. package/lib/types/client/mention-candidates.d.ts +46 -0
  76. package/lib/types/client/mention-candidates.d.ts.map +1 -0
  77. package/lib/types/client/navigation-cache.d.ts.map +1 -1
  78. package/lib/types/client/read-deadline.d.ts +3 -0
  79. package/lib/types/client/read-deadline.d.ts.map +1 -0
  80. package/lib/types/client/realtime-client-events.d.ts.map +1 -1
  81. package/lib/types/client/realtime-connection.d.ts +9 -0
  82. package/lib/types/client/realtime-connection.d.ts.map +1 -0
  83. package/lib/types/client/recordings/RecordingTranscriptForward.d.ts.map +1 -1
  84. package/lib/types/client/scan-guide-icons.d.ts +7 -0
  85. package/lib/types/client/scan-guide-icons.d.ts.map +1 -0
  86. package/lib/types/client/scan-guide-styles.d.ts +2 -0
  87. package/lib/types/client/scan-guide-styles.d.ts.map +1 -0
  88. package/lib/types/client/slots-contract.d.ts +23 -0
  89. package/lib/types/client/slots-contract.d.ts.map +1 -1
  90. package/lib/types/client/source-tree.d.ts.map +1 -1
  91. package/lib/types/client/use-call-record-preview.d.ts +8 -0
  92. package/lib/types/client/use-call-record-preview.d.ts.map +1 -0
  93. package/lib/types/client/use-call-transcript-playback.d.ts +13 -0
  94. package/lib/types/client/use-call-transcript-playback.d.ts.map +1 -0
  95. package/lib/types/dsh-agent-input-source.d.ts +0 -1
  96. package/lib/types/dsh-agent-input-source.d.ts.map +1 -1
  97. package/lib/types/extensions/profile-restart-helper.d.ts.map +1 -1
  98. package/lib/types/host-api.d.ts.map +1 -1
  99. package/lib/types/index.d.ts.map +1 -1
  100. package/lib/types/plugin-updater-helper.d.ts.map +1 -1
  101. package/lib/types/realtime-events.d.ts +9 -5
  102. package/lib/types/realtime-events.d.ts.map +1 -1
  103. package/lib/types/sdk/index.d.ts +4 -0
  104. package/lib/types/sdk/index.d.ts.map +1 -1
  105. package/lib/types/services/bot-conversation-service.d.ts.map +1 -1
  106. package/lib/types/services/bot-service.d.ts.map +1 -1
  107. package/lib/types/services/call-history-service.d.ts +3 -1
  108. package/lib/types/services/call-history-service.d.ts.map +1 -1
  109. package/lib/types/services/chat-service.d.ts +1 -0
  110. package/lib/types/services/chat-service.d.ts.map +1 -1
  111. package/lib/types/services/media-service.d.ts.map +1 -1
  112. package/lib/types/services/search-service.d.ts.map +1 -1
  113. package/lib/types/services/source-service.d.ts +4 -0
  114. package/lib/types/services/source-service.d.ts.map +1 -1
  115. package/lib/types/services/topic-metadata.d.ts +10 -0
  116. package/lib/types/services/topic-metadata.d.ts.map +1 -0
  117. package/lib/types/services/topic-record-page.d.ts +18 -0
  118. package/lib/types/services/topic-record-page.d.ts.map +1 -0
  119. package/lib/types/tools/business/conversation/index.d.ts.map +1 -1
  120. package/lib/types/tools/business/conversation/topic-home-visibility.d.ts +2 -0
  121. package/lib/types/tools/business/conversation/topic-home-visibility.d.ts.map +1 -0
  122. package/lib/types/tools/business/index.d.ts.map +1 -1
  123. package/lib/types/tools/ports/bots.d.ts +1 -0
  124. package/lib/types/tools/ports/bots.d.ts.map +1 -1
  125. package/lib/types/tools/ports/conversations.d.ts +3 -0
  126. package/lib/types/tools/ports/conversations.d.ts.map +1 -1
  127. package/lib/types/tools/registry/registrar.d.ts.map +1 -1
  128. package/lib/types/topic-policy.d.ts +9 -0
  129. package/lib/types/topic-policy.d.ts.map +1 -0
  130. package/lib/types/types.d.ts +22 -1
  131. package/lib/types/types.d.ts.map +1 -1
  132. package/package.json +5 -5
@@ -84,6 +84,7 @@ function start(plan) {
84
84
  async function healthy(plan) {
85
85
  const deadline = Date.now() + HEALTH_TIMEOUT_MS;
86
86
  while (Date.now() < deadline) {
87
+ let extensionReady = false;
87
88
  try {
88
89
  const response = await fetch(plan.healthUrl, {
89
90
  method: "POST",
@@ -101,14 +102,17 @@ async function healthy(plan) {
101
102
  const body = await response.json();
102
103
  if (plan.desktopQuarantineActivation === true) {
103
104
  const status = body.value;
104
- if (body.ok === true && status?.profileEnabled === true && status.active === true) return true;
105
- await new Promise((resolve) => setTimeout(resolve, 500));
106
- continue;
105
+ extensionReady = body.ok === true && status?.profileEnabled === true && status.active === true;
106
+ } else {
107
+ const installed = Array.isArray(body.value) ? body.value.find((item) => item.extensionId === plan.extensionId) : void 0;
108
+ extensionReady = body.ok === true && (plan.activationChange === true ? plan.expectActive ? installed?.enabled === true && installed.active === true : installed?.enabled === false && installed.active === false : plan.expectActive ? installed?.active === true : installed === void 0);
107
109
  }
108
- const installed = Array.isArray(body.value) ? body.value.find((item) => item.extensionId === plan.extensionId) : void 0;
109
- if (body.ok === true && (plan.activationChange === true ? plan.expectActive ? installed?.enabled === true && installed.active === true : installed?.enabled === false && installed.active === false : plan.expectActive ? installed?.active === true : installed === void 0)) return true;
110
110
  }
111
111
  } catch {}
112
+ if (extensionReady) try {
113
+ const root = await fetch(new URL("/", plan.healthUrl), { signal: AbortSignal.timeout(2e3) });
114
+ if (root.ok || root.status === 401 || root.status === 403) return true;
115
+ } catch {}
112
116
  await new Promise((resolve) => setTimeout(resolve, 500));
113
117
  }
114
118
  return false;
@@ -220,7 +224,7 @@ async function main() {
220
224
  if (planPath === void 0) throw new Error("extension restart plan path is required");
221
225
  const rawPlan = JSON.parse(await readFile(planPath, "utf8"));
222
226
  if (managed && isPluginUpdateRestartPlan(rawPlan)) {
223
- const pluginUpdate = await import("./plugin-updater-helper-B0yVav4f.js");
227
+ const pluginUpdate = await import("./plugin-updater-helper-n8JrMPum.js");
224
228
  if (mode === "--managed-finalize") {
225
229
  const healthUrl = process.argv[4];
226
230
  if (healthUrl === void 0) throw new Error("managed plugin update health URL is required");
@@ -751,6 +751,14 @@ window.__ModuleLoader__.load({
751
751
  pinned
752
752
  }, signal);
753
753
  }
754
+ /** Read or explicitly set the existing topic home preference. */
755
+ async topicHomeVisibility(sourceRef, showInHome, signal) {
756
+ if (sourceRef.trim() === "") throw new TypeError("Arkme topic source reference must not be empty");
757
+ return await this.call("topic.home-visibility", {
758
+ sourceRef,
759
+ ...showInHome === void 0 ? {} : { showInHome }
760
+ }, signal);
761
+ }
754
762
  async listGroupMembers(sourceRef, signal) {
755
763
  if (sourceRef.trim() === "") throw new TypeError("Arkme group source reference must not be empty");
756
764
  return await this.call("group.members", {
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as ARKME_DEFAULT_SHARE_WEBSITE, A as inspectNativeBundleArtifactV3, At as __exportAll, D as bundleSha256, Dt as createDesktopLifecycleReader, E as arkmeSandboxEntryId, Et as retryAfterMillis, F as assertExtensionArtifactSize, G as validateVoiceprintPcm16Wav, I as canonicalExtensionJson, J as arkmeRequiredLinkMetadataFallback, K as arkmeExtensionShareRefFromLink, L as sha256Hex, M as packLocalNativeBundleDirectoryV3, Mt as __toCommonJS, N as readNativeBundleTarballV3, O as canonicalBundleJson, Ot as __commonJSMin, P as renderArkmeSandboxHostEntry, Q as parseArkmeRecordReeditAttachments, R as unpackArkmeExtension, S as ARKME_BUNDLE_ARTIFACT_KIND, St as sameRecordingImportIdentity, T as ArkmeBundleArtifactError, Tt as ArkmePluginError, U as ARKME_EXTENSION_RUNTIME_UNAVAILABLE_MESSAGE, W as ArkmeService, X as arkmeRichBackgroundSound, Y as arkmeFileBackgroundSound, Z as ArkmeRecordReeditDraftConflict, _ as arkmeClientContentDigest, _t as SecretValue, at as ARKME_WORLD_PUBLISH_MAX_IMAGE_BYTES, b as verifyExtensionResolutionSignature, bt as isUnresolvedRecordingImportJob, c as persistentExtensionBundleDirectory, ct as mergeMemberJoinEvents, d as readPersistentExtensionActivation, dt as ARKME_TOOL_FILE_MAX_BYTES, et as ARKME_PROVIDER_CONTRACT_VERSION, f as refreshPersistentClientWrapper, ft as arkmeCanInlineLocalFile, g as activeProfileExtensionOwnerConflicts, gt as ArkmeOutgoingCallError, h as renderArkmeBundleClientBundle, ht as isArkmeBotAvatarRef, i as invokePersistentArkmeExtension, it as ARKME_WORLD_PUBLISH_MAX_IMAGES, j as packBundleFiles, jt as __require, k as inspectBundleArtifact, kt as __esmMin, l as persistentExtensionPackageIdentity, lt as validateMemberUpdate, m as writePersistentExtensionActivation, mt as arkmePickedFileKind, o as persistentArkmeExtensionRuntimeState, ot as applyMemberUpdate, p as repairPersistentExtensionInstallation, pt as arkmeNormalizedFileMimeType, q as arkmeIsGenericLinkMetadataTitle, r as deactivatePersistentArkmeExtension, s as materializePersistentExtensionBundle, st as cachedMemberItem, t as activatePersistentArkmeExtension, u as quarantinePersistentExtension, ut as ARKME_RUNTIME_INSTANCE_ID, v as arkmeClientContentDigestFromSource, vt as ArkmeDirectMessageAdmissionError, w as ARKME_NATIVE_BUNDLE_ARTIFACT_KIND, wt as recordingImportFileNameKey, x as verifyNativeBundleResolutionSignature, xt as recordingImportFileKind, y as verifyBundleResolutionSignature, yt as isRecordingInstantOnOrAfterUnixEpoch, z as ARKME_EXTENSION_FORMAT } from "./persistent-runtime-YkrM3K7s.js";
2
- 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-BbjKUV9T.js";
1
+ import { $ as ARKME_DEFAULT_SHARE_WEBSITE, A as inspectNativeBundleArtifactV3, At as __exportAll, D as bundleSha256, Dt as createDesktopLifecycleReader, E as arkmeSandboxEntryId, Et as retryAfterMillis, F as assertExtensionArtifactSize, G as validateVoiceprintPcm16Wav, I as canonicalExtensionJson, J as arkmeRequiredLinkMetadataFallback, K as arkmeExtensionShareRefFromLink, L as sha256Hex, M as packLocalNativeBundleDirectoryV3, Mt as __toCommonJS, N as readNativeBundleTarballV3, O as canonicalBundleJson, Ot as __commonJSMin, P as renderArkmeSandboxHostEntry, Q as parseArkmeRecordReeditAttachments, R as unpackArkmeExtension, S as ARKME_BUNDLE_ARTIFACT_KIND, St as sameRecordingImportIdentity, T as ArkmeBundleArtifactError, Tt as ArkmePluginError, U as ARKME_EXTENSION_RUNTIME_UNAVAILABLE_MESSAGE, W as ArkmeService, X as arkmeRichBackgroundSound, Y as arkmeFileBackgroundSound, Z as ArkmeRecordReeditDraftConflict, _ as arkmeClientContentDigest, _t as SecretValue, at as ARKME_WORLD_PUBLISH_MAX_IMAGE_BYTES, b as verifyExtensionResolutionSignature, bt as isUnresolvedRecordingImportJob, c as persistentExtensionBundleDirectory, ct as mergeMemberJoinEvents, d as readPersistentExtensionActivation, dt as ARKME_TOOL_FILE_MAX_BYTES, et as ARKME_PROVIDER_CONTRACT_VERSION, f as refreshPersistentClientWrapper, ft as arkmeCanInlineLocalFile, g as activeProfileExtensionOwnerConflicts, gt as ArkmeOutgoingCallError, h as renderArkmeBundleClientBundle, ht as isArkmeBotAvatarRef, i as invokePersistentArkmeExtension, it as ARKME_WORLD_PUBLISH_MAX_IMAGES, j as packBundleFiles, jt as __require, k as inspectBundleArtifact, kt as __esmMin, l as persistentExtensionPackageIdentity, lt as validateMemberUpdate, m as writePersistentExtensionActivation, mt as arkmePickedFileKind, o as persistentArkmeExtensionRuntimeState, ot as applyMemberUpdate, p as repairPersistentExtensionInstallation, pt as arkmeNormalizedFileMimeType, q as arkmeIsGenericLinkMetadataTitle, r as deactivatePersistentArkmeExtension, s as materializePersistentExtensionBundle, st as cachedMemberItem, t as activatePersistentArkmeExtension, u as quarantinePersistentExtension, ut as ARKME_RUNTIME_INSTANCE_ID, v as arkmeClientContentDigestFromSource, vt as ArkmeDirectMessageAdmissionError, w as ARKME_NATIVE_BUNDLE_ARTIFACT_KIND, wt as recordingImportFileNameKey, x as verifyNativeBundleResolutionSignature, xt as recordingImportFileKind, y as verifyBundleResolutionSignature, yt as isRecordingInstantOnOrAfterUnixEpoch, z as ARKME_EXTENSION_FORMAT } from "./persistent-runtime-BRy2sNmS.js";
2
+ 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-y7wzJLOx.js";
3
3
  import { a as securePrivateDirectory, c as securePrivateFileSync, i as prepareProfilePackageManager, n as isArkmeProfilePackageName, o as securePrivateDirectorySync, r as localExtensionPnpmArgs, s as securePrivateFile, t as applyArkmeProfileBundlePolicy } from "./profile-bundle-policy-DLXDyohJ.js";
4
4
  import { i as invokeArkmeBundle, n as arkmeBundleActive, r as deactivateArkmeBundle } from "./bundle-runtime-CE73h3vS.js";
5
5
  import { t as ArkmeExtensionInstallStore } from "./install-store-bnyQDtYt.js";
@@ -31,9 +31,9 @@ import { getOrCreateAnonymousUserId } from "@deepseek-ai/dsh-anonymous-user-id";
31
31
  import { EMPTY_RESPONSE_CODE, LlmAdapter, LlmError, ProviderRequestId, ReasoningEffortId, attributionHeaders, createUserMessage } from "@deepseek-ai/dsh-llm";
32
32
  import { DeepSeekAdapter, resolveAdapterOptions } from "@deepseek-ai/dsh-llm-deepseek";
33
33
  import sharp from "sharp";
34
+ import WebSocket$1, { WebSocket, WebSocketServer } from "ws";
34
35
  import { Buffer as Buffer$1 } from "node:buffer";
35
36
  import { AttachmentError, AttachmentId } from "@deepseek-ai/dsh-attachment";
36
- import WebSocket from "ws";
37
37
  import { scheduler, setTimeout as setTimeout$1 } from "node:timers/promises";
38
38
  //#region src/tools/shared/output.ts
39
39
  const TEXT_OUTPUT$3 = {
@@ -11453,6 +11453,7 @@ async function dispatchArkmeHostOperation(service, operation, params, updateMana
11453
11453
  return await service.createBotSummary({
11454
11454
  name: stringParam(params, "name"),
11455
11455
  provider: botProviderParam(params),
11456
+ ...stringParam(params, "requestUid").trim() === "" ? {} : { requestUid: stringParam(params, "requestUid").trim() },
11456
11457
  ...stringParam(params, "description").trim() === "" ? {} : { description: stringParam(params, "description") },
11457
11458
  ...avatar === "" ? {} : { avatar }
11458
11459
  });
@@ -11700,6 +11701,9 @@ async function dispatchArkmeHostOperation(service, operation, params, updateMana
11700
11701
  ...requestSignal === void 0 ? {} : { signal: requestSignal }
11701
11702
  });
11702
11703
  case "topic.rename": return await service.renameTopic(stringParam(params, "sourceRef"), stringParam(params, "title"));
11704
+ case "topic.home-visibility":
11705
+ if (params.showInHome !== void 0 && typeof params.showInHome !== "boolean") throw new ArkmePluginError("topic-policy-invalid", "首页展示开关必须为布尔值", false);
11706
+ return await service.topicHomeVisibility(stringParam(params, "sourceRef"), params.showInHome, requestSignal);
11703
11707
  case "topic.dissolve": return await service.dissolveTopic(stringParam(params, "sourceRef"), stringParam(params, "parentSourceRef") || void 0, stringListParam(params, "childSourceRefs"), stringParam(params, "requestId") || void 0, numberParam(params, "expectedRecordCount", 0));
11704
11708
  case "topic.dissolve.status": return await service.topicDissolveStatus(stringParam(params, "requestId")) ?? null;
11705
11709
  case "topic.dissolve.active": return await service.activeTopicDissolve() ?? null;
@@ -11722,7 +11726,8 @@ async function dispatchArkmeHostOperation(service, operation, params, updateMana
11722
11726
  const cursor = timelineCursorParam(params);
11723
11727
  return await service.readSource(stringParam(params, "sourceRef"), {
11724
11728
  limit: numberParam(params, "limit", 30),
11725
- ...cursor === void 0 ? {} : { cursor }
11729
+ ...cursor === void 0 ? {} : { cursor },
11730
+ ...requestSignal === void 0 ? {} : { signal: requestSignal }
11726
11731
  });
11727
11732
  }
11728
11733
  case "source.timeline-around": return await service.readSourceAround(stringParam(params, "sourceRef"), stringParam(params, "itemUid"), numberParam(params, "recordOwnerUserId", 0), {
@@ -17747,80 +17752,84 @@ const HEARTBEAT_MS = 2e4;
17747
17752
  function isLoopback$2(address) {
17748
17753
  return address === "127.0.0.1" || address === "::1" || address === "::ffff:127.0.0.1";
17749
17754
  }
17750
- function dataLine(event) {
17751
- return `data: ${JSON.stringify({
17755
+ function eventFrame(event) {
17756
+ return JSON.stringify({
17752
17757
  ...event,
17753
17758
  providerInstanceId: ARKME_RUNTIME_INSTANCE_ID
17754
- })}\n\n`;
17759
+ });
17755
17760
  }
17761
+ /** Host-owned, receive-only event transport; no business commands or credentials. */
17756
17762
  var ArkmeRealtimeEvents = class {
17763
+ service;
17757
17764
  options;
17758
- connections = /* @__PURE__ */ new Set();
17765
+ server = new WebSocketServer({
17766
+ noServer: true,
17767
+ maxPayload: 1024,
17768
+ perMessageDeflate: false
17769
+ });
17770
+ awaitingPong = /* @__PURE__ */ new Set();
17759
17771
  unsubscribe;
17760
17772
  heartbeat;
17773
+ closed = false;
17761
17774
  constructor(service, options) {
17775
+ this.service = service;
17762
17776
  this.options = options;
17763
17777
  this.unsubscribe = service.subscribeChatRealtime((event) => {
17764
- this.broadcast(dataLine(event));
17778
+ const frame = eventFrame(event);
17779
+ for (const client of this.server.clients) if (client.readyState === WebSocket.OPEN) client.send(frame);
17765
17780
  });
17766
17781
  this.heartbeat = setInterval(() => {
17767
- this.broadcast(": heartbeat\n\n");
17782
+ for (const client of this.server.clients) {
17783
+ if (this.awaitingPong.has(client)) {
17784
+ client.terminate();
17785
+ continue;
17786
+ }
17787
+ this.awaitingPong.add(client);
17788
+ client.ping();
17789
+ }
17768
17790
  }, HEARTBEAT_MS);
17769
17791
  this.heartbeat.unref();
17770
- this.service = service;
17771
17792
  }
17772
- service;
17773
- handler = (req, res) => {
17774
- if (req.method !== "GET") {
17775
- res.writeHead(405);
17776
- res.end();
17777
- return;
17778
- }
17779
- if (!this.options.allowNonLoopback && !isLoopback$2(req.socket.remoteAddress)) {
17780
- res.writeHead(403);
17781
- res.end();
17782
- return;
17783
- }
17784
- const origin = req.headers.origin;
17785
- if (origin !== void 0) try {
17786
- const parsed = new URL(origin);
17787
- const port = parsed.port === "" ? parsed.protocol === "https:" ? 443 : 80 : Number(parsed.port);
17788
- if (!["127.0.0.1", "localhost"].includes(parsed.hostname) || port !== this.options.expectedPort) {
17789
- res.writeHead(403);
17790
- res.end();
17791
- return;
17792
- }
17793
- } catch {
17794
- res.writeHead(403);
17795
- res.end();
17793
+ handler = (req, socket, head) => {
17794
+ if (req.method !== "GET" || !this.allowed(req)) {
17795
+ socket.end("HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n");
17796
17796
  return;
17797
17797
  }
17798
- res.writeHead(200, {
17799
- "Content-Type": "text/event-stream; charset=utf-8",
17800
- "Cache-Control": "no-cache, no-transform",
17801
- Connection: "keep-alive",
17802
- "X-Accel-Buffering": "no",
17803
- "X-Content-Type-Options": "nosniff"
17804
- });
17805
- res.write("retry: 1000\n: connected\n\n");
17806
- res.write(dataLine(this.service.chatRealtimeInitialEvent()));
17807
- this.connections.add(res);
17808
- res.on("close", () => {
17809
- this.connections.delete(res);
17798
+ this.server.handleUpgrade(req, socket, head, (client) => {
17799
+ client.on("error", () => {
17800
+ client.terminate();
17801
+ });
17802
+ client.on("pong", () => {
17803
+ this.awaitingPong.delete(client);
17804
+ });
17805
+ client.on("close", () => {
17806
+ this.awaitingPong.delete(client);
17807
+ });
17808
+ client.on("message", () => {
17809
+ client.close(1008, "Receive-only channel");
17810
+ });
17811
+ client.send(eventFrame(this.service.chatRealtimeInitialEvent()));
17810
17812
  });
17811
17813
  };
17812
17814
  close() {
17815
+ if (this.closed) return;
17816
+ this.closed = true;
17813
17817
  this.unsubscribe();
17814
17818
  clearInterval(this.heartbeat);
17815
- for (const response of this.connections) response.destroy();
17816
- this.connections.clear();
17819
+ for (const client of this.server.clients) client.terminate();
17820
+ this.awaitingPong.clear();
17821
+ this.server.close();
17817
17822
  }
17818
- broadcast(frame) {
17819
- for (const response of [...this.connections]) try {
17820
- response.write(frame);
17823
+ allowed(req) {
17824
+ if (!this.options.allowNonLoopback && !isLoopback$2(req.socket.remoteAddress)) return false;
17825
+ const origin = req.headers.origin;
17826
+ if (origin === void 0) return true;
17827
+ try {
17828
+ const parsed = new URL(origin);
17829
+ const port = parsed.port === "" ? parsed.protocol === "https:" ? 443 : 80 : Number(parsed.port);
17830
+ return ["http:", "https:"].includes(parsed.protocol) && ["127.0.0.1", "localhost"].includes(parsed.hostname) && port === this.options.expectedPort;
17821
17831
  } catch {
17822
- response.destroy();
17823
- this.connections.delete(response);
17832
+ return false;
17824
17833
  }
17825
17834
  }
17826
17835
  };
@@ -25442,6 +25451,36 @@ const pinBotDirectoryToolModule = defineArkmeCoreToolModule({
25442
25451
  }
25443
25452
  });
25444
25453
  //#endregion
25454
+ //#region src/tools/business/conversation/topic-home-visibility.ts
25455
+ const topicHomeVisibilityToolModule = defineArkmeCoreToolModule({
25456
+ meta: {
25457
+ id: "business.conversation.topic-home-visibility.v1",
25458
+ toolName: "arkme_topic_home_visibility",
25459
+ kind: "business",
25460
+ phase: "core",
25461
+ effect: "write",
25462
+ grant: "explicit-user-write",
25463
+ profiles: ["business", "hybrid"]
25464
+ },
25465
+ create: (ports) => defineTool({
25466
+ name: "arkme_topic_home_visibility",
25467
+ description: "Read a topic home visibility preference. Only set show_in_home after an explicit user request. This never changes topic contents, name, privacy or the origin of any message.",
25468
+ parameters: {
25469
+ source_ref: {
25470
+ type: "string",
25471
+ required: true,
25472
+ description: "Account-bound topic source_ref from arkme_sources_list."
25473
+ },
25474
+ show_in_home: {
25475
+ type: "boolean",
25476
+ description: "Omit to read; true to show topic records on home, false to hide."
25477
+ }
25478
+ },
25479
+ output: TEXT_OUTPUT$3,
25480
+ execute: async (args) => taggedJSON("主题首页展示", await ports.topicHomeVisibility(args.source_ref, args.show_in_home))
25481
+ })
25482
+ });
25483
+ //#endregion
25445
25484
  //#region src/tools/business/conversation/group-ai-polish.ts
25446
25485
  const groupAiPolishToolModule = defineArkmeCoreToolModule({
25447
25486
  meta: {
@@ -29234,6 +29273,7 @@ const businessToolModules = [
29234
29273
  ...wechatToolModules,
29235
29274
  listSourcesToolModule,
29236
29275
  pinBotDirectoryToolModule,
29276
+ topicHomeVisibilityToolModule,
29237
29277
  unreadConversationsToolModule,
29238
29278
  ...groupMemberToolModules,
29239
29279
  readSourceToolModule,
@@ -29400,6 +29440,7 @@ const arkmeToolCatalog = defineArkmeToolCatalog([
29400
29440
  const CORE_CONFIRMATION_TOOLS = /* @__PURE__ */ new Set([
29401
29441
  "arkme_bot_conversation_pin",
29402
29442
  "arkme_direct_message_refusal_set",
29443
+ "arkme_topic_home_visibility",
29403
29444
  "arkme_background_sound_disable",
29404
29445
  "arkme_file_prepare",
29405
29446
  "arkme_files_send",
@@ -29445,6 +29486,7 @@ function cleanArgument(value, maxLength) {
29445
29486
  function coreConfirmationQuestion(name, args) {
29446
29487
  if (name === "arkme_direct_message_refusal_set") return args.refused === true ? "是否确认拒收这个私聊用户的消息?拒收期间双方都无法发送新消息,历史记录保留。" : "是否确认解除你对这个私聊用户的拒收?如果对方仍拒收,双方依然无法发送新消息。";
29447
29488
  if (name === "arkme_recording_import") return args.action === "retry" ? "是否确认重试这条失败的录音上传任务?" : `是否确认按指定的开始时间导入所选录音,并将归属设为“${args.ownership === "other" ? "其他" : "自己"}”?`;
29489
+ if (name === "arkme_topic_home_visibility") return args.show_in_home === true ? "是否确认将这个主题的快记展示在首页?" : "是否确认在首页隐藏这个主题的快记?主题与快记不会被删除。";
29448
29490
  if (name === "arkme_background_sound_disable") return "是否确认关闭当前 Arkme 账号的文字背景音?这不会删除已经发送的背景音。";
29449
29491
  if (name === "arkme_user_ban") return "是否确认封禁这个私聊用户?确认后将无法重新登录;Backend、聊天和录音请求立即受限;其他仅离线验 JWT 的服务中,旧 Access Token 最迟约 1 小时失效。";
29450
29492
  if (name === "arkme_user_unban") return "是否确认解封这个私聊用户?确认后该用户可重新登录并恢复操作。";
@@ -29495,6 +29537,7 @@ function withCoreConversationalConfirmation(definition, conversation) {
29495
29537
  const violations = validateJsonSchemaValue(definition.parameters, args, "");
29496
29538
  if (violations.length > 0) throw new ToolArgsError(violations);
29497
29539
  if (definition.name === "arkme_recording_import" && typeof args === "object" && args !== null && "action" in args && args.action === "status") return await definition.execute(args, exec);
29540
+ if (definition.name === "arkme_topic_home_visibility" && args.show_in_home === void 0) return await definition.execute(args, exec);
29498
29541
  if (exec.agent === void 0) throw new Error("该 Arkme 操作必须在一个真实 DSH Agent 会话中执行");
29499
29542
  const hooks = arkmeConfirmationContextHooks(definition);
29500
29543
  const request = hooks?.confirmationRequest?.(args);
@@ -31141,7 +31184,7 @@ function createDefaultDshRemoteSocket(input) {
31141
31184
  if (accessToken === "") throw new TypeError("DSH remote Realtime access token is required");
31142
31185
  if (input.signal.aborted) throw input.signal.reason;
31143
31186
  const diagnosticRequestId = randomUUID();
31144
- const socket = new WebSocket(dshRemoteRealtimeEndpoint(input.realtimeBaseUrl), {
31187
+ const socket = new WebSocket$1(dshRemoteRealtimeEndpoint(input.realtimeBaseUrl), {
31145
31188
  headers: {
31146
31189
  Authorization: `Bearer ${accessToken}`,
31147
31190
  "X-Request-ID": diagnosticRequestId
@@ -36340,8 +36383,7 @@ function apply(ctx, config) {
36340
36383
  handler: extensionPreviewReadHandler
36341
36384
  }), "dsh-arkme: extension preview read route");
36342
36385
  ctx.effect(() => {
36343
- const disposeRoute = ctx.webServer.register({
36344
- kind: "exact",
36386
+ const disposeRoute = ctx.webServer.registerUpgrade({
36345
36387
  path: `${config.routePath}/events`,
36346
36388
  handler: realtimeEvents.handler
36347
36389
  });
@@ -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-YkrM3K7s.js";
1
+ import { a as persistentArkmeExtensionActive, i as invokePersistentArkmeExtension, n as applyPersistentArkmeHostExtension, o as persistentArkmeExtensionRuntimeState, r as deactivatePersistentArkmeExtension, t as activatePersistentArkmeExtension } from "./persistent-runtime-BRy2sNmS.js";
2
2
  export { activatePersistentArkmeExtension, applyPersistentArkmeHostExtension, deactivatePersistentArkmeExtension, invokePersistentArkmeExtension, persistentArkmeExtensionActive, persistentArkmeExtensionRuntimeState };