opencode系统提示词加载机制

系统提示词加载机制

概述

OpenCode 的系统提示词(System Prompt)采用双架构并行策略,分为 V1 架构(当前主要使用的组合式加载)和 V2 架构(基于 System Context 的新一代机制)。V2 通过 Context Epoch 支持增量更新和持久化快照。

一、提示词文件

文件清单

所有提示词模板位于 packages/opencode/src/session/prompt/,共 14 个 .txt 文件,通过 Bun 编译时静态导入 嵌入 JavaScript bundle:

import PROMPT_ANTHROPIC from "./prompt/anthropic.txt"
import PROMPT_DEFAULT   from "./prompt/default.txt"
import PROMPT_BEAST     from "./prompt/beast.txt"
import PROMPT_GEMINI    from "./prompt/gemini.txt"
import PROMPT_GPT       from "./prompt/gpt.txt"
import PROMPT_KIMI      from "./prompt/kimi.txt"
import PROMPT_CODEX     from "./prompt/codex.txt"
import PROMPT_TRINITY   from "./prompt/trinity.txt"

文件用途与模型映射

文件 匹配规则(model.api.id 包含) 风格特点
beast.txt gpt-4 / o1 / o3 长篇结构化,自称 "the best coding agent",强调迭代直到完成
codex.txt gpt + codex 强调行动、轻描述,针对 GPT Codex 模型优化
gpt.txt gpt(不含 codex) 专业、重规则,自称 "opencode, an interactive CLI agent"
gemini.txt gemini- 简洁风格,自称 "opencode, an interactive CLI tool"
anthropic.txt claude 简洁对话式,使用 "OpenCode" 自称
trinity.txt trinity 强调持续直到完成
kimi.txt kimi 最详细版本,含 AGENTS.md 长篇说明
default.txt 兜底(所有未匹配) 简明,强调工具使用

辅助文件

文件 用途
plan.txt Plan 模式附加提示词,追加到 user message
plan-mode.txt 实验性 Plan 模式模板,含 ${planInfo} 占位符
build-switch.txt Plan→Build 切换时的附加提示词
max-steps.txt 最大步数限制提示,追加为最后一条 assistant 消息
copilot-gpt-5.txt 遗留文件,未使用
plan-reminder-anthropic.txt 遗留文件,未使用

二、选择逻辑

定义于 packages/opencode/src/session/system.tsprovider() 函数:

export function provider(model: Provider.Model) {
  if (model.api.id.includes("gpt-4") || model.api.id.includes("o1") || model.api.id.includes("o3"))
    return [PROMPT_BEAST]
  if (model.api.id.includes("gpt")) {
    if (model.api.id.includes("codex")) return [PROMPT_CODEX]
    return [PROMPT_GPT]
  }
  if (model.api.id.includes("gemini-")) return [PROMPT_GEMINI]
  if (model.api.id.includes("claude")) return [PROMPT_ANTHROPIC]
  if (model.api.id.toLowerCase().includes("trinity")) return [PROMPT_TRINITY]
  if (model.api.id.toLowerCase().includes("kimi")) return [PROMPT_KIMI]
  return [PROMPT_DEFAULT]  // 兜底
}

匹配逻辑:基于 model.api.id 字符串包含关系,顺序判断。default.txt 是最后的兜底选项。

三、V1 架构加载流程

调用栈

用户输入
  → SessionPrompt.prompt()        [packages/opencode/src/session/prompt.ts]
    → provider(model)             [system.ts:19]     选择模型特定提示词
    → sys.environment(model)      [system.ts:48]     构建环境信息
    → instruction.system()        [instruction.ts:100] 加载 AGENTS.md
    → sys.skills(agent)           [system.ts:65]     加载技能列表
    → Plugin triggers             [prompt.ts]         插件修改 system array
    → handle.process({ system, ... })                 发送给 LLM

系统提示的组成部分

最终传入 LLM 的 system 数组按顺序拼接:

system = [...env, ...instructions, ...skills]
        ↑ 环境信息     ↑ AGENTS.md     ↑ 技能列表

1. 环境信息 (env)

定义于 system.ts:48-63,包含:

You are powered by the model named {model.api.id}.
The exact model ID is {providerID}/{modelID}
Here is some useful information about the environment you are running in:
<env>
  Working directory: {directory}
  Workspace root folder: {worktree}
  Is directory a git repo: yes/no
  Platform: {platform}
  Today's date: {date}
</env>

2. AGENTS.md / 指令 (instructions)

定义于 packages/opencode/src/session/instruction.ts:100-115Instruction.system() 方法加载:

