新增: 初始化 DevFlow 项目仓库

Tauri 2 + Vue 3 + Vite 6 桌面应用,Rust workspace 含 13 个 crate
(df-ai / df-storage / df-workflow / df-core / df-execute 等)。
核心能力:AI 聊天 agentic 循环(工具调用+人工审批)、工作流引擎、
任务/想法/项目/阶段管理、可追溯性,及配套前端组件。
This commit is contained in:
2026-06-12 01:31:05 +08:00
commit 98393b4908
178 changed files with 27859 additions and 0 deletions

90
src/api/ai.ts Normal file
View File

@@ -0,0 +1,90 @@
//! AI 聊天 API — IPC invoke 封装 + 事件监听
import { invoke } from '@tauri-apps/api/core'
import { listen, type UnlistenFn } from '@tauri-apps/api/event'
import type { AiChatEvent, AiConversationDetail, AiConversationSummary, AiProviderConfig } from './types'
export const aiApi = {
/** 发送消息(非阻塞,通过 ai-chat-event 流式返回) */
sendMessage(message: string, language?: string): Promise<string> {
return invoke('ai_chat_send', { message, language: language || 'zh-CN' })
},
/** 批准/拒绝工具调用 */
approve(toolCallId: string, approved: boolean): Promise<string> {
return invoke('ai_approve', { toolCallId, approved })
},
/** 清空对话 */
clearChat(): Promise<void> {
return invoke('ai_chat_clear')
},
/** 停止当前生成 */
stopChat(): Promise<void> {
return invoke('ai_chat_stop')
},
/** 列出所有 AI 提供商 */
listProviders(): Promise<AiProviderConfig[]> {
return invoke('ai_list_providers')
},
/** 保存 AI 提供商 */
saveProvider(input: {
id?: string
name: string
providerType: string
baseUrl: string
apiKey: string
defaultModel: string
}): Promise<string> {
return invoke('ai_save_provider', {
id: input.id,
name: input.name,
providerType: input.providerType,
baseUrl: input.baseUrl,
apiKey: input.apiKey,
defaultModel: input.defaultModel,
})
},
/** 设置活跃提供商 */
setProvider(providerId: string): Promise<void> {
return invoke('ai_set_provider', { providerId })
},
/** 监听 AI 聊天事件 */
onEvent(callback: (event: AiChatEvent) => void): Promise<UnlistenFn> {
return listen<AiChatEvent>('ai-chat-event', (e) => {
callback(e.payload)
})
},
// ── 对话管理 ──
/** 创建新对话 */
createConversation(): Promise<{ id: string }> {
return invoke('ai_conversation_create')
},
/** 列出所有对话(摘要) */
listConversations(): Promise<AiConversationSummary[]> {
return invoke('ai_conversation_list')
},
/** 切换到指定对话 */
switchConversation(conversationId: string): Promise<AiConversationDetail> {
return invoke('ai_conversation_switch', { conversationId })
},
/** 删除对话 */
deleteConversation(conversationId: string): Promise<void> {
return invoke('ai_conversation_delete', { conversationId })
},
/** 重命名对话标题 */
renameConversation(conversationId: string, title: string): Promise<void> {
return invoke('ai_conversation_rename', { conversationId, title })
},
}

20
src/api/idea.ts Normal file
View File

@@ -0,0 +1,20 @@
import { invoke } from '@tauri-apps/api/core'
import type { IdeaRecord, CreateIdeaInput } from './types'
export const ideaApi = {
list(): Promise<IdeaRecord[]> {
return invoke('list_ideas')
},
create(input: CreateIdeaInput): Promise<IdeaRecord> {
return invoke('create_idea', { input })
},
update(id: string, field: string, value: string): Promise<boolean> {
return invoke('update_idea', { id, field, value })
},
delete(id: string): Promise<boolean> {
return invoke('delete_idea', { id })
},
}

6
src/api/index.ts Normal file
View File

@@ -0,0 +1,6 @@
export * from './types'
export { projectApi } from './project'
export { taskApi } from './task'
export { ideaApi } from './idea'
export { workflowApi } from './workflow'
export { aiApi } from './ai'

24
src/api/project.ts Normal file
View File

@@ -0,0 +1,24 @@
import { invoke } from '@tauri-apps/api/core'
import type { ProjectRecord, CreateProjectInput } from './types'
export const projectApi = {
list(): Promise<ProjectRecord[]> {
return invoke('list_projects')
},
create(input: CreateProjectInput): Promise<ProjectRecord> {
return invoke('create_project', { input })
},
get(id: string): Promise<ProjectRecord | null> {
return invoke('get_project', { id })
},
update(id: string, field: string, value: string): Promise<boolean> {
return invoke('update_project', { id, field, value })
},
delete(id: string): Promise<boolean> {
return invoke('delete_project', { id })
},
}

20
src/api/task.ts Normal file
View File

