@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.
- package/docs/dsh-input-system-topic.md +26 -0
- package/lib/client.js +4430 -3115
- package/lib/client.js.map +1 -1
- package/lib/extension-profile-restart-helper.js +10 -6
- package/lib/harness-model-client.js +8 -0
- package/lib/index.js +99 -57
- package/lib/persistent-extension.js +1 -1
- package/lib/{persistent-runtime-YkrM3K7s.js → persistent-runtime-BRy2sNmS.js} +312 -81
- package/lib/{plugin-updater-helper-B0yVav4f.js → plugin-updater-helper-n8JrMPum.js} +1 -1
- package/lib/{plugin-updater-helper-BbjKUV9T.js → plugin-updater-helper-y7wzJLOx.js} +11 -4
- package/lib/plugin-updater-helper.js +1 -1
- package/lib/sdk.js +8 -0
- package/lib/types/arkme-service.d.ts +3 -0
- package/lib/types/arkme-service.d.ts.map +1 -1
- package/lib/types/call-record-presentation.d.ts +2 -0
- package/lib/types/call-record-presentation.d.ts.map +1 -1
- package/lib/types/client/ArkmeArkoSurface.d.ts.map +1 -1
- package/lib/types/client/ArkmeBotConversationSurface.d.ts.map +1 -1
- package/lib/types/client/ArkmeBotCreateDialog.d.ts.map +1 -1
- package/lib/types/client/ArkmeCallDetailContent.d.ts +13 -0
- package/lib/types/client/ArkmeCallDetailContent.d.ts.map +1 -0
- package/lib/types/client/ArkmeCallDetailDrawer.d.ts +2 -1
- package/lib/types/client/ArkmeCallDetailDrawer.d.ts.map +1 -1
- package/lib/types/client/ArkmeCallRecordContent.d.ts +4 -2
- package/lib/types/client/ArkmeCallRecordContent.d.ts.map +1 -1
- package/lib/types/client/ArkmeCallSurface.d.ts.map +1 -1
- package/lib/types/client/ArkmeComposerSendButton.d.ts +10 -0
- package/lib/types/client/ArkmeComposerSendButton.d.ts.map +1 -0
- package/lib/types/client/ArkmeDshAgentInputMarker.d.ts +1 -1
- package/lib/types/client/ArkmeDshAgentInputMarker.d.ts.map +1 -1
- package/lib/types/client/ArkmeLinkText.d.ts +1 -1
- package/lib/types/client/ArkmeLinkText.d.ts.map +1 -1
- package/lib/types/client/ArkmeLogin.d.ts.map +1 -1
- package/lib/types/client/ArkmeMarketplace.d.ts +1 -0
- package/lib/types/client/ArkmeMarketplace.d.ts.map +1 -1
- package/lib/types/client/ArkmeMentionSuggestionRow.d.ts +20 -0
- package/lib/types/client/ArkmeMentionSuggestionRow.d.ts.map +1 -0
- package/lib/types/client/ArkmeMessageActions.d.ts.map +1 -1
- package/lib/types/client/ArkmeNoteDetails.d.ts +6 -2
- package/lib/types/client/ArkmeNoteDetails.d.ts.map +1 -1
- package/lib/types/client/ArkmeOfficialAuthorGuide.d.ts +7 -0
- package/lib/types/client/ArkmeOfficialAuthorGuide.d.ts.map +1 -0
- package/lib/types/client/ArkmePersistentShell.d.ts +1 -1
- package/lib/types/client/ArkmePersistentShell.d.ts.map +1 -1
- package/lib/types/client/ArkmeRichContent.d.ts +2 -1
- package/lib/types/client/ArkmeRichContent.d.ts.map +1 -1
- package/lib/types/client/ArkmeRichText.d.ts +9 -5
- package/lib/types/client/ArkmeRichText.d.ts.map +1 -1
- package/lib/types/client/ArkmeScanGuide.d.ts +5 -0
- package/lib/types/client/ArkmeScanGuide.d.ts.map +1 -0
- package/lib/types/client/ArkmeSidebar.d.ts +3 -35
- package/lib/types/client/ArkmeSidebar.d.ts.map +1 -1
- package/lib/types/client/ArkmeSourceBreadcrumb.d.ts.map +1 -1
- package/lib/types/client/ArkmeTopicDirectoryPopover.d.ts +2 -1
- package/lib/types/client/ArkmeTopicDirectoryPopover.d.ts.map +1 -1
- package/lib/types/client/ArkmeTopicReadOnlyNotice.d.ts +3 -0
- package/lib/types/client/ArkmeTopicReadOnlyNotice.d.ts.map +1 -0
- package/lib/types/client/ArkmeVirtualWorkspace.d.ts +13 -7
- package/lib/types/client/ArkmeVirtualWorkspace.d.ts.map +1 -1
- package/lib/types/client/api.d.ts +1 -1
- package/lib/types/client/api.d.ts.map +1 -1
- package/lib/types/client/arkme-login-locales.d.ts +13 -0
- package/lib/types/client/arkme-login-locales.d.ts.map +1 -1
- package/lib/types/client/call-detail-presentation.d.ts +13 -0
- package/lib/types/client/call-detail-presentation.d.ts.map +1 -0
- package/lib/types/client/chat-directory-store.d.ts.map +1 -1
- package/lib/types/client/composer-draft-store.d.ts +7 -0
- package/lib/types/client/composer-draft-store.d.ts.map +1 -1
- package/lib/types/client/conversation-composer-presentation.d.ts +3 -0
- package/lib/types/client/conversation-composer-presentation.d.ts.map +1 -1
- package/lib/types/client/conversation-resize-anchor.d.ts +1 -1
- package/lib/types/client/conversation-resize-anchor.d.ts.map +1 -1
- package/lib/types/client/index.d.ts +2 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/mention-candidates.d.ts +46 -0
- package/lib/types/client/mention-candidates.d.ts.map +1 -0
- package/lib/types/client/navigation-cache.d.ts.map +1 -1
- package/lib/types/client/read-deadline.d.ts +3 -0
- package/lib/types/client/read-deadline.d.ts.map +1 -0
- package/lib/types/client/realtime-client-events.d.ts.map +1 -1
- package/lib/types/client/realtime-connection.d.ts +9 -0
- package/lib/types/client/realtime-connection.d.ts.map +1 -0
- package/lib/types/client/recordings/RecordingTranscriptForward.d.ts.map +1 -1
- package/lib/types/client/scan-guide-icons.d.ts +7 -0
- package/lib/types/client/scan-guide-icons.d.ts.map +1 -0
- package/lib/types/client/scan-guide-styles.d.ts +2 -0
- package/lib/types/client/scan-guide-styles.d.ts.map +1 -0
- package/lib/types/client/slots-contract.d.ts +23 -0
- package/lib/types/client/slots-contract.d.ts.map +1 -1
- package/lib/types/client/source-tree.d.ts.map +1 -1
- package/lib/types/client/use-call-record-preview.d.ts +8 -0
- package/lib/types/client/use-call-record-preview.d.ts.map +1 -0
- package/lib/types/client/use-call-transcript-playback.d.ts +13 -0
- package/lib/types/client/use-call-transcript-playback.d.ts.map +1 -0
- package/lib/types/dsh-agent-input-source.d.ts +0 -1
- package/lib/types/dsh-agent-input-source.d.ts.map +1 -1
- package/lib/types/extensions/profile-restart-helper.d.ts.map +1 -1
- package/lib/types/host-api.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/plugin-updater-helper.d.ts.map +1 -1
- package/lib/types/realtime-events.d.ts +9 -5
- package/lib/types/realtime-events.d.ts.map +1 -1
- package/lib/types/sdk/index.d.ts +4 -0
- package/lib/types/sdk/index.d.ts.map +1 -1
- package/lib/types/services/bot-conversation-service.d.ts.map +1 -1
- package/lib/types/services/bot-service.d.ts.map +1 -1
- package/lib/types/services/call-history-service.d.ts +3 -1
- package/lib/types/services/call-history-service.d.ts.map +1 -1
- package/lib/types/services/chat-service.d.ts +1 -0
- package/lib/types/services/chat-service.d.ts.map +1 -1
- package/lib/types/services/media-service.d.ts.map +1 -1
- package/lib/types/services/search-service.d.ts.map +1 -1
- package/lib/types/services/source-service.d.ts +4 -0
- package/lib/types/services/source-service.d.ts.map +1 -1
- package/lib/types/services/topic-metadata.d.ts +10 -0
- package/lib/types/services/topic-metadata.d.ts.map +1 -0
- package/lib/types/services/topic-record-page.d.ts +18 -0
- package/lib/types/services/topic-record-page.d.ts.map +1 -0
- package/lib/types/tools/business/conversation/index.d.ts.map +1 -1
- package/lib/types/tools/business/conversation/topic-home-visibility.d.ts +2 -0
- package/lib/types/tools/business/conversation/topic-home-visibility.d.ts.map +1 -0
- package/lib/types/tools/business/index.d.ts.map +1 -1
- package/lib/types/tools/ports/bots.d.ts +1 -0
- package/lib/types/tools/ports/bots.d.ts.map +1 -1
- package/lib/types/tools/ports/conversations.d.ts +3 -0
- package/lib/types/tools/ports/conversations.d.ts.map +1 -1
- package/lib/types/tools/registry/registrar.d.ts.map +1 -1
- package/lib/types/topic-policy.d.ts +9 -0
- package/lib/types/topic-policy.d.ts.map +1 -0
- package/lib/types/types.d.ts +22 -1
- package/lib/types/types.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -15558,6 +15558,48 @@ async function patchChatPolicy(runtime, session, chatSessionUid, patch, signal)
|
|
|
15558
15558
|
return updated;
|
|
15559
15559
|
}
|
|
15560
15560
|
//#endregion
|
|
15561
|
+
//#region src/services/topic-record-page.ts
|
|
15562
|
+
/** Transport contract shared by timeline reading and complete pre-dissolution enumeration.
|
|
15563
|
+
* Privacy visibility and mutation policy remain in their respective business owners.
|
|
15564
|
+
*/
|
|
15565
|
+
async function readTopicRecordPage(runtime, session, topicUid, options) {
|
|
15566
|
+
const data = await runtime.authenticatedPost("/api/v1/topics/display/records/page", {
|
|
15567
|
+
topic_uid: topicUid,
|
|
15568
|
+
limit: options.limit,
|
|
15569
|
+
...options.cursor === void 0 ? {} : {
|
|
15570
|
+
cursor_send_at: options.cursor.sendAtMillis,
|
|
15571
|
+
cursor_record_uid: options.cursor.itemUid
|
|
15572
|
+
}
|
|
15573
|
+
}, session, options.signal);
|
|
15574
|
+
const sendAt = data.next_cursor_send_at;
|
|
15575
|
+
const uid = stringValue$2(data.next_cursor_record_uid).trim();
|
|
15576
|
+
const hasCursor = typeof sendAt === "number" && Number.isSafeInteger(sendAt) && sendAt > 0 && uid !== "";
|
|
15577
|
+
if (data.topic_uid !== topicUid || !Array.isArray(data.records) || typeof data.has_more !== "boolean" || data.privacy_state !== 1 && data.privacy_state !== 2 || data.has_more && !hasCursor || data.records.some((raw) => stringValue$2(objectValue$2(raw).record_uid).trim() === "")) throw new ArkmePluginError("topic-record-page-invalid", "主题快记返回不完整,请重试或确认服务端已升级", true, 502);
|
|
15578
|
+
if (data.has_more && options.cursor !== void 0 && sendAt === options.cursor.sendAtMillis && uid === options.cursor.itemUid) throw new ArkmePluginError("topic-record-page-invalid", "主题快记分页未推进,请重试", true, 502);
|
|
15579
|
+
return {
|
|
15580
|
+
records: data.records,
|
|
15581
|
+
privacyState: data.privacy_state,
|
|
15582
|
+
hasMore: data.has_more,
|
|
15583
|
+
...hasCursor ? { nextCursor: {
|
|
15584
|
+
sendAtMillis: sendAt,
|
|
15585
|
+
itemUid: uid
|
|
15586
|
+
} } : {}
|
|
15587
|
+
};
|
|
15588
|
+
}
|
|
15589
|
+
//#endregion
|
|
15590
|
+
//#region src/services/topic-metadata.ts
|
|
15591
|
+
/** Lightweight topic identity/settings contract. It never loads records or summary statistics. */
|
|
15592
|
+
async function readTopicMetadata(runtime, session, topicUid, signal) {
|
|
15593
|
+
const core = objectValue$2((await runtime.authenticatedPost("/api/v1/topics/display/metadata", { topic_uid: topicUid }, session, signal)).topic_core);
|
|
15594
|
+
const topicKind = typeof core.kind === "number" ? core.kind : 0;
|
|
15595
|
+
if (stringValue$2(core.topic_uid).trim() !== topicUid || !Number.isSafeInteger(topicKind) || topicKind <= 0 || core.privacy_state !== 1 && core.privacy_state !== 2 || typeof core.show_in_home !== "boolean") throw new ArkmePluginError("topic-metadata-invalid", "主题信息返回不完整,请重试或确认服务端已升级", true, 502);
|
|
15596
|
+
return {
|
|
15597
|
+
topicKind,
|
|
15598
|
+
privacyState: core.privacy_state,
|
|
15599
|
+
showInHome: core.show_in_home
|
|
15600
|
+
};
|
|
15601
|
+
}
|
|
15602
|
+
//#endregion
|
|
15561
15603
|
//#region node_modules/bail/index.js
|
|
15562
15604
|
/**
|
|
15563
15605
|
* Throw a given error.
|
|
@@ -35063,6 +35105,17 @@ function arkmeEmojiPlainText(value) {
|
|
|
35063
35105
|
if (value === "" || !value.includes("_emoji:")) return value;
|
|
35064
35106
|
return arkmeEmojiTextRuns(value).map((run) => run.kind === "emoji" ? run.emoji.unicode : run.text).join("");
|
|
35065
35107
|
}
|
|
35108
|
+
const ARKME_DSH_INPUT_TOPIC_TITLE = "发给 DSH 的消息";
|
|
35109
|
+
/** Display only; source identities and stored titles remain unchanged. */
|
|
35110
|
+
function arkmeTopicDisplayName(title, topicKind) {
|
|
35111
|
+
return topicKind === 3 ? ARKME_DSH_INPUT_TOPIC_TITLE : title;
|
|
35112
|
+
}
|
|
35113
|
+
function isArkmeDSHInputTopic(source) {
|
|
35114
|
+
return source?.kind === "topic" && source.topicKind === 3;
|
|
35115
|
+
}
|
|
35116
|
+
function arkmeSourceAllowsUserWrite(source) {
|
|
35117
|
+
return !isArkmeDSHInputTopic(source);
|
|
35118
|
+
}
|
|
35066
35119
|
//#endregion
|
|
35067
35120
|
//#region src/services/source-service.ts
|
|
35068
35121
|
const SOURCE_LIST_CACHE_TTL_MS = 3e4;
|
|
@@ -35674,6 +35727,20 @@ var SourceService = class {
|
|
|
35674
35727
|
displayName: title
|
|
35675
35728
|
};
|
|
35676
35729
|
}
|
|
35730
|
+
/** Reuse the record owner's topic policy, without replaying title/privacy defaults. */
|
|
35731
|
+
async topicHomeVisibility(sourceRef, showInHome, signal) {
|
|
35732
|
+
const session = await this.runtime.requireSession();
|
|
35733
|
+
const topic = await this.openSourceRef(sourceRef, session.userId);
|
|
35734
|
+
if (topic.kind !== "topic") throw new ArkmePluginError("topic-policy-invalid", "请选择主题", false);
|
|
35735
|
+
if (showInHome === void 0) return { showInHome: (await readTopicMetadata(this.runtime, session, topic.ownerRef, signal)).showInHome };
|
|
35736
|
+
const value = (await this.runtime.authenticatedPost("/api/v1/topics/display/policy/set", {
|
|
35737
|
+
topic_uid: topic.ownerRef,
|
|
35738
|
+
show_in_home: showInHome
|
|
35739
|
+
}, session, void 0)).show_in_home;
|
|
35740
|
+
if (typeof value !== "boolean") throw new ArkmePluginError("topic-policy-contract-invalid", "主题设置响应不完整,请重试", true, 502);
|
|
35741
|
+
this.invalidateSourceListCache(session.userId, "send_to_self");
|
|
35742
|
+
return { showInHome: value };
|
|
35743
|
+
}
|
|
35677
35744
|
/**
|
|
35678
35745
|
* Dissolving a topic promotes its direct children and moves the topic's own
|
|
35679
35746
|
* records into its parent. Root-topic records return to the default category.
|
|
@@ -35772,21 +35839,18 @@ var SourceService = class {
|
|
|
35772
35839
|
let cursorSendAt;
|
|
35773
35840
|
let cursorRecordUid;
|
|
35774
35841
|
for (let pageIndex = 0; pageIndex < 1e3; pageIndex += 1) {
|
|
35775
|
-
const
|
|
35776
|
-
topic_uid: topicUid,
|
|
35842
|
+
const page = await readTopicRecordPage(this.runtime, session, topicUid, {
|
|
35777
35843
|
limit: 100,
|
|
35778
|
-
...cursorSendAt === void 0 ? {} : {
|
|
35779
|
-
|
|
35780
|
-
|
|
35781
|
-
|
|
35782
|
-
|
|
35783
|
-
|
|
35784
|
-
if (uid !== "") recordUids.add(uid);
|
|
35785
|
-
}
|
|
35844
|
+
...cursorSendAt === void 0 || cursorRecordUid === void 0 ? {} : { cursor: {
|
|
35845
|
+
sendAtMillis: cursorSendAt,
|
|
35846
|
+
itemUid: cursorRecordUid
|
|
35847
|
+
} }
|
|
35848
|
+
});
|
|
35849
|
+
for (const raw of page.records) recordUids.add(stringValue$2(objectValue$2(raw).record_uid).trim());
|
|
35786
35850
|
onProgress?.(recordUids.size);
|
|
35787
|
-
if (
|
|
35788
|
-
const nextSendAt =
|
|
35789
|
-
const nextRecordUid =
|
|
35851
|
+
if (!page.hasMore) return [...recordUids];
|
|
35852
|
+
const nextSendAt = page.nextCursor?.sendAtMillis ?? 0;
|
|
35853
|
+
const nextRecordUid = page.nextCursor?.itemUid ?? "";
|
|
35790
35854
|
const cursorKey = `${String(nextSendAt)}:${nextRecordUid}`;
|
|
35791
35855
|
if (nextSendAt <= 0 || nextRecordUid === "" || seenCursors.has(cursorKey)) throw new ArkmePluginError("topic-dissolve-record-page-invalid", "主题快记加载不完整,未解散主题,请刷新后重试", true, 502);
|
|
35792
35856
|
seenCursors.add(cursorKey);
|
|
@@ -35924,6 +35988,11 @@ var SourceService = class {
|
|
|
35924
35988
|
const entry = objectValue$2(raw);
|
|
35925
35989
|
const core = objectValue$2(entry.topic_core);
|
|
35926
35990
|
if (arkmePrivacyLockedTopic(entry) || core.status !== 1) continue;
|
|
35991
|
+
const topicKind = numberValue$26(core.kind) || 1;
|
|
35992
|
+
if (!arkmeSourceAllowsUserWrite({
|
|
35993
|
+
kind: "topic",
|
|
35994
|
+
topicKind
|
|
35995
|
+
})) continue;
|
|
35927
35996
|
const topicUid = stringValue$2(core.topic_uid).trim();
|
|
35928
35997
|
const title = stringValue$2(core.title).trim();
|
|
35929
35998
|
if (!topicUid || !title || seen.has(topicUid)) continue;
|
|
@@ -35931,6 +36000,7 @@ var SourceService = class {
|
|
|
35931
36000
|
const recordCount = objectValue$2(entry.summary).record_count;
|
|
35932
36001
|
items.push({
|
|
35933
36002
|
kind: "topic",
|
|
36003
|
+
topicKind,
|
|
35934
36004
|
displayName: title,
|
|
35935
36005
|
activeAtMillis: numberValue$26(core.update_at),
|
|
35936
36006
|
unreadCount: 0,
|
|
@@ -36121,6 +36191,7 @@ var SourceService = class {
|
|
|
36121
36191
|
const parentTopicUid = stringValue$2(parentTopicUidByChild.get(topicUid) ?? core.parent_topic_uid ?? core.parent_uid ?? item.parent_topic_uid ?? item.parent_uid ?? parent.topic_uid ?? parent.uid).trim();
|
|
36122
36192
|
topicDescriptors.push({
|
|
36123
36193
|
topicUid,
|
|
36194
|
+
topicKind: numberValue$26(core.kind) || 1,
|
|
36124
36195
|
...parentTopicUid === "" || parentTopicUid === topicUid ? {} : { parentTopicUid },
|
|
36125
36196
|
siblingOrder: numberValue$26(siblingOrderByChild.get(topicUid) ?? core.sibling_order ?? item.sibling_order),
|
|
36126
36197
|
title,
|
|
@@ -36147,7 +36218,8 @@ var SourceService = class {
|
|
|
36147
36218
|
...parentTopicHierarchyKey === void 0 ? {} : { parentTopicHierarchyKey },
|
|
36148
36219
|
...topic.siblingOrder > 0 ? { siblingOrder: topic.siblingOrder } : {},
|
|
36149
36220
|
kind: "topic",
|
|
36150
|
-
|
|
36221
|
+
topicKind: topic.topicKind,
|
|
36222
|
+
displayName: arkmeTopicDisplayName(topic.title, topic.topicKind),
|
|
36151
36223
|
...topic.latestPreview === "" ? {} : { latestPreview: topic.latestPreview },
|
|
36152
36224
|
activeAtMillis: topic.activeAtMillis,
|
|
36153
36225
|
unreadCount: 0,
|
|
@@ -36665,7 +36737,7 @@ function botConversationCapabilities(target, provider) {
|
|
|
36665
36737
|
const owner = target.kind === "subject" ? BOT_CONVERSATION_OWNER.subject : target.kind === "chat" ? BOT_CONVERSATION_OWNER.chat : void 0;
|
|
36666
36738
|
return {
|
|
36667
36739
|
directChatAvailable: owner !== void 0,
|
|
36668
|
-
privateChatOutboundEnabled: owner
|
|
36740
|
+
privateChatOutboundEnabled: owner !== void 0 && provider === "openclaw",
|
|
36669
36741
|
refreshOnRecordChanges: owner === BOT_CONVERSATION_OWNER.subject,
|
|
36670
36742
|
conversationProjection: owner === BOT_CONVERSATION_OWNER.subject ? "record" : owner === BOT_CONVERSATION_OWNER.chat ? "chat" : "none"
|
|
36671
36743
|
};
|
|
@@ -36754,10 +36826,18 @@ var BotService = class {
|
|
|
36754
36826
|
name,
|
|
36755
36827
|
provider,
|
|
36756
36828
|
description,
|
|
36757
|
-
avatar
|
|
36829
|
+
avatar,
|
|
36830
|
+
direct_chat_owner: BOT_CONVERSATION_OWNER.chat,
|
|
36831
|
+
request_uid: input.requestUid?.trim() || randomUUID()
|
|
36758
36832
|
}, session, options.signal);
|
|
36759
36833
|
} catch (error) {
|
|
36760
|
-
if (error instanceof ArkmePluginError && [
|
|
36834
|
+
if (error instanceof ArkmePluginError && ([
|
|
36835
|
+
"arkme-network-error",
|
|
36836
|
+
"arkme-timeout",
|
|
36837
|
+
"arkme-response-invalid",
|
|
36838
|
+
"arkme-code-1002"
|
|
36839
|
+
].includes(error.code) || error.code === "arkme-http-error" && error.retryable)) throw new ArkmePluginError("bot-create-outcome-unknown", "Bot 创建结果未知,请刷新 Bot 列表确认;不会自动重试", false, 409, { cause: error });
|
|
36840
|
+
if (error instanceof ArkmePluginError && error.code === "arkme-code-1001") throw new ArkmePluginError(error.code, error.message, false, 400, { cause: error });
|
|
36761
36841
|
throw error;
|
|
36762
36842
|
}
|
|
36763
36843
|
try {
|
|
@@ -37105,6 +37185,7 @@ var BotService = class {
|
|
|
37105
37185
|
const signature = createHmac("sha256", secret).update(`bot-directory-entry-v1:${userId}:${payload}`).digest("base64url");
|
|
37106
37186
|
return [{
|
|
37107
37187
|
...bot,
|
|
37188
|
+
privateChatOutboundEnabled: bot.directChatAvailable && bot.provider === "openclaw",
|
|
37108
37189
|
botRef: `arkme-bot-directory-entry-v1.${payload}.${signature}`
|
|
37109
37190
|
}];
|
|
37110
37191
|
});
|
|
@@ -37263,7 +37344,6 @@ var SubjectBotConversationAdapter = class {
|
|
|
37263
37344
|
async send(context, contentInput, signal) {
|
|
37264
37345
|
this.subjectTarget(context);
|
|
37265
37346
|
const content = contentInput.trim();
|
|
37266
|
-
if (context.reference.provider === "webhook") throw new ArkmePluginError("bot-conversation-send-unsupported", "Webhook Bot 仅接收外部系统推送", false, 400);
|
|
37267
37347
|
if (content === "" || content.length > this.runtime.config.maxTextLength) throw new ArkmePluginError("bot-conversation-content-invalid", "Bot 消息为空或超过长度限制", false, 400);
|
|
37268
37348
|
let data;
|
|
37269
37349
|
try {
|
|
@@ -37416,6 +37496,7 @@ var BotConversationService = class {
|
|
|
37416
37496
|
}
|
|
37417
37497
|
async send(botRef, content, options = {}) {
|
|
37418
37498
|
const context = await this.context(botRef);
|
|
37499
|
+
if (context.reference.provider === "webhook") throw new ArkmePluginError("bot-conversation-send-unsupported", "Webhook Bot 仅接收外部系统推送", false, 400);
|
|
37419
37500
|
const result = await this.adapter(context).send(context, content, options.signal);
|
|
37420
37501
|
if (context.reference.target.kind === "subject") await this.invalidateRecordProjection();
|
|
37421
37502
|
return result;
|
|
@@ -37644,6 +37725,44 @@ function object(value) {
|
|
|
37644
37725
|
function first(source, keys) {
|
|
37645
37726
|
return keys.map((key) => source[key]).find((value) => value !== void 0 && value !== null && value !== "");
|
|
37646
37727
|
}
|
|
37728
|
+
/** Flutter-compatible summary templates, resolved on the host before projection. */
|
|
37729
|
+
function renderCallRecordSummary(source, viewerUserId, displayNames = /* @__PURE__ */ new Map()) {
|
|
37730
|
+
const fallback = String(first(source, [
|
|
37731
|
+
"sm",
|
|
37732
|
+
"call_summary",
|
|
37733
|
+
"callSummary",
|
|
37734
|
+
"summary_text",
|
|
37735
|
+
"summaryText",
|
|
37736
|
+
"summary"
|
|
37737
|
+
]) ?? "").trim();
|
|
37738
|
+
const template = String(first(source, [
|
|
37739
|
+
"smt",
|
|
37740
|
+
"call_summary_template",
|
|
37741
|
+
"callSummaryTemplate",
|
|
37742
|
+
"summary_template",
|
|
37743
|
+
"summaryTemplate"
|
|
37744
|
+
]) ?? "").trim();
|
|
37745
|
+
const labels = object(first(source, [
|
|
37746
|
+
"ssl",
|
|
37747
|
+
"summary_speaker_labels",
|
|
37748
|
+
"call_summary_speaker_labels"
|
|
37749
|
+
]));
|
|
37750
|
+
const users = object(first(source, [
|
|
37751
|
+
"ssu",
|
|
37752
|
+
"summary_speaker_user_ids",
|
|
37753
|
+
"call_summary_speaker_user_ids"
|
|
37754
|
+
]));
|
|
37755
|
+
const rendered = template.replace(/\{\{(user|speaker):([^{}]+)\}\}/g, (token, kind, key) => {
|
|
37756
|
+
const userId = Number(kind === "user" ? key : users[token] ?? users[key]);
|
|
37757
|
+
if (userId > 0 && userId === viewerUserId) return "我";
|
|
37758
|
+
const name = displayNames.get(userId);
|
|
37759
|
+
if (name?.trim()) return name.trim();
|
|
37760
|
+
const label = kind === "speaker" ? labels[token] ?? labels[key] : void 0;
|
|
37761
|
+
return typeof label === "string" && label.trim() ? label.trim() : token;
|
|
37762
|
+
});
|
|
37763
|
+
const text = rendered && !rendered.includes("{{") ? rendered : fallback;
|
|
37764
|
+
return text.includes("{{") ? "" : text;
|
|
37765
|
+
}
|
|
37647
37766
|
function callRecordCandidates(raw) {
|
|
37648
37767
|
const root = object(raw);
|
|
37649
37768
|
const record = object(root.record);
|
|
@@ -37777,9 +37896,27 @@ function projectCallRecord(raw, viewerUserId) {
|
|
|
37777
37896
|
text = isCaller ? "对方离线" : "未接听(离线)";
|
|
37778
37897
|
break;
|
|
37779
37898
|
}
|
|
37899
|
+
const summary = renderCallRecordSummary(source, viewerUserId);
|
|
37900
|
+
const rawStatus = String(first(source, [
|
|
37901
|
+
"ss",
|
|
37902
|
+
"call_summary_status",
|
|
37903
|
+
"summary_status",
|
|
37904
|
+
"summaryStatus"
|
|
37905
|
+
]) ?? "").toLowerCase();
|
|
37906
|
+
const summaryStatus = [
|
|
37907
|
+
"pending",
|
|
37908
|
+
"processing",
|
|
37909
|
+
"generating"
|
|
37910
|
+
].includes(rawStatus) ? "pending" : [
|
|
37911
|
+
"done",
|
|
37912
|
+
"success",
|
|
37913
|
+
"finished"
|
|
37914
|
+
].includes(rawStatus) ? "done" : ["failed", "error"].includes(rawStatus) ? "failed" : void 0;
|
|
37780
37915
|
return {
|
|
37781
37916
|
mediaType,
|
|
37782
|
-
text
|
|
37917
|
+
text,
|
|
37918
|
+
...summary && !summary.includes("{{") ? { summaryText: summary } : {},
|
|
37919
|
+
...summaryStatus ? { summaryStatus } : {}
|
|
37783
37920
|
};
|
|
37784
37921
|
}
|
|
37785
37922
|
//#endregion
|
|
@@ -38130,9 +38267,11 @@ function decodeJson(value) {
|
|
|
38130
38267
|
var CallHistoryService = class {
|
|
38131
38268
|
runtime;
|
|
38132
38269
|
profile;
|
|
38133
|
-
|
|
38270
|
+
media;
|
|
38271
|
+
constructor(runtime, profile, media) {
|
|
38134
38272
|
this.runtime = runtime;
|
|
38135
38273
|
this.profile = profile;
|
|
38274
|
+
this.media = media;
|
|
38136
38275
|
}
|
|
38137
38276
|
async listCallHistory(options = {}, signal) {
|
|
38138
38277
|
const session = await this.runtime.requireSession();
|
|
@@ -38475,13 +38614,6 @@ var CallHistoryService = class {
|
|
|
38475
38614
|
"callResult",
|
|
38476
38615
|
"result"
|
|
38477
38616
|
]);
|
|
38478
|
-
const summaryText = safeSummary(firstString$1(raw, [
|
|
38479
|
-
"call_summary",
|
|
38480
|
-
"callSummary",
|
|
38481
|
-
"summary_text",
|
|
38482
|
-
"summaryText",
|
|
38483
|
-
"summary"
|
|
38484
|
-
]));
|
|
38485
38617
|
const summaryUpdatedAtMillis = firstEpochMillis(raw, [
|
|
38486
38618
|
"call_summary_updated_at",
|
|
38487
38619
|
"callSummaryUpdatedAt",
|
|
@@ -38495,7 +38627,7 @@ var CallHistoryService = class {
|
|
|
38495
38627
|
"mediaType"
|
|
38496
38628
|
]));
|
|
38497
38629
|
const videoRecord = callVideoRecord(raw, mediaType, session.userId);
|
|
38498
|
-
const transcriptSegments = this.transcriptSegments(raw, startedAtMillis).slice(0, 200);
|
|
38630
|
+
const transcriptSegments = this.transcriptSegments(raw, startedAtMillis, session.userId).slice(0, 200);
|
|
38499
38631
|
const hangupUserId = callResult.toLowerCase().replace(/[_\s-]/g, "") === "normalend" ? listValue$19(raw.member_actions).map(objectValue$2).reverse().find((action) => firstString$1(action, ["action"]).toLowerCase() === "hangup" && firstNumber(action, ["user_id"]) > 0)?.user_id : void 0;
|
|
38500
38632
|
const participantSeeds = this.participants(raw, session.userId);
|
|
38501
38633
|
const userIds = [
|
|
@@ -38511,6 +38643,7 @@ var CallHistoryService = class {
|
|
|
38511
38643
|
...userId === session.userId ? { isCurrentUser: true } : {}
|
|
38512
38644
|
});
|
|
38513
38645
|
const participants = await this.attachParticipantAvatars(participantSeeds.slice(0, 50), session, signal);
|
|
38646
|
+
const summaryText = safeSummary(renderCallRecordSummary(raw, session.userId, new Map(participants.flatMap((participant) => participant.userId ? [[participant.userId, participant.displayName]] : []))));
|
|
38514
38647
|
const hangupParticipant = participants.find((participant) => participant.userId === numberValue$22(hangupUserId));
|
|
38515
38648
|
return {
|
|
38516
38649
|
callRef: await this.sealCallRef({
|
|
@@ -38591,7 +38724,7 @@ var CallHistoryService = class {
|
|
|
38591
38724
|
};
|
|
38592
38725
|
}).filter((item) => item !== void 0).slice(0, 50);
|
|
38593
38726
|
}
|
|
38594
|
-
transcriptSegments(raw, startedAtMillis) {
|
|
38727
|
+
transcriptSegments(raw, startedAtMillis, viewerUserId) {
|
|
38595
38728
|
return listValue$19(firstValue(raw, [
|
|
38596
38729
|
"segments",
|
|
38597
38730
|
"transcript_segments",
|
|
@@ -38609,6 +38742,13 @@ var CallHistoryService = class {
|
|
|
38609
38742
|
"segmentId",
|
|
38610
38743
|
"id"
|
|
38611
38744
|
]) || `segment-${String(index + 1)}`;
|
|
38745
|
+
const remoteAudioUrl = firstString$1(rawItem, ["audio_url", "audioUrl"]);
|
|
38746
|
+
const audioBlock = remoteAudioUrl ? this.media?.forwardContentBlocks([{
|
|
38747
|
+
type: 2,
|
|
38748
|
+
name: "通话片段",
|
|
38749
|
+
download_url: remoteAudioUrl
|
|
38750
|
+
}], viewerUserId).find((block) => block.kind === "audio") : void 0;
|
|
38751
|
+
const audioUrl = audioBlock ? `${this.runtime.config.routePath}/media?ref=${encodeURIComponent(audioBlock.mediaRef)}` : void 0;
|
|
38612
38752
|
const speakerUserId = Math.trunc(firstNumber(rawItem, [
|
|
38613
38753
|
"speaker_user_id",
|
|
38614
38754
|
"speakerUserId",
|
|
@@ -38633,6 +38773,7 @@ var CallHistoryService = class {
|
|
|
38633
38773
|
const absoluteEnd = end >= 1e11;
|
|
38634
38774
|
return {
|
|
38635
38775
|
segmentId,
|
|
38776
|
+
...audioUrl ? { audioUrl } : {},
|
|
38636
38777
|
speakerDisplayName: firstString$1(rawItem, [
|
|
38637
38778
|
"speaker_display_name",
|
|
38638
38779
|
"speakerDisplayName",
|
|
@@ -42681,6 +42822,8 @@ function arkmeRichContentPayload(input, normalizedTextContent, mentionPayload) {
|
|
|
42681
42822
|
}
|
|
42682
42823
|
const OFFICIAL_AUTHOR_USER_ID = 11;
|
|
42683
42824
|
const OFFICIAL_AUTHOR_FALLBACK_DISPLAY_NAME = "即我作者";
|
|
42825
|
+
const RESERVED_ASEN_BOT_UID = "asen";
|
|
42826
|
+
const RESERVED_ASEN_DISPLAY_NAME = "阿森";
|
|
42684
42827
|
const MAX_MESSAGE_COPY_LINK_ITEMS = 100;
|
|
42685
42828
|
const RECORD_UID_PATTERN$1 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
42686
42829
|
const CHAT_MEMBER_REF_PREFIX = "arkme-chat-member-v1";
|
|
@@ -43738,7 +43881,7 @@ var ChatService = class {
|
|
|
43738
43881
|
callHistory;
|
|
43739
43882
|
memberEvents;
|
|
43740
43883
|
favoriteStickerMutationTail = Promise.resolve();
|
|
43741
|
-
constructor(runtime, source, profile, media, record, bot, arko, aiPolish, realtime, privacy = new ArkmePrivacyVisibilityService(runtime), messageActions, callHistory = new CallHistoryService(runtime, profile)) {
|
|
43884
|
+
constructor(runtime, source, profile, media, record, bot, arko, aiPolish, realtime, privacy = new ArkmePrivacyVisibilityService(runtime), messageActions, callHistory = new CallHistoryService(runtime, profile, media)) {
|
|
43742
43885
|
this.runtime = runtime;
|
|
43743
43886
|
this.source = source;
|
|
43744
43887
|
this.profile = profile;
|
|
@@ -44377,14 +44520,13 @@ var ChatService = class {
|
|
|
44377
44520
|
}
|
|
44378
44521
|
if (source.kind === "topic") {
|
|
44379
44522
|
const lockedRecordUids = await this.privacy.lockedRecordUids(session, options.signal);
|
|
44380
|
-
const
|
|
44381
|
-
|
|
44382
|
-
limit
|
|
44383
|
-
|
|
44384
|
-
|
|
44385
|
-
|
|
44386
|
-
|
|
44387
|
-
const rawRecords = listValue$16(data.records).filter((raw) => !arkmePrivacyLockedRecord(raw) && !lockedRecordUids.has(this.record.recordUid(raw)));
|
|
44523
|
+
const [page, metadata] = await Promise.all([readTopicRecordPage(this.runtime, session, source.ownerRef, {
|
|
44524
|
+
...options,
|
|
44525
|
+
limit
|
|
44526
|
+
}), readTopicMetadata(this.runtime, session, source.ownerRef, options.signal)]);
|
|
44527
|
+
if (arkmePrivacyLockedTopic({ privacy_state: page.privacyState }) || metadata.privacyState === 2) throw new ArkmePluginError("topic-privacy-locked", "隐私锁主题不能在 Arkme 插件中查看", false, 403);
|
|
44528
|
+
const topicKind = metadata.topicKind;
|
|
44529
|
+
const rawRecords = page.records.filter((raw) => !arkmePrivacyLockedRecord(raw) && !lockedRecordUids.has(this.record.recordUid(raw)));
|
|
44388
44530
|
const media = await this.media.hydrateRecordMediaPage(rawRecords, session, options.signal);
|
|
44389
44531
|
const signingKey = await this.runtime.stateStore.uniqueCode();
|
|
44390
44532
|
const records = rawRecords.map((raw) => {
|
|
@@ -44396,16 +44538,15 @@ var ChatService = class {
|
|
|
44396
44538
|
});
|
|
44397
44539
|
return this.withRecordTopicAssignmentRef(source, item, session.userId, signingKey, numberValue$19(objectValue$2(raw).owner_user_id), source.ownerRef);
|
|
44398
44540
|
});
|
|
44399
|
-
const nextSendAt = numberValue$19(data.next_cursor_send_at);
|
|
44400
|
-
const nextUid = stringValue$2(data.next_cursor_record_uid).trim();
|
|
44401
44541
|
return {
|
|
44402
|
-
source:
|
|
44542
|
+
source: {
|
|
44543
|
+
...await this.source.sourceItem(source),
|
|
44544
|
+
topicKind,
|
|
44545
|
+
displayName: arkmeTopicDisplayName(source.displayName, topicKind)
|
|
44546
|
+
},
|
|
44403
44547
|
items: records.map((item) => this.withRecordMessageActionRef(source, item, session.userId, signingKey)),
|
|
44404
|
-
hasMore:
|
|
44405
|
-
...
|
|
44406
|
-
sendAtMillis: nextSendAt,
|
|
44407
|
-
itemUid: nextUid
|
|
44408
|
-
} } : {}
|
|
44548
|
+
hasMore: page.hasMore,
|
|
44549
|
+
...page.nextCursor === void 0 ? {} : { nextCursor: page.nextCursor }
|
|
44409
44550
|
};
|
|
44410
44551
|
}
|
|
44411
44552
|
const aiPolishDecorations = source.kind === "group_chat" && options.cursor === void 0 ? Promise.allSettled([this.aiPolish.queryGroupAiPolishConfig(source.ownerRef, session, options.signal), this.aiPolish.queryGroupAiPolishNotices(source.ownerRef, session, options.signal)]) : void 0;
|
|
@@ -44956,13 +45097,21 @@ var ChatService = class {
|
|
|
44956
45097
|
parent_record_uid: parentRecordUid,
|
|
44957
45098
|
limit: 100
|
|
44958
45099
|
}, session, signal);
|
|
44959
|
-
const projections =
|
|
45100
|
+
const projections = [];
|
|
45101
|
+
for (const child of listValue$16(data.children)) {
|
|
44960
45102
|
const extension = chatExtensionTreeItemFromData(child, parentRecordUid);
|
|
44961
|
-
|
|
44962
|
-
|
|
45103
|
+
if (extension === void 0) continue;
|
|
45104
|
+
const record = objectValue$2(objectValue$2(objectValue$2(child).item).record);
|
|
45105
|
+
const payload = objectValue$2(record.payload);
|
|
45106
|
+
const mentions = await this.timelineMentionTargets(record, payload, session.userId, chatSessionUid);
|
|
45107
|
+
projections.push({
|
|
45108
|
+
extension: mentions === void 0 ? extension : {
|
|
45109
|
+
...extension,
|
|
45110
|
+
mentions
|
|
45111
|
+
},
|
|
44963
45112
|
mediaRecord: chatExtensionMediaRecord(child, extension.recordUid)
|
|
44964
|
-
}
|
|
44965
|
-
}
|
|
45113
|
+
});
|
|
45114
|
+
}
|
|
44966
45115
|
const extensions = (await this.hydrateExtensionMedia(projections, session, signal)).sort((left, right) => right.sendAtMillis - left.sendAtMillis);
|
|
44967
45116
|
const extensionCount = Math.max(integerLikeValue(data.total), extensions.length);
|
|
44968
45117
|
return extensionCount <= 0 ? void 0 : {
|
|
@@ -45669,22 +45818,30 @@ var ChatService = class {
|
|
|
45669
45818
|
const leadingTrim = textFormat === "markdown" ? 0 : rawText.length - rawText.trimStart().length;
|
|
45670
45819
|
const uniqueRefs = [...new Set(inputs.map((input) => input.botRef.trim()))];
|
|
45671
45820
|
if (uniqueRefs.some((ref) => ref === "")) throw new ArkmePluginError("bot-mention-ref-invalid", "Bot mention 引用为空", false);
|
|
45672
|
-
const
|
|
45821
|
+
const requestedReservedAsen = uniqueRefs.some((ref) => ref.toLowerCase() === RESERVED_ASEN_BOT_UID);
|
|
45822
|
+
const regularRefs = uniqueRefs.filter((ref) => ref.toLowerCase() !== RESERVED_ASEN_BOT_UID);
|
|
45823
|
+
const references = await Promise.all(regularRefs.map(async (ref) => ({
|
|
45673
45824
|
ref,
|
|
45674
45825
|
value: await this.bot.openBotRef(ref, session.userId)
|
|
45675
45826
|
})));
|
|
45676
45827
|
const allowedByBotId = /* @__PURE__ */ new Map();
|
|
45828
|
+
const reservedAsen = requestedReservedAsen ? {
|
|
45829
|
+
bot_uid: RESERVED_ASEN_BOT_UID,
|
|
45830
|
+
display_name_snapshot: RESERVED_ASEN_DISPLAY_NAME
|
|
45831
|
+
} : void 0;
|
|
45677
45832
|
if (source.kind === "group_chat") {
|
|
45678
|
-
|
|
45679
|
-
|
|
45680
|
-
|
|
45681
|
-
|
|
45682
|
-
|
|
45683
|
-
|
|
45684
|
-
|
|
45685
|
-
|
|
45833
|
+
if (references.length > 0) {
|
|
45834
|
+
const groupBots = await this.bot.listMentionableGroupBots(source, session, signal);
|
|
45835
|
+
const requested = new Set(references.map((item) => item.value.botId));
|
|
45836
|
+
for (const { botId, name } of groupBots) {
|
|
45837
|
+
if (!requested.has(botId)) continue;
|
|
45838
|
+
allowedByBotId.set(botId, {
|
|
45839
|
+
bot_uid: botId,
|
|
45840
|
+
display_name_snapshot: name
|
|
45841
|
+
});
|
|
45842
|
+
}
|
|
45686
45843
|
}
|
|
45687
|
-
} else {
|
|
45844
|
+
} else if (references.length > 0) {
|
|
45688
45845
|
const bots = (await this.bot.listBots(signal === void 0 ? {} : { signal })).items;
|
|
45689
45846
|
const botNameByRef = new Map(bots.filter((bot) => bot.provider === "openclaw").map((bot) => [bot.botRef, bot.name]));
|
|
45690
45847
|
for (const reference of references) {
|
|
@@ -45700,8 +45857,9 @@ var ChatService = class {
|
|
|
45700
45857
|
const refToBotId = new Map(references.map((item) => [item.ref, item.value.botId]));
|
|
45701
45858
|
return [...inputs].sort((left, right) => left.startIndex - right.startIndex).map((input) => {
|
|
45702
45859
|
const botRef = input.botRef.trim();
|
|
45703
|
-
const
|
|
45704
|
-
const
|
|
45860
|
+
const isReservedAsen = botRef.toLowerCase() === RESERVED_ASEN_BOT_UID;
|
|
45861
|
+
const botId = isReservedAsen ? void 0 : refToBotId.get(botRef);
|
|
45862
|
+
const bot = isReservedAsen ? reservedAsen : botId === void 0 ? void 0 : allowedByBotId.get(botId);
|
|
45705
45863
|
if (bot === void 0) throw new ArkmePluginError("bot-mention-not-available", "所选 Bot 当前不可 mention", false, 409);
|
|
45706
45864
|
const startIndex = Math.trunc(input.startIndex) - leadingTrim;
|
|
45707
45865
|
const length = Math.trunc(input.length);
|
|
@@ -45716,29 +45874,48 @@ var ChatService = class {
|
|
|
45716
45874
|
});
|
|
45717
45875
|
}
|
|
45718
45876
|
async groupBotMentionSend(sourceRef, source, text, botRefs, recordUid, relationUid, session, signal, options = {}) {
|
|
45719
|
-
const
|
|
45877
|
+
const normalizedRefs = botRefs.map((ref) => {
|
|
45878
|
+
const normalized = ref.trim();
|
|
45879
|
+
return normalized.toLowerCase() === RESERVED_ASEN_BOT_UID ? RESERVED_ASEN_BOT_UID : normalized;
|
|
45880
|
+
});
|
|
45881
|
+
const uniqueRefs = new Set(normalizedRefs);
|
|
45720
45882
|
if (uniqueRefs.has("") || uniqueRefs.size !== botRefs.length) throw new ArkmePluginError("bot-mention-ref-invalid", "Bot mention 引用为空或重复", false);
|
|
45721
|
-
const
|
|
45883
|
+
const requestedReservedAsen = [...uniqueRefs].some((ref) => ref.toLowerCase() === RESERVED_ASEN_BOT_UID);
|
|
45884
|
+
const regularRefs = [...uniqueRefs].filter((ref) => ref.toLowerCase() !== RESERVED_ASEN_BOT_UID);
|
|
45885
|
+
const references = await Promise.all(regularRefs.map(async (ref) => ({
|
|
45722
45886
|
ref,
|
|
45723
45887
|
value: await this.bot.openBotRef(ref, session.userId)
|
|
45724
45888
|
})));
|
|
45725
45889
|
const requestedById = new Map(references.map((item) => [item.value.botId, item.ref]));
|
|
45726
45890
|
if (requestedById.size !== references.length) throw new ArkmePluginError("bot-mention-ref-invalid", "Bot mention 引用重复", false);
|
|
45727
|
-
const groupBots = await this.bot.listMentionableGroupBots(source, session, signal);
|
|
45728
45891
|
const mentions = [];
|
|
45729
45892
|
let visibleText = "";
|
|
45730
|
-
|
|
45731
|
-
|
|
45732
|
-
const
|
|
45893
|
+
if (requestedById.size > 0) {
|
|
45894
|
+
const groupBots = await this.bot.listMentionableGroupBots(source, session, signal);
|
|
45895
|
+
for (const { botId, name } of groupBots) {
|
|
45896
|
+
if (!requestedById.has(botId)) continue;
|
|
45897
|
+
const display = `@${name}`;
|
|
45898
|
+
const startIndex = visibleText.length;
|
|
45899
|
+
visibleText += `${display} `;
|
|
45900
|
+
mentions.push({
|
|
45901
|
+
bot_uid: botId,
|
|
45902
|
+
display_name_snapshot: name,
|
|
45903
|
+
start_index: startIndex,
|
|
45904
|
+
length: display.length
|
|
45905
|
+
});
|
|
45906
|
+
requestedById.delete(botId);
|
|
45907
|
+
}
|
|
45908
|
+
}
|
|
45909
|
+
if (requestedReservedAsen) {
|
|
45910
|
+
const display = `@${RESERVED_ASEN_DISPLAY_NAME}`;
|
|
45733
45911
|
const startIndex = visibleText.length;
|
|
45734
45912
|
visibleText += `${display} `;
|
|
45735
45913
|
mentions.push({
|
|
45736
|
-
bot_uid:
|
|
45737
|
-
display_name_snapshot:
|
|
45914
|
+
bot_uid: RESERVED_ASEN_BOT_UID,
|
|
45915
|
+
display_name_snapshot: RESERVED_ASEN_DISPLAY_NAME,
|
|
45738
45916
|
start_index: startIndex,
|
|
45739
45917
|
length: display.length
|
|
45740
45918
|
});
|
|
45741
|
-
requestedById.delete(botId);
|
|
45742
45919
|
}
|
|
45743
45920
|
if (requestedById.size > 0) throw new ArkmePluginError("bot-mention-not-installed", "所选 Bot 未安装到该群聊", false, 409);
|
|
45744
45921
|
visibleText += text;
|
|
@@ -46194,6 +46371,51 @@ var ChatService = class {
|
|
|
46194
46371
|
async chatSourceFromBundle(bundle, session, cached, timelineItems) {
|
|
46195
46372
|
return await this.source.chatSourceFromBundle(bundle, session, cached, timelineItems);
|
|
46196
46373
|
}
|
|
46374
|
+
async timelineMentionTargets(record, payload, viewerUserId, chatSessionUid) {
|
|
46375
|
+
const metadata = arkmeMentionMetadataFromRecord(record, payload);
|
|
46376
|
+
const targets = [];
|
|
46377
|
+
for (const rawMention of listValue$16(metadata.human_mentions ?? metadata.humanMentions)) {
|
|
46378
|
+
const mention = objectValue$2(rawMention);
|
|
46379
|
+
const startIndex = integerLikeValue(mention.start_index ?? mention.startIndex);
|
|
46380
|
+
const length = integerLikeValue(mention.length);
|
|
46381
|
+
const displayName = stringValue$2(mention.display_name_snapshot ?? mention.displayNameSnapshot).trim();
|
|
46382
|
+
const userId = integerLikeValue(mention.user_id ?? mention.userId);
|
|
46383
|
+
if (startIndex < 0 || length < 2 || displayName === "") continue;
|
|
46384
|
+
if (userId === 0) {
|
|
46385
|
+
targets.push({
|
|
46386
|
+
kind: "all",
|
|
46387
|
+
startIndex,
|
|
46388
|
+
length,
|
|
46389
|
+
displayName
|
|
46390
|
+
});
|
|
46391
|
+
continue;
|
|
46392
|
+
}
|
|
46393
|
+
if (userId > 0) targets.push({
|
|
46394
|
+
kind: "member",
|
|
46395
|
+
startIndex,
|
|
46396
|
+
length,
|
|
46397
|
+
displayName,
|
|
46398
|
+
memberRef: await this.sealChatMemberRef(viewerUserId, chatSessionUid, userId)
|
|
46399
|
+
});
|
|
46400
|
+
}
|
|
46401
|
+
for (const rawMention of listValue$16(metadata.bot_mentions ?? metadata.botMentions)) {
|
|
46402
|
+
const mention = objectValue$2(rawMention);
|
|
46403
|
+
const startIndex = integerLikeValue(mention.start_index ?? mention.startIndex);
|
|
46404
|
+
const length = integerLikeValue(mention.length);
|
|
46405
|
+
const displayName = stringValue$2(mention.display_name_snapshot ?? mention.displayNameSnapshot).trim();
|
|
46406
|
+
const botRef = stringValue$2(mention.bot_uid ?? mention.botUid).trim();
|
|
46407
|
+
if (startIndex < 0 || length < 2 || displayName === "" || botRef === "") continue;
|
|
46408
|
+
targets.push({
|
|
46409
|
+
kind: "bot",
|
|
46410
|
+
startIndex,
|
|
46411
|
+
length,
|
|
46412
|
+
displayName,
|
|
46413
|
+
botRef
|
|
46414
|
+
});
|
|
46415
|
+
}
|
|
46416
|
+
targets.sort((left, right) => left.startIndex - right.startIndex);
|
|
46417
|
+
return targets.length === 0 ? void 0 : targets;
|
|
46418
|
+
}
|
|
46197
46419
|
async chatTimelineItems(data, session, chatSessionUid, projectedSourceKind) {
|
|
46198
46420
|
const items = [];
|
|
46199
46421
|
const signingKey = await this.runtime.stateStore.uniqueCode();
|
|
@@ -46228,6 +46450,7 @@ var ChatService = class {
|
|
|
46228
46450
|
const conversationPreview = arkmeChatConversationPreview(item);
|
|
46229
46451
|
const callRecord = await this.callHistory.timelineCallRecord(item, session.userId);
|
|
46230
46452
|
const senderName = stringValue$2(relation.display_name_snapshot).trim() || "Arkme用户";
|
|
46453
|
+
const mentions = await this.timelineMentionTargets(record, payload, session.userId, chatSessionUid);
|
|
46231
46454
|
const mentionsViewer = senderUserId !== session.userId && arkmeMentionMetadataMentionsViewer(record, payload, session.userId);
|
|
46232
46455
|
items.push({
|
|
46233
46456
|
itemUid: uid,
|
|
@@ -46262,6 +46485,7 @@ var ChatService = class {
|
|
|
46262
46485
|
isMe: senderUserId === session.userId,
|
|
46263
46486
|
...callRecord === void 0 ? {} : { callRecord },
|
|
46264
46487
|
...mentionsViewer ? { mentionsViewer: true } : {},
|
|
46488
|
+
...mentions === void 0 ? {} : { mentions },
|
|
46265
46489
|
sendAtMillis,
|
|
46266
46490
|
title: stringValue$2(payload.title),
|
|
46267
46491
|
textContent: stringValue$2(payload.text_content),
|
|
@@ -46864,6 +47088,7 @@ var ChatService = class {
|
|
|
46864
47088
|
const contentBlocks = this.media.richContentBlocks(item, session.userId);
|
|
46865
47089
|
const extensionProjection = this.timelineExtensionProjection(item, session.userId);
|
|
46866
47090
|
const senderName = stringValue$2(relation.display_name_snapshot).trim() || "Arkme用户";
|
|
47091
|
+
const mentions = await this.timelineMentionTargets(record, payload, session.userId, source.ownerRef);
|
|
46867
47092
|
const captureContext = timelineCaptureContext({
|
|
46868
47093
|
...record,
|
|
46869
47094
|
...payload
|
|
@@ -46902,6 +47127,7 @@ var ChatService = class {
|
|
|
46902
47127
|
...agentSource === void 0 ? {} : { agentSource },
|
|
46903
47128
|
isMe: senderUserId === session.userId,
|
|
46904
47129
|
...callRecord === void 0 ? {} : { callRecord },
|
|
47130
|
+
...mentions === void 0 ? {} : { mentions },
|
|
46905
47131
|
sendAtMillis,
|
|
46906
47132
|
title: stringValue$2(payload.title),
|
|
46907
47133
|
textContent: stringValue$2(payload.text_content),
|
|
@@ -78987,6 +79213,10 @@ function allowedSignedImageHost$2(environment, hostname) {
|
|
|
78987
79213
|
function allowedSignedAudioHost(environment, hostname) {
|
|
78988
79214
|
return (environment === "prod" ? ["jotmo-useraudio.oss-cn-hangzhou.aliyuncs.com"] : ["jotmo-useraudio-test.oss-cn-hangzhou.aliyuncs.com"]).includes(hostname.toLowerCase());
|
|
78989
79215
|
}
|
|
79216
|
+
/** Call transcript clips use a separate COS bucket, not the user-audio OSS bucket. */
|
|
79217
|
+
function allowedSignedCallAudioHost(environment, hostname) {
|
|
79218
|
+
return environment === "prod" && hostname.toLowerCase() === "webrtc-record-prod-1403070603.cos.ap-shanghai.myqcloud.com";
|
|
79219
|
+
}
|
|
78990
79220
|
/** Record audio can originate from the dedicated audio or generic file bucket. */
|
|
78991
79221
|
function allowedSignedRecordAudioHost(environment, hostname) {
|
|
78992
79222
|
return allowedSignedAudioHost(environment, hostname) || allowedSignedImageHost$2(environment, hostname);
|
|
@@ -79256,7 +79486,7 @@ var MediaService = class {
|
|
|
79256
79486
|
}
|
|
79257
79487
|
if (originalOnly && descriptor.purpose !== "original") throw new ArkmePluginError("original-unavailable", "原文件不可用,请刷新后重试;不会用预览图代替原文件", false, 404);
|
|
79258
79488
|
const url = new URL(descriptor.remoteUrl);
|
|
79259
|
-
if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || !(allowedSignedImageHost$2(this.runtime.config.environment, url.hostname) || allowedSignedAudioHost(this.runtime.config.environment, url.hostname))) throw new ArkmePluginError("media-host-rejected", "媒体来源不受信任", false, 403);
|
|
79489
|
+
if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.port !== "" || url.hash !== "" || !(allowedSignedImageHost$2(this.runtime.config.environment, url.hostname) || allowedSignedAudioHost(this.runtime.config.environment, url.hostname) || allowedSignedCallAudioHost(this.runtime.config.environment, url.hostname))) throw new ArkmePluginError("media-host-rejected", "媒体来源不受信任", false, 403);
|
|
79260
79490
|
const response = await this.runtime.fetchImpl(url, {
|
|
79261
79491
|
headers: range === void 0 ? {} : { Range: range },
|
|
79262
79492
|
redirect: "error",
|
|
@@ -79753,7 +79983,7 @@ var MediaService = class {
|
|
|
79753
79983
|
const value = safeHttpsUrl(raw);
|
|
79754
79984
|
if (value === void 0) return void 0;
|
|
79755
79985
|
const url = new URL(value);
|
|
79756
|
-
return url.port === "" && url.hash === "" && (allowedSignedImageHost$2(this.runtime.config.environment, url.hostname) || allowedSignedAudioHost(this.runtime.config.environment, url.hostname)) ? value : void 0;
|
|
79986
|
+
return url.port === "" && url.hash === "" && (allowedSignedImageHost$2(this.runtime.config.environment, url.hostname) || allowedSignedAudioHost(this.runtime.config.environment, url.hostname) || allowedSignedCallAudioHost(this.runtime.config.environment, url.hostname)) ? value : void 0;
|
|
79757
79987
|
};
|
|
79758
79988
|
const downloadUrl = trustedUrl(file.download_url ?? file.downloadUrl);
|
|
79759
79989
|
const previewUrl = trustedUrl(file.preview_url ?? file.previewUrl);
|
|
@@ -84244,10 +84474,6 @@ var RelatedRecordingService = class {
|
|
|
84244
84474
|
return `arkme-shared-recording-detail-v1.${encoded}.${createHmac("sha256", signingKey).update(encoded).digest("base64url")}`;
|
|
84245
84475
|
}
|
|
84246
84476
|
};
|
|
84247
|
-
function isDshAgentInputSourceTitle(value) {
|
|
84248
|
-
const normalized = value?.trim().toLowerCase();
|
|
84249
|
-
return normalized === "dsh agent input" || normalized === "DSH Agent 输入".toLowerCase();
|
|
84250
|
-
}
|
|
84251
84477
|
//#endregion
|
|
84252
84478
|
//#region src/services/search-service.ts
|
|
84253
84479
|
function numberValue$2(value) {
|
|
@@ -84632,7 +84858,6 @@ var SearchService = class {
|
|
|
84632
84858
|
const linkMatch = textContent.match(/https:\/\/[^\s<>()]+/u);
|
|
84633
84859
|
const sourceTitle = stringValue$2(topic.title ?? chat.title).trim();
|
|
84634
84860
|
const creationSource = Math.trunc(numberValue$2(core.creation_source ?? item.creation_source));
|
|
84635
|
-
const normalizedCreationSource = creationSource > 0 ? creationSource : isDshAgentInputSourceTitle(sourceTitle) ? 3 : 0;
|
|
84636
84861
|
return {
|
|
84637
84862
|
recordUid,
|
|
84638
84863
|
sourceKind: Math.trunc(numberValue$2(item.source_kind)),
|
|
@@ -84646,7 +84871,7 @@ var SearchService = class {
|
|
|
84646
84871
|
...stringValue$2(core.nickname).trim() === "" ? {} : { nickname: stringValue$2(core.nickname).trim() },
|
|
84647
84872
|
...numberValue$2(core.template_kind) <= 0 ? {} : { templateKind: Math.trunc(numberValue$2(core.template_kind)) },
|
|
84648
84873
|
...numberValue$2(core.display_kind) <= 0 ? {} : { displayKind: Math.trunc(numberValue$2(core.display_kind)) },
|
|
84649
|
-
...
|
|
84874
|
+
...creationSource <= 0 ? {} : { creationSource },
|
|
84650
84875
|
...sourceTitle === "" ? {} : { sourceTitle },
|
|
84651
84876
|
media,
|
|
84652
84877
|
files,
|
|
@@ -88304,7 +88529,7 @@ var ArkmeService = class {
|
|
|
88304
88529
|
this.calendar = new CalendarService(this.runtime, this.privacy);
|
|
88305
88530
|
this.wechat = new WechatService(this.runtime);
|
|
88306
88531
|
this.profile = new ProfileService(this.runtime);
|
|
88307
|
-
this.callHistory = new CallHistoryService(this.runtime, this.profile);
|
|
88532
|
+
this.callHistory = new CallHistoryService(this.runtime, this.profile, { forwardContentBlocks: (files, viewerUserId) => this.media.forwardContentBlocks(files, viewerUserId) });
|
|
88308
88533
|
this.extensionReview = new ExtensionReviewService(this.runtime, this.profile, { createTextForConversation: async (recordUid, textContent) => {
|
|
88309
88534
|
return await this.createTextForConversation(recordUid, textContent);
|
|
88310
88535
|
} });
|
|
@@ -88643,6 +88868,7 @@ var ArkmeService = class {
|
|
|
88643
88868
|
imageLibrary: true,
|
|
88644
88869
|
sourceDirectory: true,
|
|
88645
88870
|
localFirstDirectory: true,
|
|
88871
|
+
topicHomeVisibility: true,
|
|
88646
88872
|
contactDirectoryReads: true,
|
|
88647
88873
|
sourceTimeline: true,
|
|
88648
88874
|
forwardContent: true,
|
|
@@ -89000,6 +89226,11 @@ var ArkmeService = class {
|
|
|
89000
89226
|
async renameTopic(sourceRef, title) {
|
|
89001
89227
|
return await this.source.renameTopic(sourceRef, title);
|
|
89002
89228
|
}
|
|
89229
|
+
async topicHomeVisibility(sourceRef, showInHome, signal) {
|
|
89230
|
+
const result = await this.source.topicHomeVisibility(sourceRef, showInHome, signal);
|
|
89231
|
+
if (showInHome !== void 0) await this.realtime.invalidateRecordProjection();
|
|
89232
|
+
return result;
|
|
89233
|
+
}
|
|
89003
89234
|
async dissolveTopic(sourceRef, parentSourceRef, childSourceRefs, requestId, expectedRecordCount) {
|
|
89004
89235
|
return await this.source.dissolveTopic(sourceRef, parentSourceRef, childSourceRefs, requestId, expectedRecordCount);
|
|
89005
89236
|
}
|