优先级 来源 路径
1 全局 AGENTS.md ~/.config/opencode/AGENTS.md
2 回退全局 CLAUDE.md ~/.claude/CLAUDE.md
3 项目级 AGENTS.md 从当前目录向上查找第一个 AGENTS.md/CLAUDE.md/CONTEXT.md
4 配置指定文件 opencode.jsonconfig.instructions 数组(支持 URL)

格式:Instructions from: {filepath}\n{content}

就近注入机制instruction.ts:159-195):当 read 工具读取文件时,自动查找该文件祖先目录中的 AGENTS.md 并注入。每个 assistant message 只注入一次同一文件(通过 claims: Map<MessageID, Set<string>> 去重)。

3. 技能列表 (skills)

定义于 system.ts:65-75,列出基于 Agent 权限过滤后的可用 Skill:

Skills provide specialized instructions and workflows for specific tasks.
Use the skill tool to load a skill when a task matches its description.
- {skill_name}: {skill_description}

4. 结构化输出提示

当输出格式要求为 json_schema 时(prompt.ts 中的 STRUCTURED_OUTPUT_SYSTEM_PROMPT 常量),追加到 system 数组末尾。

5. 模型特定提示词 (model prompt)

模型选择的提示词(如 beast.txtanthropic.txt 等)通过 AI SDK 的 system 参数传递给 LLM,不作为 system 数组成员。

Plan / Build 模式提示

通过 packages/opencode/src/session/reminders.tsSessionReminders.apply() 注入:

  • 非实验性 Plan 模式:当前 Agent 为 "plan" 时,向最后一条 user message 追加 plan.txt;从 plan 切换到 build 时追加 build-switch.txt
  • 实验性 Plan 模式:将 plan-mode.txt 中的 ${planInfo} 替换为实际的 plan 文件路径

最大步数限制

当达到 max_steps 限制时,prompt.tsmax-steps.txt 追加为最后一条 assistant 消息内容,阻止 LLM 继续执行工具调用。

四、V2 架构:System Context

架构层次

packages/core/src/system-context/
  index.ts       — 核心类型:Source, SystemContext, Snapshot, Generation
  registry.ts    — SystemContextRegistry(Entry 注册与组合加载)
  builtins.ts    — 内置 Source:environment + date

核心类型

Source(可独立刷新的类型化源)

interface Source<A> {
  readonly key: string
  readonly codec: Schema.Codec<A>
  readonly load: () => Effect<A>
  readonly baseline: (value: A) => string       // 首次渲染完整文本
  readonly update: (prev: A, curr: A) => string  // 增量更新文本
  readonly removed: (value: A) => string         // 移除通知
}

SystemContext

不透明的上下文载体,包含多个 PackedSource

Snapshot

持久化的比较状态:Record<Key, { value: Json, removed?: string }>

Generation

type Generation = { baseline: string, snapshot: Snapshot }

——不可变基线文本 + 当前快照。

ReconcileResult

type ReconcileResult = Unchanged | Updated | ReplacementReady | ReplacementBlocked

内置 Source

定义于 packages/core/src/system-context/builtins.ts:10-32

Source Key 说明
core/environment 工作目录、工作区根目录、git 状态、平台
core/date 当前日期

AGENTS.md 作为 Source

定义于 packages/core/src/instruction-context.ts:17-54

  • Keycore/instructions
  • baseline():渲染为 Instructions from: {path}\n{content}(多个文件用 \n\n 连接)
  • update()These instructions replace all previously loaded ambient instructions.\n\n{current}
  • removed()Previously loaded instructions no longer apply.
  • 加载逻辑:从当前目录向上找 AGENTS.md(停止于 project root),加上全局 AGENTS.md

System Context Registry

定义于 registry.ts:42

1. 遍历所有注册的 Entry(builtins + instructions + skills)
2. 调用 entry.load() 并行加载
3. 组合为 SystemContext.combine(...)

Context Epoch(上下文纪元)

定义于 packages/core/src/session/context-epoch.ts

管理 Session 的 System Context 版本生命周期。持久化存储在 SQLite 表 SessionContextEpochTable

Schema: {
  session_id, baseline, agent, snapshot, baseline_seq, revision, replacement_seq
}

工作流程

SessionRunner.run(sessionID)
  → SessionContextEpoch.prepare()
    → SystemContextRegistry.load()          // 加载所有 Source
    → SystemContext.combine(...)            // 组合
    → SystemContext.reconcile(previous)     // 与上次快照比较
      ├─ "Unchanged"       → revision 不变
      ├─ "Updated"         → 生成增量更新文本,revision +1
      └─ "ReplacementReady"  → 重建完整 Generation
    → 持久化到 SQLite
  → LLM.request({ system: [agent.system, baseline], ... })

