新增: obscura 安装引导(prompt AI 看 hint 帮装 + 前端工具卡片 AI 帮装按钮)
This commit is contained in:
@@ -99,6 +99,17 @@ export interface ToolResult {
|
||||
files?: string[]
|
||||
counts?: Array<{ file?: string; count?: number }>
|
||||
total_files?: number
|
||||
// fetch_url result fields(commands/ai/fetch_url.rs execute_fetch_url):
|
||||
// - markdown: 已清洗 + 截断的 markdown 主体
|
||||
// - title: HTML <title> 或 obscura markdown 首个 H1/首行(可能为 null)
|
||||
// - length: markdown 字符数(后端 result.length)
|
||||
// - render_mode: 'static' | 'static_fallback' | 'obscura'(obscura=成功用 JS 渲染)
|
||||
// static_fallback = render=true 但 obscura 未装/失败/超时 → 回退静态 + 附 hint(引导安装 obscura)
|
||||
// - hint: 仅 static_fallback 时存在,obscura 安装引导提示
|
||||
markdown?: string
|
||||
length?: number | null
|
||||
render_mode?: string
|
||||
hint?: string
|
||||
}
|
||||
|
||||
/** 内联 SVG 图标字符串(经 v-html 注入,常量安全;图标库改造见决策记录) */
|
||||
@@ -496,6 +507,7 @@ const TOOL_FORMATTERS: Record<string, (r: ToolResult) => string> = {
|
||||
bind_directory: formatBindDir,
|
||||
run_workflow: formatRunWorkflow,
|
||||
http_request: formatHttpResult,
|
||||
fetch_url: formatFetchUrl,
|
||||
grep: formatGrep,
|
||||
}
|
||||
|
||||
@@ -552,6 +564,43 @@ export function formatHttpResult(r: ToolResult): string {
|
||||
return parts.join('\n')
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch_url 结果摘要(commands/ai/fetch_url.rs):URL + render_mode 标识 + markdown(截断)。
|
||||
*
|
||||
* 通用 fallback 文案(供 formatToolResult 在 ToolResultBody 无专用模板前/或解析失败时回退)。
|
||||
* 折叠态 header 文案由 summaryFetchUrl 单独提供(更短)。markdown 主体由 ToolResultBody
|
||||
* fetch_url 专用模板渲染(可折叠 + obscura 引导按钮),此 formatter 仅做兜底文本。
|
||||
*
|
||||
* - render_mode='obscura':成功用 obscura JS 渲染,显已渲染标识。
|
||||
* - render_mode='static_fallback':render=true 但 obscura 未装/失败 → 回退静态,显 hint。
|
||||
* - render_mode='static':普通静态渲染(默认)。
|
||||
*/
|
||||
export function formatFetchUrl(r: ToolResult): string {
|
||||
const url = typeof r.url === 'string' ? r.url : ''
|
||||
const title = typeof r.title === 'string' && r.title ? r.title : ''
|
||||
const mode = typeof r.render_mode === 'string' ? r.render_mode : 'static'
|
||||
const parts: string[] = []
|
||||
if (title) parts.push(t('aiTool.fetchUrlTitle', { title }))
|
||||
parts.push(url)
|
||||
if (mode === 'obscura') {
|
||||
parts.push(t('aiTool.fetchUrlRendered'))
|
||||
} else if (mode === 'static_fallback') {
|
||||
parts.push(t('aiTool.fetchUrlFallbackHint'))
|
||||
}
|
||||
const md = typeof r.markdown === 'string' ? r.markdown : ''
|
||||
if (md) {
|
||||
const MAX_LINES = 20
|
||||
const lines = md.split('\n')
|
||||
if (lines.length > MAX_LINES) {
|
||||
parts.push(lines.slice(0, MAX_LINES).join('\n'))
|
||||
parts.push(t('aiTool.commandOutputLines', { n: lines.length }))
|
||||
} else {
|
||||
parts.push(md)
|
||||
}
|
||||
}
|
||||
return parts.join('\n')
|
||||
}
|
||||
|
||||
/**
|
||||
* completed 工具结果的一句话摘要(折叠态 header 也能看到,避免光秃秃)。
|
||||
* UX-260616-04:覆盖范围与 formatToolResult 对齐(header+body 一致);
|
||||
@@ -628,6 +677,21 @@ function summaryHttpRequest(r: ToolResult): string {
|
||||
: t('aiTool.httpFailed', { method, status })
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch_url summary 版(折叠态 header 副标题):
|
||||
* - obscura 已装渲染成功 → "已 JS 渲染"
|
||||
* - static_fallback(obscura 未装/失败) → "obscura 未装,已静态回退"(红色提示,引导安装)
|
||||
* - static(默认静态) → 显 markdown 截断字符数或空(无 markdown 静默)
|
||||
* 返空串 → header 不显副标题(对齐其他 summary 缺数据返空)。
|
||||
*/
|
||||
function summaryFetchUrl(r: ToolResult): string {
|
||||
const mode = typeof r.render_mode === 'string' ? r.render_mode : 'static'
|
||||
if (mode === 'obscura') return t('aiTool.fetchUrlRendered')
|
||||
if (mode === 'static_fallback') return t('aiTool.fetchUrlFallbackHint')
|
||||
const len = typeof r.length === 'number' ? r.length : 0
|
||||
return len > 0 ? t('aiTool.fetchUrlChars', { n: len }) : ''
|
||||
}
|
||||
|
||||
/** 工具结果摘要策略表(name → 纯函数)。仅 summary 独有的工具(create/update_project/restore/purge)在此登记。 */
|
||||
const TOOL_SUMMARIES: Record<string, (r: ToolResult) => string> = {
|
||||
list_projects: r => summaryList(r, 'list_projects'),
|
||||
@@ -654,6 +718,7 @@ const TOOL_SUMMARIES: Record<string, (r: ToolResult) => string> = {
|
||||
bind_directory: summaryBindDir,
|
||||
run_workflow: summaryRunWorkflow,
|
||||
http_request: summaryHttpRequest,
|
||||
fetch_url: summaryFetchUrl,
|
||||
grep: formatGrep,
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +130,12 @@ export function useToolCardHeader(getTc: () => AiToolCallInfo) {
|
||||
const host = httpHost(url)
|
||||
return host ? `${method} ${host}` : t('aiTool.httpRequestFallback')
|
||||
}
|
||||
case 'fetch_url': {
|
||||
// fetch_url 头部:获取 host(对齐 http_request 精简模式,折叠态一眼知抓哪个站点)
|
||||
const url = argString(tc.args, 'url')
|
||||
const host = httpHost(url)
|
||||
return host ? `${t('aiTool.fetchUrlPrefix')} ${host}` : t('aiTool.fetchUrlFallback')
|
||||
}
|
||||
default: return formatToolName(tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user