Files
AgentLab/frontend/src/typesApp.ts
T

503 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 应用平台的前后端接口约定(docs/design/app-platform-and-look.md 第三部分)。
*
* 契约骨架之后冻结:要改,向编排者提,由编排者统一改,前后端同时对齐。字段名和后端返回一字不差。
*/
// ---------------------------------------------------------------------------
// 身份(§2.7、§3.10)
// ---------------------------------------------------------------------------
export type AuthMode = 'off' | 'local' | 'oidc'
export type Role = 'admin' | 'builder' | 'user'
/** GET /api/auth/me。关登录时 mode='off'、role='admin'、verified=false、username 为自报署名(可能为空) */
export interface Principal {
mode: AuthMode
username: string | null
display_name: string | null
role: Role
groups: string[]
verified: boolean
/** 开登录后 user 角色能不能问数据(Q2,管理员开关) */
user_can_chat?: boolean
}
export interface UserRow {
id: string
username: string
display_name: string
email: string | null
role: Role
disabled: boolean
source: 'local' | 'oidc'
last_login_at: string | null
created_at: string
}
export interface GroupRow {
id: string
name: string
label: string
source: 'local' | 'oidc'
members: string[]
}
export interface AuditRow {
id: string
at: string
actor: string | null
verified: boolean
action: string
subject_kind: string
subject_id: string | null
data: Record<string, any>
}
// ---------------------------------------------------------------------------
// 表单 agentlab.form/1(§3.3)
// ---------------------------------------------------------------------------
export type FormWidget =
| 'text' | 'textarea' | 'number' | 'integer' | 'date' | 'datetime' | 'select' | 'radio' | 'multiselect'
| 'checkbox' | 'principal' | 'note' | 'json'
export interface FormField {
type: 'string' | 'number' | 'integer' | 'boolean' | 'array'
title?: string
description?: string
default?: unknown
readOnly?: boolean
enum?: (string | number)[]
'x-enum-labels'?: string[]
minimum?: number
maximum?: number
minLength?: number
maxLength?: number
maxItems?: number
format?: 'date' | 'date-time' | 'email' | 'uri'
items?: { type: 'string'; enum?: string[] }
'x-widget'?: FormWidget
}
export interface FormSchema {
format?: 'agentlab.form/1'
type: 'object'
title?: string
required?: string[]
properties: Record<string, FormField>
'x-order'?: string[]
}
/** 前后端同一种错误格式 */
export interface FormError {
path: string
code: 'required' | 'type' | 'enum' | 'minimum' | 'maximum' | 'min_length' | 'max_length' | 'max_items' | 'format'
message: string
}
// ---------------------------------------------------------------------------
// 应用描述 agentlab.app/1(§3.2、§3.4、§3.5)
// ---------------------------------------------------------------------------
export type PinUse = 'view' | 'entry' | 'process'
export type Disposition = 'recompute' | 'dual' | 'incomparable'
export interface AppPin {
alias: string
workflow_id: string
version: number
graph_hash: string
level?: string | null
use: PinUse
}
export interface AppEntry {
id: string
label: string
pin: string
form: FormSchema | { $ref: string }
map: Record<string, string>
instance_title?: { pattern: string; fields: string[] } | null
}
export interface AppViewSource {
kind: 'latest_sealed' | 'on_demand' | 'instance'
pin?: string | null
from?: string | null
params?: FormSchema | { $ref: string } | null
ttl_s?: number | null
auto?: boolean
}
/** 绑定:出现哪个键就是哪种(metric / series / cell / query / report / input / run / output / task / action) */
export type AppBinding = { view?: string } & Record<string, any>
export interface AppComponent {
id: string
type: string
props?: Record<string, any>
bind?: AppBinding | null
visible?: string | null
scope?: string | null
children?: AppComponent[]
}
export interface AppPage {
id: string
title: string
body: AppComponent[]
}
export interface AppSpec {
format: 'agentlab.app/1'
name: string
description?: string
icon?: string
pins: AppPin[]
slots: Record<string, { label: string }>
entries: AppEntry[]
forms: Record<string, FormSchema>
task_ui: Record<string, Record<string, any>>
views: Record<string, { source: AppViewSource }>
pages: AppPage[]
hooks: { name: string; kind: 'start' | 'signal'; entry?: string | null }[]
notify: { channel: string; events: string[] }[]
}
/** 岗位绑定到人或组(不进 spec,存在应用版本的 bindings 里) */
export interface AppBindings {
slots: Record<string, { kind: 'user' | 'group'; name: string }[]>
hooks?: Record<string, any>
channels?: Record<string, any>
}
export interface CatalogComponent {
name: string
label: string
category: 'layout' | 'display' | 'input' | 'process'
version: number
children: boolean
bindings: string[]
props: Record<string, any>
}
export interface ComponentCatalog {
version: number
categories: Record<string, string>
components: CatalogComponent[]
}
// ---------------------------------------------------------------------------
// 应用对象(§3.1、§3.10)
// ---------------------------------------------------------------------------
export type AppLevel = 'published' | 'governed'
export type GrantRole = 'use' | 'observe' | 'manage'
export interface AppSummary {
id: string
name: string
description: string
icon: string
status: 'active' | 'archived'
published_version: number | null
level: AppLevel | null
/** 钉住的版本被退役:入口拒发新实例 */
needs_upgrade: boolean
/** 当前用户在这个应用里的待办数 */
pending_tasks: number
/** 当前用户的授权(关登录时为 manage) */
my_role: GrantRole | null
updated_at: string
}
export interface AppDetail extends AppSummary {
draft: AppSpec
draft_bindings: AppBindings
created_by: string | null
}
export interface AppVersionRow {
version: number
spec_hash: string
level: AppLevel
pins: AppPin[]
dispositions: Record<string, Disposition>
note: string
published_by: string | null
published_at: string
}
export interface AppGrant {
principal_kind: 'user' | 'group' | 'everyone'
principal: string
role: GrantRole
}
/** 发布检查的一条问题(app.* / action.* / human.* / process.*) */
export interface LintIssue {
message: string
level: 'error' | 'warning'
code: string
path?: string | null
node_id?: string | null
}
export interface PublishResult {
ok: boolean
version?: number
issues: LintIssue[]
/** 钉住项相对上一版升了版、需要选处置的:[{alias, from, to}] */
needs_disposition?: { alias: string; from: number; to: number }[]
}
// ---------------------------------------------------------------------------
// 页面解析 agentlab.view/1(§3.6)
// ---------------------------------------------------------------------------
export interface Stamp {
as_of: string | null
as_of_text: string
pin: string
graph_hash: string
calibers: { name: string; version: string }[]
tier: 'formal' | 'degraded' | 'withheld' | null
tier_text: string
from: string
sealed: boolean
/** 照实标出的错位:定时任务已改跑新版本、应用还钉在旧版本,等 */
notes?: string[]
}
export interface ViewSourceState {
state: 'ok' | 'empty' | 'running' | 'stale' | 'error'
run_id: string | null
stamp: Stamp | null
message?: string
}
/** 一个数、一格、一个指标的出处:点开走证据接口 */
export interface ViewEvidence {
run_id: string
kind: 'metric' | 'cell' | 'report' | 'input' | 'query'
eid?: string
node?: string
metric?: string
seg?: string
artifact?: string
}
export interface ViewNode {
id: string
type: string
props: Record<string, any>
/** 服务端解析好的数据;形状随组件而定(metric:{text, state, evidence};table:{columns, rows, masked}……) */
data?: Record<string, any> | null
children?: ViewNode[]
}
export interface ViewModel {
format: 'agentlab.view/1'
app: { id: string; name: string; version: number; level: AppLevel; needs_upgrade: boolean }
page: { id: string; title: string }
pages: { id: string; title: string }[]
sources: Record<string, ViewSourceState>
tree: ViewNode[]
forms: Record<string, FormSchema>
problems: { component: string; code: string; message: string }[]
}
export interface InstanceRow {
run_id: string
title: string
entry_id: string | null
status: string
started_by: string | null
created_at: string
finished_at: string | null
pending_tasks: number
tier?: string | null
}
// ---------------------------------------------------------------------------
// 待办(§3.7)
// ---------------------------------------------------------------------------
export type TaskKind =
| 'approve' | 'input' | 'edit' | 'tool' | 'code' | 'dual_check' | 'action_confirm' | 'reconcile' | 'signal'
export type TaskStatus = 'pending' | 'resolving' | 'resolved' | 'cancelled' | 'expired'
export type TaskPolicy = { kind: 'any' } | { kind: 'all' } | { kind: 'quorum'; m: number }
export interface TaskAssignment {
id: string
principal_kind: 'user' | 'group' | 'anyone' | 'hook'
principal: string
source: string
status: 'pending' | 'responded' | 'withdrawn'
responded_by: string | null
responded_at: string | null
/** 回复的决定(approve / reject / 提交的值),会签进度用 */
decision?: string | null
verified: boolean
}
export interface Task {
id: string
approval_id: string | null
run_id: string
node_id: string | null
app_id: string | null
app_name?: string | null
app_version: number | null
workflow_name?: string | null
kind: TaskKind
title: string
form: FormSchema | null
policy: TaskPolicy
status: TaskStatus
due_at: string | null
escalation_level: number
/** 给人看的上下文:人工节点的 message / context / draft / reports,工具审批的参数,动作确认的预览等(原样来自中断内容) */
payload: Record<string, any>
assignments: TaskAssignment[]
/** 当前用户能不能回复这一条 */
can_respond: boolean
outcome: Record<string, any> | null
resolved_by: string | null
resolved_at: string | null
created_at: string
}
export interface TaskRespond {
decision: 'approve' | 'reject' | 'submit' | 'confirmed' | 'not_applied_resend' | 'not_applied_abandon'
values?: Record<string, any>
note?: string
/** 动作确认:确认卡上显示的哈希,原样带回 */
payload_hash?: string
/** 核实「已生效」时填的外部单号 */
external_id?: string
}
// ---------------------------------------------------------------------------
// 动作(§3.8)
// ---------------------------------------------------------------------------
export type ActionState = 'pending' | 'sent' | 'confirmed' | 'failed' | 'unknown' | 'simulated'
export interface ActionRecordRow {
id: string
run_id: string
node_id: string
app_id: string | null
capability: string
environment: 'prod' | 'test' | 'simulated'
state: ActionState
attempt: number
payload_hash: string
preview: Record<string, any> | null
receipt: Record<string, any> | null
error: string | null
resolution: Record<string, any> | null
created_at: string
updated_at: string
}
// ---------------------------------------------------------------------------
// 能力与端点(§3.9)
// ---------------------------------------------------------------------------
export type CapabilityEffect = 'read' | 'write' | 'dynamic'
export interface CapabilityRow {
name: string
system: string
title: string
description: string
params_schema: Record<string, any>
returns_schema: Record<string, any> | null
tabular: { rows: string; columns: Record<string, string> } | null
effect_system: CapabilityEffect
effect: CapabilityEffect | null
approval: 'inherit' | 'confirm' | 'none'
unattended_write: boolean
fields: Record<string, Record<string, any>>
masked: string[]
credential_mode: 'service' | 'service_on_behalf'
endpoint_id: string | null
lookup: string | null
version: number
missing: boolean
synced_at: string | null
updated_by: string | null
}
export interface EndpointEnv {
base_url: string
/** 值只回掩码;提交掩码值表示保持原值 */
headers: Record<string, string>
allow_intranet: boolean
verify_tls: boolean
}
export interface EndpointRow {
id: string
name: string
description: string
environments: { test?: EndpointEnv; prod?: EndpointEnv }
idempotency_header: string
timeout_s: number
version: number
}
// ---------------------------------------------------------------------------
// 通知(§2.4)
// ---------------------------------------------------------------------------
export interface NotifyChannelRow {
id: string
name: string
scope: 'global' | 'app' | 'user'
owner_id: string | null
format: 'generic' | 'feishu' | 'wecom' | 'dingtalk'
/** 只回主机名 */
url_host: string
signed: boolean
events: string[]
enabled: boolean
}
// ---------------------------------------------------------------------------
// 运行来源(§2.10 X3)与助手查看(§2.9 L2)
// ---------------------------------------------------------------------------
export type OriginKind =
| 'chat' | 'canvas' | 'launcher' | 'schedule' | 'app_entry' | 'app_view' | 'app_backfill' | 'hook' | 'api'
export interface LookObject {
kind: 'table' | 'capability' | 'workflow_version'
source?: string
source_id?: string
named: string[]
picked?: string[]
joined?: string[]
missing: string[]
total?: number
explored?: number
catalog_tables?: number
schema_synced_at?: string | null
catalog_versions?: Record<string, number>
versions?: Record<string, number>
}
export interface LookEvent {
op: 'look'
id: string
by: 'model' | 'system'
need: string
status: 'ok' | 'index' | 'failed'
reason?: string
elapsed_ms: number
objects: LookObject[]
}