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>
字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
sessionID | string | 是 | 会话 ID |
messageID | string | 否 | 消息 ID(用于继续会话) |
model | object | 否 | 模型配置 |
model.providerID | string | - | 提供商 ID |
model.modelID | string | - | 模型 ID |
agent | string | 否 | Agent 名称 |
noReply | boolean | 否 | 禁用回复(仅分析) |
tools | Record<string, boolean> | 否 | 工具启用状态 |
systemPrompt | string | 否 | 自定义系统提示词 |
variant | string | 否 | 变体标识 |
parts | Part[] | 否 | 预先定义的 Part |
核心方法
SessionPrompt.prompt()
定义:packages/opencode/src/session/prompt.ts:55-80
export async function prompt(input: PromptInput): Promise<MessageV2.WithParts>
功能: 处理用户提示词并启动 LLM 对话
执行流程:
- 清理会话恢复状态
- 创建 User Message
- 更新会话权限(如果指定)
- 设置系统提示词(如果指定)
- 解析并转换 prompt 为 Parts
- 启动 Prompt loop
- 返回结果
示例:
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))
// 返回结果
})
执行步骤:
- 初始化中止信号
- 加载会话的所有消息
- 过滤已压缩的消息
- 找到最后一个 User 消息和 Assistant 消息对
- 调用 LLM 流式生成 Assistant Message
- 解析 LLM 响应并创建 Parts
- 更新 Session
- 处理错误和重试
消息处理
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、成本等元数据
系统提示词
提示词来源
- Agent 自定义提示词:通过
agent.prompt字段 - 全局系统提示词:通过
systemPrompt参数 - 内置提示词模板: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)
错误处理和重试机制
错误类型
- 输出长度错误:
MessageV2.OutputLengthError - 中止错误:
MessageV2.AbortedError - 认证错误:
MessageV2.AuthError - API 错误:
MessageV2.APIError
错误处理流程
- 捕获错误
- 判断错误类型
- 如果可重试,记录重试并重新请求
- 如果不可重试,返回错误消息
相关文档
- MessageV2 - 消息系统详解
- Session - 会话管理
- Agent - Agent 配置
- Tool System - 工具系统
- PermissionNext - 权限系统
- LLM - LLM 调用系统
变更历史
| 版本 | 变更内容 | 日期 |
|---|---|---|
| v1 | 初始 Prompt 系统文档 | - |
| v1.1 | 添加提示词模板和变量解析 | - |