import { MilkyClient, milky } from "@fraqjs/fraq"; import { AiService } from "@fraqjs/plugin-ai"; import { HonoService } from "@fraqjs/plugin-hono"; import { FraqDatabase, KyselyService } from "@fraqjs/plugin-kysely"; import { WebuiGatewayService } from "@fraqjs/plugin-webui-gateway"; import { Kysely } from "kysely"; //#region src/models/index.d.ts type BottleSegment = Extract | (Extract & { data: { messages?: milky.IncomingForwardedMessage[]; }; }); type BottleSignature = { type: 'anonymous'; } | { type: 'original'; } | { type: 'alias'; name: string; }; type BottleModerationMode = 'ai' | 'manual'; interface DriftBottleOptions { moderationMode?: BottleModerationMode; moderationModel?: string; ownerIds?: number[]; /** 兼容旧配置:WebUI 挂载路径已固定为 /webui/drift-bottle,此选项不再生效。 */ webuiPath?: string; /** WebUI 静态资源目录;默认使用构建产物 dist/webui。 */ webuiDirectory?: string; } interface DriftBottle { id: string; senderId: number; createdAt: number; displayName?: string; source: { scene: milky.IncomingMessage['message_scene']; peerId: number; }; segments: milky.IncomingSegment[]; } interface NewDriftBottle { senderId: number; displayName?: string; source: DriftBottle['source']; segments: BottleSegment[]; } interface BottleTextSegmentUpdate { segmentIndex: number; text: string; } type BottleUpdateInput = Pick & { content?: string; textSegments?: BottleTextSegmentUpdate[]; }; type UpdateBottleResult = { status: 'updated'; bottle: DriftBottle; } | { status: 'not-found' | 'content-read-only'; }; interface BottleComment { id: string; bottleId: string; senderId: number; createdAt: number; displayName?: string; content: string; } type NewBottleComment = Pick; type BottleOperationAction = 'bottle-created' | 'bottle-picked' | 'comment-created' | 'bottle-deleted' | 'bottle-updated' | 'signature-updated' | 'moderator-added' | 'moderator-removed' | 'repeat-pick-updated' | 'moderation-approved' | 'moderation-rejected'; interface BottleOperationRecord { id: string; createdAt: number; action: BottleOperationAction; actorId?: number; bottleId?: string; targetUserId?: number; detail?: string; } type NewBottleOperationRecord = Omit; //#endregion //#region src/processing/moderation.d.ts interface ModerationResult { approved: boolean; categories: ('profanity' | 'r18')[]; reason: string; usage?: ModerationUsage; } interface ModerationUsage { inputTokens?: number; outputTokens?: number; totalTokens?: number; } interface ModerationAttemptDiagnostic { responseTextSummary?: string; finishReason?: string; warnings: string[]; usage?: ModerationUsage; } declare class ModerationFailureError extends Error { readonly attempts: ModerationAttemptDiagnostic[]; readonly usage: ModerationUsage; constructor(cause: unknown, attempts: ModerationAttemptDiagnostic[]); } type ModerationTarget = 'bottle-content' | 'bottle-signature' | 'comment-content' | 'comment-signature' | 'profile-signature'; interface ModerationContext { target: ModerationTarget; bottleDraft?: NewDriftBottle; } type BottleModerator = (segments: BottleSegment[], context?: ModerationContext) => Promise; //#endregion //#region src/processing/moderation-records.d.ts type ModerationProcess = { manual: { reason: string; }; } | { result: Pick; } | { error: { name: string; message: string; cause?: { name: string; message: string; }; responseTextSummary?: string; finishReason?: string; providerWarnings?: string[]; attempts?: number; }; }; interface ModerationRecord { id: string; createdAt: number; content: BottleSegment[]; process: ModerationProcess; inputTokens?: number; outputTokens?: number; totalTokens?: number; success: boolean; approved?: boolean; target?: ModerationContext['target']; bottleDraft?: ModerationContext['bottleDraft']; resolution?: 'approved' | 'rejected'; resolvedBy?: number; resolvedAt?: number; rejectionReason?: string; publishedBottleId?: string; } type NewModerationRecord = Omit; //#endregion //#region src/persistence/bottle-store.d.ts interface PersistedWebuiSettings { moderationMode?: BottleModerationMode; moderationModel?: string; ownerIds: unknown; webuiPath: string; } type ApproveModerationRecordResult = { status: 'approved'; bottle: DriftBottle; } | { status: 'not-found' | 'already-resolved' | 'not-pending' | 'publish-unavailable'; }; type RejectModerationRecordResult = { status: 'rejected'; } | { status: 'not-found' | 'already-resolved' | 'not-pending' | 'invalid-reason'; }; declare class BottleStore { private readonly database; private disposeTestDatabase?; constructor(database: Kysely, disposeTestDatabase?: (() => Promise) | undefined); dispose(): Promise; add(input: NewDriftBottle): Promise; pick(removeAfterPick: boolean, randomValue?: number): Promise; count(): Promise; bottles(limit?: number, offset?: number): Promise; bottle(id: string): Promise; updateBottle(id: string, input: NewDriftBottle): Promise; deleteBottle(id: string): Promise; hasBottle(id: string): Promise; isBottleOwner(id: string, userId: number): Promise; addComment(input: NewBottleComment): Promise; commentsFor(bottleId: string, limit?: number): Promise; commentCount(bottleId: string): Promise; addModerator(userId: number): Promise; removeModerator(userId: number): Promise; isModerator(userId: number): Promise; moderators(): Promise; setRepeatPick(userId: number, enabled?: boolean): Promise; repeatPickFor(userId: number): Promise; addModerationRecord(input: NewModerationRecord): Promise; moderationRecords(limit?: number): Promise; pendingModerationRecords(limit?: number, offset?: number): Promise; pendingModerationCount(): Promise; approveModerationRecord(id: string, actorId?: number): Promise; rejectModerationRecord(id: string, actorId: number | undefined, reason: string): Promise; addOperationRecord(input: NewBottleOperationRecord): Promise; operationRecords(limit?: number): Promise; webuiSettings(): Promise; setWebuiSettings(settings: Omit & { ownerIds: number[]; }): Promise; setSignature(senderId: number, signature: BottleSignature): Promise; signatureFor(senderId: number): Promise; } //#endregion //#region src/api/drift-bottle-api.d.ts type DriftBottleApiErrorCode = 'read-reply' | 'read-forward' | 'moderation' | 'resolve-signature' | 'publish-comment'; declare class DriftBottleApiError extends Error { readonly code: DriftBottleApiErrorCode; constructor(code: DriftBottleApiErrorCode, options?: ErrorOptions); } type CreateBottleResult = { status: 'created'; bottle: DriftBottle; } | { status: 'pending'; reviewId: string; } | { status: 'empty'; } | { status: 'unsupported'; } | { status: 'rejected'; target: 'content' | 'signature'; reason: string; }; type PublishCommentResult = { status: 'created'; comment: BottleComment; } | { status: 'not-found'; } | { status: 'too-long'; } | { status: 'rejected'; target: 'content' | 'signature'; reason: string; }; type UpdateSignatureResult = { status: 'updated'; } | { status: 'too-long'; } | { status: 'rejected'; reason: string; }; interface BottleComments { comments: BottleComment[]; total: number; } type BottleImageResult = { status: 'found'; url: string; } | { status: 'not-found' | 'not-image' | 'unavailable'; }; declare class DriftBottleApi { private readonly client; private readonly store; private readonly moderator; private readonly moderationMode; constructor(client: MilkyClient, store: BottleStore, moderator: BottleModerator, moderationMode?: () => BottleModerationMode); createBottle(message: milky.IncomingMessage, content: milky.IncomingSegment[]): Promise; pickBottle(userId: number, randomValue?: number): Promise; outgoingSegments(bottle: DriftBottle, userId?: number): Promise; publishComment(message: milky.IncomingMessage, bottleId: string, content: string): Promise; commentsFor(bottleId: string, limit?: number): Promise; commentCountFor(bottleId: string): Promise; bottleImage(bottleId: string, segmentIndex: number): Promise; bottleIdFromReply(reply: Extract, message: milky.IncomingMessage): Promise; updateSignature(message: milky.IncomingMessage, signature: BottleSignature): Promise; signatureFor(userId: number): Promise; hasBottle(id: string): Promise; isBottleOwner(id: string, userId: number): Promise; deleteBottle(id: string, actorId?: number): Promise; addModerator(userId: number, actorId?: number): Promise; removeModerator(userId: number, actorId?: number): Promise; isModerator(userId: number): Promise; moderators(): Promise; setRepeatPick(userId: number, enabled?: boolean): Promise; repeatPickFor(userId: number): Promise; moderationRecords(limit?: number): Promise; pendingModerationRecords(limit?: number, offset?: number): Promise; pendingModerationCount(): Promise; approveModerationRecord(id: string, actorId?: number): Promise; rejectModerationRecord(id: string, actorId: number | undefined, reason: string): Promise; operationRecords(limit?: number): Promise; add(input: NewDriftBottle, actorId?: number): Promise; updateBottle(id: string, input: BottleUpdateInput, actorId?: number): Promise; count(): Promise; bottles(limit?: number, offset?: number): Promise; private moderate; private resolveSignature; private resolveApprovedSignature; } //#endregion //#region src/webui/dashboard.d.ts interface DashboardRelease { version: string; items: string[]; } interface DashboardOperation { id: string; createdAt: number; title: string; detail?: string; tone: 'neutral' | 'success' | 'warning' | 'danger'; } interface DashboardRuntimeInfo { fraqVersion: string; protocolEndpoint?: { name: string; version: string; }; } interface DashboardSnapshot { generatedAt: number; instanceStartedAt: number; counts: { totalBottles: number; pendingReview: number; }; changelog: DashboardRelease[]; operations: DashboardOperation[]; runtime: DashboardRuntimeInfo; } //#endregion //#region src/webui/lists.d.ts interface WebuiContentSummary { preview: string; kinds: string[]; parts: WebuiContentPart[]; } interface WebuiContentPart { segmentIndex: number; text: string; faceId?: string; imageSegmentIndex?: number; forwardMessages?: WebuiForwardMessage[]; forwardMessageCount?: number; } interface WebuiForwardMessage { sequence: number; sender: string; markdown: string; } interface WebuiPendingReviewItem { id: string; createdAt: number; content: WebuiContentSummary; status: 'pending' | 'rejected' | 'error'; reason: string; categories: string[]; totalTokens?: number; target: string; canApprove: boolean; bottleDraft?: { senderId: number; displayName?: string; source: { scene: string; peerId: number; }; }; } interface WebuiBottleListItem { id: string; createdAt: number; commentCount: number; senderId: number; displayName?: string; editableText?: string; editableTextSegments: { segmentIndex: number; text: string; }[]; content: WebuiContentSummary; source: { scene: string; peerId: number; }; } interface WebuiListPage { generatedAt: number; page: number; pageSize: number; total: number; totalPages: number; items: T[]; } //#endregion //#region src/index.d.ts declare const _default: import("@fraqjs/fraq").Plugin<[options?: DriftBottleOptions | undefined], { ai: typeof AiService; hono: typeof HonoService; kysely: typeof KyselyService; webuiGateway: typeof WebuiGatewayService; }, import("@fraqjs/fraq").Injection | undefined>; //#endregion export { type ApproveModerationRecordResult, type BottleComment, type BottleComments, type BottleModerationMode, type BottleOperationAction, type BottleOperationRecord, type BottleSegment, type BottleSignature, type CreateBottleResult, type DashboardOperation, type DashboardRelease, type DashboardRuntimeInfo, type DashboardSnapshot, type DriftBottle, DriftBottleApi, DriftBottleApiError, type DriftBottleApiErrorCode, type DriftBottleOptions, type ModerationAttemptDiagnostic, type ModerationContext, ModerationFailureError, type ModerationProcess, type ModerationRecord, type ModerationTarget, type NewBottleComment, type NewBottleOperationRecord, type NewDriftBottle, type PublishCommentResult, type RejectModerationRecordResult, type UpdateSignatureResult, type WebuiBottleListItem, type WebuiContentSummary, type WebuiListPage, type WebuiPendingReviewItem, _default as default };