import type { TeamRepresentationSelection } from '../team-group-contract.js'; import { type PersonRecordSourcesPage } from '../person-records.js'; import type { ArkmeTimelineMemberJoinEvent } from '../unified-chat-timeline.js'; import { type ArkmeMessageQuote } from '../message-quote.js'; import { type MessageUnderlineChange } from '../message-annotations.js'; import { type ResolvedMentions } from './mention-metadata-codec.js'; import type { RecordEditHistoryTarget } from './record-edit-history-service.js'; import { type RecordOwnerId } from '../record-owner-id.js'; import { type BotDisplayProfilesReader } from '../chat-sender-display.js'; import { CallHistoryService } from './call-history-service.js'; import { MemberEventService } from './member-event-service.js'; import type { ArkmeSessionCredentials } from '../keychain-store.js'; import type { ArkmeChatNotificationResult, ArkmeConversationMemberJoinEvent, ArkmeConversationMemberList, ArkmeConversationMemberPage, ArkmeConversationMemberPresentation, ArkmeConversationMemberCache, ArkmeConversationMemberRecordMode, ArkmeConversationMemberRecordPage, ArkmeBotMentionInput, ArkmeBotConversation, ArkmeBotConversationReadResult, ArkmeBotConversationSendResult, ArkmeBotNotificationPreference, ArkmeDirectTextSendResult, ArkmeFavoriteStickerList, ArkmeFavoriteStickerAddInput, ArkmeFavoriteStickerManageAction, ArkmeGroupJoinRestrictionMutationResult, ArkmeGroupJoinRestrictionPage, ArkmeGroupSelfNickname, ArkmeGroupMemberRemoveResult, ArkmeHumanMentionInput, ArkmeLongArticleDetail, ArkmeLongArticleDraft, ArkmeMessageCopyLinkExtendResult, ArkmeMessageCopyLinkResult, ArkmeMessageCopyLinkResolveResult, ArkmeMessageSnapshotDetail, ArkmeMessageReadReceiptDetail, ArkmeMessageReadReceiptQueryItem, ArkmeMessageReadReceiptSummaryList, ArkmeMessageReportResult, ArkmeMessageWithdrawalResult, ArkmeOfficialAuthorProfile, ArkmeOpenPrivateChatResult, ArkmeRichSendInput, ArkmeRecordCaptureContext, ArkmeRecordLocationCapture, ArkmeSourceItem, ArkmeSourceReadResult, ArkmeSourceSendResult, ArkmeSourceMessageExtendResult, ArkmeSourceMessageExtensionContext, ArkmeSharedRecordingPreview, ArkmeTimelineCursor, ArkmeTimelineAroundPage, ArkmeTimelineItem, ArkmeTimelineExtensionParent, ArkmeTimelinePage, ArkmeUploadedAsset } from '../types.js'; import { ArkoService } from './arko-service.js'; import { BotService } from './bot-service.js'; import { GroupAiPolishService } from './group-ai-polish-service.js'; import { MediaService, type ArkmeMediaDescriptor } from './media-service.js'; import { MessageActionService } from './message-action-service.js'; import { ProfileService } from './profile-service.js'; import { ArkmePrivacyVisibilityService } from './privacy-visibility.js'; import { RecordService } from './record-service.js'; import type { ArkmeRelatedQuickNoteSourceLocator } from './related-quick-note-service.js'; import { ServiceRuntime } from './service.js'; import { SourceService, type ArkmeSourceRefPayload } from './source-service.js'; interface ArkmeMessageRefPayload { version: 1; userId: number; chatSessionUid: string; relationUid: string; } /** Single owner for the provider-safe rich payload shared by UI, SDK, durable files and Tools. */ export declare function arkmeRichContentPayload(input: ArkmeRichSendInput, normalizedTextContent: string, mentionPayload?: Record): Record | undefined; export interface ArkmeChatRealtimePort { beginLocalReadCursor(userId: number, sessionUid: string, sequence: number): (confirmedSequence?: number) => void; emitChatClientEvent(event: Parameters[0]): void; nextChatClientRevision(): number; scheduleChatSessionProjection(chatSessionUid: string, latestSequence: number): void; invalidateRecordProjection(options?: { contentOnly?: boolean; }): Promise; refreshAttentionSummary(): Promise; } /** Background availability is a media fact; waveform samples alone never manufacture it. */ export declare function arkmeSnapshotBackgroundSoundState(values: Record): ArkmeMessageSnapshotDetail['backgroundSound']; interface ArkmeJoinEventProjectionOptions { viewerUserId: number; memberRefForUserId(userId: number): Promise; eventIdForStableKey(stableKey: string): Promise; } /** Converts allowlisted member join metadata into a Browser-safe projection. */ export declare function projectArkmeConversationMemberJoinEvents(rawItems: readonly Record[], options: ArkmeJoinEventProjectionOptions): Promise; export declare class ChatService { private readonly runtime; private readonly source; private readonly profile; private readonly media; private readonly record; private readonly bot; private readonly arko; private readonly aiPolish; private readonly realtime; private readonly privacy; private readonly messageActions?; private readonly callHistory; private readonly senderProfiles; readonly memberEvents: MemberEventService; private favoriteStickerMutationTail; constructor(runtime: ServiceRuntime, source: SourceService, profile: ProfileService, media: MediaService, record: RecordService, bot: BotService, arko: ArkoService, aiPolish: GroupAiPolishService, realtime: ArkmeChatRealtimePort, privacy?: ArkmePrivacyVisibilityService, messageActions?: MessageActionService | undefined, callHistory?: CallHistoryService, senderProfiles?: BotDisplayProfilesReader); private hydrateExtensionMedia; private hydrateUploadedExtension; readDirectBotConversation(botId: string, chatSessionUid: string, options?: { signal?: AbortSignal; }): Promise; sendDirectBotText(chatSessionUid: string, contentInput: string, options?: { signal?: AbortSignal; }): Promise; conversationNotification(sourceRef: string, enabled?: boolean, signal?: AbortSignal): Promise; directBotNotificationPreference(chatSessionUid: string, options?: { signal?: AbortSignal; }): Promise; updateDirectBotNotificationPreference(chatSessionUid: string, muted: boolean, options?: { signal?: AbortSignal; }): Promise; markDirectBotRead(chatSessionUid: string, readSequence: number, options?: { signal?: AbortSignal; }): Promise; private directBotPolicy; private serializeFavoriteStickerMutation; cachedSourceMembers(sourceRef: string, signal?: AbortSignal): Promise; /** Read-only human candidates for team management, not group invitations. */ teamMemberCandidates(sourceRef: string, options?: { cursor?: string; signal?: AbortSignal; }): Promise; pageSourceMembers(sourceRef: string, options?: { cursor?: string; limit?: number; signal?: AbortSignal; }): Promise; sourceMembersPresentation(sourceRef: string, memberRefs: readonly string[], options?: { signal?: AbortSignal; }): Promise; private memberRead; private sealMemberPageCursor; private openMemberPageCursor; listSourceMembers(sourceRef: string, options?: { activeOnly?: boolean; signal?: AbortSignal; }): Promise; /** Seal only an owner-authorized article source returned by Record's library. */ articleSearchActionRef(raw: Record, sourceRef: string, signal?: AbortSignal): Promise; personRecordsPage(sourceRef: string, memberRef: string, options?: { cursor?: string; limit?: number; knownEventRefs?: readonly string[]; validateOnly?: boolean; signal?: AbortSignal; }): Promise; personRecordsCapabilities(sourceRef: string, memberRef: string, signal?: AbortSignal): Promise<{ version: 1; shared: boolean; strategy: "existing-conversations"; }>; /** Discover bounded batches; reading this view never creates a chat or marks it read. */ personRecordSources(sourceRef: string, memberRef: string, cursor?: string, signal?: AbortSignal): Promise; sourceMemberRecords(sourceRef: string, memberRef: string, mode: ArkmeConversationMemberRecordMode, options?: { limit?: number; beforeSequence?: number; basicPresentation?: boolean; signal?: AbortSignal; }): Promise; memberWorldTarget(sourceRef: string, memberRef: string, signal?: AbortSignal): Promise<{ userId: number; }>; openPrivateChatFromMember(sourceRef: string, memberRef: string, options?: { signal?: AbortSignal; }): Promise; openPrivateChatFromUser(peerUserId: RecordOwnerId, options?: { presentationDisplayName?: string; expectedViewerUserId?: number; signal?: AbortSignal; }): Promise; openOfficialAuthorPrivateChat(options?: { signal?: AbortSignal; }): Promise; /** * Contact-author is an entry point, not a second conversation type. Scan the * ordinary directory first so repeated clicks always reuse the existing chat. */ private findPrivateChatByPeerUserId; officialAuthorProfile(options?: { signal?: AbortSignal; }): Promise; private readTopicTimelineRawStream; private readTopicTimelineRawStreams; readSource(sourceRef: string, options?: { limit?: number; cursor?: ArkmeTimelineCursor; signal?: AbortSignal; }): Promise; readSourceAround(sourceRef: string, itemUid: string, recordOwnerUserId: RecordOwnerId, options?: { beforeLimit?: number; afterLimit?: number; signal?: AbortSignal; }): Promise; reportMessage(messageRef: string, reportType: 1 | 2 | 3 | 4, options?: { reason?: string; requestUid?: string; signal?: AbortSignal; }): Promise; withdrawGroupMessage(messageWithdrawalRef: string, options?: { signal?: AbortSignal; }): Promise; groupSelfNickname(sourceRef: string, signal?: AbortSignal): Promise; setGroupSelfNickname(sourceRef: string, nickname: string, signal?: AbortSignal): Promise; removeGroupMember(sourceRef: string, memberRef: string, options?: { preventRejoin?: boolean; signal?: AbortSignal; }): Promise; listGroupJoinRestrictions(sourceRef: string, options?: { cursor?: string; limit?: number; signal?: AbortSignal; }): Promise; setGroupJoinRestriction(sourceRef: string, memberRef: string, restricted: boolean, options?: { signal?: AbortSignal; }): Promise; messageReadReceiptSummaries(sourceRef: string, rawItems: readonly ArkmeMessageReadReceiptQueryItem[], options?: { signal?: AbortSignal; }): Promise; messageReadReceiptDetail(sourceRef: string, itemUid: string, sequence: number, options?: { signal?: AbortSignal; basicOnly?: boolean; }): Promise; private requireReadReceiptChatSource; private requireReadReceiptItems; private readReceiptItemKey; copySourceMessageLink(sourceRef: string, actionRefs: readonly string[], options?: { signal?: AbortSignal; }): Promise; resolveMessageCopyLink(sid: string, options?: { signal?: AbortSignal; }): Promise; private loadMessageCopyLinkPublicExtensions; private loadChatMessageExtensions; /** Personal and topic notes share the record-owned tree, including replies outside the original topic. */ private ownedRecordParentFromTree; /** Lightweight visible-row enrichment; never reads an entire topic before showing it. */ sourceMessageExtensionParent(sourceRef: string, actionRef: string, options?: { signal?: AbortSignal; }): Promise<{ extensionParent?: ArkmeTimelineExtensionParent; recordUid: string; }>; private loadOwnedRecordExtensions; recordEditHistoryTarget(sourceRef: string, messageActionRef: string): Promise; reactionTarget(sourceRef: string, messageActionRef: string): Promise; reactionActorReferences(sourceRef: string, userIds: readonly number[]): Promise>; /** Keep viewer-owned remarks separate from group nicknames and public profiles. */ reactionActorLabels(sourceRef: string, userIds: readonly number[], signal?: AbortSignal): Promise>; private underlineContext; private localMarkContext; sourceLocalMarkCapabilities(sourceRef: string): Promise<{ supported: boolean; maxLength: number; storage: "local"; }>; sourceLocalMarks(sourceRef: string, actionRefs: readonly string[]): Promise<{ actionRef: string; snapshot: import("../message-annotations.js").MessageUnderlineSnapshot; }[]>; changeSourceLocalMark(sourceRef: string, actionRef: string, change: MessageUnderlineChange): Promise; captureSourceMessageAnchor(sourceRef: string, actionRef: string, start: number, end: number): Promise; sourceUnderlineCapabilities(sourceRef: string, signal?: AbortSignal): Promise; sourceUnderlines(sourceRef: string, actionRefs: readonly string[], signal?: AbortSignal): Promise<{ actionRef: string; snapshot: { revision: number; accessible: boolean; items: { id: string; actorId: number; actorName: string; mine: boolean; anchor: ArkmeMessageQuote; state: "available" | "stale"; }[]; }; }[]>; changeSourceUnderline(sourceRef: string, actionRef: string, change: MessageUnderlineChange, signal?: AbortSignal): Promise<{ revision: number; accessible: boolean; items: { id: string; actorId: number; actorName: string; mine: boolean; anchor: ArkmeMessageQuote; state: "available" | "stale"; }[]; }>; sourceMessageExtensionCapabilities(sourceRef: string, signal?: AbortSignal): Promise; validateQuoteReply(sourceRef: string, messageActionRef: string, value: unknown, signal?: AbortSignal): Promise; sourceMessageExtensionContext(sourceRef: string, messageActionRef: string, options?: { signal?: AbortSignal; }): Promise; extendSourceMessage(sourceRef: string, messageActionRef: string, textContent: string, recordUid: string, assets?: readonly ArkmeUploadedAsset[], options?: { relationUid?: string; parentRecordUid?: string; quote?: ArkmeMessageQuote; signal?: AbortSignal; } & Pick): Promise; extendMessageCopyLink(sid: string, itemIndex: number, textContent: string, recordUid: string, options?: { signal?: AbortSignal; }): Promise; forwardSourceMessages(sourceRef: string, actionRefs: readonly string[], options?: { representation?: TeamRepresentationSelection; targetSourceRef?: string; recordUid?: string; relationUid?: string; commentText?: string; expectedUserId?: number; sendAtMillis?: number; signal?: AbortSignal; }): Promise; sendSourceText(sourceRef: string, textContent: string, options?: { recordUid?: string; relationUid?: string; recordDurationMillis?: number; captureContext?: ArkmeRecordCaptureContext; botRefs?: readonly string[]; humanMentions?: readonly ArkmeHumanMentionInput[]; botMentions?: readonly ArkmeBotMentionInput[]; expectedUserId?: number; signal?: AbortSignal; representation?: TeamRepresentationSelection; sendAtMillis?: number; agentAuthored?: boolean; }): Promise; private mentionContentPayload; resolveMentions(source: ArkmeSourceRefPayload, rawText: string, normalizedText: string, humanInputs: readonly ArkmeHumanMentionInput[], botInputs: readonly ArkmeBotMentionInput[], session: ArkmeSessionCredentials, signal?: AbortSignal, textFormat?: 'plain' | 'markdown'): Promise; private humanMentionMetadata; private botMentionMetadata; groupBotMentionSend(sourceRef: string, source: ArkmeSourceRefPayload, text: string, botRefs: readonly string[], recordUid: string, relationUid: string, session: ArkmeSessionCredentials, signal?: AbortSignal, options?: { representation?: TeamRepresentationSelection; sendAtMillis?: number; agentAuthored?: boolean; recordDurationMillis?: number; captureContext?: ArkmeRecordCaptureContext; }): Promise; sendChatSourceTextRaw(sourceRef: string, chatSessionUid: string, text: string, recordUid: string, relationUid: string, session: ArkmeSessionCredentials, initialAiPolish?: Record, contentPayload?: Record, signal?: AbortSignal, options?: { representation?: TeamRepresentationSelection; sendAtMillis?: number; agentAuthored?: boolean; recordDurationMillis?: number; captureContext?: ArkmeRecordCaptureContext; }): Promise; private postChatTextRecord; sendSourceRich(sourceRef: string, input: ArkmeRichSendInput, options?: { recordUid?: string; relationUid?: string; expectedUserId?: number; signal?: AbortSignal; sendAtMillis?: number; }): Promise; private favoriteStickerDocument; private favoriteStickerView; favoriteStickers(signal?: AbortSignal): Promise; addFavoriteSticker(item: ArkmeFavoriteStickerAddInput, signal?: AbortSignal): Promise; manageFavoriteSticker(fileAssetUid: string, action: ArkmeFavoriteStickerManageAction, signal?: AbortSignal): Promise; sendFavoriteSticker(sourceRef: string, fileAssetUid: string, options?: { recordUid?: string; relationUid?: string; signal?: AbortSignal; } & import('./../team-group-contract.js').TeamRepresentationSendOptions): Promise; confirmSourceSend(input: import('../file-transfer-contract.js').ArkmeFileSendInput, signal?: AbortSignal): Promise; confirmLongArticlePublication(sourceRef: string, input: import('../types.js').ArkmeLongArticlePublishInput, userId: number, signal?: AbortSignal): Promise; longArticleDetail(sourceRef: string, itemUid: string, signal?: AbortSignal, actionRef?: string): Promise; private withLongArticleActions; /** Resolve a complete, owned article, never trust a search excerpt as send content. */ ownLongArticle(itemUid: string, expectedUserId: number, signal?: AbortSignal): Promise<{ detail: ArkmeLongArticleDetail; messageActionRef: string; }>; updateLongArticle(sourceRef: string, itemUid: string, input: import('../types.js').ArkmeLongArticleUpdateInput & { assets?: import('../types.js').ArkmeUploadedAsset[]; }): Promise; getLongArticleDraft(sourceRef: string, itemUid?: string, draftScope?: string): Promise; putLongArticleDraft(draft: ArkmeLongArticleDraft): Promise; removeLongArticleDraft(sourceRef: string, itemUid?: string, expectedRecordUid?: string, draftScope?: string): Promise; uploadLocalFile(filePath: string, metadata: { size: number; sha256: string; mimeType: string; fileName: string; fileKind: 1 | 2 | 3 | 4; }, options?: { expectedUserId?: number; signal?: AbortSignal; }): Promise; fetchMedia(mediaRef: string, range?: string, signal?: AbortSignal, method?: 'GET' | 'HEAD'): Promise<{ response: Response; descriptor: ArkmeMediaDescriptor; }>; sendDirectText(recipientArkmeId: string, textContent: string, options?: { recordUid?: string; relationUid?: string; sendAtMillis?: number; signal?: AbortSignal; }): Promise; reportMessagePreparing(sourceRef: string, prepareAtMillis: number, options?: { signal?: AbortSignal; }): Promise; cancelMessagePreparing(sourceRef: string, cancelAtMillis: number, options?: { signal?: AbortSignal; }): Promise; private writeMessagePreparing; markSourceRead(sourceRef: string, readSequence: number, options?: { signal?: AbortSignal; }): Promise; private advanceChatReadCursor; chatSourceFromBundle(bundle: Record, session: ArkmeSessionCredentials, cached: ArkmeSourceItem | undefined, timelineItems: ArkmeTimelineItem[]): Promise; private timelineMentionTargets; chatTimelineItems(data: Record, session: ArkmeSessionCredentials, chatSessionUid: string, projectedSourceKind?: 'private_chat' | 'group_chat', bundle?: Record, signal?: AbortSignal): Promise; relatedQuickNoteLocator(sourceRef: string, messageActionRef: string): Promise; chatForwardRecordsPreview(raw: unknown, viewerUserId: number, fallbackCreatedAtMillis: number): Promise; chatSharedRecordingPreview(raw: unknown): ArkmeTimelineItem['sharedRecording'] | undefined; private sharedRecordingParticipantsFromPayload; private sharedRecordingTranscriptFromPayload; private sharedRecordingPreviewFromPayload; private sharedRecordingSourceDigestCompatible; private withSharedRecordingDetailRef; private sealSharedRecordingDetailRef; private openSharedRecordingDetailRef; calendarSharedRecordingPreview(raw: unknown, session: ArkmeSessionCredentials): Promise; sharedRecordingDetail(detailRef: string, options?: { signal?: AbortSignal; }): Promise; messageSnapshotDetail(sourceRef: string, actionRef: string, options?: { signal?: AbortSignal; includeAttachments?: boolean; }): Promise; private hydratedMessageSnapshotDetail; saveMessageLocation(sourceRef: string, itemUid: string, location: ArkmeRecordLocationCapture, recordVersion: number | undefined, options?: { signal?: AbortSignal; }): Promise; resolvePrivateChatPeer(sourceRef: string, signal?: AbortSignal): Promise<{ userId: number; displayName: string; }>; private rawChatMembers; private projectChatMembers; projectUnifiedMemberJoins(payloads: Record[], source: ArkmeSourceRefPayload, session: ArkmeSessionCredentials, signal?: AbortSignal): Promise<(ArkmeTimelineMemberJoinEvent | undefined)[]>; projectChatTimelineItems(rawItems: unknown[], source: ArkmeSourceRefPayload, session: ArkmeSessionCredentials, signal?: AbortSignal, options?: { basicPresentation?: boolean; }): Promise; private timelineBotDisplayProfiles; private timelineSenderName; private timelineBotAvatar; private timelineExtensionProjection; private hydrateTimelineExtensionParents; private sealChatMemberRef; private openChatMemberRef; private sealChatHumanMentionRef; private openChatHumanMentionRef; private messageActionRefPayload; /** * Attach the same signed action reference used by authoritative timeline reads * directly to a confirmed send result. Signing is best-effort after the remote * write: a local key-store failure must never turn an accepted write into a * retryable send failure. */ private withConfirmedSendReferences; private withPersonalRecordCapabilities; private withRecordMessageActionRef; private sealMessageActionRef; private openMessageActionRefs; private openMessageActionRef; private forwardPayloadItem; private forwardClientRequestId; private forwardReferencesOrderedForCommand; private validateForwardReferences; private forwardSourceItemBody; sealMessageRef(userId: number, chatSessionUid: string, relationUid: string, signingKey: string): string; private sealMessageWithdrawalRef; private openMessageWithdrawalRef; private sealJoinRestrictionCursor; private openJoinRestrictionCursor; private openSignedOpaquePayload; openMessageRef(messageRef: string, expectedUserId: number): Promise; } export {}; //# sourceMappingURL=chat-service.d.ts.map