优化: 批A前端(timer所有权+会话族+审批conv-scoped+FilePreview+失败反馈)
A1-B1 timer所有权:新建 useTimerOwnership composable(每实例独立ref+onUnmounted清理)+ useToast _timer 下沉 + Ideas debounce 补清理(治跨实例串扰) A1-B2 FilePreview:reqSeq 双计数器守卫(loadFile/loadDiff 最新seq才写,防乱序覆盖)+ mermaid securityLevel strict + filePath 比对(防跨文件SVG注入) A1-B3 会话族:load_more 滚顶加载接线(switch透传has_more/earliest_seq+prepend去重+scrollTop恢复)+ switch失败保留视图+报错(仅对话不存在才create-new)+ new/delete失败反馈(withConvOp helper收敛)+ delete清ai_messages孤儿 A1-B5前端契约:isToolFailure 三处加 success===false 判定(useToolCard/ToolResultBody/ToolCard,git只读失败不再绿框) A2-B10 审批conv-scoped:pendingApprovals 补conversationId + cleanup 按convId filter + 移除全局清(AiError不再误清其他conv)+ :676 dir auth filter方向修 usage打标前端:is_estimated 字段+事件透传+MessageList『估算』角标(详情面板说明) A2-B9前端:clearChat try/catch 错误气泡
This commit is contained in:
@@ -301,6 +301,19 @@ export const aiApi = {
|
||||
return invoke('ai_conversation_switch', { conversationId })
|
||||
},
|
||||
|
||||
/**
|
||||
* 加载更早历史消息(G3.5 滚顶分页)。
|
||||
* beforeSeq=当前已加载最早消息的 seq(游标,后端返 earliest_seq),返回更早的 PAGE_SIZE 条。
|
||||
* 返 messages JSON 数组 + has_more(是否还有更早)+ earliest_seq(新游标,null=已到尽头)。
|
||||
*/
|
||||
loadMoreMessages(conversationId: string, beforeSeq: number): Promise<{
|
||||
messages: string
|
||||
has_more: boolean
|
||||
earliest_seq: number | null
|
||||
}> {
|
||||
return invoke('ai_conversation_load_more', { conversationId, beforeSeq })
|
||||
},
|
||||
|
||||
/** 删除对话 */
|
||||
deleteConversation(conversationId: string): Promise<void> {
|
||||
return invoke('ai_conversation_delete', { conversationId })
|
||||
|
||||
@@ -175,10 +175,38 @@ export interface TaskRecord {
|
||||
output_json?: string
|
||||
/** 关联灵感 ID(F-260619-01,1对1 单向,任务→灵感)。未关联时为 undefined。 */
|
||||
idea_id?: string
|
||||
/**
|
||||
* 管理维度池标记(知识图谱 Phase 1,V29 列)。与 status(执行维度)正交。
|
||||
* 取值 backlog(需求池)/todo(待办池)/decision(待决策池)/active(执行中)/done(已完成)。
|
||||
* 后端 DEFAULT 'todo' 保证老任务迁移后取值确定,前端始终收到该字段。
|
||||
*/
|
||||
queue: string
|
||||
/** 父任务 ID(1 级嵌套,无孙任务,由 IPC 校验)。顶层任务(无父)为 null/undefined。 */
|
||||
parent_id?: string | null
|
||||
/**
|
||||
* 结构化需求规格 JSON 字符串(知识图谱 Phase 1,V29 列)。
|
||||
* 结构 { background, acceptance_criteria[], scope[], technical_design, custom_fields }。
|
||||
* 老任务无结构化规格时为 undefined。
|
||||
*/
|
||||
content_json?: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export interface TaskTreeNode {
|
||||
/** 父任务记录(含 parent_id/queue 等全字段) */
|
||||
parent: TaskRecord
|
||||
/** 父任务的直接子任务(1 级嵌套,无孙任务) */
|
||||
children: TaskRecord[]
|
||||
}
|
||||
|
||||
/** delete_task 新返回结构(破坏性变更):删除父任务时级联软删其子任务 */
|
||||
export interface TaskDeleteResult {
|
||||
ok: boolean
|
||||
/** 级联软删的子任务数 */
|
||||
cascaded: number
|
||||
}
|
||||
|
||||
export interface CreateTaskInput {
|
||||
project_id: ProjectId
|
||||
title: string
|
||||
@@ -188,6 +216,10 @@ export interface CreateTaskInput {
|
||||
assignee?: string
|
||||
/** 关联灵感 ID(1对1 单向,可空)。空字符串视为不关联(与后端一致)。 */
|
||||
idea_id?: string
|
||||
/** 管理池标记(backlog/todo/decision/active/done,可空)。不传后端默认 todo。 */
|
||||
queue?: string
|
||||
/** 父任务 ID(1 级嵌套,可空)。顶层任务不传;空字符串后端视为 None。 */
|
||||
parent_id?: string | null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,6 +246,10 @@ export interface TaskQuery {
|
||||
order_by?: string | null
|
||||
limit?: number | null
|
||||
offset?: number | null
|
||||
/** 管理池标记精确匹配(backlog/todo/decision/active/done,可空) */
|
||||
queue?: string | null
|
||||
/** 父任务 ID 精确匹配(取某父任务的全部子任务,可空) */
|
||||
parent_id?: string | null
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
@@ -400,6 +436,12 @@ export type AiChatEvent = ({
|
||||
prompt_cache_miss_tokens: number
|
||||
/** 思考(deepseek-reasoner/o1 reasoning_tokens,隐藏输出)。0=非 reasoning 模型 */
|
||||
reasoning_tokens: number
|
||||
/**
|
||||
* G4.3:该轮 token 用量是否估算值(后端 agentic 运行时兜底:round_usage.prompt_tokens==0
|
||||
* 时用 estimated_prompt 填充并打标)。true=per-response 估算(prompt 非真实,provider 未报),
|
||||
* undefined/false=真实值。前端 MessageList 据此标注『估算』区分 estimated vs real。
|
||||
*/
|
||||
is_estimated?: boolean
|
||||
incomplete?: boolean; pinned_goals?: GoalEntry[]
|
||||
} | {
|
||||
type: 'AiError'; error: string; error_type?: AiErrorType
|
||||
@@ -533,6 +575,11 @@ export interface AiMessage {
|
||||
cache_miss?: number
|
||||
/** 思考 token(隐藏输出) */
|
||||
reasoning?: number
|
||||
/**
|
||||
* G4.3:该轮 token 用量是否估算值(后端 AiCompleted.is_estimated 透传)。
|
||||
* true=prompt_tokens 缺失按估算展示,MessageList 标注『估算』;undefined=false=真实值。
|
||||
*/
|
||||
is_estimated?: boolean
|
||||
}
|
||||
/**
|
||||
* 本轮输入 token(消息级持久化,后端 ChatMessage.prompt_tokens 镜像)。
|
||||
@@ -646,6 +693,15 @@ export interface AiToolCallInfo {
|
||||
/** path_auth 审批链阶段3b:'path' 类挂起携带的原始路径(工具调用参数中的 path)。
|
||||
* ToolCard 审批提示文案展示用(LLM 想访问 path,父目录为 dir)。'risk' 类为 undefined。 */
|
||||
path?: string
|
||||
/**
|
||||
* A2-B10 conv-scoped 审批收尾:挂起审批所属的会话 id(前端判定用,仅挂起项设置)。
|
||||
* 来源:AiApprovalRequired / AiDirAuthRequired(统一审批归一)事件透传 conversation_id
|
||||
* (缺失时兜底 activeConversationId);switchConversation 恢复历史挂起时填目标会话 id。
|
||||
* cleanupTerminatedConversation 据此仅清目标会话的待审批项 + 对称清其审批超时计时器,
|
||||
* 不连累并发会话正在审批的卡(conv-scoped,误清其他会话审批 = 回归)。
|
||||
* undefined = 非挂起项或无法归属(保守保留,不清)。对齐 PendingDirAuth.conversationId。
|
||||
*/
|
||||
conversationId?: string
|
||||
}
|
||||
|
||||
/** 对话列表摘要 */
|
||||
|
||||
Reference in New Issue
Block a user