- 新增小红书前端模块(启动服务、内容分析、爆款创作、发布记录、技能卡片、拟人设置、AI 助手) - 新增 xhs-agent-desktop 独立桌面 Agent,对接 OMS 任务调度 - 登录页重构,整合微信登录与 OMS JWT 认证 - 订单、渠道、用户中心等页面与 API 增强 Co-authored-by: Cursor <cursoragent@cursor.com>
203 lines
6.4 KiB
TypeScript
203 lines
6.4 KiB
TypeScript
/** 拟人配置默认值(对齐 LIKE AI human_behavior.py / human_guard.py) */
|
||
|
||
export type MsRange = { min_ms: number; max_ms: number };
|
||
export type BrowsePlan = Record<string, number>;
|
||
|
||
export interface GuardConfig {
|
||
enabled: boolean;
|
||
publish: {
|
||
max_per_day: number;
|
||
min_interval_hours: number;
|
||
pre_delay_min_sec: number;
|
||
pre_delay_max_sec: number;
|
||
warmup_enabled: boolean;
|
||
warmup_pause_min_sec: number;
|
||
warmup_pause_max_sec: number;
|
||
post_stay_min_sec: number;
|
||
post_stay_max_sec: number;
|
||
};
|
||
browse: {
|
||
min_interval_sec: number;
|
||
max_interval_sec: number;
|
||
max_per_hour: number;
|
||
};
|
||
interact: {
|
||
min_interval_sec: number;
|
||
max_per_day: number;
|
||
};
|
||
quiet_hours: {
|
||
enabled: boolean;
|
||
start: string;
|
||
end: string;
|
||
};
|
||
content: {
|
||
max_title_len: number;
|
||
warn_extreme_words: boolean;
|
||
};
|
||
}
|
||
|
||
export interface BehaviorConfig {
|
||
default_max_attempts: number;
|
||
stagnant_limit: number;
|
||
min_scroll_delta: number;
|
||
max_click_per_round: number;
|
||
stagnant_check_threshold: number;
|
||
large_scroll_trigger: number;
|
||
button_click_interval: number;
|
||
final_sprint_push_count: number;
|
||
human_delay: MsRange;
|
||
reaction_time: MsRange;
|
||
hover_time: MsRange;
|
||
read_time: MsRange;
|
||
short_read: MsRange;
|
||
scroll_wait: MsRange;
|
||
post_scroll: MsRange;
|
||
navigation_delay: MsRange;
|
||
scroll_slow: { interval_base_ms: number; interval_jitter_ms: number; scroll_ratio: number };
|
||
scroll_normal: { interval_base_ms: number; interval_jitter_ms: number; scroll_ratio: number };
|
||
scroll_fast: { interval_base_ms: number; interval_jitter_ms: number; scroll_ratio: number };
|
||
home_browse_plan: BrowsePlan;
|
||
search_browse_plan: BrowsePlan;
|
||
inaccessible_keywords: string[];
|
||
}
|
||
|
||
export function defaultBrowsePlan(): BrowsePlan {
|
||
return {
|
||
stable_sec_lo: 2,
|
||
stable_sec_hi: 3,
|
||
scroll_lo: 8,
|
||
scroll_hi: 15,
|
||
click_lo: 1,
|
||
click_hi: 3,
|
||
sprint_sec_lo: 4,
|
||
sprint_sec_hi: 6,
|
||
parse_sec_lo: 1.5,
|
||
parse_sec_hi: 2.5,
|
||
detail_stay_sec_lo: 10,
|
||
detail_stay_sec_hi: 20,
|
||
detail_scroll_lo: 3,
|
||
detail_scroll_hi: 6,
|
||
};
|
||
}
|
||
|
||
export function defaultBehavior(): BehaviorConfig {
|
||
return {
|
||
default_max_attempts: 500,
|
||
stagnant_limit: 20,
|
||
min_scroll_delta: 10,
|
||
max_click_per_round: 3,
|
||
stagnant_check_threshold: 2,
|
||
large_scroll_trigger: 5,
|
||
button_click_interval: 3,
|
||
final_sprint_push_count: 15,
|
||
human_delay: { min_ms: 300, max_ms: 700 },
|
||
reaction_time: { min_ms: 300, max_ms: 800 },
|
||
hover_time: { min_ms: 100, max_ms: 300 },
|
||
read_time: { min_ms: 500, max_ms: 1200 },
|
||
short_read: { min_ms: 600, max_ms: 1200 },
|
||
scroll_wait: { min_ms: 100, max_ms: 200 },
|
||
post_scroll: { min_ms: 300, max_ms: 500 },
|
||
navigation_delay: { min_ms: 1000, max_ms: 2500 },
|
||
scroll_slow: { interval_base_ms: 1200, interval_jitter_ms: 300, scroll_ratio: 0.5 },
|
||
scroll_normal: { interval_base_ms: 600, interval_jitter_ms: 200, scroll_ratio: 0.7 },
|
||
scroll_fast: { interval_base_ms: 300, interval_jitter_ms: 100, scroll_ratio: 0.9 },
|
||
home_browse_plan: { ...defaultBrowsePlan(), scroll_lo: 16, scroll_hi: 51, click_lo: 2, click_hi: 8 },
|
||
search_browse_plan: { ...defaultBrowsePlan(), scroll_lo: 13, scroll_hi: 39, click_lo: 1, click_hi: 5 },
|
||
inaccessible_keywords: [
|
||
'当前笔记暂时无法浏览',
|
||
'该内容因违规已被删除',
|
||
'该笔记已被删除',
|
||
'内容不存在',
|
||
'笔记不存在',
|
||
'已失效',
|
||
'私密笔记',
|
||
'仅作者可见',
|
||
'因用户设置,你无法查看',
|
||
'因违规无法查看',
|
||
],
|
||
};
|
||
}
|
||
|
||
export function defaultGuard(): GuardConfig {
|
||
return {
|
||
enabled: true,
|
||
publish: {
|
||
max_per_day: 2,
|
||
min_interval_hours: 6,
|
||
pre_delay_min_sec: 60,
|
||
pre_delay_max_sec: 180,
|
||
warmup_enabled: true,
|
||
warmup_pause_min_sec: 30,
|
||
warmup_pause_max_sec: 90,
|
||
post_stay_min_sec: 0,
|
||
post_stay_max_sec: 0,
|
||
},
|
||
browse: {
|
||
min_interval_sec: 25,
|
||
max_interval_sec: 45,
|
||
max_per_hour: 20,
|
||
},
|
||
interact: {
|
||
min_interval_sec: 45,
|
||
max_per_day: 10,
|
||
},
|
||
quiet_hours: {
|
||
enabled: true,
|
||
start: '02:00',
|
||
end: '07:00',
|
||
},
|
||
content: {
|
||
max_title_len: 20,
|
||
warn_extreme_words: true,
|
||
},
|
||
};
|
||
}
|
||
|
||
export function mergeBehavior(raw: unknown): BehaviorConfig {
|
||
const base = defaultBehavior();
|
||
if (!raw || typeof raw !== 'object') return base;
|
||
const r = raw as Record<string, unknown>;
|
||
return {
|
||
...base,
|
||
...r,
|
||
human_delay: { ...base.human_delay, ...(r.human_delay as object) },
|
||
reaction_time: { ...base.reaction_time, ...(r.reaction_time as object) },
|
||
hover_time: { ...base.hover_time, ...(r.hover_time as object) },
|
||
read_time: { ...base.read_time, ...(r.read_time as object) },
|
||
short_read: { ...base.short_read, ...(r.short_read as object) },
|
||
scroll_wait: { ...base.scroll_wait, ...(r.scroll_wait as object) },
|
||
post_scroll: { ...base.post_scroll, ...(r.post_scroll as object) },
|
||
navigation_delay: { ...base.navigation_delay, ...(r.navigation_delay as object) },
|
||
scroll_slow: { ...base.scroll_slow, ...(r.scroll_slow as object) },
|
||
scroll_normal: { ...base.scroll_normal, ...(r.scroll_normal as object) },
|
||
scroll_fast: { ...base.scroll_fast, ...(r.scroll_fast as object) },
|
||
home_browse_plan: { ...base.home_browse_plan, ...(r.home_browse_plan as object) },
|
||
search_browse_plan: { ...base.search_browse_plan, ...(r.search_browse_plan as object) },
|
||
inaccessible_keywords: Array.isArray(r.inaccessible_keywords)
|
||
? r.inaccessible_keywords.map(String)
|
||
: base.inaccessible_keywords,
|
||
} as BehaviorConfig;
|
||
}
|
||
|
||
export function mergeGuard(raw: unknown): GuardConfig {
|
||
const base = defaultGuard();
|
||
if (!raw || typeof raw !== 'object') return base;
|
||
const r = raw as Record<string, unknown>;
|
||
return {
|
||
...base,
|
||
enabled: r.enabled !== undefined ? Boolean(r.enabled) : base.enabled,
|
||
publish: { ...base.publish, ...(r.publish as object) },
|
||
browse: { ...base.browse, ...(r.browse as object) },
|
||
interact: { ...base.interact, ...(r.interact as object) },
|
||
quiet_hours: { ...base.quiet_hours, ...(r.quiet_hours as object) },
|
||
content: { ...base.content, ...(r.content as object) },
|
||
};
|
||
}
|
||
|
||
export function applyClickFromScroll(plan: BrowsePlan) {
|
||
const lo = Math.max(0, Math.floor((plan.scroll_lo ?? 0) / 3));
|
||
const hi = Math.max(lo, Math.ceil((plan.scroll_hi ?? 0) / 3));
|
||
plan.click_lo = lo;
|
||
plan.click_hi = hi;
|
||
}
|