Files
PRA-only-demo/src/shared/types.ts
T
yu f28b5ffc5e feat: 浏览器类型字段改为下拉选择
- catalog.json: WebBrowser_Create/V2/V3/CreateBackground 的 type 字段补 options(内置运行浏览器/Chrome/Edge,label 与存储值分离)
- shared/types.ts: CatalogField.options 支持字符串或 {label,value} 对象
- Properties.tsx: select/radio 选项归一化渲染 label;当前值不在选项中时追加显示(兼容历史手填值如 zexplorer)
- typecheck 通过;全量 vitest 除 4 项依赖真实 COM 的历史失败外全部通过
2026-10-30 11:26:33 +08:00

252 lines
5.1 KiB
TypeScript

export type CatalogWidget =
| "text"
| "textarea"
| "number"
| "select"
| "radio"
| "boolean"
| "file"
| "folder"
| "element"
| "code"
| "secret"
| "region"
| "hidden";
export interface CatalogField {
key: string;
label: string;
widget: CatalogWidget;
type: "string" | "number" | "boolean" | "object";
displayType: string;
required: boolean;
defaultValue: string;
placeholder: string;
description: string;
advanced: boolean;
valueTypes: string[];
/** 下拉/单选选项:字符串(显示=存储值)或 { label, value }(显示与存储分离) */
options?: Array<string | { label: string; value: string }>;
unit?: string;
}
export interface CatalogOutput {
label: string;
key: string;
suggestedName: string;
valueTypes: string[];
fields: Array<{ key: string; label: string; defaultValue: string; valueTypes: string[] }>;
}
export interface CatalogComponent {
id: string;
name: string;
kind: "vendor" | "native" | "trigger";
group: string;
categories: string[];
categorySignature: string;
description: string;
messageTemplate: string;
baseType: string;
functionName: string;
functionCalls: Array<{ function: string; args: string[]; assignTo: string }>;
version: string;
tags: string[];
platformTag: string | null;
icon: string;
risk: "low" | "high";
fields: CatalogField[];
output: CatalogOutput;
slots: string[];
nodeKind?: string;
implemented?: boolean;
}
export interface CatalogGroup {
id: string;
label: string;
icon: string;
count: number;
}
export interface Catalog {
schemaVersion: number;
generatedAt: string;
counts: {
total: number;
vendor: number;
native: number;
triggers: number;
fields: number;
};
groups: CatalogGroup[];
components: CatalogComponent[];
}
export interface FlowVariable {
name: string;
type: string;
defaultValue?: string;
description?: string;
scope?: "flow" | "local";
}
export interface FlowNodeOptions {
outputVar?: string;
delayBeforeMs?: number;
delayAfterMs?: number;
timeoutMs?: number;
retryCount?: number;
retryIntervalMs?: number;
skipOnError?: boolean;
logException?: boolean;
errorRouteEnabled?: boolean;
}
export interface FlowNode {
id: string;
componentId: string;
label?: string;
position: { x: number; y: number };
values: Record<string, unknown>;
options: FlowNodeOptions;
parentId?: string | null;
slot?: string;
enabled?: boolean;
width?: number;
height?: number;
}
export interface FlowEdge {
id: string;
source: string;
target: string;
sourceHandle?: string | null;
targetHandle?: string | null;
label?: string;
}
export interface FlowDefinition {
schemaVersion: 1;
id: string;
name: string;
description?: string;
enabled?: boolean;
trigger?: {
type: "manual" | "schedule" | "file";
label: string;
};
variables: FlowVariable[];
nodes: FlowNode[];
edges: FlowEdge[];
meta: {
createdAt: string;
updatedAt: string;
appVersion: string;
};
}
export interface FlowSaveOptions {
/** 编辑器加载任务时磁盘上的 updatedAt,用于外部修改冲突检测 */
expectedUpdatedAt?: string;
/** 为 true 时跳过冲突检测,强制覆盖磁盘 */
force?: boolean;
}
export type FlowSaveResult =
| { conflict: false; flow: FlowDefinition }
| { conflict: true; diskFlow: FlowDefinition };
export interface FlowSummary {
id: string;
name: string;
updatedAt: string;
nodeCount: number;
enabled?: boolean;
triggerLabel?: string;
lastRunAt?: string;
lastRunStatus?: "succeeded" | "failed" | "cancelled" | "never";
lastRunDurationMs?: number;
lastRunError?: string;
}
export interface AppInfo {
version: string;
electron: string;
chrome: string;
node: string;
userData: string;
catalogPath: string;
packaged: boolean;
fixtureUrl?: string;
}
export interface AiServiceConfig {
baseUrl: string;
apiKey: string;
model: string;
}
export interface AppSettings {
browserElementWaitMs: number;
aiConfig: AiServiceConfig;
}
export interface AppSettings {
browserElementWaitMs: number;
}
export interface ElementPickResult {
selector: string;
tag: string;
id?: string;
className?: string;
name?: string;
type?: string;
placeholder?: string;
label?: string;
text?: string;
value?: string;
url: string;
}
export interface RunNodeState {
nodeId: string;
status: "idle" | "running" | "succeeded" | "failed" | "skipped" | "cancelled";
startedAt?: string;
finishedAt?: string;
durationMs?: number;
output?: unknown;
error?: RunError;
evidence?: string[];
attempt?: number;
}
export interface RunError {
code: string;
reason: string;
recommendation?: string;
location?: { flowId?: string; nodeId?: string; componentId?: string; arg?: string };
detail?: string;
}
export interface RunEvent {
type:
| "run.started"
| "node.started"
| "node.log"
| "node.finished"
| "run.finished";
runId: string;
nodeId?: string;
level?: "info" | "warn" | "error";
message?: string;
status?: string;
output?: unknown;
error?: RunError;
durationMs?: number;
evidence?: string[];
attempt?: number;
startedAt?: string;
}