Code Reader
首页
帮助
设计文档
首页
帮助
设计文档
  • Prompt 系统

Prompt 系统

Prompt 系统负责处理用户输入、生成系统提示词、转换工具参数、管理提示词模板和消息历史。

概述

Prompt 系统是 OpenCode 的核心提示词生成引擎,它:

  • 处理用户输入并创建 User Message
  • 生成系统提示词(System Prompt)
  • 转换工具参数为 LLM 可用格式
  • 支持提示词模板和变量替换
  • 管理消息历史和上下文管理
  • 与 LLM 提供商集成

定义位置

packages/opencode/src/session/prompt.ts:1-2000

核心架构

PromptInput 类型

定义:packages/opencode/src/session/prompt.ts:85-98

export const PromptInput = z.object({
  sessionID: Identifier.schema("session"),
  messageID: Identifier.schema("message").optional(),
  model: z
    .object({
      providerID: z.string(),
      modelID: z.string(),
    })
    .optional(),
  agent: z.string().optional(),
  noReply: z.boolean().optional(),
  tools: z.record(z.string(), z.boolean()).optional(),
  systemPrompt: z.string().optional(),
  variant: z.string().optional(),
  parts: z
    .array(
      z.discriminatedUnion("type", [
        MessageV2.TextPart.omit({
          messageID: true,
          sessionID: true,
        }),
        MessageV2.FilePart.omit({
          messageID: true,
          sessionID: true,
        }),
        MessageV2.AgentPart.omit({
          messageID: true,
          sessionID: true,
        }),
        MessageV2.SubtaskPart.omit({
          messageID: true,
          sessionID: true,
        }),
      ]),
    )
    .optional(),
})
export type PromptInput = z.infer<typeof PromptInput>

字段说明

字段类型必填说明
sessionIDstring是会话 ID
messageIDstring否消息 ID(用于继续会话)
modelobject否模型配置
model.providerIDstring-提供商 ID
model.modelIDstring-模型 ID
agentstring否Agent 名称
noReplyboolean否禁用回复(仅分析)
toolsRecord<string, boolean>否工具启用状态
systemPromptstring否自定义系统提示词
variantstring否变体标识
partsPart[]否预先定义的 Part

核心方法

SessionPrompt.prompt()

定义:packages/opencode/src/session/prompt.ts:55-80

export async function prompt(input: PromptInput): Promise<MessageV2.WithParts>

功能: 处理用户提示词并启动 LLM 对话

执行流程:

  1. 清理会话恢复状态
  2. 创建 User Message
  3. 更新会话权限(如果指定)
  4. 设置系统提示词(如果指定)
  5. 解析并转换 prompt 为 Parts
  6. 启动 Prompt loop
  7. 返回结果

示例:

const result = await SessionPrompt.prompt({
  sessionID: "sess_abc123",
  model: {
    providerID: "anthropic",
    modelID: "claude-3-5-sonnet",
  },
  agent: "fixer",
  systemPrompt: "You are an expert at fixing bugs. Focus on identifying root causes...",
})

console.log(result.parts.length) // 生成的 Parts 数量

SessionPrompt.resolvePromptParts()

定义:packages/opencode/src/session/prompt.ts:185-231

export async function resolvePromptParts(template: string): Promise<PromptInput["parts"]>

功能: 解析提示词模板并转换为 Part 数组

支持的语法:

  • 文本内容:直接转换为 TextPart
  • 文件引用:[path/to/file.ts] 转换为 FilePart
  • Agent 引用:@agent-name 转换为 AgentPart
  • 变量:通过模板变量系统解析

示例:

// 文本
const parts1 = await SessionPrompt.resolvePromptParts("分析以下代码:")

// 文件引用
const parts2 = await SessionPrompt.resolvePromptParts("[src/app.ts, src/utils.ts]")

// Agent 引用
const parts3 = await SessionPrompt.resolvePromptParts("@code-reviewer")

SessionPrompt.start()

定义:packages/opencode/src/session/prompt.ts:234-242

export function start(sessionID: string): AbortSignal

功能: 启动 Prompt 循环的中止信号

用途:

  • 停止正在运行的 LLM 请求
  • 清理会话状态
  • 取消所有待处理的回调

示例:

const abort = SessionPrompt.start(session.id)

// 后续可以中止
abort.abort()

SessionPrompt.cancel()

定义:packages/opencode/src/session/prompt.ts:244-250

export function cancel(sessionID: string): void

功能: 取消会话的 Prompt 循环

示例:

SessionPrompt.cancel(session.id)

Prompt 循环机制

循环结构

定义:packages/opencode/src/session/prompt.ts:258-350

export const loop = fn(Identifier.schema("session"), async (sessionID) => {
const abort = start(sessionID)
// 循环逻辑
using \_ = defer(() => cancel(sessionID))
// 返回结果
})

