import { type RecordOwnerId } from '../record-owner-id.js'; import { type ChatPolicySnapshot } from './chat-policy.js'; import type { ArkmeSessionCredentials } from '../keychain-store.js'; import type { ArkmeChatAttentionSummary, ArkmeConversationNameSearchResult, ArkmeGroupAvatarPresentation, ArkmeSelfRecordItem, ArkmeSelfSummary, ArkmeSourceDirectory, ArkmeSourceDirectoryPinResult, ArkmeSourceItem, ArkmeSourceKind, ArkmeSourceList, ArkmeTimelineItem, ArkmeTopicCreateResult, ArkmeTopicDissolveResult, ArkmeTopicDissolveTask, ArkmeTopicHierarchyMoveResult, ArkmeTopicRenameResult } from '../types.js'; import { ProfileService, type ArkmePublicProfile } from './profile-service.js'; import { ArkmePrivacyVisibilityService } from './privacy-visibility.js'; import { type ConversationListPreferenceEntry } from './conversation-list-preference-service.js'; import { ServiceRuntime } from './service.js'; export interface ArkmeSourceRefPayload { version: 1; userId: number; kind: ArkmeSourceKind; ownerRef: string; displayName: string; botGroupTarget?: ArkmeGroupBotBindingTarget; sidebarSubjectUid?: string; conversationListActivityAtMillis?: number; conversationListLatestSequence?: number; } export interface ArkmeGroupBotBindingTarget { rmSubjectId?: number; subjectUid?: string; } export interface ArkmeGroupAvatarSnapshotProjection { memberCount: number; strategy: string; computedAtMillis: number; memberIds: number[]; } interface ArkmeChatDirectoryMetadata { subjectUid?: string; activityAtMillis: number; latestSequence: number; } export interface ArkmePrivateChatViewerLabel { displayName: string; remark: string; } export interface ArkmeSourceRecordReader { summary(): Promise; recordItem(raw: unknown): ArkmeSelfRecordItem | undefined; isDSHAgentInput?(raw: unknown): boolean; isPrivacyLocked?(raw: unknown): boolean; } export declare function arkmeGroupBotBindingTargetFromBundle(bundle: Record): ArkmeGroupBotBindingTarget | undefined; export declare function arkmeGroupBotBindingBody(source: Pick): Record; export declare function arkmeChatConversationPreview(raw: Record, viewerUserId?: number): string; export declare function arkmeTimelineConversationPreview(item: ArkmeTimelineItem): string; export declare class SourceService { private readonly runtime; private readonly profile; private readonly recordReader; private readonly privacy; private readonly chatSourceCache; private readonly sourceListCache; private readonly sourceListInFlight; private readonly selfDirectoryContexts; private readonly selfDirectoryContextReads; private readonly groupAvatarSnapshotCache; private readonly topicDissolveProgress; constructor(runtime: ServiceRuntime, profile: ProfileService, recordReader: ArkmeSourceRecordReader, privacy?: ArkmePrivacyVisibilityService); topicDissolveStatus(requestId: string): Promise; activeTopicDissolve(): Promise; private updateTopicDissolveProgress; cachedChatSource(userId: number, chatSessionUid: string): ArkmeSourceItem | undefined; cachedChatSourceByKey(cacheKey: string): ArkmeSourceItem | undefined; applyConfirmedChatPolicy(policy: ChatPolicySnapshot): void; private projectChatSourceAttention; private storeChatSourceByKey; /** * Server-owned tray summary. `summary` covers every visible conversation; * paginated `items` from this endpoint must never be summed as the Dock total. */ chatUnreadBadgeSummary(signal?: AbortSignal): Promise; /** Resolve a remote-search owner into the same viewer-bound source used by the conversation UI. */ searchTargetSource(sourceKind: number, sourceUid: string, displayNameInput: string, signal?: AbortSignal): Promise; /** Search one canonical directory page, including names with no matching messages. */ searchConversationNames(options: { query: string; cursor?: string; signal?: AbortSignal; }): Promise; /** Resolve a bounded set in one directory walk, reusing viewer-scoped source projections. */ chatSourcesBySessionUids(uids: readonly string[], signal?: AbortSignal): Promise>; setChatSource(userId: number, chatSessionUid: string, source: ArkmeSourceItem): void; setChatSourceByKey(cacheKey: string, source: ArkmeSourceItem): void; /** * Resolve the current viewer's private-chat labels for the supplied people. * The result is deliberately keyed only inside the Provider; callers project * the resolved label into their own viewer-bound response. */ privateDisplayNamesByUserIds(userIds: readonly number[], options?: { signal?: AbortSignal; }): Promise>; /** * Resolve the current viewer's private-chat display label and its exact * remark source without compressing fallback snapshots into remark facts. */ privateChatViewerLabelsByUserIds(userIds: readonly number[], options?: { signal?: AbortSignal; }): Promise>; /** * Resolve only viewer-owned contact remarks for the supplied people. * This deliberately does not fall back to a private nickname or snapshot: * callers must keep those identities in their own domain-specific order. */ privateRemarksByUserIds(userIds: readonly T[], options?: { signal?: AbortSignal; }): Promise>; invalidateGroupAvatar(userId: number, chatSessionUid: string): void; dispose(): void; createTopic(titleInput: string, parentSourceRef?: string, options?: { contextSourceRef?: string; signal?: AbortSignal; }): Promise; renameTopic(sourceRef: string, titleInput: string): Promise; /** Reuse the record owner's topic policy, without replaying title/privacy defaults. */ topicHomeVisibility(sourceRef: string, showInHome?: boolean, signal?: AbortSignal): Promise<{ showInHome: boolean; }>; /** * Dissolving a topic promotes its direct children and moves the topic's own * records into its parent. Root-topic records return to the default category. */ dissolveTopic(sourceRef: string, parentSourceRef: string | undefined, childSourceRefs: readonly string[], requestId?: string, expectedRecordCount?: number): Promise; private topicRecordUids; private moveTopicRecordsForDissolve; private rollbackDissolvedTopicRecords; private moveTopicHierarchyForDissolve; private rollbackDissolvedTopicChildren; /** Move a topic atomically, including its persisted order among siblings. */ moveTopicHierarchy(sourceRef: string, currentParentSourceRef: string | undefined, nextParentSourceRef: string | undefined, insertBeforeSourceRef: string | undefined): Promise; /** Lightweight personal-topic choices; independent of conversation cards and their summaries. */ listTopicCandidates(keyword: string, cursor?: string, signal?: AbortSignal): Promise>; listSources(directory: ArkmeSourceDirectory, options?: { limit?: number; cursor?: string; signal?: AbortSignal; refresh?: boolean; firstPaint?: boolean; background?: boolean; }): Promise; selfTarget(signal?: AbortSignal): Promise; /** * Resolve one personal topic and every visible descendant from the same * paginated directory contract used by the topic picker. Keeping this owner * here prevents a timeline read from trusting a partial browser-side tree or * exposing raw topic ids across the Host boundary. */ topicSubtreeSources(sourceRef: string, signal?: AbortSignal): Promise; private selfTargetForAccount; setChatDirectoryPin(sourceRef: string, pinned: boolean, signal?: AbortSignal): Promise; chatConversationListPreferenceEntry(sourceRef: string, signal?: AbortSignal): Promise; chatConversationListPreferenceEntryBySessionUid(chatSessionUid: string, expectedOwnerUserId: number): Promise; listGroupSources(options?: { limit?: number; cursor?: string; signal?: AbortSignal; refresh?: boolean; firstPaint?: boolean; }): Promise; countGroupSources(signal?: AbortSignal): Promise; private selfDirectoryContext; private listSourcesUncached; invalidateSourceListCache(userId: number, directory?: ArkmeSourceDirectory): void; private pruneSourceListCache; hydrateDirectoryPage(items: ArkmeSourceItem[], signal: AbortSignal): Promise; hydrateSourceAvatars(items: ArkmeSourceItem[], privateUserIdByIndex: ReadonlyMap, groupSessionUidByIndex: ReadonlyMap, session: ArkmeSessionCredentials, signal?: AbortSignal): Promise; groupAvatarPresentation(snapshot: ArkmeGroupAvatarSnapshotProjection, profiles: ReadonlyMap, viewerUserId: number): Promise; chatDirectorySourceKey(userId: number, chatSessionUid: string): Promise; chatTimelineItemKey(userId: number, chatSessionUid: string, relationUid: string): Promise; chatPreparingActorKey(viewerUserId: number, chatSessionUid: string, actorUserId: number): Promise; chatPreparingActorPresentation(viewerUserId: number, chatSessionUid: string, actorUserId: number): Promise<{ actorKey: string; avatarRef: string; }>; topicHierarchyKey(userId: number, topicUid: string): Promise; sealSourceRef(userId: number, kind: ArkmeSourceKind, ownerRef: string, displayName: string, options?: { botGroupTarget?: ArkmeGroupBotBindingTarget; chatDirectoryMetadata?: ArkmeChatDirectoryMetadata; omitDirectoryActivity?: boolean; }): Promise; openSourceRef(sourceRef: string, expectedUserId: number): Promise; sourceItem(source: ArkmeSourceRefPayload): Promise; chatSourceFromBundle(bundle: Record, session: ArkmeSessionCredentials, cached: ArkmeSourceItem | undefined, timelineItems: ArkmeTimelineItem[], options?: { previewSnapshot?: boolean; previewUpdatedAtMillis?: number; }): Promise; private encodeCursor; private decodeCursor; private encodeTopicDirectoryCursor; private decodeTopicDirectoryCursor; } export {}; //# sourceMappingURL=source-service.d.ts.map