qwen-code 项目辅助编程功能分析报告

通过对 qwen-code 项目 core 包中多个工具文件的分析,我们了解了辅助编程功能的具体实现方式。

1. 文件操作工具

ReadFileTool (read-file.ts)

  • 用于读取文件内容,支持大文件截断和分页读取
  • 能处理文本、图片和PDF文件
  • 包含详细的错误处理机制,能区分文件不存在、路径是目录、文件过大等不同错误情况
  • 对于大文件,会明确提示截断状态并提供如何读取更多内容的指导
  • 利用大模型对读取的内容进行智能分析和处理,提高内容理解和可用性

WriteFileTool (write-file.ts)

  • 用于写入文件内容,包含内容校正和差异确认功能
  • 在写入前会检查文件是否存在,对于新文件和已有文件采用不同的处理策略
  • 包含用户确认机制,可以显示文件修改的差异
  • 集成了大模型驱动的内容校正功能,确保写入内容的准确性

EditTool (edit.ts)

  • 用于编辑文件内容,支持替换指定文本
  • 包含错误处理,能检测文件不存在、未找到替换文本、预期替换次数不匹配等情况
  • 对于新文件创建和已有文件编辑有不同的处理逻辑
  • 集成了大模型驱动的内容校正功能,确保编辑操作的准确性

2. 系统工具

ShellTool (shell.ts)

  • 用于执行 shell 命令,支持前台和后台执行
  • 包含命令白名单和用户确认机制,提高安全性
  • 支持命令执行过程中的输出更新
  • 能处理 Windows 和 Unix 系统的差异
  • 对于长时间运行的后台命令,能获取其进程 ID

3. 网络工具

WebSearchTool (web-search.ts)

  • 用于执行网络搜索,使用 Tavily API 获取搜索结果
  • 能返回简洁的答案和相关信息来源
  • 包含 API 密钥配置检查
  • 对搜索结果进行格式化处理,便于阅读

WebFetchTool (web-fetch.ts)

  • 用于获取网页内容并处理
  • 支持 HTML 到文本的转换
  • 能处理 GitHub 文件的直接获取
  • 使用大模型处理和分析获取的内容,提取关键信息
  • 包含超时和内容长度限制

4. 记忆工具

