assistant/renderer/types.ts

448 lines
12 KiB
TypeScript

export type TaskStatus =
| 'collecting'
| 'running'
| 'paused'
| 'submitted'
| 'completed'
| 'failed'
| 'blocked'
| 'rejected'
| 'cancelled';
export const STATUS_LABEL: Record<TaskStatus, string> = {
collecting: '等待补充信息',
running: '正在执行',
paused: '等待你的回答',
submitted: '已提交',
completed: '已完成',
failed: '未完成',
blocked: '需要处理',
rejected: '已驳回',
cancelled: '已停止',
};
export const TERMINAL_STATUSES: TaskStatus[] = ['submitted', 'completed', 'failed', 'blocked', 'rejected', 'cancelled'];
export interface TaskSummary {
id: string;
status: TaskStatus;
current_step: string | null;
goal: string;
business_name: string | null;
created_at: string;
updated_at: string;
next_check_at: string | null;
}
export interface PendingBlocker {
id: string;
title?: string;
resolution?: string;
message?: string;
advice?: string;
}
export interface TrackingEntry {
at: string;
status: string;
verdict: string;
note: string;
}
export interface TrackingState {
checks: number;
history: TrackingEntry[];
max_checks?: number;
}
export interface TaskInputs {
goal?: string;
business_id?: string;
pending_blocker?: PendingBlocker;
[key: string]: unknown;
}
export interface TaskArtifacts {
summary?: string;
tracking?: TrackingState;
leads?: ProspectLead[];
coverage_note?: string;
browser_summary?: string;
messages?: ChatMessage[];
plan?: { summary?: string; stages?: string[]; missing?: string[]; assumptions?: string[] };
stop_reason?: string | { code?: string; message?: string };
stop_detail?: string;
feedback?: TaskFeedbackValue | TaskFeedbackValue[];
business_outcomes?: BusinessOutcomeEvent[];
alternatives?: (string | RecoveryRoute)[];
exports?: ExportFile[];
[key: string]: unknown;
}
export interface TaskFeedbackValue {
rating: 'up' | 'down';
reason?: string;
at?: string;
result_version?: string | number;
}
export type BusinessOutcomeValue = 'replied' | 'need_confirmed' | 'cooperated' | 'no_reply' | 'not_relevant';
export interface BusinessOutcomeEvent {
id: string;
source_id: string;
outcome: BusinessOutcomeValue;
note?: string;
at?: string;
source: 'user';
attribution?: string;
}
export interface Task {
id: string;
status: TaskStatus;
current_step: string | null;
inputs: TaskInputs;
artifacts: TaskArtifacts;
pause_reason: string | null;
next_check_at: string | null;
created_at: string;
updated_at: string;
business_name?: string | null;
reply?: string | null;
latest_screenshot?: string | null;
live_session?: boolean;
takeover?: boolean;
progress_doc_path?: string | null;
needs_input?: string[];
ui?: TaskUi;
}
export interface ClarificationField {
id: string;
key: 'product' | 'target_customer' | 'region' | 'action_scope' | 'message_text' | 'target_candidates' | 'context';
label: string;
input_kind: 'text' | 'textarea' | 'number';
required: boolean;
prefill: string;
options: string[];
min?: number;
step?: number;
}
export interface Clarification {
id: string;
goal_version: number;
status: 'active';
fields: ClarificationField[];
}
export interface PhaseState {
id: string;
title: string;
status: TaskStatus;
current_step: string;
detail: string;
counts: { notes: number; comments: number; replies: number; profiles: number; leads: number };
events: { id: string; title: string; status: string; detail: string; at: string | null }[];
coverage: { observed_keywords: string[]; pending_keywords: string[] };
stages: string[];
}
export interface ExportFile {
id: string;
path: string;
filename: string;
count: number;
format: 'csv';
generated_at: string;
result_version: string;
goal_version: number;
download_url: string;
is_current: boolean;
available?: boolean;
}
export interface RecoveryRoute {
id?: 'review' | 'export';
title: string;
reason?: string;
description?: string;
deliverable?: string;
status?: string;
action?: 'review_saved' | 'export';
enabled?: boolean;
disabled_reason?: string;
message?: string;
prompt?: string;
}
export interface TaskUi {
version: 1;
goal_version: number;
result_version: string;
clarification: Clarification | null;
phase: PhaseState;
delivery: { result_version: string; goal_version: number; lead_count: number; source_count: number; exports: ExportFile[] };
recovery: { reason: string; detail: string; routes: RecoveryRoute[]; underlying_reason?: string; underlying_detail?: string } | null;
goal_progress?: GoalProgress;
delivery_status?: DeliveryStatus;
usage?: ModelUsage;
}
export interface EvidenceBadge {
status: string;
label: string;
detail?: string;
evidence?: { source_id?: string; quote?: string }[];
source_ids?: string[];
}
export interface CandidateBadges {
demand: EvidenceBadge;
identity: EvidenceBadge;
region: EvidenceBadge;
account: EvidenceBadge;
outreach: EvidenceBadge;
business?: EvidenceBadge;
}
export interface CandidateMissingField {
key: string;
label: string;
required?: boolean;
}
export interface DeliveryPerson {
person_key: string;
eligible: boolean;
group: 'eligible' | 'supplemental' | 'unresolved';
badges: CandidateBadges;
missing: (string | CandidateMissingField)[];
}
export interface PreflightSummary {
version: 1;
completed: boolean;
run_available: boolean;
recorded: boolean;
visited_known: boolean;
inspected_notes: number;
visited_notes: number;
checked_count: number;
eligible_count: number;
classification_counts: { unique_dom_deep_reply: number; needs_native_identity: number; ambiguous: number; unknown: number };
not_in_view_notes: number;
unknown_notes: number;
folded_notes: number;
folded_unknown_notes: number;
scope_passed: boolean | null;
history_truncated: boolean;
max_notes: number | null;
unknown_click_blocked_count: number;
headline: string;
detail: string;
notes: { ordinal: number; inspected: boolean; status: 'inspected' | 'not_in_view' | 'unknown'; checked_count: number; eligible_count: number; has_unexpanded_replies: boolean | null }[];
}
export interface DeliveryStatus {
version: 1;
status: 'fulfilled' | 'partial' | 'in_progress' | 'no_evidence' | 'no_matches' | 'unknown';
headline: string;
runtime: { status: string; step?: string; stop_reason?: unknown; stop_detail?: string; raw_browser_success?: boolean | null };
fulfillment: { scope_met: boolean; requirements_met: boolean; complete: boolean; assessment_current: boolean; target: number | null; current: number; remaining: number | null };
artifacts: { list_available: boolean; file_required: boolean; file_available: boolean; delivered: boolean; export_count: number };
counts: { eligible: number; known_identity: number; supplemental: number; unresolved: number; signals: number; verified_accounts: number };
conditions: { key: string; label: string; required: boolean; met: boolean; current?: number | null; target?: number | null }[];
people: DeliveryPerson[];
preflight?: PreflightSummary;
}
export interface CandidateGroup {
person_key: string;
source_ids: string[];
representative: ProspectLead;
evidence: ProspectLead[];
identity_status: 'source_link' | 'profile_verified' | 'unresolved';
account_verified: boolean;
eligible?: boolean;
group?: DeliveryPerson['group'];
badges?: CandidateBadges;
missing?: DeliveryPerson['missing'];
}
export interface GoalProgress {
scope: 'candidate_count' | 'route_pass';
target: number | null;
current: number;
remaining: number | null;
reached: boolean;
scope_note?: string;
assessment_current?: boolean;
groups: CandidateGroup[];
counts: { candidates: number; signals: number; unresolved_sources: number; verified_accounts: number; eligible?: number; supplemental?: number };
}
export interface ModelUsageTotals {
requests: number;
input_tokens: number | null;
output_tokens: number | null;
total_tokens: number | null;
cache_hit_tokens: number | null;
cache_miss_tokens: number | null;
unknown_usage_requests: number;
incomplete_usage_requests: number;
parse_failed_requests: number;
failed_requests: number;
pending_requests: number;
}
export interface ModelUsage extends ModelUsageTotals {
version: 1;
legacy_incomplete: boolean;
recorded_since: string | null;
coverage: 'recorded_calls_only';
ledger_error?: boolean;
models?: string[];
phases: (ModelUsageTotals & { phase: string })[];
}
export interface LearnedEntry {
id: number;
key: string;
value: string;
category: string;
observations: number;
status: string;
}
export type KnowledgeMethodStatus = 'preferred' | 'trial' | 'exploration' | 'paused' | 'legacy';
export interface KnowledgeMethod {
id: string;
key: string;
title: string;
version: string | number;
kind: string;
status: KnowledgeMethodStatus;
capability?: string;
source_kind?: string;
platform?: string;
stage?: string;
page_variant?: string;
match_reasons: string[];
applicability: boolean;
stats: Partial<Record<'success' | 'contradiction' | 'blocked' | 'program_error' | 'unknown' | 'unused' | 'independent_tasks' | 'independent_objects' | 'coverage_tasks' | 'coverage_objects', number | null>>;
last_validation: { at?: string; outcome?: string; reason?: string; verifier?: string; event_id?: string; task_id?: string } | null;
evidence_refs: { task_id?: string; event_id?: string; pre?: string | string[]; post?: string | string[]; action_id?: string }[];
provenance: string;
steps?: unknown;
expected_result?: unknown;
recovery?: unknown;
dependencies?: (string | { id?: string; key?: string; version?: string | number })[];
preconditions?: unknown;
parameters?: unknown;
historical_unverified?: boolean;
}
export interface KnowledgeMethods {
methods: KnowledgeMethod[];
selected_ids: string[];
policy: { version?: string; [key: string]: unknown };
}
export interface ValidationProof {
id: string;
capability: string;
outcome: string;
verifier: string;
observed_at: string;
pre: unknown;
post: unknown;
}
export interface LlmStatus {
provider: string;
model: string;
api_key_set: boolean;
fallback_configured: boolean;
using_fallback: boolean;
primary_exhausted_at: string | null;
retry_hours: number;
}
export interface Meta {
pid: number;
version: string;
operator_mode: boolean;
embedded: boolean;
school_id: string;
tracking: { enabled: boolean; poll_seconds: number };
llm?: LlmStatus;
product?: string;
}
export interface ProspectLead {
id?: string;
source_id?: string;
source_type: 'note' | 'comment' | 'reply';
source_url: string;
quote: string;
reason: string;
author?: string;
profile_url?: string;
xiaohongshu_id?: string;
account_id?: string;
correction?: string | { text: string };
observed_at?: string;
seeking_service?: 'yes' | 'no' | 'unknown';
region_match?: 'yes' | 'no' | 'unknown';
region_quote?: string;
status: 'pending';
}
export interface ProspectingInputs {
product: string;
target_customer: string;
keywords: string[];
region: string | null;
max_notes?: number | null;
max_comments_per_note?: number | null;
use_web_search: boolean;
user_notes: string;
}
export interface SettingsInfo {
llm_provider: string;
llm_api_key_set: boolean;
fallback_key_set?: boolean;
using_fallback?: boolean;
llm_model: string;
llm_base_url: string;
providers: string[];
models_by_provider: Record<string, string[]>;
}
export type MessageRole = 'user' | 'assistant' | 'system';
export interface ChatMessage {
id: string;
role: MessageRole;
text: string;
}
export interface BrowserViewState {
taskId: string;
url: string;
title: string;
loading: boolean;
mode: 'agent' | 'user';
}
export const CATEGORY_LABEL: Record<string, string> = {
control_tip: '控件技巧',
path: '入口路径',
rule: '系统规则',
note: '其他',
};