opencode (SST)
一句话定位
opencode 是 SST 团队维护的开源终端/服务化编码 agent,整体用 TypeScript + Bun 实现,
底层构建在 Effect 函数式效应框架之上(每个服务是 Effect.Service/Layer,
Effect.gen(function* () {...}) 写法贯穿全仓)。仓库当前处于双实现并存的中间态:
真正跑在用户机器上的是 packages/opencode/src/(V1,本文档绝大多数论断的证据来源);
packages/core/src/ 是一套尚未成为默认路径的 Effect-native 重写(V2,见
specs/v2/*.md 与根目录 CONTEXT.md),本文档中凡引用 V2 spec 的内容均明确标注为
“设计意图 / 未上线”,不作为当前行为断言。
核心架构总览(目录结构关键路径 + 引用的 commit)
Commit: eb6ff0c1e049e5dfb6f61eb74f925c0a8007490c(浅克隆单 commit,commit 时间
2026-07-06 13:35:10 UTC,2026-07-07 拉取)。
opencode/ (Bun workspaces monorepo)
├── packages/opencode/src/ — V1,实际 shipped 的 CLI/server 实现,本文档主要证据来源
│ ├── session/ — 主循环(prompt.ts)、压缩(compaction.ts/overflow.ts)、
│ │ 事件处理(processor.ts)、系统提示组装(system.ts)、
│ │ reminders.ts、instruction.ts(AGENTS.md 发现,未深挖)
│ ├── tool/ — 工具定义(tool.ts)、注册表(registry.ts)、
│ │ task.ts(subagent)、shell.ts(bash 执行+静态分析)
│ ├── agent/ — Agent 定义(agent.ts)、subagent-permissions.ts
│ ├── permission/ — 权限引擎(index.ts)
│ ├── skill/ — Skill 发现与加载(index.ts/discovery.ts)
│ ├── plugin/ — 插件 loader
│ └── mcp/ — MCP 客户端(stdio/SSE/StreamableHTTP)
├── packages/core/src/ — V2,Effect-native 重写中,未成为默认路径
│ ├── database/migration/ — Drizzle/SQLite 迁移,event-sourced session 存储
│ └── observability.ts, observability/otlp.ts — OTel 导出
├── packages/plugin/src/index.ts — 插件 Hooks 类型定义
├── packages/tui, packages/server, packages/sdk(-next) — 终端 UI / HTTP API / 生成客户端(未深挖)
├── packages/stats — opencode.ai 公开用量排行榜网站,与训练无关
├── packages/docs — 空的 Mintlify 起始模板,**不是**真实 opencode.ai 公开文档内容
├── CONTEXT.md(根目录,226 行)— 官方 V2 设计文档,定义 System Context / Context Epoch 等术语
└── specs/v2/session.md, specs/v2/tools.md — 官方 V2 设计 spec
V1/V2 通过 spec 中提到的 “V1-to-V2 shadow bridge” 共存(specs/v2/session.md),
V2 尚不是默认运行时路径。
Agent Loop(主循环 / 何时继续何时停)
Shipped(V1)主循环在 session/prompt.ts 的 runLoop(sessionID)(约 1081-1339 行),
是一个 while(true) 循环,每轮迭代:
- 通过
MessageV2.filterCompactedEffect加载消息; - 若最后一条 assistant 消息已完成且无待执行 tool call →
break退出; - 优先处理排队中的
subtask/compaction任务(约 1142-1159 行); - 通过
compaction.isOverflow检查 token 溢出 → 触发compaction.create({auto:true})并continue; - 解析当前
agent,计算isLastStep = step >= agent.steps(agent 可配置最大步数上限,默认Infinity),应用SessionReminders.apply(向历史注入合成 reminder); - 创建新的 assistant 消息,取得
SessionProcessor.Handle(见processor.ts),经SessionTools.resolve解析可用工具,组装系统提示数组(env + instructions + mcpInstructions + skills),调用handle.process(...); handle.process返回"compact" | "stop" | "continue"(processor.ts679-682 行):needsCompaction→"compact";blocked || error→"stop";否则"continue";- 收到
"stop"则跳出循环,否则继续(若为"compact"先触发压缩)。
停止条件:assistant 的 finish 原因不是 tool-calls,且无待执行 tool call,且
lastUser.id < lastAssistant.id(没有新内容需要响应)。Doom-loop 防护:
processor.ts 中 DOOM_LOOP_THRESHOLD = 3,检测到 3 次连续相同 tool call(相同工具+
相同输入)会强制触发 doom_loop 权限 ask,而非无限循环。
每轮模型流式响应由 session/llm.ts 的 LLM.stream(本次未深挖)驱动,产出事件流
(reasoning-start/delta/end、tool-input-*、tool-call、tool-result、
tool-error、step-start/finish、text-start/delta/end、provider-error、
finish),由 processor.ts 的 handleEvent 消费。
V2 设计(未上线):specs/v2/session.md 描述更形式化的 SessionRunner/
SessionExecution/SessionRunCoordinator 模型,含显式 “Session Drain”(一次执行
span)、steer vs queue 两种 inbox 投递模式、resume/wake 入口——这是目标架构,
不是当前行为。
记忆与上下文管理(压缩、长期记忆、会话持久化)
Shipped 压缩机制(session/compaction.ts 562 行 + session/overflow.ts):
- Token 预算 =
model.limit.input - reserved,reserved = config.compaction.reserved ?? min(20_000, maxOutputTokens)(overflow.ts的usable()); isOverflow()在累计 token ≥ 可用预算时触发(compaction.auto配置可关闭);- 压缩算法(
compaction.ts):把历史切成”轮次”(turns()—— 一轮 = 从一条用户消息到下一条),保留最近若干轮原文(DEFAULT_TAIL_TURNS = 2,预算感知,preserveRecentBudget= 可用预算的 25%,夹在 2k-8k 之间),更早的部分用专门的compactionagent +agent/prompt/compaction.txt提示词摘要(“anchored context summarization assistant… If the prompt includes a<previous-summary>block, treat it as the current anchored summary… merging in new facts”); - 重复压缩会更新已有的滚动摘要而非从头重来(
specs/v2/session.md119 行,与 V1 行为一致); PRUNE_MINIMUM/PRUNE_PROTECT常量(20k/40k token)与PRUNE_PROTECTED_TOOLS = ["skill"]表明工具输出裁剪也是压缩流程的一部分(保护 skill 工具输出不被裁剪);- 溢出触发的压缩:若 provider 调用本身因上下文溢出失败,
processor.ts的halt()(约 599-625 行)捕获SessionV1.ContextOverflowError并设needsCompaction=true(仅一次重试:压缩+重建,非循环,与 V2 spec 中”仅剩一次物理尝试”的表述一致)。
长期/会话持久化:SQLite via Drizzle(packages/core/src/database/*),event-sourced
(V2 spec 定义的 session.next.* 事件族;V1 通过 session/session.ts 的消息分页已经
落盘持久化)。Session 可 fork(session.ts 接口中的 fork),有父子关系(subagent
session 带 parentID)。
系统提示动态组装 = runLoop 调用时拼接的 4 个部分(prompt.ts 约 1257-1269 行):
sys.environment(model)(per-model 基础提示 + 环境块 + 项目引用)、
instruction.system()(AGENTS.md 发现,本次未完整读 session/instruction.ts,237 行)、
sys.mcp(agent, permission)(MCP server 说明块)、sys.skills(agent)(可用 skill
列表)。另外 session/reminders.ts 把合成 reminder 注入消息历史本身(而非系统提示),
用于 plan-mode 进出、build-mode 切换等(prompt/plan.txt、prompt/build-switch.txt、
prompt/plan-mode.txt)。
V2 设计文档(CONTEXT.md,官方、未上线)把这一套形式化为由”Context Source”组成的
“System Context”,包裹在一个”Context Epoch”内——一个对 provider 缓存友好的不可变
基线,只能通过在安全的轮次边界插入的持久化”Mid-Conversation System Messages”改变,
从不在流式过程中改变;压缩会开启新的 Context Epoch。明显是为了 prompt-cache
友好性(避免每次小的上下文变化就使 Anthropic/OpenAI 的前缀缓存失效)。
工具体系(定义/调用协议/注册/权限)
定义:tool/tool.ts 的 Tool.define(id, init) —— 每个工具有 description、
parameters(Effect Schema.Decoder)、可选 jsonSchema 覆盖、execute(args, ctx)。
注册时统一包一层:schema 解码 + 统一的执行后输出截断(truncate.output)+
OpenTelemetry span(Effect.withSpan("Tool.execute", {"tool.name", "session.id", "message.id", "tool.call_id"}))。
注册表(tool/registry.ts,451 行):内置工具列表(invalid, question?, shell, read, glob, grep, edit, write, task, fetch, todo, search, skill, patch, execute?(codemode), lsp?, plan?),另外:
- 项目自定义工具:配置目录下任意
tool/*.{js,ts}或tools/*.{js,ts}文件,动态import()(命名空间=文件名); - 插件工具:来自已加载插件的
Hooks.toolmap,从 Zod schema 桥接到 JSON Schema(zodJsonSchema),含一处文档化的历史 bug 兼容 shim(args ?? {}归一化,引用 GH issue 27630); - 按模型条件可见性:
apply_patch工具只在部分 GPT 模型下展示(modelID.includes("gpt-") && !includes("oss") && !includes("gpt-4")),否则展示edit/write;websearch仅在webSearchEnabled(providerID, {exa, parallel})标志开启时展示; tool.definition插件钩子可在每轮发送给模型前修改某个工具的 description/parameters/jsonSchema。
权限集成是逐工具在 execute 内通过 ctx.ask(...) 完成的(例如 shell.ts 在用
tree-sitter 静态解析命令找到涉及路径后调用 ctx.ask({permission: "bash"|"external_directory", patterns, always, metadata}))。
输出边界:tool.ts 的 wrap() 中统一截断——每个工具结果都过 truncate.output(),
超限输出写入受管临时文件(tool/truncation-dir.ts,本次未完整读)并替换为有界预览
outputPath元数据,与specs/v2/tools.md中形式化的 “Managed Tool Output File” 一致(V1 代码已提前实现该模式)。
Prompt 设计(系统提示结构、动态组装)
基础系统提示按模型家族在 session/system.ts 的 provider(model) 中选择:
gpt-4/o1/o3 → beast.txt;其他 gpt 且 id 含 “codex” → codex.txt;其他 gpt →
gpt.txt;gemini-* → gemini.txt;claude → anthropic.txt;trinity →
trinity.txt;kimi → kimi.txt;否则 → default.txt。default.txt(96 行,全文
读完)在结构上高度接近 Anthropic 自家 Claude Code 系统提示:包含 “Tone and style” /
“Proactiveness” / “Following conventions” / “Code style: DO NOT ADD ANY COMMENTS
unless asked” / “Doing tasks” / “Tool usage policy” / “Code References” 等分节,
部分措辞近乎逐字(例如 <4 lines 简洁性规则、file_path:line_number 引用惯例、
并行工具调用指示)。这是一个可观察到的相似性事实,不是”直接抄袭”的证据——原文
判断为佐证性观察,不作确凿溯源结论。
动态组装发生在每轮 prompt.ts 中(同”记忆”节所述):环境块 + AGENTS.md 指令 + MCP
指令 + skill 列表,拼接为一个系统消息字符串数组(不是单一 blob)——数组元素似乎
映射为发给 provider 的多条独立系统消息/块。
任务专用提示:agent/prompt/title.txt(标题生成)、summary.txt(摘要生成)、
explore.txt(explore subagent 专用提示)、compaction.txt(压缩 agent 使用)。
Reminders(session/reminders.ts)注入的是合成用户轮文本部分(标记
synthetic: true),而非系统消息,例如 agent 为 plan 时自动注入 PROMPT_PLAN,
或从 plan-agent 轮次切回 build 时注入 BUILD_SWITCH 文本。
插件钩子 experimental.chat.system.transform(修改系统消息数组)与
experimental.chat.messages.transform(修改整个消息数组)赋予插件任意的系统提示
修改能力(标记为 “experimental”,CONTEXT.md 的 “Flagged ambiguities” 中明确指出
尚未移植到 V2 —— 仅 V1 有此逃生口)。
Router / 编排(任务分解、多 agent、子 agent)
没有独立的”router”组件——编排是基于 agent 的,通过 task 工具(tool/task.ts,
347 行)实现:
- 任何
mode: "subagent"或"all"的 agent 都可以经task(subagent_type, prompt, description, task_id?, background?)调用; - 内置 subagent(定义于
agent/agent.ts):general(宽泛多步 subagent,禁用todowrite)、explore(只读的快速代码搜索 agent——仅允许grep/glob/list/bash/webfetch/websearch/read,其余全拒,配专用提示explore.txt); - 内置主 agent:
build(默认,完整权限)、plan(除白名单路径.opencode/plans/*.md外禁用一切编辑工具,禁用task.general,只允许plan_exit权限); - 隐藏系统 agent:
compaction、title、summary——全部工具禁用 ("*": "deny"),纯文本生成、供循环内部使用; - Subagent session 是真正的子
Session,parentID指向调用方 session;deriveSubagentSessionPermission()(agent/subagent-permissions.ts)把父 session 权限与目标 subagent 自身权限规则合并,并强制拒绝todowrite/task递归(除非 subagent 显式重新允许)以及任何被配置为experimental.primary_tools的主 agent 专属工具; - 后台模式(
background: true,需OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS实验开关):subagent 通过BackgroundJob.Service异步运行,完成后一条合成 结果消息(<task id state>...</task>类 XML 包装,renderOutput())被注入 父 session,如同该工具已经返回,并通过一个 forked effect 的notify()通知父 session; task_id参数允许调用方复用之前的 subagent session 而非重新生成(跨调用的 session 身份复用);- 用户自定义 agent 来自
config.agent条目(name/model/permission/prompt/steps 等覆盖默认值)——多 agent 配置是用户可扩展的,不是硬编码在内置 agent 里。
未发现”planner→executor”式的层级式 router 模式,仅有这一套扁平的 task-dispatch
工具;plan 模式是一种权限受限的 UI 模式,不是独立的规划子系统。
Skill / 插件体系
Skill(skill/index.ts、skill/discovery.ts):兼容 Claude Code 的 SKILL.md
frontmatter 格式(name、description),从 .claude/skills/**/SKILL.md、
.agents/skills/**/SKILL.md、.opencode/{skill,skills}/**/SKILL.md(glob 常量
EXTERNAL_SKILL_PATTERN/OPENCODE_SKILL_PATTERN/SKILL_PATTERN)发现。一个
skill 工具(tool/skill.ts,70 行)让模型按需加载 skill 正文;系统提示里只列出
name+description(按 agent 权限过滤,经 Permission.disabled(["skill"], ...)),
不含完整正文——与 Claude Code/Claude Skills 中的”渐进式披露”模式一致。远程 skill
包可经 skill/discovery.ts 的 pull(url) 拉取——抓取 index.json manifest +
逐个 skill 文件,带版本化的原子替换缓存更新(临时目录 + rename,失败回滚),
存于 ~/.cache (Global.Path.cache)/skills/<name>/。内置 customize-opencode
skill 专门教模型 opencode 自身的配置 schema。
插件(packages/plugin/src/index.ts 类型定义 + packages/opencode/src/ plugin/loader.ts + plugin/index.ts 运行时):插件是
(input: PluginInput, options?) => Promise<Hooks>。Loader(plugin/loader.ts)
把插件规格解析为 npm 包(按需安装)或本地文件,检查版本兼容性(npm 插件声明
支持的 opencode 版本范围),动态 import(),文件插件依赖未就绪时有一次重试。
完整 Hooks 接口(直接读自 packages/plugin/src/index.ts):dispose、
event(订阅全部事件总线事件)、config(修改已解析配置)、tool(注册自定义
工具)、auth(provider 自定义 OAuth/API-key 认证流程)、provider(向 provider
注入自定义模型)、chat.message、chat.params(修改
temperature/topP/topK/maxOutputTokens/provider options)、chat.headers、
permission.ask(覆盖 ask/deny/allow 决策)、command.execute.before、
tool.execute.before/tool.execute.after、shell.env(向 shell 工具注入环境
变量)、experimental.chat.messages.transform、
experimental.chat.system.transform、experimental.provider.small_model、
experimental.session.compacting(自定义压缩提示)、
experimental.compaction.autocontinue、experimental.text.complete。仓库内
自带多个一方示例插件:xai.ts、digitalocean.ts、cloudflare.ts、azure.ts、
snowflake-cortex.ts、github-copilot/、openai/。
自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)
未实现。 未发现 eval 驱动的自我纠错循环、微调管线、reward model 集成,或
“从历史 session 学习”的机制(对 packages/ 全仓搜索 “fine-tun”、
“reinforcement”、“reward model”、“self-improv”、“training data”、
“eval-driven” 均无真实命中)。packages/stats 是 opencode.ai 的公开用量排行榜
网站,与模型训练/自我改进无关。会话摘要(session/summary.ts)和压缩摘要
只服务于上下文窗口管理,不构成跨 session 学习。若未来版本加入此能力,本
commit 中不可见。
可观测性(日志 / trace 格式)
两层:
- Effect 原生的 trace/log 原语被广泛使用:
Effect.withSpan(...)(在tool/tool.ts和tool/registry.ts的插件工具路径中包裹每次工具执行, 携带tool.name、session.id、message.id、tool.call_id属性),以及Effect.logInfo/Effect.logWarning/Effect.logError结构化日志(例如processor.ts记录process/SessionProcessor.halt事件,带session.id、messageID、error、stack)。 - OpenTelemetry 导出,选择性开启:
packages/core/src/observability.ts+observability/otlp.ts。若设置环境变量OTEL_EXPORTER_OTLP_ENDPOINT, 构建 OTLP 日志导出器(OtlpLogger.make)和 OTLP trace 导出器 (@opentelemetry/exporter-trace-otlp-http+NodeSdk.layer+BatchSpanProcessor),resource 属性含service.name=opencode、service.version、deployment.environment.name、opencode.client、opencode.run(进程级运行 UUID),以及任意OTEL_RESOURCE_ATTRIBUTES。 还显式注册了AsyncLocalStorageContextManager作为全局 OTel context manager,使 Vercel AI SDK 自身的内部 span 能正确嵌套在 Effect 的 span 之下——一次刻意的跨库 trace-context 桥接(otlp.ts注释:“The Effect Node SDK does not register a global context manager, but the AI SDK uses it to parent spans”)。
除 SQLite event-sourced session 存储本身(session.next.* 事件族,按 V2 spec)
外,未发现独立的自定义”trace/replay” JSON 格式;这套事件存储事实上已经是一份
可持久、可回放的轨迹日志(见”轨迹利用”节)。
安全与权限(审批门、密钥管理)
核心引擎:permission/index.ts(全文读完,224 行)。模型:
PermissionV1.Ruleset 是有序的 {permission, pattern, action: "allow"|"ask"|"deny"} 规则列表;evaluate(permission, pattern, ...rulesets)
在拼接后的规则集中用 Wildcard.match 找最后一条匹配规则,无匹配则默认
ask。ask() 遍历某次请求涉及的所有 pattern:任一 deny 短路为
DeniedError;若有 pattern 需要询问,注册一个 Deferred 并发布 Asked
事件(由 CLI/TUI/server 层消费以提示用户);reply() 解析该 Deferred——
"reject" 使该 Deferred 失败(并级联拒绝该 session 同批的其它待处理请求,
即一次拒绝清空整批);"always" 把新规则持久化进内存态 approved
列表(仅进程生命周期内有效,不写盘,除非用户自己的 opencode.json
配置中已有该规则),并回溯性地解析其它已被新规则覆盖的待处理请求。
默认权限集(agent/agent.ts 的 defaults):基线 "*": "allow",但
doom_loop: "ask";external_directory(项目根目录外的路径)默认 ask
(白名单目录例外:截断输出目录、tmp 目录、skill 目录、reference 目录);
question: "deny"(question 工具在权限层默认禁用,另外还受工具注册表里
questionEnabled 的客户端类型检查约束);plan_enter/plan_exit: "deny"
默认禁用;以及一条**.env 文件读取 ask 规则**,仿照 GitHub Node.gitignore
的 .env 模式(*.env、*.env.* → ask;*.env.example → allow)——即
默认策略中硬编码了一个针对密钥文件的启发式防护。
每个 agent 在此之上叠加覆盖(例如 build agent 允许 question/
plan_enter;plan agent 拒绝除白名单 plans-markdown 路径外的一切编辑,
拒绝 task.general;explore agent 除只读工具白名单外全部拒绝)。
Subagent 权限继承:agent/subagent-permissions.ts 的
deriveSubagentSessionPermission() 把父 session 权限与 subagent 自身规则
合并,并强制拒绝 todowrite/task 递归以及任何配置在
config.experimental.primary_tools 中的工具(保留给主 agent 专用)。
凭据/认证:独立的 Auth/Credential/McpAuth/McpOAuthProvider 服务
(packages/opencode/src/auth、packages/core/src/credential.ts、
mcp/auth.ts、mcp/oauth-provider.ts)——本次未逐行深挖,但结构上这些
服务持有 provider API key/OAuth token 及 MCP server 认证信息,与权限规则
系统(“能否触碰这个工具/路径”)职责分离(认证 = “如何向 provider/MCP
server 证明身份”)。
沙箱与执行隔离
无沙箱。 官方 V2 spec 明确写明(specs/v2/tools.md 204 行):“Bash is
not sandboxed: the spawned shell runs with the host user’s filesystem,
process, and network authority.”(Bash 未沙箱化:生成的 shell 以宿主用户的
文件系统、进程与网络权限运行)。V1 的 shell 工具(tool/shell.ts)通过
ChildProcess.make/cross-spawn(CrossSpawnSpawner)直接在宿主 OS 上以
宿主用户权限生成命令——工具实现中未发现容器、VM、seccomp/AppArmor
profile 或 chroot。
取而代之的是静态预执行风险分析 + 权限门控:tool/shell.ts 用
tree-sitter-bash/tree-sitter-powershell(经 web-tree-sitter 加载的
WASM 解析器)解析 shell 命令,遍历语法树找出涉及文件的命令
(FILES/CWD/CMD_FILES 命令名集合:rm, cp, mv, mkdir, touch, chmod, chown, cat, cd, ... 及 PowerShell 对应项),解析涉及路径,若任一路径落在
当前项目/实例目录之外(containsPath() 检查),触发
external_directory 权限 ask。非文件类命令则触发一个基于粗粒度 pattern
(BashArity.prefix(tokens) + " *" 通配符)的通用 bash 权限 ask,
使”always allow”授权能覆盖整个命令族而非单次精确调用。这是尽力而为的静态
分析,明确不具强制力(specs/v2/tools.md:“Best-effort scans of absolute
command arguments produce advisory warnings only; they are not sandbox
boundaries”)。
命令执行有超时(defaultTimeoutMs,默认 2 分钟,可按次覆盖),可中止
(ctx.abort AbortSignal),输出捕获有界/截断(truncate.ts,
MAX_METADATA_LENGTH = 30_000 字符,用于实时元数据预览)。
与模型的协同设计
- 按模型家族分化系统提示(
session/system.ts的provider()): Anthropic/OpenAI-gpt/OpenAI-o-series(“beast”)/Codex/Gemini/Kimi/Trinity 各有专属基础提示——即该 harness 显式按 vendor 调整提示风格,而非用一份 通用提示; - 按模型选择工具:
apply_patch(OpenAI 的 patch 格式)只在部分 GPT 模型下替换通用的edit/write工具(tool/registry.ts的usePatch检查)——直接证据表明工具面会适配模型的原生编辑能力; - Provider 请求编码通过一层基于 AI SDK 的
LLM/aisdk.ts/native-request.ts/native-runtime.ts(session/llm/*,本次未深挖) 抽象,把 provider 中立的请求映射到各 provider 的具体协议——V2 spec (CONTEXT.md)称之为 “LLM protocol adapter”,明确区分 “Model Request Options”(provider 语义相关)与 “Generation Controls”(provider 中立的 采样参数),是刻意为多 provider 协同设计留出的抽象边界; - 推理/思考 token 处理:
processor.ts处理reasoning-start/delta/end事件并透传 provider 元数据;CONTEXT.md明确讨论了 “Native Continuation Metadata”(推理签名、provider 托管的 item ID)只有在同一 provider/model 继续对话时才存活——若模型/provider 切换则退化为纯文本。这是专门针对 Anthropic 扩展思考签名和 OpenAI 加密推理续接语义的设计适配; experimental.provider.small_model插件钩子专门用于让集成方为轻量任务 (如标题生成)按 provider 替换为更便宜/更快的模型。
轨迹利用(session/trajectory 是否反哺训练/评测)
未发现 session/轨迹反哺训练或评测的证据。属实的部分:session 在 SQLite 中
事件溯源持久化(session.next.* 事件族,sessions.events({sessionID, after}) 持久回放 API,按 specs/v2/session.md),因此支撑此类复用所需
的原始数据在结构上是存在的,但未发现任何代码路径把轨迹导出用于微调、RL
或 benchmark 构建。packages/share/session.ts/share/share-next.ts
实现的是 session 分享功能(大概率是 opencode.ai 的公开可分享会话
链接),这是面向人类的会话转录分享功能,不是训练/评测数据管线。
packages/stats 是 opencode.ai 公开排行榜网站(用量统计聚合),不是
轨迹到训练的桥梁。
与同类 harness 的关键差异(1-3 条,可以先留一句概述,后续 synthesis 阶段会做跨 harness 对比)
- 整体建构在 Effect 函数式效应框架之上(
Effect.Service/Layer/Effect.gen),这在同类开源编码 agent harness 中较少见,天然带来 统一的 span/日志埋点(Effect.withSpan)和跨库 trace-context 桥接 (AI SDK span 挂靠 Effect span 之下)。 - 系统提示层面存在与 Claude Code 已知系统提示高度相似的结构与措辞
(
session/system.ts的default.txt),这是本次调研中在同类 harness 里观察到的较明显案例,值得在跨 harness 对比阶段专门列出。 - V1(shipped)/V2(Effect-native 重写,未上线)两套实现并存于同一
仓库,且 V2 official spec(
CONTEXT.md、specs/v2/*.md)比大多数 同类项目的公开设计文档更形式化、更精确(专门定义 Context Epoch / System Context 等术语),是本次调研中”设计文档质量”维度上的一个正 样本,具体跨 harness 排位留待 synthesis 阶段。 - 跨 harness 详细对比(agent loop 结构、压缩策略、权限模型等的量化 比较)留待 synthesis 阶段统一处理,此处不展开。
原始源码定位
- repo: https://github.com/sst/opencode
- commit/version analyzed:
eb6ff0c1e049e5dfb6f61eb74f925c0a8007490c(浅克隆, commit 时间 2026-07-06 13:35:10 UTC,2026-07-07 拉取分析) - 关键文件列表(相对仓库根目录):
packages/opencode/src/session/prompt.ts(1631 行,runLoop主循环)packages/opencode/src/session/processor.ts(718 行,事件处理/doom-loop 防护)packages/opencode/src/session/system.ts(系统提示组装)packages/opencode/src/session/compaction.ts(562 行)+session/overflow.ts(压缩/溢出)packages/opencode/src/session/reminders.ts(合成 reminder 注入)packages/opencode/src/session/session.ts(1018 行,Session CRUD/分页)packages/opencode/src/session/prompt/*.txt(各模型家族系统提示)packages/opencode/src/agent/prompt/*.txt(任务专用提示)packages/opencode/src/tool/tool.ts(工具定义包装)packages/opencode/src/tool/registry.ts(451 行,工具注册表)packages/opencode/src/tool/task.ts(347 行,subagent 派生)packages/opencode/src/tool/shell.ts(646 行,bash 执行+静态分析)packages/opencode/src/agent/agent.ts(454 行,agent 定义)packages/opencode/src/agent/subagent-permissions.tspackages/opencode/src/permission/index.ts(224 行,权限引擎)packages/opencode/src/skill/discovery.ts(141 行)+skill/index.ts(354 行)packages/opencode/src/plugin/loader.ts(238 行)packages/plugin/src/index.ts(Hooks 接口)packages/opencode/src/mcp/index.ts(MCP 客户端)packages/core/src/observability.ts+observability/otlp.ts(OTel 导出)CONTEXT.md(根目录,226 行,官方 V2 设计文档)specs/v2/session.md、specs/v2/tools.md(官方 V2 设计 spec)packages/core/src/database/migration/*(Drizzle/SQLite 迁移)
一手源存档(sources/)
存档目录:/Users/zhao/projects/self-wiki/ai-research/sources/harness/opencode/
NOTES.md— stage 1 调研员详细笔记(12 维度逐条,含文件路径/行号)key-files/AGENTS.md、key-files/CONTEXT.md— 根目录官方文档key-files/agent/agent.ts、key-files/agent/subagent-permissions.ts、key-files/agent/prompt-txt/— agent 定义与专用提示key-files/session/prompt.ts、session/processor.ts、session/system.ts、session/compaction.ts、session/overflow.ts、session/reminders.ts、session/session.ts、session/prompt-txt/— session 核心实现key-files/tool/tool.ts、tool/registry.ts、tool/task.ts、tool/shell.ts— 工具体系key-files/permission/index.ts— 权限引擎key-files/skill/index.ts、skill/discovery.ts— skill 体系key-files/plugin/loader.ts、plugin/hooks-index.ts— 插件体系key-files/core-observability/observability.ts、core-observability/observability-dir/— OTel 可观测性key-files/specs/config.md、specs/instructions.md、specs/provider-policy.md、specs/session.md、specs/tools.md— 官方 V2 设计 spec