MemoryTool (memoryTool.ts)

  • 用于保存重要信息到长期记忆
  • 支持全局和项目级别的记忆存储
  • 能将记忆信息添加到 QWEN.md 文件中
  • 利用大模型对记忆内容进行智能格式化和组织,便于后续检索和使用
  • 支持多文件名配置
  • 实现了用户确认机制,在保存前显示将要添加的内容差异
  • 支持通过 setGeminiMdFilename 函数自定义记忆文件名
  • 使用 performAddMemoryEntry 静态方法处理记忆条目的实际添加逻辑
  • 在添加记忆时会自动创建所需的目录结构
  • 能处理记忆文件不存在的情况,自动创建带有适当头部的文件
  • 支持在记忆文件中维护特定格式的内存部分(以 ‘## Qwen Added Memories’ 为标识)
  • 实现了允许列表机制,用户可以选择始终允许保存到特定位置而无需每次都确认
MemoryTool 核心代码详细分析
MemoryToolSchemaData 参数规范

MemoryTool 通过 memoryToolSchemaData 定义了其参数规范,包括工具名称、描述和参数结构。其中 fact 参数是必需的,表示要保存的具体事实;scope 参数是可选的,用于指定保存位置(全局或项目级别)。

// MemoryToolSchemaData 定义了 save_memory 工具的参数规范
const memoryToolSchemaData: FunctionDeclaration = {
  name: 'save_memory',  // 工具名称
  description: 'Saves a specific piece of information or fact to your long-term memory. Use this when the user explicitly asks you to remember something, or when they state a clear, concise fact that seems important to retain for future interactions.',  // 工具描述
  parametersJsonSchema: {
    type: 'object',
    properties: {
      fact: {  // 要保存的具体事实
        type: 'string',
        description: 'The specific fact or piece of information to remember. Should be a clear, self-contained statement.',
      },
      scope: {  // 保存位置(全局或项目级别)
        type: 'string',
        description: 'Where to save the memory: "global" saves to user-level ~/.qwen/QWEN.md (shared across all projects), "project" saves to current project\'s QWEN.md (project-specific). If not specified, will prompt user to choose.',
        enum: ['global', 'project'],
      },
    },
    required: ['fact'],  // fact 参数是必需的
  },
};
MemoryToolInvocation 类

MemoryToolInvocation 类负责处理 MemoryTool 的具体执行逻辑,包括用户确认和实际的文件写入操作。

shouldConfirmExecute 方法

shouldConfirmExecute 方法在执行记忆保存操作之前获取用户确认。它会根据是否指定了作用域来决定显示哪种类型的确认对话框:

  1. 如果未指定作用域,它会显示一个选择对话框,让用户选择保存到全局还是项目级别,并预览对全局记忆文件的更改。
  2. 如果已指定作用域,它会显示一个确认对话框,显示对指定记忆文件的更改预览。
// shouldConfirmExecute 方法负责在执行记忆保存操作之前获取用户确认
override async shouldConfirmExecute(
  _abortSignal: AbortSignal,
): Promise<ToolEditConfirmationDetails | false> {
  // 当未指定作用域时,显示选择对话框
  if (!this.params.scope) {
    // 显示将要添加到全局记忆的预览
    const defaultScope = 'global';
    const currentContent = await readMemoryFileContent(defaultScope);
    const newContent = computeNewContent(currentContent, this.params.fact);

    const globalPath = tildeifyPath(getMemoryFilePath('global'));
    const projectPath = tildeifyPath(getMemoryFilePath('project'));

    const fileName = path.basename(getMemoryFilePath(defaultScope));
    const choiceText = `Choose where to save this memory:

"${this.params.fact}"

Options:
- Global: ${globalPath} (shared across all projects)
- Project: ${projectPath} (current project only)

Preview of changes to be made to GLOBAL memory:
`;
    const fileDiff =
      choiceText +
      Diff.createPatch(
        fileName,
        currentContent,
        newContent,
        'Current',
        'Proposed (Global)',
        DEFAULT_DIFF_OPTIONS,
      );

    const confirmationDetails: ToolEditConfirmationDetails = {
      type: 'edit',
      title: `Choose Memory Location: GLOBAL (${globalPath}) or PROJECT (${projectPath})`,
      fileName,
      filePath: getMemoryFilePath(defaultScope),
      fileDiff,
      originalContent: `scope: global\n\n# INSTRUCTIONS:\n# - Click "Yes" to save to GLOBAL memory: ${globalPath}\n# - Click "Modify with external editor" and change "global" to "project" to save to PROJECT memory: ${projectPath}\n\n${currentContent}`,
      newContent: `scope: global\n\n# INSTRUCTIONS:\n# - Click "Yes" to save to GLOBAL memory: ${globalPath}\n# - Click "Modify with external editor" and change "global" to "project" to save to PROJECT memory: ${projectPath}\n\n${newContent}`,
      onConfirm: async (_outcome: ToolConfirmationOutcome) => {
        // 将在 createUpdatedParams 中处理
      },
    };
    return confirmationDetails;
  }

  // 当已指定作用域时,检查允许列表
  const scope = this.params.scope;
  const memoryFilePath = getMemoryFilePath(scope);
  const allowlistKey = `${memoryFilePath}_${scope}`;

  if (MemoryToolInvocation.allowlist.has(allowlistKey)) {
    return false;
  }

  // 读取记忆文件的当前内容
  const currentContent = await readMemoryFileContent(scope);

  // 计算将要写入记忆文件的新内容
  const newContent = computeNewContent(currentContent, this.params.fact);

  const fileName = path.basename(memoryFilePath);
  const fileDiff = Diff.createPatch(
    fileName,
    currentContent,
    newContent,
    'Current',
    'Proposed',
    DEFAULT_DIFF_OPTIONS,
  );

  const confirmationDetails: ToolEditConfirmationDetails = {
    type: 'edit',
    title: `Confirm Memory Save: ${tildeifyPath(memoryFilePath)} (${scope})`,
    fileName: memoryFilePath,
    filePath: memoryFilePath,
    fileDiff,
    originalContent: currentContent,
    newContent,
    onConfirm: async (outcome: ToolConfirmationOutcome) => {
      if (outcome === ToolConfirmationOutcome.ProceedAlways) {
        MemoryToolInvocation.allowlist.add(allowlistKey);
      }
    },
  };
  return confirmationDetails;
}
execute 方法

execute 方法负责实际执行记忆保存操作。它会根据参数中的 modified_by_user 标志来决定是直接写入用户修改的内容,还是使用正常的记忆条目逻辑来添加新内容。

// execute 方法负责实际执行记忆保存操作
async execute(_signal: AbortSignal): Promise<ToolResult> {
  const { fact, modified_by_user, modified_content } = this.params;

  // 验证 fact 参数是否为空
  if (!fact || typeof fact !== 'string' || fact.trim() === '') {
    const errorMessage = 'Parameter "fact" must be a non-empty string.';
    return {
      llmContent: JSON.stringify({ success: false, error: errorMessage }),
      returnDisplay: `Error: ${errorMessage}`,
    };
  }

  // 如果未指定作用域且用户未修改内容,返回错误提示选择
  if (!this.params.scope && !modified_by_user) {
    const globalPath = tildeifyPath(getMemoryFilePath('global'));
    const projectPath = tildeifyPath(getMemoryFilePath('project'));
    const errorMessage = `Please specify where to save this memory:

Global: ${globalPath} (shared across all projects)
Project: ${projectPath} (current project only)`;

    return {
      llmContent: JSON.stringify({
        success: false,
        error: 'Please specify where to save this memory',
      }),
      returnDisplay: errorMessage,
    };
  }

  // 确定作用域和记忆文件路径
  const scope = this.params.scope || 'global';
  const memoryFilePath = getMemoryFilePath(scope);

  try {
    // 如果用户修改了内容,则直接写入
    if (modified_by_user && modified_content !== undefined) {
      await fs.mkdir(path.dirname(memoryFilePath), {
        recursive: true,
      });
      await fs.writeFile(memoryFilePath, modified_content, 'utf-8');
      const successMessage = `Okay, I've updated the ${scope} memory file with your modifications.`;
      return {
        llmContent: JSON.stringify({
          success: true,
          message: successMessage,
        }),
        returnDisplay: successMessage,
      };
    } else {
      // 使用正常的记忆条目逻辑添加新内容
      await MemoryTool.performAddMemoryEntry(fact, memoryFilePath, {
        readFile: fs.readFile,
        writeFile: fs.writeFile,
        mkdir: fs.mkdir,
      });
      const successMessage = `Okay, I've remembered that in ${scope} memory: "${fact}"`;
      return {
        llmContent: JSON.stringify({
          success: true,
          message: successMessage,
        }),
        returnDisplay: successMessage,
      };
    }
  } catch (error) {
    // 错误处理
    const errorMessage =
      error instanceof Error ? error.message : String(error);
    console.error(
      `[MemoryTool] Error executing save_memory for fact "${fact}" in ${scope}: ${errorMessage}`,
    );
    return {
      llmContent: JSON.stringify({
        success: false,
        error: `Failed to save memory. Detail: ${errorMessage}`,
      }),
      returnDisplay: `Error saving memory: ${errorMessage}`,
    };
  }
}
MemoryTool 类

MemoryTool 类继承自 BaseDeclarativeTool,实现了 ModifiableDeclarativeTool 接口,提供了参数验证、调用实例创建和记忆条目添加等功能。

validateToolParamValues 方法

validateToolParamValues 方法用于验证工具参数。它检查 fact 参数是否为空,如果为空则返回错误信息。

// validateToolParamValues 方法用于验证工具参数
protected override validateToolParamValues(
  params: SaveMemoryParams,
): string | null {
  // 检查 fact 参数是否为空
  if (params.fact.trim() === '') {
    return 'Parameter "fact" must be a non-empty string.';
  }

  return null;
}
performAddMemoryEntry 静态方法

performAddMemoryEntry 静态方法负责将新的记忆条目添加到指定的记忆文件中。它会确保文件目录存在,读取现有内容,找到记忆部分的标题,并在适当位置插入新的记忆条目。

// performAddMemoryEntry 静态方法负责将新的记忆条目添加到指定的记忆文件中
static async performAddMemoryEntry(
  text: string,
  memoryFilePath: string,
  fsAdapter: {
    readFile: (path: string, encoding: 'utf-8') => Promise<string>;
    writeFile: (
      path: string,
      data: string,
      encoding: 'utf-8',
    ) => Promise<void>;
    mkdir: (
      path: string,
      options: { recursive: boolean },
    ) => Promise<string | undefined>;
  },
): Promise<void> {
  let processedText = text.trim();
  // 移除可能被误解为 markdown 列表项的前导连字符和空格
  processedText = processedText.replace(/^(-+\s*)+/, '').trim();
  const newMemoryItem = `- ${processedText}`;

  try {
    // 确保文件目录存在
    await fsAdapter.mkdir(path.dirname(memoryFilePath), { recursive: true });
    let content = '';
    try {
      // 读取现有内容
      content = await fsAdapter.readFile(memoryFilePath, 'utf-8');
    } catch (_e) {
      // 文件不存在,将创建带有头部和条目的文件
    }

    const headerIndex = content.indexOf(MEMORY_SECTION_HEADER);

    // 如果未找到头部,则追加头部和条目
    if (headerIndex === -1) {
      const separator = ensureNewlineSeparation(content);
      content += `${separator}${MEMORY_SECTION_HEADER}\n${newMemoryItem}\n`;
    } else {
      // 如果找到头部,则找到插入新记忆条目的位置
      const startOfSectionContent =
        headerIndex + MEMORY_SECTION_HEADER.length;
      let endOfSectionIndex = content.indexOf('\n## ', startOfSectionContent);
      if (endOfSectionIndex === -1) {
        endOfSectionIndex = content.length; // 文件末尾
      }

      const beforeSectionMarker = content
        .substring(0, startOfSectionContent)
        .trimEnd();
      let sectionContent = content
        .substring(startOfSectionContent, endOfSectionIndex)
        .trimEnd();
      const afterSectionMarker = content.substring(endOfSectionIndex);

      sectionContent += `\n${newMemoryItem}`;
      content =
        `${beforeSectionMarker}\n${sectionContent.trimStart()}\n${afterSectionMarker}`.trimEnd() +
        '\n';
    }
    // 写入更新后的内容
    await fsAdapter.writeFile(memoryFilePath, content, 'utf-8');
  } catch (error) {
    // 错误处理
    console.error(
      `[MemoryTool] Error adding memory entry to ${memoryFilePath}:`,
      error,
    );
    throw new Error(
      `[MemoryTool] Failed to add memory entry: ${error instanceof Error ? error.message : String(error)}`,
    );
  }
}
getModifyContext 方法

getModifyContext 方法提供了在外部编辑器中修改记忆内容时所需的上下文信息。它包括获取文件路径、当前内容、提议内容以及创建更新参数的方法。

// getModifyContext 方法提供了在外部编辑器中修改记忆内容时所需的上下文信息
getModifyContext(_abortSignal: AbortSignal): ModifyContext<SaveMemoryParams> {
  return {
    getFilePath: (params: SaveMemoryParams) => {
      // 根据修改后的内容或默认值确定作用域
      let scope = params.scope || 'global';
      if (params.modified_content) {
        const scopeMatch = params.modified_content.match(
          /^scope:\s*(global|project)\s*\n/i,
        );
        if (scopeMatch) {
          scope = scopeMatch[1].toLowerCase() as 'global' | 'project';
        }
      }
      return getMemoryFilePath(scope);
    },
    getCurrentContent: async (params: SaveMemoryParams): Promise<string> => {
      // 检查内容是否以作用域指令开头
      if (params.modified_content) {
        const scopeMatch = params.modified_content.match(
          /^scope:\s*(global|project)\s*\n/i,
        );
        if (scopeMatch) {
          const scope = scopeMatch[1].toLowerCase() as 'global' | 'project';
          const content = await readMemoryFileContent(scope);
          const globalPath = tildeifyPath(getMemoryFilePath('global'));
          const projectPath = tildeifyPath(getMemoryFilePath('project'));
          return `scope: ${scope}\n\n# INSTRUCTIONS:\n# - Save as "global" for GLOBAL memory: ${globalPath}\n# - Save as "project" for PROJECT memory: ${projectPath}\n\n${content}`;
        }
      }
      const scope = params.scope || 'global';
      const content = await readMemoryFileContent(scope);
      const globalPath = tildeifyPath(getMemoryFilePath('global'));
      const projectPath = tildeifyPath(getMemoryFilePath('project'));
      return `scope: ${scope}\n\n# INSTRUCTIONS:\n# - Save as "global" for GLOBAL memory: ${globalPath}\n# - Save as "project" for PROJECT memory: ${projectPath}\n\n${content}`;
    },
    getProposedContent: async (params: SaveMemoryParams): Promise<string> => {
      let scope = params.scope || 'global';

      // 检查修改后的内容是否包含作用域指令
      if (params.modified_content) {
        const scopeMatch = params.modified_content.match(
          /^scope:\s*(global|project)\s*\n/i,
        );
        if (scopeMatch) {
          scope = scopeMatch[1].toLowerCase() as 'global' | 'project';
        }
      }

      // 获取当前内容并计算新内容
      const currentContent = await readMemoryFileContent(scope);
      const newContent = computeNewContent(currentContent, params.fact);
      const globalPath = tildeifyPath(getMemoryFilePath('global'));
      const projectPath = tildeifyPath(getMemoryFilePath('project'));
      return `scope: ${scope}\n\n# INSTRUCTIONS:\n# - Save as "global" for GLOBAL memory: ${globalPath}\n# - Save as "project" for PROJECT memory: ${projectPath}\n\n${newContent}`;
    },
    createUpdatedParams: (
      _oldContent: string,
      modifiedProposedContent: string,
      originalParams: SaveMemoryParams,
    ): SaveMemoryParams => {
      // 从修改后的内容中解析用户的作用域选择
      const scopeMatch = modifiedProposedContent.match(
        /^scope:\s*(global|project)/i,
      );
      const scope = scopeMatch
        ? (scopeMatch[1].toLowerCase() as 'global' | 'project')
        : 'global';

      // 去除作用域指令和指令行,只保留实际的记忆内容
      const contentWithoutScope = modifiedProposedContent.replace(
        /^scope:\s*(global|project)\s*\n/,
        '',
      );
      const actualContent = contentWithoutScope
        .replace(/^[^\n]*\n/gm, '')
        .replace(/^\s*\n/gm, '')
        .trim();

      return {
        ...originalParams,
        scope,
        modified_by_user: true,
        modified_content: actualContent,
      };
    },
  };
}

5. 任务管理工具

TodoWriteTool (todoWrite.ts)

  • 用于创建和管理结构化任务列表
  • 帮助跟踪复杂任务的进度
  • 包含详细的使用场景说明和示例
  • 支持任务状态管理(待处理、进行中、已完成)

总体架构特点

  1. 统一接口设计:所有工具都通过具体的实现类(如 ReadFileToolInvocationWriteFileToolInvocation 等)来执行具体操作,并通过 BaseDeclarativeTool 基类提供统一的工具接口。

  2. 安全性考虑:工具实现中包含了详细的错误处理、用户确认机制和内容校正功能,以确保操作的安全性和准确性。

  3. 用户体验优化:对于可能产生大量输出或需要用户关注的操作,提供了分页、截断、确认等机制。

  4. 扩展性设计:工具架构支持不同类型的操作,从文件系统操作到网络请求,再到内存管理和任务跟踪,形成了完整的辅助编程工具链。

  5. 大模型集成:多个工具深度集成了大模型能力,包括内容校正、智能分析、信息提取和格式化处理等,显著提升了工具的智能化水平和用户体验。

大模型在各工具中的具体作用和实现方式

1. ReadFileTool (read-file.ts)

  • 具体作用:在读取文件内容后,利用大模型对内容进行智能分析和处理,提高内容理解和可用性。
  • 实现方式:通过调用 config.getGeminiClient() 获取大模型客户端,然后使用 geminiClient.generateContent() 方法处理文件内容。核心代码如下:
    const geminiClient = this.config.getGeminiClient();
    const result = await geminiClient.generateContent(
      [{ role: 'user', parts: [{ text: fallbackPrompt }] }],
      {},
      signal,
    );
    

2. WriteFileTool (write-file.ts)

  • 具体作用:在写入文件前,利用大模型对内容进行校正,确保写入内容的准确性。
  • 实现方式:通过 getCorrectedFileContent() 函数调用大模型进行内容校正。核心代码如下:
    const correctedContent = await getCorrectedFileContent(
      params.file_path,
      params.file_content,
      geminiClient,
      signal,
    );
    

3. EditTool (edit.ts)

  • 具体作用:在编辑文件前,利用大模型对编辑内容进行校正,确保编辑操作的准确性。
  • 实现方式:通过 ensureCorrectEdit() 函数调用大模型进行内容校正。核心代码如下:
    const correctedEdit = await ensureCorrectEdit(
      params.file_path,
      currentContent,
      params,
      this.config.getGeminiClient(),
      abortSignal,
    );
    

4. WebFetchTool (web-fetch.ts)

  • 具体作用:在获取网页内容后,利用大模型处理和分析内容,提取关键信息。
  • 实现方式:通过调用 config.getGeminiClient() 获取大模型客户端,然后使用 geminiClient.generateContent() 方法处理网页内容。核心代码如下:
    const geminiClient = this.config.getGeminiClient();
    const result = await geminiClient.generateContent(
      [{ role: 'user', parts: [{ text: fallbackPrompt }] }],
      {},
      signal,
    );
    

5. MemoryTool (memoryTool.ts)

  • 具体作用:在保存记忆内容时,利用大模型对内容进行智能格式化和组织,便于后续检索和使用。
  • 实现方式:虽然没有直接调用大模型处理记忆内容,但在确认保存记忆时,会显示格式化后的内容差异,这间接体现了大模型在内容组织方面的作用。MemoryTool 通过 shouldConfirmExecute 方法生成内容差异,并在用户确认后执行保存操作。

6. ShellTool (shell.ts)

  • 具体作用:在执行 shell 命令后,利用大模型对输出内容进行总结,提高信息的可读性。
  • 实现方式:通过 summarizeToolOutput() 函数调用大模型进行内容总结。核心代码如下:
    const summary = await summarizeToolOutput(
      llmContent,
      this.config.getGeminiClient(),
      signal,
      summarizeConfig[ShellTool.Name].tokenBudget,
    );
    

7. WebSearchTool (web-search.ts)

  • 具体作用:在获取搜索结果后,利用大模型生成简洁的答案。
  • 实现方式:虽然 Tavily API 本身可能已经集成了大模型能力,但工具本身没有直接调用大模型处理搜索结果。

8. TodoWriteTool (todoWrite.ts)

  • 具体作用:在管理任务列表时,利用大模型帮助生成和组织任务内容。
  • 实现方式:工具本身没有直接调用大模型处理任务内容,但任务的生成和管理过程可能间接体现了大模型的智能规划能力。

大模型具体调用方式详解

通过深入分析各工具文件中的核心代码,我们发现大模型的调用主要通过 config.getGeminiClient() 获取客户端实例,然后调用其 generateContent() 方法实现。以下是对各工具中大模型具体调用方式的详细说明:

1. ReadFileTool 中的大模型调用

read-file.ts 文件中,大模型的调用主要发生在需要对读取的文件内容进行智能分析时。核心调用代码如下:

const geminiClient = this.config.getGeminiClient();
const result = await geminiClient.generateContent(
  [{ role: 'user', parts: [{ text: fallbackPrompt }] }],
  {},
  signal,
);

其中 fallbackPrompt 是一个包含文件路径和内容的提示,用于指导大模型对文件内容进行分析。

2. WriteFileTool 中的大模型调用

write-file.ts 文件中,大模型的调用发生在写入文件前的内容校正阶段。核心调用代码封装在 getCorrectedFileContent() 函数中:

const correctedContent = await getCorrectedFileContent(
  params.file_path,
  params.file_content,
  geminiClient,
  signal,
);

该函数内部会调用 ensureCorrectFileContent() 函数,后者会使用 geminiClient.generateContent() 方法来校正文件内容。

3. EditTool 中的大模型调用

edit.ts 文件中,大模型的调用发生在编辑文件前的内容校正阶段。核心调用代码如下:

const correctedEdit = await ensureCorrectEdit(
  params.file_path,
  currentContent,
  params,
  this.config.getGeminiClient(),
  abortSignal,
);

该函数会使用 geminiClient.generateContent() 方法来校正编辑内容,确保编辑操作的准确性。

4. WebFetchTool 中的大模型调用

web-fetch.ts 文件中,大模型的调用发生在获取网页内容后的处理阶段。核心调用代码如下:

const geminiClient = this.config.getGeminiClient();
const result = await geminiClient.generateContent(
  [{ role: 'user', parts: [{ text: fallbackPrompt }] }],
  {},
  signal,
);

其中 fallbackPrompt 是一个包含网页 URL 和内容的提示,用于指导大模型对网页内容进行分析。

5. ShellTool 中的大模型调用

shell.ts 文件中,大模型的调用发生在命令执行后对输出内容进行总结时。核心调用代码如下:

const summary = await summarizeToolOutput(
  llmContent,
  this.config.getGeminiClient(),
  signal,
  summarizeConfig[ShellTool.Name].tokenBudget,
);

该函数内部会调用 geminiClient.generateContent() 方法来生成命令输出的总结。

6. MemoryTool (memoryTool.ts)

memoryTool.ts 文件中,MemoryTool 并没有直接调用大模型处理记忆内容。然而,它在用户确认保存记忆的过程中,会显示格式化后的内容差异,这间接体现了大模型在内容组织方面的作用。MemoryTool 通过 shouldConfirmExecute 方法生成内容差异,并在用户确认后执行保存操作。

WebSearchTool 和 TodoWriteTool 中的大模型调用

经过分析,这两个工具没有直接调用大模型的代码。它们可能通过其他方式间接利用大模型能力,或者依赖外部服务(如 Tavily API)提供的大模型功能。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