Add monitoring service and database schema
- Implement monitoring service with heartbeat, lease tasks, resume tasks, and task result handling. - Create monitoring time utilities for business date calculations. - Add unit tests for date window resolution and business day handling. - Define database schema for monitoring-related tables including quotas, daily reports, and task management. - Establish migration scripts for creating and dropping monitoring tables.
This commit is contained in:
@@ -403,6 +403,183 @@ export interface PublisherPluginPingResponse {
|
||||
plugin_installation_id?: number | null;
|
||||
}
|
||||
|
||||
export interface MonitoringLocalPlatformState {
|
||||
ai_platform_id: string;
|
||||
connected: boolean;
|
||||
accessible: boolean;
|
||||
detected_at?: string | null;
|
||||
reason_code?: string | null;
|
||||
reason_message?: string | null;
|
||||
message?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringPluginPingResponse {
|
||||
installed: boolean;
|
||||
version?: string;
|
||||
capabilities?: Array<"ping" | "detect" | "heartbeat" | "lease" | "background">;
|
||||
installation_key?: string;
|
||||
plugin_installation_id?: number | null;
|
||||
}
|
||||
|
||||
export interface MonitoringHeartbeatPlatformPayload {
|
||||
ai_platform_id: string;
|
||||
access_status?: string | null;
|
||||
connected?: boolean | null;
|
||||
accessible?: boolean | null;
|
||||
detected_at?: string | null;
|
||||
reason_code?: string | null;
|
||||
reason_message?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringHeartbeatPayload {
|
||||
platforms: MonitoringHeartbeatPlatformPayload[];
|
||||
}
|
||||
|
||||
export interface MonitoringHeartbeatResponse {
|
||||
installation_id: number;
|
||||
business_date: string;
|
||||
updated_platform_count: number;
|
||||
reconciled_skipped_task_count: number;
|
||||
}
|
||||
|
||||
export interface MonitoringHeartbeatSyncResult {
|
||||
success: boolean;
|
||||
source: "remote" | "local";
|
||||
platform_states: MonitoringLocalPlatformState[];
|
||||
heartbeat?: MonitoringHeartbeatResponse | null;
|
||||
message?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringLeaseTasksPayload {
|
||||
limit?: number;
|
||||
ai_platform_ids?: string[];
|
||||
}
|
||||
|
||||
export interface MonitoringResumeTasksPayload {
|
||||
ai_platform_ids?: string[];
|
||||
}
|
||||
|
||||
export interface MonitoringLeaseTask {
|
||||
task_id: number;
|
||||
brand_id: number;
|
||||
question_id: number;
|
||||
question_hash: string;
|
||||
question_text: string;
|
||||
ai_platform_id: string;
|
||||
platform_name: string;
|
||||
collector_type: string;
|
||||
run_mode: string;
|
||||
trigger_source: string;
|
||||
business_date: string;
|
||||
lease_token: string;
|
||||
lease_expires_at: string;
|
||||
}
|
||||
|
||||
export interface MonitoringLeaseTasksResponse {
|
||||
business_date: string;
|
||||
lease_count: number;
|
||||
tasks: MonitoringLeaseTask[];
|
||||
}
|
||||
|
||||
export interface MonitoringResumeTasksResponse {
|
||||
business_date: string;
|
||||
resume_count: number;
|
||||
tasks: MonitoringLeaseTask[];
|
||||
}
|
||||
|
||||
export interface MonitoringCycleResult {
|
||||
success: boolean;
|
||||
leased_task_count: number;
|
||||
processed_task_count: number;
|
||||
failed_task_count: number;
|
||||
skipped_task_count: number;
|
||||
message?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringCycleKickoffResponse {
|
||||
accepted: boolean;
|
||||
status: "started" | "already_running";
|
||||
message?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringSourceItem {
|
||||
url: string;
|
||||
title?: string | null;
|
||||
site_name?: string | null;
|
||||
site_key?: string | null;
|
||||
normalized_url?: string | null;
|
||||
host?: string | null;
|
||||
registrable_domain?: string | null;
|
||||
subdomain?: string | null;
|
||||
suffix?: string | null;
|
||||
article_id?: number | null;
|
||||
publish_record_id?: number | null;
|
||||
resolution_status?: string | null;
|
||||
resolution_confidence?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringTaskResultPayload {
|
||||
lease_token: string;
|
||||
status: "succeeded" | "failed";
|
||||
provider_model?: string | null;
|
||||
provider_request_id?: string | null;
|
||||
request_id?: string | null;
|
||||
answer?: string | null;
|
||||
raw_response_json?: Record<string, JsonValue>;
|
||||
citations?: MonitoringSourceItem[];
|
||||
search_results?: MonitoringSourceItem[];
|
||||
brand_mentioned?: boolean | null;
|
||||
brand_mention_position?: string | null;
|
||||
first_recommended?: boolean | null;
|
||||
sentiment_label?: string | null;
|
||||
matched_brand_terms?: string[];
|
||||
error_message?: string | null;
|
||||
completed_at?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringTaskResultResponse {
|
||||
task_id: number;
|
||||
run_id?: number | null;
|
||||
task_status: string;
|
||||
citation_source_count: number;
|
||||
content_citation_count: number;
|
||||
}
|
||||
|
||||
export interface MonitoringSkipTaskPayload {
|
||||
lease_token: string;
|
||||
skip_reason?: string | null;
|
||||
error_message?: string | null;
|
||||
completed_at?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringSkipTaskResponse {
|
||||
task_id: number;
|
||||
task_status: string;
|
||||
skip_reason: string;
|
||||
completed_at?: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringRuntimeStateSnapshot {
|
||||
installation_key: string;
|
||||
plugin_installation_id: number | null;
|
||||
api_base_url: string | null;
|
||||
monitoring_last_heartbeat_at: string | null;
|
||||
monitoring_last_heartbeat_status: string | null;
|
||||
monitoring_last_cycle_at: string | null;
|
||||
monitoring_last_cycle_status: string | null;
|
||||
monitoring_platforms: Array<
|
||||
MonitoringLocalPlatformState & {
|
||||
platform_name: string;
|
||||
short_name: string;
|
||||
accent_color: string;
|
||||
home_url: string;
|
||||
login_url: string | null;
|
||||
access_requirement: "login_required" | "anonymous_allowed";
|
||||
cookie_domains: string[];
|
||||
}
|
||||
>;
|
||||
}
|
||||
|
||||
export interface RegisterPluginInstallationRequest {
|
||||
installation_key: string;
|
||||
installation_name: string;
|
||||
@@ -538,6 +715,155 @@ export interface Competitor {
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface MonitoringOverview {
|
||||
collection_mode: string;
|
||||
mention_rate: number | null;
|
||||
top1_mention_rate: number | null;
|
||||
first_recommend_rate: number | null;
|
||||
positive_mention_rate: number | null;
|
||||
citation_rate: number | null;
|
||||
desired_sample_count: number;
|
||||
planned_sample_count: number;
|
||||
actual_sample_count: number;
|
||||
coverage_rate: number | null;
|
||||
confidence_level: string;
|
||||
last_sampled_at: string | null;
|
||||
last_trigger_source: string | null;
|
||||
prev_snapshot_mention_rate: number | null;
|
||||
prev_snapshot_top1_mention_rate: number | null;
|
||||
prev_snapshot_first_recommend_rate: number | null;
|
||||
prev_snapshot_positive_mention_rate: number | null;
|
||||
}
|
||||
|
||||
export interface MonitoringPlatformBreakdownItem {
|
||||
ai_platform_id: string;
|
||||
platform_name: string;
|
||||
mention_rate: number | null;
|
||||
top1_mention_rate: number | null;
|
||||
platform_sample_status: string;
|
||||
actual_sample_count: number;
|
||||
last_sampled_at: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringTimeBucket {
|
||||
date: string;
|
||||
sample_status: string;
|
||||
metric_value: number | null;
|
||||
mention_rate: number | null;
|
||||
top1_mention_rate: number | null;
|
||||
first_recommend_rate: number | null;
|
||||
positive_mention_rate: number | null;
|
||||
citation_rate: number | null;
|
||||
planned_sample_count: number;
|
||||
actual_sample_count: number;
|
||||
coverage_rate: number | null;
|
||||
trigger_source: string | null;
|
||||
snapshot_updated_at: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringHotQuestion {
|
||||
question_id: number;
|
||||
question_hash: string;
|
||||
question_text: string;
|
||||
mention_rate: number | null;
|
||||
last_sampled_at: string | null;
|
||||
}
|
||||
|
||||
export interface MonitoringCitationRankingItem {
|
||||
ai_platform_id: string;
|
||||
platform_name: string;
|
||||
sample_status: string;
|
||||
cited_answer_count: number;
|
||||
cited_article_count: number;
|
||||
citation_rate: number | null;
|
||||
}
|
||||
|
||||
export interface MonitoringCitedArticle {
|
||||
article_id: number;
|
||||
article_title: string;
|
||||
publish_platform: string;
|
||||
citation_count: number;
|
||||
citation_rate: number | null;
|
||||
}
|
||||
|
||||
export interface MonitoringDashboardCompositeResponse {
|
||||
overview: MonitoringOverview;
|
||||
platform_breakdown: MonitoringPlatformBreakdownItem[];
|
||||
brand_time_buckets: MonitoringTimeBucket[];
|
||||
hot_questions: MonitoringHotQuestion[];
|
||||
citation_ranking: MonitoringCitationRankingItem[];
|
||||
cited_articles: MonitoringCitedArticle[];
|
||||
}
|
||||
|
||||
export interface MonitoringQuestionDetailCitation {
|
||||
cited_url: string;
|
||||
cited_title: string | null;
|
||||
site_name: string;
|
||||
site_key: string;
|
||||
favicon_url: string;
|
||||
article_id: number | null;
|
||||
article_title?: string | null;
|
||||
resolution_status: string;
|
||||
resolution_confidence: string;
|
||||
}
|
||||
|
||||
export interface MonitoringQuestionDetailPlatform {
|
||||
ai_platform_id: string;
|
||||
platform_name: string;
|
||||
sample_status: string;
|
||||
run_id: number | null;
|
||||
sampled_at: string | null;
|
||||
provider_model: string | null;
|
||||
answer_text: string | null;
|
||||
brand_mentioned: boolean | null;
|
||||
brand_mention_position: string | null;
|
||||
citations: MonitoringQuestionDetailCitation[];
|
||||
}
|
||||
|
||||
export interface MonitoringQuestionCitationAnalysisItem {
|
||||
ai_platform_id: string;
|
||||
platform_name: string;
|
||||
site_name: string;
|
||||
site_key: string;
|
||||
site_domain: string;
|
||||
citation_count: number;
|
||||
citation_rate: number | null;
|
||||
content_citation_count: number;
|
||||
}
|
||||
|
||||
export interface MonitoringQuestionContentCitation {
|
||||
article_id: number;
|
||||
article_title: string;
|
||||
publish_platform: string;
|
||||
ai_platform_id: string;
|
||||
platform_name: string;
|
||||
citation_count: number;
|
||||
citation_rate: number | null;
|
||||
}
|
||||
|
||||
export interface MonitoringQuestionDetailResponse {
|
||||
question_id: number;
|
||||
question_hash: string;
|
||||
question_text: string;
|
||||
time_window: {
|
||||
date_from: string;
|
||||
date_to: string;
|
||||
};
|
||||
platforms: MonitoringQuestionDetailPlatform[];
|
||||
citation_analysis: MonitoringQuestionCitationAnalysisItem[];
|
||||
content_citations: MonitoringQuestionContentCitation[];
|
||||
}
|
||||
|
||||
export interface MonitoringCollectNowResponse {
|
||||
collection_mode: string;
|
||||
refreshed_task_count: number;
|
||||
created_task_count?: number;
|
||||
leased_task_count: number;
|
||||
completed_task_count: number;
|
||||
has_effective_snapshot: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface KnowledgeGroup {
|
||||
id: number;
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user