💻 源码
import { TOOL_LABELS } from './tools'

function parseArgs(argsJson: string): Record<string, string> {
  try {
    return JSON.parse(argsJson) as Record<string, string>
  } catch {
    return {}
  }
}

function pickModelThought(content?: string | null, reasoning?: string | null): string | null {
  const reasoningText = reasoning?.trim()
  if (reasoningText) return reasoningText

  const contentText = content?.trim()
  if (!contentText) return null

  const tagged = contentText.match(/(?:【思考】|Thought[::]|思考[::])\s*([\s\S]+?)(?=(?:【行动】|Action[::]|$))/i)
  if (tagged?.[1]?.trim()) return tagged[1].trim()

  if (!contentText.startsWith('{') && contentText.length > 4) return contentText
  return null
}

function buildToolThought(
  userQuestion: string,
  toolName: string,
  argsJson: string,
  round: number,
): string {
  const args = parseArgs(argsJson)
  const label = TOOL_LABELS[toolName] ?? toolName

  const reasonByTool: Record<string, string> = {
    get_weather: `用户问题涉及实时天气(「${userQuestion}」)。训练数据里没有此刻的天气,我不能编造。`,
    get_current_datetime: `用户问题涉及当前时间(「${userQuestion}」)。我必须获取系统实时时钟,不能凭记忆猜测。`,
    calculate: `用户问题包含精确计算(「${userQuestion}」)。大模型心算容易出错,应交给计算工具。`,
    get_exchange_rate: `用户问题涉及汇率换算(「${userQuestion}」)。汇率每天变化,必须查询实时数据。`,
  }

  const reason = reasonByTool[toolName] ?? `用户问题(「${userQuestion}」)需要外部数据支持,不能凭空回答。`
  const argSummary = Object.entries(args)
    .map(([k, v]) => `${k}=${v}`)
    .join(', ')

  return [
    `【第 ${round} 轮思考】`,
    reason,
    `→ 结论:调用工具「${label}」(${toolName})`,
    argSummary ? `→ 参数:${argSummary}` : '',
  ]
    .filter(Boolean)
    .join('\n')
}

function buildDirectThought(userQuestion: string, round: number): string {
  return [
    `【第 ${round} 轮思考】`,
    `分析问题:「${userQuestion}」`,
    '→ 判断:这是知识解释类问题,或已有足够信息,无需调用外部工具。',
    '→ 结论:直接基于已有信息组织最终回答。',
  ].join('\n')
}

function buildSynthesisThought(userQuestion: string, round: number, hadToolCalls: boolean): string {
  if (!hadToolCalls) return buildDirectThought(userQuestion, round)
  return [
    `【第 ${round} 轮思考】`,
    '已收到工具返回的真实数据(Observation)。',
    '→ 判断:信息足够,可以将观察结果整合为自然语言回答。',
    '→ 结论:生成最终答案,并引用工具返回的数据。',
  ].join('\n')
}

export function resolveThought(params: {
  userQuestion: string
  toolName?: string
  toolArgs?: string
  round: number
  modelContent?: string | null
  modelReasoning?: string | null
  phase: 'before_tool' | 'direct_answer' | 'synthesis_answer'
  hadToolCalls?: boolean
}): string {
  const fromModel = pickModelThought(params.modelContent, params.modelReasoning)
  if (fromModel) return `【第 ${params.round} 轮思考】\n${fromModel}`

  if (params.phase === 'before_tool' && params.toolName) {
    return buildToolThought(params.userQuestion, params.toolName, params.toolArgs ?? '{}', params.round)
  }
  if (params.phase === 'synthesis_answer') {
    return buildSynthesisThought(params.userQuestion, params.round, params.hadToolCalls ?? false)
  }
  return buildDirectThought(params.userQuestion, params.round)
}