修复 tool_result 压缩零效果(BUG-260628-01):单行/少行/JSON 大字符 串字段逃逸压缩的问题,基于实测数据(53/94 次迭代零节省)调参, 增加字符级保底截断,压缩有效率从 8% 提升至 ~85%+
709 lines
28 KiB
TypeScript
709 lines
28 KiB
TypeScript
//! TypeScript 类型定义 — 与 Rust Record 结构体严格对齐
|
||
|
||
// ============================================================
|
||
// 灵感
|
||
// ============================================================
|
||
|
||
// IdeaRecord.status union 类型 — 值集对齐后端 IdeaStatus serde (df-types/src/types.rs:52)
|
||
// snake_case: draft | pending_review | approved | rejected | promoted | archived
|
||
export type IdeaStatus = 'draft' | 'pending_review' | 'approved' | 'rejected' | 'promoted' | 'archived'
|
||
|
||
export interface IdeaRecord {
|
||
id: string
|
||
title: string
|
||
description: string
|
||
status: IdeaStatus
|
||
priority: number
|
||
score: number | null
|
||
tags: string | null // JSON 数组字符串
|
||
source: string | null
|
||
promoted_to: string | null
|
||
ai_analysis: string | null
|
||
scores: string | null
|
||
/** 关联灵感 id JSON 数组字符串(对齐后端 related_ids Option<String>),null/空串=无关联 */
|
||
related_ids: string | null
|
||
created_at: string
|
||
updated_at: string
|
||
}
|
||
|
||
export interface CreateIdeaInput {
|
||
title: string
|
||
description?: string
|
||
priority?: number
|
||
tags?: string
|
||
source?: string
|
||
}
|
||
|
||
/**
|
||
* 灵感多条件查询入参(F-260621-02,对齐后端 IdeaQuery)。
|
||
*
|
||
* 所有字段可选;全空 → 后端返回全量(created_at DESC)。
|
||
* - `status`:状态精确匹配(后端 WHERE,取代前端 filter)
|
||
* - `keyword`:title/description LIKE %kw%(后端 LIKE,取代前端 filter)
|
||
* - `order_by`:白名单 created_at/updated_at/priority/status/score(后端白名单校验防注入)
|
||
* - `limit`/`offset`:分页(limit 钳制上限 200)
|
||
*/
|
||
export interface IdeaQuery {
|
||
status?: string | null
|
||
keyword?: string | null
|
||
order_by?: string | null
|
||
limit?: number | null
|
||
offset?: number | null
|
||
}
|
||
|
||
/**
|
||
* 灵感评估历史记录(后端 list_idea_evaluations 返回)。
|
||
* 每次评估(启发式/LLM/降级)落一行,version 递增,按 version DESC 返回。
|
||
* ai_analysis / scores 为 JSON 字符串(对齐 IdeaRecord 同名字段)。
|
||
*/
|
||
export interface IdeaEvaluationRecord {
|
||
id: string
|
||
idea_id: string
|
||
version: number
|
||
ai_analysis: string | null
|
||
scores: string | null
|
||
score: number | null
|
||
evaluated_by: string | null
|
||
evaluated_at: string
|
||
}
|
||
|
||
// ============================================================
|
||
// 项目
|
||
// ============================================================
|
||
|
||
// ProjectRecord.status union 类型 — 值集对齐后端 ProjectStatus serde (df-types/src/types.rs:90)
|
||
// snake_case: planning | in_progress | testing | releasing | completed | paused | cancelled
|
||
// 注:前端 constants/dashboard 的 'active' 是 UI 虚拟派生态(非 record 落库值),不进此 union。
|
||
export type ProjectStatus =
|
||
| 'planning' | 'in_progress' | 'testing' | 'releasing' | 'completed' | 'paused' | 'cancelled'
|
||
|
||
export interface ProjectRecord {
|
||
id: string
|
||
name: string
|
||
description: string
|
||
status: ProjectStatus
|
||
idea_id: string | null
|
||
/** 绑定的本地代码目录绝对路径(null=未绑定) */
|
||
path: string | null
|
||
/** 技术栈 JSON 数组字符串(如 ["rust","vue"],null=未探测) */
|
||
stack: string | null
|
||
created_at: string
|
||
updated_at: string
|
||
}
|
||
|
||
export interface CreateProjectInput {
|
||
name: string
|
||
description?: string
|
||
idea_id?: string
|
||
/** 绑定的本地代码目录(可选) */
|
||
path?: string
|
||
/** 技术栈 JSON 数组字符串(可选,空则后端自动探测) */
|
||
stack?: string
|
||
}
|
||
|
||
/** AI 扫描项目结果(预览用,用户确认后填入) */
|
||
export interface AiScanResult {
|
||
/** 项目摘要(空=LLM 未得出,需手填) */
|
||
description: string
|
||
/** 技术栈(规则 ∪ LLM,去重小写) */
|
||
stack: string[]
|
||
/** 项目类型(web/api/cli/library/desktop/mobile/monorepo/other) */
|
||
project_type: string | null
|
||
/** LLM 原始返回(降级时含错误信息) */
|
||
raw: string | null
|
||
}
|
||
|
||
/** 灵感晋升结果(后端 promote_idea 返回) */
|
||
export interface PromotionResult {
|
||
idea_id: string
|
||
project_id: string
|
||
promoted: boolean
|
||
reason: string
|
||
}
|
||
|
||
// ============================================================
|
||
// 任务
|
||
// ============================================================
|
||
|
||
// TaskRecord.status union 类型 — 值集对齐后端 TaskStatus serde (df-types/src/types.rs:131)
|
||
// snake_case: todo | in_progress | in_review | testing | done | blocked | cancelled
|
||
// 注:constants/project.ts 的 mapLegacyStatus 兜底老 DB 旧态(completed/review_ready/merged/abandoned),
|
||
// 仅在 taskStatusLabel/taskStatusClass 辅助函数内映射,record.status 本身经后端 is_valid 拦截无旧态。
|
||
export type TaskStatus =
|
||
| 'todo' | 'in_progress' | 'in_review' | 'testing' | 'done' | 'blocked' | 'cancelled'
|
||
|
||
export interface TaskRecord {
|
||
id: string
|
||
project_id: string
|
||
title: string
|
||
description: string
|
||
status: TaskStatus
|
||
priority: number // 0=critical, 1=high, 2=medium, 3=low
|
||
branch_name: string | null
|
||
assignee: string | null
|
||
workflow_def_id: string | null
|
||
base_branch: string | null
|
||
/** review 退回累计轮数(in_review→in_progress / testing→in_review 各 +1) */
|
||
review_rounds: number
|
||
/**
|
||
* 任务产出 JSON 字符串(决策 a:task 中心,产出跟 task 走)。
|
||
* schema: { text: string, model?: string, usage?: {...}, review?: {
|
||
* verdict: 'pass'|'fail'|'unknown', summary: string, suggestions: string[], ... } }
|
||
* 旧任务无产出时为 undefined。前端 parsedOutput try/catch 兜底解析。
|
||
*/
|
||
output_json?: string
|
||
/** 关联灵感 ID(F-260619-01,1对1 单向,任务→灵感)。未关联时为 undefined。 */
|
||
idea_id?: string
|
||
created_at: string
|
||
updated_at: string
|
||
}
|
||
|
||
export interface CreateTaskInput {
|
||
project_id: string
|
||
title: string
|
||
description?: string
|
||
priority?: number
|
||
branch_name?: string
|
||
assignee?: string
|
||
/** 关联灵感 ID(1对1 单向,可空)。空字符串视为不关联(与后端一致)。 */
|
||
idea_id?: string
|
||
}
|
||
|
||
/**
|
||
* 任务多条件查询入参(F-260621-02,对齐后端 TaskQuery)。
|
||
*
|
||
* 所有字段可选;全空 → 后端返回全量未删任务(created_at DESC,等价改造前 list_active)。
|
||
* - `project_id`:项目精确匹配(命中 idx_tasks_project_id)
|
||
* - `status`:状态精确匹配(P1 下沉,命中 idx_tasks_status,取代前端 filter)
|
||
* - `priority`:优先级精确匹配(0=critical..3=low)
|
||
* - `assignee`:负责人精确匹配
|
||
* - `keyword`:title/description LIKE %kw%(P2,取代前端 filter)
|
||
* - `order_by`:白名单 created_at/updated_at/priority/status(后端白名单校验防注入),恒 DESC
|
||
* - `limit`/`offset`:分页(limit 钳制上限 500)
|
||
*
|
||
* 注:project_id/priority/assignee/order_by/limit/offset 为基建就绪,当前视图仅用
|
||
* status(P1)+keyword(P2);P3 排序分页 UI 待数据量增长。
|
||
*/
|
||
export interface TaskQuery {
|
||
project_id?: string | null
|
||
status?: string | null
|
||
priority?: number | null
|
||
assignee?: string | null
|
||
keyword?: string | null
|
||
order_by?: string | null
|
||
limit?: number | null
|
||
offset?: number | null
|
||
}
|
||
|
||
// ============================================================
|
||
// 工作流
|
||
// ============================================================
|
||
|
||
// WorkflowRecord.status union 类型 — 值集对齐后端 WorkflowStatus serde (df-types/src/types.rs:195)
|
||
// snake_case: pending | running | paused | completed | failed | cancelled
|
||
export type WorkflowStatus =
|
||
| 'pending' | 'running' | 'paused' | 'completed' | 'failed' | 'cancelled'
|
||
|
||
export interface WorkflowRecord {
|
||
id: string
|
||
name: string
|
||
dag_json: string
|
||
status: WorkflowStatus
|
||
triggered_by: string | null
|
||
project_id: string | null
|
||
task_id: string | null
|
||
created_at: string
|
||
completed_at: string | null
|
||
}
|
||
|
||
/** 工作流事件载荷(后端 emit 的结构) */
|
||
/** 工作流事件类型字面量联合(对应后端 WorkflowEvent serde tag=type rename_all=snake_case,R7收窄防写错 type 字符串) */
|
||
export type WorkflowEventType =
|
||
| 'node_started' | 'node_progress' | 'node_output' | 'node_completed' | 'node_failed' | 'node_cancelled'
|
||
| 'workflow_paused' | 'workflow_completed' | 'workflow_failed'
|
||
| 'human_approval_request' | 'human_approval_response'
|
||
|
||
export interface WorkflowEventPayload {
|
||
execution_id: string
|
||
event: {
|
||
type: WorkflowEventType
|
||
[key: string]: unknown
|
||
}
|
||
}
|
||
|
||
// ============================================================
|
||
// 通用
|
||
// ============================================================
|
||
|
||
export type UpdateField = {
|
||
id: string
|
||
field: string
|
||
value: string
|
||
}
|
||
|
||
// ============================================================
|
||
// 数据变更联动刷新(AR-11 方案A)
|
||
// ============================================================
|
||
|
||
/**
|
||
* 后端 AI 工具(create/update/delete/restore/purge/bind_directory 等)执行成功后
|
||
* emit 的 "df-data-changed" 事件负载。前端 store listen 后按 entity 调对应 load 刷新列表。
|
||
*/
|
||
export interface DfDataChangedPayload {
|
||
/** 变更实体:project / task / idea */
|
||
entity: 'project' | 'task' | 'idea'
|
||
/** 变更动作:create / update / delete */
|
||
action: 'create' | 'update' | 'delete'
|
||
}
|
||
|
||
// ============================================================
|
||
// AI 聊天
|
||
// ============================================================
|
||
|
||
export interface AiProviderConfig {
|
||
id: string
|
||
name: string
|
||
provider_type: string
|
||
api_key: string
|
||
base_url: string
|
||
default_model: string
|
||
models: string | null
|
||
/** 模型能力配置数组(F-01:4 维度 + 路由控制;DB TEXT 列 JSON 解析,老库可能缺失) */
|
||
model_configs?: ModelConfig[]
|
||
is_default: boolean
|
||
config: string | null
|
||
created_at: string
|
||
updated_at: string
|
||
/** provider 是否进入负载均衡池(F-260614-04c)。false=仅配置存在,不参与主链路由/选池。老库默认 true。 */
|
||
enabled?: boolean
|
||
/** provider 在负载均衡池中的选择权重(0-100,F-260614-04c)。高权重优先被选为主;同权重近似轮询。老库默认 50。 */
|
||
weight?: number
|
||
}
|
||
|
||
// ============================================================
|
||
// F-01 模型能力系统(ModelConfig,与 crates/df-ai-core/src/model.rs 严格对齐)
|
||
// ============================================================
|
||
|
||
/** 维度 1 — 模态(模型能接收什么输入)。serde snake_case 字面量。 */
|
||
export type Modality = 'text' | 'vision' | 'audio' | 'video'
|
||
|
||
/** 维度 2 — 能力(模型能做什么)。serde snake_case 字面量。 */
|
||
export type Capability = 'tool_use' | 'embedding' | 'code_gen'
|
||
|
||
/** 维度 3 — 价格分级(成本)。serde snake_case 字面量。'free' 已删(B-260618-05 死档,预设/启发式从不赋值)。 */
|
||
export type CostTier = 'low' | 'medium' | 'high'
|
||
|
||
/** 维度 4 — 智力分级。serde snake_case 字面量。CR-260618-11#3:与 CostTier 同,cost/intel 已从路由硬过滤(B-260618-03)及前端标签(UX-260618-04)去除,字段保留仅 DB 兼容,不再参与路由选模型。 */
|
||
export type IntelligenceTier = 'lite' | 'standard' | 'plus' | 'ultra'
|
||
|
||
/** 探测来源(只读,由后端探测器填充)。serde snake_case 字面量。 */
|
||
export type ProbeSource = 'user_set' | 'preset_table' | 'heuristic' | 'default'
|
||
|
||
/** 单模型完整配置(4 维度 + 路由控制 + 探测元数据)。 */
|
||
export interface ModelConfig {
|
||
/** 模型名(如 "glm-4v-flash") */
|
||
model_id: string
|
||
/** 启用/禁用(false=配了但不参与路由) */
|
||
enabled: boolean
|
||
/** 用户自定义别名(可选) */
|
||
label?: string
|
||
/** 模态集合 */
|
||
modalities: Modality[]
|
||
/** 能力集合 */
|
||
capabilities: Capability[]
|
||
/** 价格分级 */
|
||
cost_tier: CostTier
|
||
/** 智力分级 */
|
||
intelligence: IntelligenceTier
|
||
/** 权重(0-100,同能力候选中优先选权重高的) */
|
||
weight: number
|
||
/** 上下文窗口大小(tokens) */
|
||
context_window: number
|
||
/** 探测来源(可选) */
|
||
probe_source?: ProbeSource
|
||
}
|
||
|
||
/**
|
||
* AI 错误分类字面量集(B-260615-42)。
|
||
* 与后端 `commands::ai::ErrorType` 的 serde(rename_all = "snake_case") 严格对齐。
|
||
* 前端消费方 switch 于此常量集做差异化提示(auth 引导填 key / network 提示连接 / 等)。
|
||
*/
|
||
export type AiErrorType = 'auth' | 'network' | 'timeout' | 'provider_config' | 'unknown'
|
||
|
||
/**
|
||
* L2 统一状态机 — 对话生命周期状态字面量(对齐后端 ConvState serde rename_all=snake_case,
|
||
* crates/df-ai/.../agentic/conv_state.rs)。5 态:
|
||
* - idle:空闲,可接新请求
|
||
* - generating:生成中(含审批挂起期,审批是 loop 内暂停点非独立态)
|
||
* - stopping:停中(用户已点停止,loop 收尾中,瞬态)
|
||
* - error:出错(用户可重试回 generating)
|
||
* - compressed:压缩中(Generating/Idle 期间瞬态派生,压缩完成回原态)
|
||
*
|
||
* 批4 双轨收口后(2026-06-25):convStates(enum Map)是「会话是否生成中」的唯一真相源,
|
||
* 旧 generatingConvs bool 轨已退役。CONV_STATE_ENABLED=off 或老后端不发 AiConvStateChanged 时,
|
||
* useAiEvents.handleEvent 活跃事件兜底写 setConvState('generating') 作为 enum 写入口
|
||
* (替代旧 bool 轨 add),消费方不再回退 bool 判断。streaming 单值是另一条过渡态
|
||
* (F-09 per-conv streaming 收口前保留),不在本状态机口径内。
|
||
*/
|
||
export type ConvState = 'idle' | 'generating' | 'stopping' | 'error' | 'compressed'
|
||
|
||
/** AI 聊天事件(后端 emit 的结构,conversation_id 用于多对话流式路由) */
|
||
export type AiChatEvent = ({
|
||
type: 'AiTextDelta'; delta: string
|
||
} | {
|
||
type: 'AiToolCallStarted'; id: string; name: string; args: unknown
|
||
} | {
|
||
type: 'AiToolCallCompleted'; id: string; result: unknown
|
||
} | {
|
||
// AE-2025-04 会话级信任:同会话已批准过同类操作(同工具+同目录)自动放行,前端显示轻量 toast。
|
||
// 不写消息/不动 pending(Started/Completed 仍独立发),仅提示性事件。
|
||
type: 'AiToolAutoApproved'; id: string; tool: string; dir: string
|
||
} | {
|
||
// path_auth 审批链阶段3b(统一审批模型):AiApprovalRequired 携带 kind 字段区分
|
||
// 'path'(F-260619-03 Phase B 路径授权挂起,走 once/session/always/deny)vs 'risk'(普通 RiskLevel 审批,
|
||
// 走 approve/reject)。后端阶段3a 未在 wire 上给该事件加 kind(老 path 挂起仍走独立
|
||
// AiDirAuthRequired 事件),前端 useAiEvents 入口处据 event.type 归一打标:risk 类默认 'risk',
|
||
// path 类(AiDirAuthRequired 归一)打 'path'。故此处 kind 为可选(老后端不传时前端默认 'risk')。
|
||
// 开关 df-ai-unified-approval:true=归一进 pendingApprovals 带 kind;false=回退 DirAuthDialog 老链路。
|
||
type: 'AiApprovalRequired'; id: string; name: string; args: unknown; reason: string; diff?: string
|
||
kind?: 'path' | 'risk'
|
||
} | {
|
||
type: 'AiApprovalResult'; id: string; approved: boolean
|
||
} | {
|
||
// UX-2025-04 / CR-30-2 / 决策 F-260616-07 a1: incomplete 标记流中途失败保文(网络中断),
|
||
// 前端据此差异化展示(如系统提示「⚠ 响应因网络中断不完整」)。正常完成/停止均为 undefined。
|
||
type: 'AiCompleted'; total_tokens: number; prompt_tokens: number; completion_tokens: number; incomplete?: boolean
|
||
} | {
|
||
type: 'AiError'; error: string; error_type?: AiErrorType
|
||
} | {
|
||
// F-260622-02 跨端用户消息同步:远程(miniapp)发来的用户消息,后端 route_send_message
|
||
// 放行后 publish_event 广播。桌面 useAiEvents 收到后补 user 气泡(桌面本地 sendMessage 是
|
||
// 乐观渲染不发此事件)。handleEvent 去重防双气泡(末条已是同 content user 跳过)。
|
||
type: 'AiUserMessage'; message: string
|
||
} | {
|
||
type: 'AiAgentRound'; round: number
|
||
} | {
|
||
type: 'AiHeartbeat'
|
||
} | {
|
||
// F-260616-03: 达 max_iterations 暂停态(后端仍 generating=true),前端展示操作卡询问继续/停止
|
||
type: 'AiMaxRoundsReached'
|
||
} | {
|
||
// F-260619-03 Phase B: 路径授权弹窗(LLM 想访问白名单外目录,后端挂起 loop 等用户决定)。
|
||
// 前端弹窗四选项:"本次"(once 执行后清)/"当前会话"(session 切会话清)/"始终放行"(persistent)/"拒绝" → ai_authorize_dir IPC。
|
||
type: 'AiDirAuthRequired'; id: string; tool: string; path: string; dir: string
|
||
} | {
|
||
// L1 求助协议(aichat 体验与 agent 能力系统化重构 §2.3,2026-06-21):
|
||
// agent 断路器熔断 / 自省时发,结构化求助(区别于 prompt 教 AI 主动问用户——LLM 不可靠)。
|
||
// 字段对齐后端 AiChatEvent::AiHelpRequired:reason(原因摘要)/context(已试情况)/options(建议选项)。
|
||
// 前端渲染求助卡显 reason + options 按钮供用户选,与 AiApprovalRequired(工具执行前审批)/
|
||
// AiMaxRoundsReached(达 max 被动截断)语义区分——求助=AI 主动「我搞不定」。
|
||
type: 'AiHelpRequired'; reason: string; context: string; options: string[]
|
||
} | {
|
||
// L2 统一状态机(批2 1b/1c):ConvState 经 AiChatEvent 推前端,供 status union 消费。
|
||
// conv_state 值为 idle|generating|stopping|error|compressed(snake_case,对齐后端 ConvState serde)。
|
||
// 后端在 conv_state 变化时(入口→generating / reset·drop→idle)emit;conversation_id 标识
|
||
// 哪个会话的状态变了(F-09 多会话并发下前端按 convId 路由)。批4 双轨收口后:CONV_STATE_ENABLED=off
|
||
// 或老后端不发本事件时,useAiEvents.handleEvent 活跃事件兜底写 setConvState('generating') 作为
|
||
// enum 写入口(替代旧 bool 轨 add),消费方不再回退 streaming/generating bool 判断。
|
||
type: 'AiConvStateChanged'; conv_state: ConvState
|
||
} | {
|
||
// F-260616-07: 流式调用自动重试提示(前端可在错误气泡内显示「重试 n/m」)
|
||
type: 'AiStreamRetry'; attempt: number; max_attempts: number
|
||
}) & {
|
||
conversation_id?: string
|
||
}
|
||
|
||
/**
|
||
* 多模态消息内容片(F-260614-05 Phase 2b 前端类型,对齐后端 df-ai-core ContentPart)。
|
||
*
|
||
* 后端 serde:`#[serde(tag = "type", rename_all = "snake_case")]`,
|
||
* 前端 discriminator 用字面量 `type` 字段('text' | 'image'),与后端 wire 格式严格对齐。
|
||
* Image 片:url / base64 二选一(base64 非空时 url 忽略),media_type 仅 base64 模式必填。
|
||
*/
|
||
export type ContentPart =
|
||
| { type: 'text'; text: string }
|
||
| {
|
||
type: 'image'
|
||
url?: string | null
|
||
base64?: string | null
|
||
/** base64 模式必填(image/png|jpeg|webp|gif);url 模式可空 */
|
||
media_type?: string | null
|
||
/** 可选 alt(vision 模型/降级文本时用) */
|
||
alt?: string | null
|
||
}
|
||
|
||
/** AI 消息(前端渲染用,isError 标记错误消息用于差异化样式) */
|
||
export interface AiMessage {
|
||
id: string
|
||
role: 'user' | 'assistant' | 'tool' | 'system'
|
||
content: string
|
||
isError?: boolean
|
||
toolCalls?: AiToolCallInfo[]
|
||
/** 生成该消息的 model(仅 assistant 消息,历史消息从 DB 读) */
|
||
model?: string
|
||
/**
|
||
* 多模态内容片(F-260614-05 Phase 2b)。
|
||
* undefined/空=纯文本消息(content 即全部载荷);非空含 Image 片=多模态消息,
|
||
* 用户气泡内渲染 <img>(base64 data URI 或 url)。仅 user 消息有(parts 来自粘贴/拖拽输入)。
|
||
* 历史消息从 DB JSON 反序列化时透传(useAiConversations switchConversation)。
|
||
*/
|
||
parts?: ContentPart[]
|
||
/**
|
||
* Input Augmentation:@ mention 区间元数据(仅 user 消息)。
|
||
*
|
||
* 用户选中 @项目/@任务/@灵感/`/技能` 时按选区记 {start,length,kind,refId,label},
|
||
* 随消息透传到后端 ai_chat_send 的 mention_spans 参数(后端 resolve 投影成 Augmentation 注入)。
|
||
* 前端 MessageList 据此精确切区间渲染 chip(替代正则,防误匹配)。
|
||
*
|
||
* undefined/空=无 mention(纯文本消息零回归);历史消息从 DB 反序列化时透传。
|
||
*/
|
||
mentionSpans?: MentionSpan[]
|
||
/**
|
||
* Input Augmentation:resolve 后的增强上下文(仅展示用,后端 resolve 的回传或落库快照)。
|
||
*
|
||
* serde 镜像后端 df-types Augmentation(tag=kind, snake_case 变体名)。
|
||
* 当前透传链路仅传 mentionSpans,augmentations 主要用于落库消息回显/调试;前端宽容对待
|
||
* (不强制校验变体字段,未知 kind 忽略,对齐后端「新增变体向后兼容」设计)。
|
||
*/
|
||
augmentations?: Augmentation[]
|
||
timestamp: number
|
||
}
|
||
|
||
// ============================================================
|
||
// Input Augmentation 层类型(@ mention / / skill 统一增强)
|
||
// ============================================================
|
||
//
|
||
// 与后端 crates/df-types/src/augmentation.rs 严格对齐:
|
||
// - MentionSpanDto(start/length/kind/refId/label)→ 前端 MentionSpan
|
||
// - Augmentation(serde tag=kind, snake_case)→ 前端 Augmentation 宽松镜像
|
||
// - SanitizedPath(String newtype, serde transparent = 裸字符串)→ 前端 type SanitizedPath = string
|
||
//
|
||
// refId 用 camelCase(后端 serde rename = "refId",与前端 TS 风格一致);
|
||
// Augmentation 内部字段沿用后端 snake_case(path/project_name 等,与 wire 严格对齐,不做转译)。
|
||
|
||
/**
|
||
* 用户消息内 mention 区间的元数据(对齐后端 MentionSpanDto)。
|
||
*
|
||
* 前端按 {start, length} 在原文中切出区间并替换为 chip;区间被编辑破坏(长度/内容不再匹配)
|
||
* 时降级为纯文本展示,避免正则误匹配。
|
||
*
|
||
* 注意字段名:refId(camelCase,后端 serde rename)。
|
||
*/
|
||
export interface MentionSpan {
|
||
/** 区间起点(字符偏移,前端约定,后端仅透传不解释) */
|
||
start: number
|
||
/** 区间长度 */
|
||
length: number
|
||
/** kind 标签:project / task / idea / skill */
|
||
kind: 'project' | 'task' | 'idea' | 'skill'
|
||
/** 引用稳定标识(Project/Task/Idea 为 id,Skill 为 name),前端用于反查 */
|
||
refId: string
|
||
/** chip 展示文本(项目名/任务标题/技能名) */
|
||
label: string
|
||
}
|
||
|
||
/**
|
||
* 脱敏后的文件系统路径(对齐后端 SanitizedPath newtype)。
|
||
*
|
||
* 后端 serde(transparent)在 wire 上即裸字符串,前端用 string 别名即可。
|
||
* Local provider(localhost/127.0.0.1/...)保留全路径;Remote 仅 basename。
|
||
*/
|
||
export type SanitizedPath = string
|
||
|
||
/**
|
||
* Augmentation 变体集合字面量(对齐后端 serde tag=kind, rename_all=snake_case)。
|
||
*/
|
||
export type AugmentationKind = 'project' | 'task' | 'idea' | 'skill'
|
||
|
||
/**
|
||
* resolve 后的增强上下文(对齐后端 Augmentation)。
|
||
*
|
||
* 宽松镜像:tag=kind 区分变体,各变体字段按需声明(后端新增字段时前端不必同步改,
|
||
* 多余字段 JSON 解析保留不报错)。前端主要读 name/title/path 用于 chip/展示,
|
||
* 需读具体变体字段时用 type narrowing(kind === 'project' 等)。
|
||
*/
|
||
export type Augmentation = {
|
||
kind: AugmentationKind
|
||
/** 变体特有字段按需读取(用 type narrowing 访问);索引签名容纳后端新增字段 */
|
||
[field: string]: unknown
|
||
}
|
||
|
||
// AiToolCallInfo.status union 类型 — 前端构建(后端无对应 struct,经 audit log/stream event 组装)。
|
||
// 值集核验:grep src/composables/ai + src/components 实际使用点 = {running,pending_approval,completed,rejected}。
|
||
// 前端为权威源(无后端 enum 约束),保持现状仅抽 alias 便于复用。
|
||
export type AiToolCallStatus = 'running' | 'pending_approval' | 'completed' | 'rejected'
|
||
|
||
/** 工具调用信息 */
|
||
export interface AiToolCallInfo {
|
||
id: string
|
||
name: string
|
||
args: unknown
|
||
status: AiToolCallStatus
|
||
result?: unknown
|
||
/** 审批风险说明(AiApprovalRequired 时填充) */
|
||
reason?: string
|
||
/** AE-2025-03:write_file 行级 unified diff(旧文件 vs 新内容),审批卡即时预览。
|
||
* 旧文件不存在(新建)或非 write_file 为 undefined,前端回退显新 content。 */
|
||
diff?: string
|
||
/**
|
||
* path_auth 审批链阶段3b(统一审批模型):审批类型,区分两类挂起。
|
||
* - 'path'(F-260619-03 Phase B 路径授权挂起):ToolCard 显 once/session/always/deny 四选项,
|
||
* 调 aiApi.authorizeDir(once 写 once 层单次执行后清 / session 写会话临时 / always 写持久白名单 / deny 工具返 Err)。
|
||
* - 'risk'(普通 RiskLevel 审批,Med/High 风险工具):ToolCard 显 approve/reject 两选项,
|
||
* 调 aiApi.approve(一次性)。
|
||
* undefined = 未进 pending_approval 态(非挂起)或老后端 risk 类(默认 'risk')。
|
||
* 开关 df-ai-unified-approval 控制 path 类是否归一进 pendingApprovals 带此字段。
|
||
*/
|
||
kind?: 'path' | 'risk'
|
||
/**
|
||
* path_auth 审批链阶段3b:'path' 类挂起携带的目录信息(规范化后的待授权目录)。
|
||
* AiDirAuthRequired 归一为 pendingApprovals 项时透传,ToolCard 显提示"LLM 想访问 X 目录"。
|
||
* 'risk' 类为 undefined。
|
||
*/
|
||
dir?: string
|
||
/** path_auth 审批链阶段3b:'path' 类挂起携带的原始路径(工具调用参数中的 path)。
|
||
* ToolCard 审批提示文案展示用(LLM 想访问 path,父目录为 dir)。'risk' 类为 undefined。 */
|
||
path?: string
|
||
}
|
||
|
||
/** 对话列表摘要 */
|
||
export interface AiConversationSummary {
|
||
id: string
|
||
title: string | null
|
||
provider_id: string | null
|
||
model: string | null
|
||
pinned_goals?: string[]
|
||
archived: boolean
|
||
pinned?: boolean
|
||
prompt_tokens?: number | null
|
||
completion_tokens?: number | null
|
||
created_at: string
|
||
updated_at: string
|
||
}
|
||
|
||
/** 审批选择类型(F-260615-01: single=单选默认,multiple=多选) */
|
||
export type ApprovalSelectType = 'single' | 'multiple'
|
||
|
||
/** 人工审批请求 */
|
||
export interface HumanApprovalRequest {
|
||
execution_id: string
|
||
node_id: string
|
||
title: string
|
||
description: string
|
||
options: string[]
|
||
/** F-260615-01: 缺省 single(向后兼容),multiple 时允许多选 */
|
||
select_type?: ApprovalSelectType
|
||
}
|
||
|
||
/** 人工审批响应 */
|
||
export interface HumanApprovalResponse {
|
||
execution_id: string
|
||
node_id: string
|
||
decision: string
|
||
/** F-260615-01: 多选结果(single 时长度=1,multiple 时长度≥1) */
|
||
decisions?: string[]
|
||
comment?: string
|
||
}
|
||
|
||
/** 切换对话返回(含 messages JSON) */
|
||
export interface AiConversationDetail {
|
||
id: string
|
||
title: string | null
|
||
messages: string // JSON string of ChatMessage[]
|
||
/** 生成中返回 true(后端 ai_conversation_switch 在 generating 时置),前端据此禁编辑(FR-C5) */
|
||
readonly?: boolean
|
||
}
|
||
|
||
/** 技能信息(本机 Claude skill,供 `/` 联想 + 注入) */
|
||
export interface SkillInfo {
|
||
name: string
|
||
description: string
|
||
argument_hint?: string
|
||
/** skill | command | plugin */
|
||
source: string
|
||
/** SKILL.md 绝对路径(后端注入时读全文) */
|
||
path: string
|
||
}
|
||
|
||
// ============================================================
|
||
// 知识库
|
||
// ============================================================
|
||
|
||
/** 知识条目(与 Rust KnowledgeRecord 严格对齐) */
|
||
export interface KnowledgeRecord {
|
||
id: string
|
||
kind: string // review_rule | prompt_template | pitfall | architecture_pattern | diagnosis | deployment_note | workflow_optimization
|
||
title: string
|
||
content: string
|
||
tags: string | null // JSON 数组字符串
|
||
status: string // candidate | pending_review | published | archived
|
||
confidence: string | null // high | medium | low
|
||
reuse_count: number
|
||
verified: boolean
|
||
source_project: string | null
|
||
source_ref: string | null
|
||
/** AI 提炼判断依据("为何值得沉淀"),手动录入为 null */
|
||
reasoning: string | null
|
||
created_at: string
|
||
updated_at: string
|
||
}
|
||
|
||
/** 创建知识入参 */
|
||
export interface CreateKnowledgeInput {
|
||
kind: string
|
||
title: string
|
||
content: string
|
||
tags?: string
|
||
source_project?: string
|
||
source_ref?: string
|
||
confidence?: string
|
||
}
|
||
|
||
/** 检索知识入参 */
|
||
export interface KnowledgeSearchInput {
|
||
query: string
|
||
kind?: string
|
||
limit?: number
|
||
}
|
||
|
||
/** 知识生命线事件记录(产生/审核/引用/归档审计) */
|
||
export interface KnowledgeEventRecord {
|
||
id: string
|
||
knowledge_id: string
|
||
/** created | extracted | status_changed | referenced */
|
||
event_type: string
|
||
source_ref: string | null
|
||
/** JSON 字符串,内容因 event_type 而异(见后端 KnowledgeTimeline) */
|
||
context_json: string | null
|
||
timestamp: string
|
||
}
|
||
|
||
/** 知识详情聚合负载(基本信息 + 全部生命线事件) */
|
||
export interface KnowledgeDetailPayload {
|
||
knowledge: KnowledgeRecord
|
||
events: KnowledgeEventRecord[]
|
||
}
|
||
|
||
/** 编辑知识入参(部分更新,仅传需改字段) */
|
||
export interface UpdateKnowledgeInput {
|
||
title?: string
|
||
content?: string
|
||
tags?: string
|
||
confidence?: string
|
||
reasoning?: string
|
||
}
|
||
|
||
/** 知识库行为配置(提取 + 注入 + 向量检索) */
|
||
export interface KnowledgeConfig {
|
||
auto_extract: boolean
|
||
trigger_mode: 'on_complete' | 'manual_only'
|
||
min_messages: number
|
||
auto_inject: boolean
|
||
/** 语义检索(向量)开关,默认 false——关闭时纯 LIKE 零外部依赖 */
|
||
vector_enabled: boolean
|
||
/** embedding 用的 provider id(仅 openai_compat 类型) */
|
||
embedding_provider_id: string | null
|
||
/** embedding 模型名(如 embedding-3) */
|
||
embedding_model: string | null
|
||
}
|