V2 最终组装

// runner/llm.ts:220
system: [agent.info?.system, system.baseline]
  .filter(part => part !== undefined && part.length > 0)
  .map(SystemPart.make)
  • agent.info?.system:Agent 配置中 prompt 字段指定的提示词
  • system.baseline:从 SystemContextRegistry 加载并经过 initialize() 处理的基线文本

基线 vs 更新

方法 时机 输出
baseline() 首次初始化 Generation 完整的系统提示文本
update(prev, curr) Context Epoch revision 增加 增量更新文本(写入 session event)
removed() Source 被移除 移除通知文本

五、Agent 特定提示词

内置 Agent 的提示词

Agent 自定义 prompt 说明
build 使用模型默认提示词,权限全部允许
plan 权限控制只读,额外提示由 reminders.ts 注入
general 使用模型默认提示词
explore PROMPT_EXPLORE 专用探索提示词
compaction 隐藏 Agent,全部禁用

插件系统修改提示词

packages/opencode/src/session/prompt.ts 中通过插件钩子修改:

yield* plugin.trigger("experimental.chat.system.transform", {}, { system })

该钩子在 agent.ts:227 用于 Agent 生成功能,允许插件动态修改 system array。

六、架构对比

维度 V1 架构 V2 架构(System Context)
提示词选择 字符串匹配模型 ID 同 V1
环境信息 每次拼接 Source + 持久化快照
AGENTS.md 每次文件读取 Source 懒加载
增量更新 不支持(全量重建) 支持(reconcile 生成 diff)
持久化 SQLite 存储 Snapshot + revision
进程恢复 不支持 持久化后跨进程复用
插件扩展 experimental.chat.system.transform 钩子 注册新 Source 到 Registry

七、完整数据流(V1 架构)

用户输入
  ↓
SessionPrompt.prompt(input)                     [prompt.ts]
  ↓
├─ provider(model)                              [system.ts:19]
│   → 根据 model.api.id 选择提示词文件
│   → 返回 [PROMPT_BEAST / ANTHROPIC / ...]
│
├─ sys.environment(model)                       [system.ts:48]
│   → 读取 InstanceState.context
│   → 构建环境信息块
│
├─ instruction.system()                         [instruction.ts:100]
│   → 读取全局 AGENTS.md
│   → 向上查找项目级 AGENTS.md
│   → 加载 config.instructions 指定文件
│   → 去重(已注入的文件不重复)
│
├─ sys.skills(agent)                            [system.ts:65]
│   → 按权限过滤可用 skill
│   → 格式化 skill 列表
│
├─ 合并 system = [...env, ...instructions, ...skills]
│
├─ SessionReminders.apply()                     [reminders.ts]
│   → plan/build 切换提示
│   → max-steps 提示
│
├─ Plugin "experimental.chat.system.transform"  [prompt.ts]
│   → 插件修改 system array
│
└─ handle.process({ system, messages, tools, model })
    → LLM stream API

八、关键文件索引

文件 职责
packages/opencode/src/session/system.ts 提示词选择 + 环境/技能信息构建
packages/opencode/src/session/prompt.ts 主提示词组装入口(V1)
packages/opencode/src/session/instruction.ts AGENTS.md 加载与就近注入
packages/opencode/src/session/reminders.ts Plan/Build 切换提示注入
packages/opencode/src/session/prompt/default.txt 通用兜底提示词
packages/opencode/src/session/prompt/anthropic.txt Claude 系列提示词
packages/opencode/src/session/prompt/beast.txt GPT-4/o1/o3 提示词
packages/opencode/src/session/prompt/gpt.txt GPT 系列提示词
packages/opencode/src/session/prompt/codex.txt GPT Codex 提示词
packages/opencode/src/session/prompt/gemini.txt Gemini 提示词
packages/opencode/src/session/prompt/kimi.txt Kimi 提示词
packages/opencode/src/session/prompt/trinity.txt Trinity 提示词
packages/opencode/src/session/prompt/plan.txt Plan 模式提示
packages/opencode/src/session/prompt/build-switch.txt Plan→Build 切换提示
packages/opencode/src/session/prompt/max-steps.txt 最大步数限制提示
packages/core/src/system-context/index.ts System Context 核心抽象
packages/core/src/system-context/registry.ts 上下文源注册表
packages/core/src/system-context/builtins.ts 内置上下文源
packages/core/src/instruction-context.ts AGENTS.md 作为 System Context Source
packages/core/src/session/context-epoch.ts Context Epoch 管理
packages/core/src/session/runner/llm.ts V2 架构最终组装
posted @ 2026-07-09 00:30  jiftle  阅读(60)  评论(0)    收藏  举报