@@ -0,0 +1,20 @@
import { invoke } from '@tauri-apps/api/core'
import type { TaskRecord, CreateTaskInput } from './types'
export const taskApi = {
list(projectId?: string): Promise<TaskRecord[]> {
return invoke('list_tasks', { projectId: projectId ?? null })
},
create(input: CreateTaskInput): Promise<TaskRecord> {
return invoke('create_task', { input })
},
update(id: string, field: string, value: string): Promise<boolean> {
return invoke('update_task', { id, field, value })
},
delete(id: string): Promise<boolean> {
return invoke('delete_task', { id })
},
}

204
src/api/types.ts Normal file
View File

@@ -0,0 +1,204 @@
//! TypeScript 类型定义 — 与 Rust Record 结构体严格对齐
// ============================================================
// 想法
// ============================================================
export interface IdeaRecord {
id: string
title: string
description: string
status: string // draft | pending_review | approved | promoted | rejected
priority: number
score: number | null
tags: string | null // JSON 数组字符串
source: string | null
promoted_to: string | null
ai_analysis: string | null
scores: string | null
created_at: string
updated_at: string
}
export interface CreateIdeaInput {
title: string
description?: string
priority?: number
tags?: string
source?: string
}
// ============================================================
// 项目
// ============================================================
export interface ProjectRecord {
id: string
name: string
description: string
status: string // planning | in_progress | paused | completed | cancelled
idea_id: string | null
created_at: string
updated_at: string
}
export interface CreateProjectInput {
name: string
description?: string
idea_id?: string
}
// ============================================================
// 任务
// ============================================================
export interface TaskRecord {
id: string
project_id: string
title: string
description: string
status: string // todo | in_progress | review_ready | merged | abandoned
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
created_at: string
updated_at: string
}
export interface CreateTaskInput {
project_id: string
title: string
description?: string
priority?: number
branch_name?: string
assignee?: string
}
// ============================================================
// 工作流
// ============================================================
export interface WorkflowRecord {
id: string
name: string
dag_json: string
status: string // running | completed | failed | cancelled
triggered_by: string | null
project_id: string | null
task_id: string | null
created_at: string
completed_at: string | null
}
/** 工作流事件载荷(后端 emit 的结构) */
export interface WorkflowEventPayload {
execution_id: string
event: {
type: string
[key: string]: unknown
}
}
// ============================================================
// 通用
// ============================================================
export type UpdateField = {
id: string
field: string
value: string
}
// ============================================================
// AI 聊天
// ============================================================
export interface AiProviderConfig {
id: string
name: string
provider_type: string
api_key: string
base_url: string
default_model: string
models: string | null
is_default: boolean
config: string | null
created_at: string
updated_at: string
}
/** 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
} | {
type: 'AiApprovalRequired'; id: string; name: string; args: unknown; reason: string
} | {
type: 'AiApprovalResult'; id: string; approved: boolean
} | {
type: 'AiCompleted'; total_tokens: number
} | {
type: 'AiError'; error: string
} | {
type: 'AiAgentRound'; round: number
}) & {
conversation_id?: string
}
/** AI 消息前端渲染用isError 标记错误消息用于差异化样式) */
export interface AiMessage {
id: string
role: 'user' | 'assistant' | 'tool'
content: string
isError?: boolean
toolCalls?: AiToolCallInfo[]
timestamp: number
}
/** 工具调用信息 */
export interface AiToolCallInfo {
id: string
name: string
args: unknown
status: 'running' | 'pending_approval' | 'completed' | 'rejected'
result?: unknown
}
/** 对话列表摘要 */
export interface AiConversationSummary {
id: string
title: string | null
provider_id: string | null
model: string | null
created_at: string
updated_at: string
}
/** 人工审批请求 */
export interface HumanApprovalRequest {
execution_id: string
node_id: string
title: string
description: string
options: string[]
}
/** 人工审批响应 */
export interface HumanApprovalResponse {
execution_id: string
node_id: string
decision: string
comment?: string
}
/** 切换对话返回(含 messages JSON */
export interface AiConversationDetail {
id: string
title: string | null
messages: string // JSON string of ChatMessage[]
}

29
src/api/workflow.ts Normal file
View File

@@ -0,0 +1,29 @@
import { invoke } from '@tauri-apps/api/core'
import { listen } from '@tauri-apps/api/event'
import type { WorkflowRecord, WorkflowEventPayload } from './types'
export const workflowApi = {
/** 触发工作流执行,返回 execution_id */
run(name: string, dag: unknown, config?: Record<string, unknown>): Promise<string> {
return invoke('run_workflow', {
name,
dag,
config: config ?? {},
})
},
listExecutions(): Promise<WorkflowRecord[]> {
return invoke('list_workflow_executions')
},
getExecution(id: string): Promise<WorkflowRecord | null> {
return invoke('get_workflow_execution', { id })
},
/** 监听工作流实时事件,返回 unlisten 函数 */
onEvent(callback: (payload: WorkflowEventPayload) => void): Promise<() => void> {
return listen<WorkflowEventPayload>('workflow-event', (event) => {
callback(event.payload)
})
},
}