mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-04-23 01:39:37 +08:00
fix: 修复部分ts报错
This commit is contained in:
5
electron/preload/index.d.ts
vendored
5
electron/preload/index.d.ts
vendored
@@ -24,6 +24,8 @@ import type {
|
||||
MergeParams,
|
||||
MergeResult,
|
||||
MemberWithStats,
|
||||
TableSchema,
|
||||
SQLResult,
|
||||
} from '../../src/types/chat'
|
||||
|
||||
interface TimeFilter {
|
||||
@@ -67,6 +69,9 @@ interface ChatApi {
|
||||
getMembers: (sessionId: string) => Promise<MemberWithStats[]>
|
||||
updateMemberAliases: (sessionId: string, memberId: number, aliases: string[]) => Promise<boolean>
|
||||
deleteMember: (sessionId: string, memberId: number) => Promise<boolean>
|
||||
// SQL 实验室
|
||||
getSchema: (sessionId: string) => Promise<TableSchema[]>
|
||||
executeSQL: (sessionId: string, sql: string) => Promise<SQLResult>
|
||||
}
|
||||
|
||||
interface Api {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"build": "electron-vite build",
|
||||
"build:mac": "npm run build && electron-builder --mac --config electron-builder.yml -p never",
|
||||
"build:win": "npm run build && electron-builder --win --config electron-builder.yml -p never",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"type-check": "vue-tsc --noEmit -p tsconfig.web.json",
|
||||
"postinstall": "electron-rebuild"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { AnchorItem } from '@/composables'
|
||||
|
||||
const props = withDefaults(
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
/** 锚点配置列表 */
|
||||
anchors: AnchorItem[]
|
||||
|
||||
@@ -171,12 +171,6 @@ function handleDeleteConversation(convId: string) {
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化时间戳
|
||||
function formatTimestamp(ts: number): string {
|
||||
const date = new Date(ts * 1000)
|
||||
return date.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' })
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(async () => {
|
||||
await checkLLMConfig()
|
||||
|
||||
@@ -3,7 +3,7 @@ import { computed } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import userAvatar from '@/assets/images/momo.png'
|
||||
import type { ContentBlock } from '@/composables/useAIChat'
|
||||
import type { ContentBlock, ToolBlockContent } from '@/composables/useAIChat'
|
||||
|
||||
// Props
|
||||
const props = defineProps<{
|
||||
@@ -79,7 +79,7 @@ function formatTimeParams(params: Record<string, unknown>): string {
|
||||
}
|
||||
|
||||
// 格式化工具参数显示
|
||||
function formatToolParams(tool: ContentBlock extends { type: 'tool'; tool: infer T } ? T : never): string {
|
||||
function formatToolParams(tool: ToolBlockContent): string {
|
||||
if (!tool.params) return ''
|
||||
|
||||
const name = tool.name
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
// Props
|
||||
|
||||
@@ -7,7 +7,7 @@ interface Props {
|
||||
animated?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
withDefaults(defineProps<Props>(), {
|
||||
color: 'from-pink-400 to-pink-600',
|
||||
height: 8,
|
||||
showLabel: false,
|
||||
|
||||
@@ -60,8 +60,8 @@ onMounted(() => {
|
||||
unsubscribeProgress = window.mergeApi.onParseProgress(({ filePath, progress }) => {
|
||||
const file = files.value.find((f) => f.path === filePath)
|
||||
if (file && file.status === 'pending') {
|
||||
// 使用 percentage 而不是 progress(更准确)
|
||||
file.progress = progress.percentage ?? progress.progress ?? 0
|
||||
// 使用 progress
|
||||
file.progress = progress.progress ?? 0
|
||||
// 构建更详细的进度消息
|
||||
if (progress.messagesProcessed && progress.messagesProcessed > 0) {
|
||||
file.progressMessage = `已处理 ${progress.messagesProcessed.toLocaleString()} 条消息`
|
||||
@@ -407,7 +407,7 @@ const file2Name = computed(() => files.value[1]?.name || '文件 2')
|
||||
|
||||
<!-- 拖拽上传区域 -->
|
||||
<FileDropZone multiple :accept="['.json', '.txt']" :disabled="isLoading" @files="handleFileDrop">
|
||||
<template #default="{ isDragOver, openFileDialog }">
|
||||
<template #default="{ isDragOver }">
|
||||
<div
|
||||
class="flex cursor-pointer flex-col items-center justify-center rounded-lg border-2 border-dashed border-gray-300 px-6 py-6 transition-all hover:border-primary-400 hover:bg-primary-50/50 dark:border-gray-600 dark:hover:border-primary-500 dark:hover:bg-primary-900/10"
|
||||
:class="{
|
||||
|
||||
@@ -17,17 +17,19 @@ export interface ToolCallRecord {
|
||||
params?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export interface ToolBlockContent {
|
||||
name: string
|
||||
displayName: string
|
||||
status: 'running' | 'done' | 'error'
|
||||
params?: Record<string, unknown>
|
||||
}
|
||||
|
||||
// 内容块类型(用于 AI 消息的流式混合渲染)
|
||||
export type ContentBlock =
|
||||
| { type: 'text'; text: string }
|
||||
| {
|
||||
type: 'tool'
|
||||
tool: {
|
||||
name: string
|
||||
displayName: string
|
||||
status: 'running' | 'done' | 'error'
|
||||
params?: Record<string, unknown>
|
||||
}
|
||||
tool: ToolBlockContent
|
||||
}
|
||||
|
||||
// 消息类型
|
||||
@@ -152,7 +154,6 @@ export function useAIChat(
|
||||
toolCalls: [], // 工具调用会在这里更新
|
||||
}
|
||||
messages.value.push(userMessage)
|
||||
const userMessageIndex = messages.value.length - 1
|
||||
console.log('[AI] 已添加用户消息')
|
||||
|
||||
// 开始处理
|
||||
@@ -259,89 +260,98 @@ export function useAIChat(
|
||||
content: msg.content,
|
||||
}))
|
||||
|
||||
console.log('[AI] 调用 Agent API...', context, 'historyLength:', historyMessages.length, 'chatType:', chatType, 'promptConfig:', currentPromptConfig.value)
|
||||
console.log(
|
||||
'[AI] 调用 Agent API...',
|
||||
context,
|
||||
'historyLength:',
|
||||
historyMessages.length,
|
||||
'chatType:',
|
||||
chatType,
|
||||
'promptConfig:',
|
||||
currentPromptConfig.value
|
||||
)
|
||||
|
||||
// 获取 requestId 和 promise(传递历史消息、聊天类型和提示词配置)
|
||||
const { requestId: agentReqId, promise: agentPromise } = window.agentApi.runStream(
|
||||
content,
|
||||
context,
|
||||
(chunk) => {
|
||||
// 如果已中止或请求 ID 不匹配,忽略后续 chunks
|
||||
if (isAborted || thisRequestId !== currentRequestId) {
|
||||
console.log('[AI] 已中止或请求已过期,忽略 chunk', {
|
||||
isAborted,
|
||||
thisRequestId,
|
||||
currentRequestId,
|
||||
})
|
||||
return
|
||||
}
|
||||
// 如果已中止或请求 ID 不匹配,忽略后续 chunks
|
||||
if (isAborted || thisRequestId !== currentRequestId) {
|
||||
console.log('[AI] 已中止或请求已过期,忽略 chunk', {
|
||||
isAborted,
|
||||
thisRequestId,
|
||||
currentRequestId,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 只在工具调用时记录,减少日志噪音
|
||||
if (chunk.type === 'tool_start' || chunk.type === 'tool_result') {
|
||||
console.log('[AI] Agent chunk:', chunk.type, chunk.toolName)
|
||||
}
|
||||
// 只在工具调用时记录,减少日志噪音
|
||||
if (chunk.type === 'tool_start' || chunk.type === 'tool_result') {
|
||||
console.log('[AI] Agent chunk:', chunk.type, chunk.toolName)
|
||||
}
|
||||
|
||||
switch (chunk.type) {
|
||||
case 'content':
|
||||
// 流式内容更新 - 追加到 contentBlocks
|
||||
if (chunk.content) {
|
||||
currentToolStatus.value = null
|
||||
appendTextToBlocks(chunk.content)
|
||||
}
|
||||
break
|
||||
|
||||
case 'tool_start':
|
||||
// 工具开始执行 - 添加工具块到 contentBlocks
|
||||
console.log('[AI] 工具开始执行:', chunk.toolName, chunk.toolParams)
|
||||
if (chunk.toolName) {
|
||||
const toolParams = chunk.toolParams as Record<string, unknown> | undefined
|
||||
currentToolStatus.value = {
|
||||
name: chunk.toolName,
|
||||
displayName: TOOL_DISPLAY_NAMES[chunk.toolName] || chunk.toolName,
|
||||
status: 'running',
|
||||
switch (chunk.type) {
|
||||
case 'content':
|
||||
// 流式内容更新 - 追加到 contentBlocks
|
||||
if (chunk.content) {
|
||||
currentToolStatus.value = null
|
||||
appendTextToBlocks(chunk.content)
|
||||
}
|
||||
toolsUsedInCurrentRound.value.push(chunk.toolName)
|
||||
break
|
||||
|
||||
// 添加工具块到 AI 消息的 contentBlocks
|
||||
addToolBlock(chunk.toolName, toolParams)
|
||||
}
|
||||
break
|
||||
case 'tool_start':
|
||||
// 工具开始执行 - 添加工具块到 contentBlocks
|
||||
console.log('[AI] 工具开始执行:', chunk.toolName, chunk.toolParams)
|
||||
if (chunk.toolName) {
|
||||
const toolParams = chunk.toolParams as Record<string, unknown> | undefined
|
||||
currentToolStatus.value = {
|
||||
name: chunk.toolName,
|
||||
displayName: TOOL_DISPLAY_NAMES[chunk.toolName] || chunk.toolName,
|
||||
status: 'running',
|
||||
}
|
||||
toolsUsedInCurrentRound.value.push(chunk.toolName)
|
||||
|
||||
case 'tool_result':
|
||||
// 工具执行结果 - 更新工具块状态
|
||||
console.log('[AI] 工具执行结果:', chunk.toolName, chunk.toolResult)
|
||||
if (chunk.toolName) {
|
||||
if (currentToolStatus.value?.name === chunk.toolName) {
|
||||
// 添加工具块到 AI 消息的 contentBlocks
|
||||
addToolBlock(chunk.toolName, toolParams)
|
||||
}
|
||||
break
|
||||
|
||||
case 'tool_result':
|
||||
// 工具执行结果 - 更新工具块状态
|
||||
console.log('[AI] 工具执行结果:', chunk.toolName, chunk.toolResult)
|
||||
if (chunk.toolName) {
|
||||
if (currentToolStatus.value?.name === chunk.toolName) {
|
||||
currentToolStatus.value = {
|
||||
...currentToolStatus.value,
|
||||
status: 'done',
|
||||
}
|
||||
}
|
||||
// 更新 contentBlocks 中的工具块状态
|
||||
updateToolBlockStatus(chunk.toolName, 'done')
|
||||
}
|
||||
isLoadingSource.value = false
|
||||
break
|
||||
|
||||
case 'done':
|
||||
// 完成
|
||||
console.log('[AI] Agent 完成')
|
||||
currentToolStatus.value = null
|
||||
break
|
||||
|
||||
case 'error':
|
||||
// 错误
|
||||
console.error('[AI] Agent 错误:', chunk.error)
|
||||
if (currentToolStatus.value) {
|
||||
currentToolStatus.value = {
|
||||
...currentToolStatus.value,
|
||||
status: 'done',
|
||||
status: 'error',
|
||||
}
|
||||
// 更新对应工具块状态为错误
|
||||
updateToolBlockStatus(currentToolStatus.value.name, 'error')
|
||||
}
|
||||
// 更新 contentBlocks 中的工具块状态
|
||||
updateToolBlockStatus(chunk.toolName, 'done')
|
||||
}
|
||||
isLoadingSource.value = false
|
||||
break
|
||||
|
||||
case 'done':
|
||||
// 完成
|
||||
console.log('[AI] Agent 完成')
|
||||
currentToolStatus.value = null
|
||||
break
|
||||
|
||||
case 'error':
|
||||
// 错误
|
||||
console.error('[AI] Agent 错误:', chunk.error)
|
||||
if (currentToolStatus.value) {
|
||||
currentToolStatus.value = {
|
||||
...currentToolStatus.value,
|
||||
status: 'error',
|
||||
}
|
||||
// 更新对应工具块状态为错误
|
||||
updateToolBlockStatus(currentToolStatus.value.name, 'error')
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
},
|
||||
historyMessages,
|
||||
chatType,
|
||||
@@ -458,13 +468,16 @@ export function useAIChat(
|
||||
const history = await window.aiApi.getMessages(conversationId)
|
||||
currentConversationId.value = conversationId
|
||||
|
||||
console.log('[AI] 从数据库加载的原始消息:', history.map((m) => ({
|
||||
id: m.id,
|
||||
role: m.role,
|
||||
contentLength: m.content?.length,
|
||||
hasContentBlocks: !!m.contentBlocks,
|
||||
contentBlocksLength: m.contentBlocks?.length,
|
||||
})))
|
||||
console.log(
|
||||
'[AI] 从数据库加载的原始消息:',
|
||||
history.map((m) => ({
|
||||
id: m.id,
|
||||
role: m.role,
|
||||
contentLength: m.content?.length,
|
||||
hasContentBlocks: !!m.contentBlocks,
|
||||
contentBlocksLength: m.contentBlocks?.length,
|
||||
}))
|
||||
)
|
||||
|
||||
messages.value = history.map((msg) => ({
|
||||
id: msg.id,
|
||||
|
||||
@@ -196,7 +196,7 @@ function getProgressDetail(): string {
|
||||
class="w-full max-w-4xl"
|
||||
@files="handleFileDrop"
|
||||
>
|
||||
<template #default="{ isDragOver, openFileDialog }">
|
||||
<template #default="{ isDragOver }">
|
||||
<div
|
||||
class="group relative flex w-full cursor-pointer flex-col items-center justify-center rounded-2xl border-2 border-dashed border-pink-300/50 bg-white/50 px-8 py-8 backdrop-blur-sm transition-all duration-300 hover:border-pink-400 hover:bg-white/80 hover:shadow-lg hover:shadow-pink-500/10 focus:outline-none focus:ring-4 focus:ring-pink-500/20 sm:px-12 sm:py-12 dark:border-pink-700/50 dark:bg-gray-900/50 dark:hover:border-pink-500 dark:hover:bg-gray-900/80"
|
||||
:class="{
|
||||
|
||||
@@ -26,7 +26,7 @@ export const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
router.beforeEach((_to, _from, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user