执行步骤:

  1. 初始化中止信号
  2. 加载会话的所有消息
  3. 过滤已压缩的消息
  4. 找到最后一个 User 消息和 Assistant 消息对
  5. 调用 LLM 流式生成 Assistant Message
  6. 解析 LLM 响应并创建 Parts
  7. 更新 Session
  8. 处理错误和重试

消息处理

User 消息创建(packages/opencode/src/session/prompt.ts:317-332)

const messageID = Identifier.ascending("message")
const userMessage: MessageV2.User = {
  id: messageID,
  sessionID: input.sessionID,
  role: "user",
  time: { created: Date.now() },
  agent: "fixer",
  model: { providerID: "anthropic", modelID: "claude-3-5-sonnet" },
}

await Session.updateMessage(userMessage)

Assistant 消息创建和 Part 处理(packages/opencode/src/session/prompt.ts:398-424)

  • 解析 LLM 文本响应
  • 创建 TextPart 用于文本内容
  • 创建 FilePart 用于附件
  • 创建 ToolPart 用于工具调用
  • 处理工具调用的输入和输出
  • 更新消息的 tokens、成本等元数据

系统提示词

提示词来源

  1. Agent 自定义提示词:通过 agent.prompt 字段
  2. 全局系统提示词:通过 systemPrompt 参数
  3. 内置提示词模板:PROMPT_PLAN, BUILD_SWITCH, MAX_STEPS

提示词模板

Plan Mode 提示词(packages/opencode/src/session/prompt/plan.txt):

<system-reminder>

# 计划模式 - 系统提示

关键提示:计划模式已激活 - 你处于只读阶段。严格禁止:
任何文件编辑、修改或系统更改。不要使用 sed、tee、echo、cat
或其他任何 bash 命令来操作文件 - 命令只能用于读取/检查。
这个绝对约束覆盖所有其他指令,包括直接的用
户编辑请求。你只能观察、分析和计划。任何修改尝试
都是严重违规。零例外。

---

## 职责

你当前的责任是思考、阅读、搜索和委托探索代理,构建一个形式良好的计划,以实现用户想要实现的目标。你的计划应该全面而简洁,足够详细以便有效执行,同时避免不必要的冗长。

在权衡权衡时询问用户澄清问题或征求他们的意见。

**注意:** 在此工作流程中的任何时候,你都可以自由地向用户提出问题或澄清。不要对用户的意图做过多假设。目标是向用户展示一个经过充分研究的计划,并在实施开始前解决所有未完成的细节。

---

## 重要提示

用户表示他们还不想让你执行 - 你绝不能进行任何编辑(下面提到的计划文件除外),运行非只读工具(包括更改配置或提交),或以其他方式对系统进行更改。

这将取代你收到的任何其他指令。

</system-reminder>

工具参数转换

工具参数解析

Prompt 系统将工具参数转换为 LLM 可用的格式:

示例:Read 工具

// 工具定义
parameters: z.object({
filePath: z.string().describe("The path to file to read"),
offset: z.coerce.number().describe("The line number to start reading from (0-based)").optional(),
limit: z.coerce.number().describe("The number of lines to read (defaults to 2000)").optional(),
})

// LLM 提供商格式
{
"type": "object",
"properties": {
"filePath": {
"type": "string",
"description": "The path to file to read"
},
"offset": {
"type": "number",
"description": "The line number to start reading from (0-based)"
},
"limit": {
"type": "number",
"description": "Number of lines to read (defaults to 2000)"
}
},
"required": ["filePath"],
"optional": ["offset", "limit"]
}

权限管理

工具启用/禁用

定义:packages/opencode/src/session/prompt.ts:60-67

const permissions = (PermissionNext.Ruleset = [])
for (const [tool, enabled] of Object.entries(input.tools ?? {})) {
  permissions.push({
    permission: tool,
    action: enabled ? "allow" : "deny",
    pattern: "\*",
  })
}

session.permission = permissions

消息历史管理

消息过滤和加载

定义:packages/opencode/src/session/prompt.ts:274-281

const messages = await MessageV2.messages({ sessionID })

消息压缩过滤

定义:packages/opencode/src/session/prompt.ts:301-303

const compressed = await SessionCompaction.filterCompacted(messages)

错误处理和重试机制

错误类型

  1. 输出长度错误:MessageV2.OutputLengthError
  2. 中止错误:MessageV2.AbortedError
  3. 认证错误:MessageV2.AuthError
  4. API 错误:MessageV2.APIError

错误处理流程

  1. 捕获错误
  2. 判断错误类型
  3. 如果可重试,记录重试并重新请求
  4. 如果不可重试,返回错误消息

相关文档

  • MessageV2 - 消息系统详解
  • Session - 会话管理
  • Agent - Agent 配置
  • Tool System - 工具系统
  • PermissionNext - 权限系统
  • LLM - LLM 调用系统

变更历史

版本变更内容日期
v1初始 Prompt 系统文档-
v1.1添加提示词模板和变量解析-