重构: CR-11 composables+ToolCard 健壮性 6 子项
⑦ useAiConversations JSON.parse 逐条 try/catch 容错(坏条降级不清空整对话);⑧ ToolCard 去 as any + argString 安全取字段;⑨ useAiSend approveToolCall 复用 findToolCall;⑩ useAiEvents 补 AiHeartbeat case 防穿透;⑪ approveHumanApproval 签名收敛(decisions:string[] + select_type 判单/多选)+ ProjectDetail 调用方同步(单选包数组/多选直传);⑫ ToolCard formatBytes/formatToolName/argString 兜底。批5 ww1mh6mry,vue-tsc 0
This commit is contained in:
@@ -136,6 +136,7 @@ function shouldKeepOpen(tc: AiToolCallInfo): boolean {
|
||||
}
|
||||
|
||||
function formatToolName(name: string): string {
|
||||
if (!name) return ''
|
||||
return name.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())
|
||||
}
|
||||
|
||||
@@ -200,6 +201,7 @@ function parseResult(result: unknown): ToolResult | null {
|
||||
}
|
||||
|
||||
function toolCategory(name: string): string {
|
||||
if (!name) return 'default'
|
||||
if (name === 'read_file') return 'file-read'
|
||||
if (name === 'write_file') return 'file-write'
|
||||
if (name === 'list_directory') return 'dir'
|
||||
@@ -223,14 +225,23 @@ function shortPath(p: string): string {
|
||||
return parts.length <= 2 ? p : '.../' + parts.slice(-2).join('/')
|
||||
}
|
||||
|
||||
/** 格式化字节数 */
|
||||
function formatBytes(bytes: number | undefined): string {
|
||||
if (!bytes) return '0 B'
|
||||
/** 格式化字节数(兜底:undefined/null/负/NaN/Infinity 统一降级为 '0 B',防渲染异常) */
|
||||
function formatBytes(bytes: number | undefined | null): string {
|
||||
if (typeof bytes !== 'number' || !Number.isFinite(bytes) || bytes <= 0) return '0 B'
|
||||
if (bytes < 1024) return bytes + ' B'
|
||||
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'
|
||||
return (bytes / 1048576).toFixed(1) + ' MB'
|
||||
}
|
||||
|
||||
/** 从工具 args(unknown)中安全取字符串字段;非对象/字段非 string 时返回空串 */
|
||||
function argString(args: unknown, key: string): string {
|
||||
if (args && typeof args === 'object' && !Array.isArray(args)) {
|
||||
const v = (args as Record<string, unknown>)[key]
|
||||
return typeof v === 'string' ? v : ''
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
/** 通用工具结果格式化(非文件类工具) */
|
||||
function formatToolResult(tc: AiToolCallInfo): string {
|
||||
const r = parseResult(tc.result)
|
||||
@@ -238,8 +249,11 @@ function formatToolResult(tc: AiToolCallInfo): string {
|
||||
// 非 JSON(纯文本:审批占位/错误/拒绝)→ 原样显示,审批占位时补拟执行参数避免空白
|
||||
const raw = typeof tc.result === 'string' ? tc.result : ''
|
||||
if (raw && tc.args && typeof tc.args === 'object') {
|
||||
const a = tc.args as any
|
||||
const detail = a.title || a.name || a.path || ''
|
||||
const a = tc.args as Record<string, unknown>
|
||||
const detail = typeof a.title === 'string' ? a.title
|
||||
: typeof a.name === 'string' ? a.name
|
||||
: typeof a.path === 'string' ? a.path
|
||||
: ''
|
||||
if (detail) return `${raw}(${detail})`
|
||||
}
|
||||
return raw
|
||||
@@ -325,8 +339,7 @@ function displayArgValue(arg: { key: string; val: unknown }): string {
|
||||
* 解析项目名(复用 projectNameById,无则走 fallback),create_* 用固定文案。
|
||||
*/
|
||||
function toolDisplayName(tc: AiToolCallInfo): string {
|
||||
const args = tc.args as any
|
||||
const p = args?.path as string | undefined
|
||||
const p = argString(tc.args, 'path')
|
||||
switch (tc.name) {
|
||||
case 'read_file': return p ? `${t('aiTool.readPrefix')} ${shortPath(p)}` : t('aiTool.readFallback')
|
||||
case 'list_directory': return p ? `${t('aiTool.dirPrefix')} ${shortPath(p)}` : t('aiTool.dirFallback')
|
||||
@@ -336,7 +349,7 @@ function toolDisplayName(tc: AiToolCallInfo): string {
|
||||
case 'purge_project':
|
||||
case 'update_project': {
|
||||
const idKey = PROJECT_ID_TOOL_ARG[tc.name]
|
||||
const id = idKey ? (args?.[idKey] as string | undefined) : ''
|
||||
const id = idKey ? argString(tc.args, idKey) : ''
|
||||
const name = id ? projectNameById.value[id] : ''
|
||||
const prefixKey = `${tc.name.replace('_project', '')}Prefix` as 'deletePrefix' | 'restorePrefix' | 'purgePrefix' | 'updatePrefix'
|
||||
const fallbackKey = `${tc.name.replace('_project', '')}Fallback` as 'deleteFallback' | 'restoreFallback' | 'purgeFallback' | 'updateFallback'
|
||||
|
||||
Reference in New Issue
Block a user