feat: force a seller scan over active conversations from the inbox
Adds a "Scan for sellers" button to the conversations header, backed by POST /api/conversations/seller-scan. The sweep reuses the existing seller detection rather than inventing a second one: the configured keyword/domain list, the seller-link funnel patterns, and the aiReplyScreening confidences all decide the verdict, so a swept conversation lands in the state the live reply loop would have given it. Being operator-forced, it deliberately ignores filterSellers and aiReplyScreening.enabled. AI is the last resort. Conversations are skipped when already flagged or killed, settled for free by the deterministic rules, or skipped against a durable sellerScreenedKey watermark when nothing new has arrived since the last clean sweep. Only the remainder reaches the model, batched eight at a time through a new screenConversationsForSellers, so the system prompt and round trip are paid per batch instead of per conversation. A classifier outage degrades the sweep instead of failing it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0a4e0064f2
commit
827eb3a1e0
15 files changed
+1169
-1
No files matched your search
@@ -13,6 +13,7 @@ import {
|
||||
SuggestedReplyResponseSchema,
|
||||
BulkMarkConversationsReadRequestSchema,
|
||||
BulkMarkConversationsReadResponseSchema,
|
||||
SellerScanResponseSchema,
|
||||
MarkConversationReadRequestSchema,
|
||||
MarkConversationUnreadRequestSchema,
|
||||
SetConversationStatusRequestSchema,
|
||||
@@ -22,6 +23,7 @@ import {
|
||||
type ConversationMediaShareOptions,
|
||||
type ConversationTriageStatus,
|
||||
type ProcessedPost,
|
||||
type SellerScanResponse,
|
||||
type SuccessResponse,
|
||||
} from '../../../../../packages/api-contracts/src/index.js';
|
||||
import { createDashboardRequest } from '../../api/request.js';
|
||||
@@ -53,6 +55,7 @@ export interface ConversationApi {
|
||||
markUnread(id: string, beforeTimestamp?: number): Promise<SuccessResponse>;
|
||||
setStatus(id: string, status: ConversationTriageStatus, snoozeUntil?: number | null): Promise<SuccessResponse>;
|
||||
bulkMarkRead(ids: string[]): Promise<BulkMarkConversationsReadResponse>;
|
||||
sellerScan(): Promise<SellerScanResponse>;
|
||||
}
|
||||
|
||||
function jsonPost(body: unknown): RequestInit {
|
||||
@@ -174,6 +177,12 @@ export function createConversationApi(fetchImplementation?: typeof fetch): Conve
|
||||
BulkMarkConversationsReadResponseSchema,
|
||||
);
|
||||
},
|
||||
async sellerScan() {
|
||||
return parseResponse(
|
||||
await request('/api/conversations/seller-scan', { method: 'POST' }),
|
||||
SellerScanResponseSchema,
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user