plandex Plan Config 计划配置全解析:从数据库设计、CLI 命令到自动化工作流的完整实现
【免费下载链接】plandexOpen source AI coding agent. Designed for large projects and real world tasks.项目地址: https://gitcode.com/GitHub_Trending/pl/plandex
本文以 plandex 仓库内功能设计文档 app/plans/plan-config.md 为主线,结合其落地源码,系统讲解 plandex 计划级配置(Plan Config)特性的设计初衷、数据模型、16 个配置项与 Auto Mode 预设、config/set-config命令体系、服务端 API 与数据库层实现,以及它如何驱动tell/continue/build/chat等命令的自动化行为。读完你将完整掌握 plandex 中"计划配置"从数据库字段到命令行交互的全链路工作原理,并能在实际项目里按需定制属于自己的自动化工作流。
一、Plan Config 是什么:一份设计蓝图到完整落地
plandex是一款面向大型项目与真实世界任务的开源 AI 编程智能体。在其仓库的 app/plans/plan-config.md 中,保存着一份完整的"计划配置(Plan Config)"功能设计文档。这份文档虽然以需求/设计说明的形式写成,但它本身就是该功能的权威技术规格:它精确到数据库字段、命令行为、服务端/客户端分工与配置项清单。
根据设计文档,Plan Config 功能需要满足以下核心诉求:
- 参照两个既有子系统建模:松散地以"计划模型设置"(plan model settings)与"模型包"(model packs)功能为设计蓝本,保证交互与心智模型的一致性;
- 纯数据库存储:在
plans表上新增一个plan_configJSON 字段保存配置,不写入文件系统、不涉及 git,配置只存在于数据库中; - 独立的命令体系:新增独立于
models/set-model的配置查看与修改命令,且拥有自己的源码文件; - 双层级配置:除计划级配置外,还要有"用户级默认配置"(Default Plan Config),新的计划创建时自动继承用户默认配置,类似
set-model与set-model default的对应关系; - 命令消费配置:
tell、continue、build、chat等执行命令默认读取配置作为默认行为,同时保留既有 flags 的显式覆盖能力。
值得注意的是,设计文档最初把命令命名为settings与set,最终落地实现命名为config与set-config(并额外衍生出set-auto),这正是"设计蓝图 → 实现调整"的典型体现,下文会逐一对照。
二、数据模型与存储:JSON 字段如何落地
2.1 数据库迁移
设计文档要求"服务端需要 api handlers、db handlers 和 db up/down 迁移"。仓库中对应迁移文件为 2024121400_plan_config.up.sql 与 2024121400_plan_config.down.sql:
-- up ALTER TABLE plans ADD COLUMN IF NOT EXISTS plan_config JSON; ALTER TABLE users ADD COLUMN IF NOT EXISTS default_plan_config JSON; -- down ALTER TABLE plans DROP COLUMN IF EXISTS plan_config; ALTER TABLE users DROP COLUMN IF EXISTS default_plan_config;两张表、两个 JSON 列,构成了双层级配置的存储底座:
plans.plan_config:计划级配置,随计划生命周期存在;users.default_plan_config:用户级默认配置,作为新计划的配置模板。
2.2 Go 端结构体与序列化
配置的 Go 模型定义在 app/shared/plan_config.go 的PlanConfig结构体中(第 53-97 行),它实现了sql.Scanner与driver.Valuer接口(第 101-126 行),使得配置可以透明地以 JSON 形式读写数据库:Scan时对nil/空值回退为DefaultPlanConfig,Value()时通过json.Marshal序列化。这意味着即便某条计划的plan_config列为 NULL,读取到的也是语义完整的默认配置对象。
结构体中标注的字段(含被注释掉的"设计未采纳"项)清晰地展示了该特性的演进:初始规划仅 6 个布尔/整型属性,最终扩展为覆盖上下文、构建、应用、执行、调试、提交等全流程的配置体系。
2.3 新计划创建时如何继承默认配置
用户级默认配置在计划创建时被写入新计划,这一逻辑位于 app/server/db/plan_helpers.go 的CreatePlan中(第 23-44 行):事务内先通过GetDefaultPlanConfig(userId)读取用户默认配置,再连同org_id、project_id、name等一起 INSERT 进plans表。也就是说,"新建计划自动套用用户默认配置"从第一行数据写入就已成立,而不是等到首次运行时才解析。
三、配置项体系:从初始 6 个属性到 16 个配置项
3.1 设计文档规划的初始属性
设计文档明确要求初始包含以下属性:
AutoApply bool AutoCommit bool AutoContext bool NoExec bool AutoDebug bool AutoDebugTries int在最终实现中,这些属性被一一映射为ConfigSettingsByKey注册表中的配置键(见 app/shared/plan_config.go):
| 设计文档属性 | 实现配置键 | 展示名 | 说明 |
|---|---|---|---|
AutoApply | autoapply | auto-apply | 计划完成后自动应用变更 |
AutoCommit | autocommit | auto-commit | 应用后自动提交 git |
AutoContext | autoloadcontext | auto-load-context | 自动查找并加载上下文 |
NoExec | canexec | can-exec | 是否允许执行命令(取反关系) |
AutoDebug | autodebug | auto-debug | 自动调试失败的命令 |
AutoDebugTries | autodebugtries | auto-debug-tries | 自动调试尝试次数 |
注意NoExec在实现中反向表达为CanExec:CLI 执行命令时的--no-execflag 对应!config.CanExec。
3.2 Auto Mode 预设:一键切换自动化程度
为了让 16 个布尔开关不被割裂使用,实现引入AutoModeType预设体系(第 21-46 行),共 6 档:
full:全自动——上下文、应用、执行、调试全部自动;semi(默认值):自动上下文,手动应用与执行;plus:手动上下文但带自动更新与智能加载,手动应用与执行;basic:全手动上下文,手动应用与执行;none:完全手动、逐步执行,一次一个响应;custom:用set-config逐项自定义(任何单项被修改后自动落入此档)。
SetAutoMode(第 128-203 行)一次性批量写入该档位对应的所有字段;而init()(第 491-498 行)将DefaultPlanConfig初始化为AutoModeSemi,同时把AutoModeChoices(形如"Semi Auto → Auto context, manual apply and execution")与AutoModeLabels组装好,供 CLI 交互选择使用。也就是说,任何计划在没有任何显式配置时,默认都是"自动上下文 + 手动应用与执行"的半自动模式。
3.3 完整配置项速查表
最终实现的全部配置键、展示名与含义如下(注册于 ConfigSettingsByKey):
| 配置键 | 展示名 | 类型 | 说明 |
|---|---|---|---|
automode | auto-mode | string | 预设自动化档位 |
editor | editor | string | 首选编辑器 |
autocontinue | auto-continue | bool | 持续迭代直到计划完成 |
autobuild | auto-build | bool | 自动生成待处理的文件编辑 |
autoupdatecontext | auto-update-context | bool | 变更后自动更新上下文 |
autoloadcontext | auto-load-context | bool | 自动查找并加载上下文 |
smartcontext | smart-context | bool | 仅为计划中每个任务加载必要上下文 |
autocommit | auto-commit | bool | 应用后自动提交 git |
skipcommit | skip-commit | bool | 应用后跳过 git 提交 |
autoapply | auto-apply | bool | 计划完成后自动应用变更 |
canexec | can-exec | bool | 允许执行命令 |
autoexec | auto-exec | bool | 应用后自动执行命令 |
autodebug | auto-debug | bool | 自动调试失败的命令 |
autodebugtries | auto-debug-tries | int | 自动调试尝试次数(默认 5) |
autorevert | auto-revert | bool | 回退计划时自动更新项目文件 |
skipchangesmenu | skip-changes-menu | bool | 跳过响应结束且有待处理变更时的交互菜单 |
3.4 配置项之间的联动与约束
从 BoolSetter/IntSetter 实现 可以清楚看到各开关并非相互独立,而是存在强联动:
- 修改任一自动化开关都会把
AutoMode置为custom(前提是新值与旧值不同),保证预设与手工定制不互相污染; - 关闭
autobuild会同时关闭autoapply;开启autoapply会强制开启autobuild; canexec关闭会连带关闭autoexec与autodebug;autoexec开启会强制开启canexec,关闭则连带关闭autodebug;autodebug开启会强制开启canexec与autoexec,且当AutoDebugTries == 0时自动回填默认值defaultAutoDebugTries = 5(第 10 行);autodebugtries设为 0 时等价于关闭autodebug;autoexec、autodebug、autodebugtries均声明了Visible条件(分别要求CanExec、AutoExec、AutoDebug为真),因此config命令的表格展示会随配置状态动态显隐,避免展示无意义的开关。
四、CLI 命令体系:查看与修改配置
4.1config与config default
查看命令实现在 app/cli/cmd/config.go:
plandex config:展示当前计划的配置。要求已解析认证与项目、存在当前计划(否则输出No current plan错误),通过api.Client.GetPlanConfig(lib.CurrentPlanId)拉取后,用表格渲染(见下);plandex config default:展示用户级默认配置,即新计划会继承的模板。
表格渲染由 app/cli/lib/plan_config.go 的ShowPlanConfig完成:列头为Name / Value / Description,按SortKey(automode的 SortKey 为"0"保证排最前,其余按配置键字母序)排序,并过滤掉不满足Visible条件的行,同时可指定key只高亮展示单个配置项。命令执行完毕后还会通过term.PrintCmds给出下一步建议命令,例如:
config default set-config set-config default4.2set-config与set-config default
修改命令实现在 app/cli/cmd/set_config.go,用法为:
plandex set-config [setting] [value] plandex set-config default [setting] [value]设计文档要求"交互提示与用户输入方式沿用set-model的做法,且不引入任何新依赖",实现完全遵循了这一点——全部交互复用term包的SelectFromList、GetRequiredUserStringInput等既有组件:
- 带两个参数:直接以命令行参数更新,如
plandex set-config auto-debug-tries 3、plandex set-config auto-apply enabled; - 带一个参数:指定配置键但省略值,则按配置类型弹交互选择(布尔型弹
Enabled/Disabled,整型提示输入数字,枚举型弹选项列表); - 不带参数:弹出一个按
Name → Desc格式排序列出的配置键选择列表,选中后再按类型进入值输入环节; - 编辑器类配置(
editor):走lib.SelectEditor(false)的选择器;直接传字符串值时会按空白切分为命令 + 参数。
布尔值解析(parseBooleanArg)支持enabled/true/t/yes/y/1与disabled/false/f/no/n/0两组写法。更新成功后输出✅ Config updated,随后以表格展示被修改项,并根据变更结果给出针对性警告:
- 同时开启了自动应用与自动执行:
⚠️ You enabled automatic apply and execution. - 仅开启自动应用或自动执行时分别提示对应警告。
更有趣的是配置变更的副作用:loadMapIfNeeded与removeMapIfNeeded(第 332-378 行)会在开启auto-load-context时自动加载上下文映射(若当前无 map),在关闭时自动清理自动加载的 map,保证配置与上下文状态即时一致。
4.3set-auto:快捷设定自动化档位
实现中还额外提供了 set-auto 命令族(含set-auto default),本质是set-config auto-mode [value]的语法糖,例如plandex set-auto full可一键切换到全自动模式。
4.4 命令建议与帮助
设计文档要求"更新 CLI help 输出并为新命令添加建议"。这体现在:config/config default/set-config/set-config default四条命令在各自的init()中注册进RootCmd(config.go 第 14-17 行、set_config.go 第 19-24 行),且每条命令执行后都会通过term.PrintCmds输出关联建议命令,形成完整的命令发现闭环。
五、服务端实现:API、DB 与路由
5.1 路由注册
设计文档明确要求"服务端新建 API 与 DB handler 文件,而不是塞进既有 plan settings handler"。路由注册位于 app/server/routes/routes.go:
GET /plans/{planId}/config → handlers.GetPlanConfigHandler PUT /plans/{planId}/config → handlers.UpdatePlanConfigHandler GET /default_plan_config → handlers.GetDefaultPlanConfigHandler PUT /default_plan_config → handlers.UpdateDefaultPlanConfigHandler5.2 API Handler
四个 handler 集中在独立的 app/server/handlers/plan_config.go:
- 两个计划级 handler 先经
Authenticate认证、再经authorizePlan校验用户对计划的访问权限,然后委托 DB 层读写plans.plan_config; - 两个默认配置 handler 仅需认证(
Authenticate(w, r, true)),以auth.User.Id作为用户维度主键; - 更新类接口解码
shared.UpdatePlanConfigRequest/shared.UpdateDefaultPlanConfigRequest(请求/响应类型定义在 app/shared/req_res.go 中,如GetPlanConfigResponse{Config}),默认配置更新包在db.WithTx事务中执行。
5.3 DB Helpers
DB 层独立文件 app/server/db/plan_config_helpers.go 提供四个函数(第 11-65 行):
GetPlanConfig(planId):SELECT plan_config FROM plans WHERE id = $1;StorePlanConfig(planId, config):UPDATE plans SET plan_config = $1 WHERE id = $2;GetDefaultPlanConfig(userId):SELECT default_plan_config FROM users WHERE id = $1;StoreDefaultPlanConfig(userId, config, tx):带事务的UPDATE users ...。
由于PlanConfig实现了driver.Valuer,$1参数直接传入结构体即可自动 JSON 序列化,无需手工编解码。
5.4 CLI API 客户端
客户端接口与实现在 app/cli/api/methods.go:GetPlanConfig/UpdatePlanConfig/GetDefaultPlanConfig/UpdateDefaultPlanConfig四个方法,统一走authenticatedFastClient,并在遇到鉴权过期错误时通过refreshAuthIfNeeded刷新后自动重试。
六、配置如何驱动命令执行:默认值 + flags 覆盖
设计文档要求"更新tell、continue、build、chat命令,让它们默认使用配置设置(可被既有 flags 覆盖)"。这一要求落地为 app/cli/cmd/plan_exec_helpers.go 中的mustSetPlanExecFlags(第 158-219 行),它在tell/continue/build等命令执行前被调用,核心逻辑是:
config := lib.MustGetCurrentPlanConfig() if !cmd.Flags().Changed("stop") { tellStop = !config.AutoContinue } if !cmd.Flags().Changed("no-build") { tellNoBuild = !config.AutoBuild } if !cmd.Flags().Changed("auto-update-context") { autoConfirm = config.AutoUpdateContext } if !cmd.Flags().Changed("apply") { tellAutoApply = config.AutoApply } if !cmd.Flags().Changed("skip-commit") { skipCommit = config.SkipCommit } if !cmd.Flags().Changed("commit") { autoCommit = config.AutoCommit } if !cmd.Flags().Changed("auto-load-context") { tellAutoContext = config.AutoLoadContext } if !cmd.Flags().Changed("smart-context") { tellSmartContext = config.SmartContext } if !cmd.Flags().Changed("no-exec") { noExec = !config.CanExec } if !cmd.Flags().Changed("auto-exec") { autoExec = config.AutoExec } if !cmd.Flags().Changed("debug") { autoDebug = config.AutoDebugTries } if !cmd.Flags().Changed("skip-menu") { tellSkipMenu = config.SkipChangesMenu }可以提炼出的优先级规则是:显式传入的 flag 永远优先;只有 flag 未被设置时,才回退到配置值。例如配置了auto-debug后,直接运行plandex tell "..."就会自动尝试调试失败命令(最多auto-debug-tries次),而--debug 0或--no-debug可以临时关闭。此外,editor配置仅在值为vim/nano时被tell命令读取(其余情况以 flag 或EDITOR环境变量为准)。配置在 CLI 侧由 app/cli/lib/plan_config.go 的MustGetCurrentPlanConfig获取并做进程内缓存,SetCachedPlanConfig可在set-config更新后刷新缓存。
这些 flag 变量随后被apply.go、build.go、continue.go、chat.go等命令构造的TellPlanRequest/BuildPlanRequest使用(如 app/cli/cmd/apply.go 的AutoApply: tellAutoApply, AutoDebug: autoDebug),最终影响服务端执行流程的自动化程度。
七、new命令:创建计划即展示默认配置
设计文档要求"new命令在计划创建后,以类似config命令的友好格式展示默认设置"。实现在 app/cli/cmd/new.go:new通过两个 goroutine 并发执行"创建计划"与"拉取默认配置"(api.Client.GetDefaultPlanConfig()),两者都成功后输出:
✅ Started new plan <name> and set it to current plan ⚙️ Using default config随后resolveAutoMode(config)根据默认配置的AutoMode与AutoLoadContext等字段决定后续行为(例如自动加载上下文映射),并按配置展示对应的建议命令(tell/chat/config或config/plans/cd/models)。这使用户在新建计划的第一时间就能看到自己将默认以何种自动化程度工作。
八、设计文档与落地实现对照总览
| 设计文档要求(app/plans/plan-config.md) | 落地实现 |
|---|---|
plans表新增plan_configJSON 字段 | 2024121400_plan_config.up.sql |
用户级默认配置(set default) | users.default_plan_config列 +config default/set-config default |
settings/set新命令(独立文件) | 最终命名为 config.go 与 set_config.go(另附set-auto) |
| 初始 6 个属性 | 映射为 16 个配置键 +auto-mode预设(见上文速查表) |
| 服务端独立 API/DB handler 文件 | handlers/plan_config.go + db/plan_config_helpers.go |
| 客户端 API 接口与实现 | app/cli/api/methods.go |
tell/continue/build/chat默认读配置、flags 可覆盖 | plan_exec_helpers.go 的mustSetPlanExecFlags |
new命令展示默认设置 | new.go |
| 不落文件系统、不用 git,纯 DB 存储 | PlanConfig实现sql.Scanner/driver.Valuer,仅与plans/users表交互 |
至此,从一份功能设计文档出发,plandex 的 Plan Config 特性已经形成了"数据库 JSON 字段 → 共享结构体与配置注册表 → CLI 查看/修改命令 → API 路由与 DB helpers → 执行命令默认值消费"的完整闭环。理解这条链路后,无论是为团队统一默认自动化策略(set-config default),还是为单个计划定制精细的调试/执行行为(set-config+set-auto),你都可以做到心中有数、按需取用。
【免费下载链接】plandexOpen source AI coding agent. Designed for large projects and real world tasks.项目地址: https://gitcode.com/GitHub_Trending/pl/plandex
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考