4.3 SessionPrompt:会话的入口

模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2025-02-17


SessionPromptsession/prompt.ts)是用户消息进入 OpenCode 核心引擎的大门。它负责接收用户输入,准备上下文,然后启动 Agentic Loop。

4.3.1 prompt() 方法的完整执行流程

export const prompt = fn(PromptInput, async (input) => {
  // 1. 获取会话
  const session = await Session.get(input.sessionID)

  // 2. 清理未完成的回滚
  await SessionRevert.cleanup(session)

  // 3. 创建用户消息
  const message = await createUserMessage(input)

  // 4. 更新会话时间戳
  await Session.touch(input.sessionID)

  // 5. 处理运行时权限覆盖(向后兼容)
  const permissions: PermissionNext.Ruleset = []
  for (const [tool, enabled] of Object.entries(input.tools ?? {})) {
    permissions.push({
      permission: tool,
      action: enabled ? "allow" : "deny",
      pattern: "*",
    })
  }

  // 6. 如果标记 noReply,直接返回(不触发 AI 响应)
  if (input.noReply === true) return message

  // 7. 进入 Agentic Loop
  return loop({ sessionID: input.sessionID })
})

PromptInput 的结构

消息的 parts 数组支持多种类型——用户不仅可以发送文本,还可以附带文件、指定 Agent、创建子任务。

4.3.2 系统指令(Instruction)注入机制

loop() 函数准备 LLM 调用上下文时,会通过 InstructionPromptsession/instruction.ts)加载系统指令。

指令文件扫描

OpenCode 会在以下位置查找指令文件:

  1. 全局位置

  2. 项目目录:从当前工作目录向上逐级查找,直到项目根目录

向上查找逻辑Filesystem.globUp):

这是一个关键设计——它允许在子目录中工作时,仍然可以读取到项目根目录的指令文件。例如:

Claim 机制——防止重复注入:

同一条消息的处理过程中,每个指令文件只会被注入一次。这防止了在多轮对话中重复加载相同的指令。

4.3.3 消息预处理与格式化

在创建用户消息时,SessionPrompt 还会处理一些特殊语法:

resolvePromptParts()——解析模板中的引用:

这意味着用户可以在消息中引用文件路径或 Agent 名称,系统会自动将其解析为对应的 Part。

Last updated