@andyqiu/codeforge 0.3.10 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -3
- package/agents/codeforge.md +35 -1
- package/agents/coder-deep.md +93 -0
- package/agents/coder-quick.md +92 -0
- package/agents/coder.md +5 -4
- package/agents/planner.md +1 -0
- package/agents/reviewer.md +1 -0
- package/codeforge.json +28 -2
- package/commands/deep.md +87 -0
- package/commands/quick.md +92 -0
- package/dist/index.js +532 -65
- package/install.sh +8 -0
- package/package.json +1 -1
- package/schemas/codeforge.schema.json +230 -224
- package/scripts/sync-agent-models.mjs +22 -3
package/install.sh
CHANGED
|
@@ -553,6 +553,14 @@ else
|
|
|
553
553
|
ok "项目级安装,跳过用户级 default_agent 配置(要装请加 --global)"
|
|
554
554
|
fi
|
|
555
555
|
|
|
556
|
+
# 如果是 CodeForge 开发仓库本身,重新生成 dev shim(install 会清掉 .opencode/plugins/)
|
|
557
|
+
# ADR-0055:本仓库内 opencode 加载本项目 dist/ 而非全局 stable,依赖 dev shim 让位
|
|
558
|
+
if [ -f ".codeforge/.dev-marker" ] && [ -f "scripts/dev-sync.mjs" ]; then
|
|
559
|
+
node scripts/dev-sync.mjs --no-build 2>/dev/null || true
|
|
560
|
+
echo " ↳ dev shim regenerated (.opencode/plugins/codeforge-dev.js)"
|
|
561
|
+
fi
|
|
562
|
+
|
|
563
|
+
|
|
556
564
|
# 验证清单
|
|
557
565
|
hr
|
|
558
566
|
ok "${C_BOLD}CodeForge v${CF_VERSION} 安装完成${C_RESET}"
|
package/package.json
CHANGED
|
@@ -1,224 +1,230 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"$id": "https://codeforge/schemas/codeforge.schema.json",
|
|
4
|
-
"title": "CodeForge Configuration",
|
|
5
|
-
"description": "Single source of truth for CodeForge: agent ↔ model mapping + global runtime preferences.",
|
|
6
|
-
"type": "object",
|
|
7
|
-
"additionalProperties": true,
|
|
8
|
-
"properties": {
|
|
9
|
-
"$schema": { "type": "string" },
|
|
10
|
-
"_doc": { "type": "string" },
|
|
11
|
-
|
|
12
|
-
"models": {
|
|
13
|
-
"type": "object",
|
|
14
|
-
"description": "Agent ↔ model bindings + reusable categories + runtime fallback policy. Synced to agents/*.md frontmatter via `npm run sync:models`.",
|
|
15
|
-
"required": ["agents"],
|
|
16
|
-
"additionalProperties": true,
|
|
17
|
-
"properties": {
|
|
18
|
-
"_doc": { "type": "string" },
|
|
19
|
-
"default": {
|
|
20
|
-
"$ref": "#/$defs/ProviderModelId",
|
|
21
|
-
"description": "Fallback for any agent that omits `model` and is not bound by category."
|
|
22
|
-
},
|
|
23
|
-
"agents": {
|
|
24
|
-
"type": "object",
|
|
25
|
-
"description": "Per-agent model binding. Key = agent name (matches agents/<name>.md).",
|
|
26
|
-
"patternProperties": {
|
|
27
|
-
"^[a-z][a-z0-9-]*$": { "$ref": "#/$defs/AgentBinding" }
|
|
28
|
-
},
|
|
29
|
-
"additionalProperties": false,
|
|
30
|
-
"minProperties": 1
|
|
31
|
-
},
|
|
32
|
-
"categories": {
|
|
33
|
-
"type": "object",
|
|
34
|
-
"description": "Reusable model presets shared by multiple agents.",
|
|
35
|
-
"patternProperties": {
|
|
36
|
-
"^[a-z][a-z0-9-]*$": { "$ref": "#/$defs/CategoryBinding" }
|
|
37
|
-
},
|
|
38
|
-
"additionalProperties": false
|
|
39
|
-
},
|
|
40
|
-
"runtime_fallback": {
|
|
41
|
-
"type": "object",
|
|
42
|
-
"description": "Behavior of plugins/model-fallback.ts when primary model fails.",
|
|
43
|
-
"additionalProperties": true,
|
|
44
|
-
"properties": {
|
|
45
|
-
"enabled": { "type": "boolean", "default": true },
|
|
46
|
-
"max_fallback_attempts": { "type": "integer", "minimum": 1, "default": 3 },
|
|
47
|
-
"notify_on_fallback": { "type": "boolean", "default": true },
|
|
48
|
-
"trigger_events": {
|
|
49
|
-
"type": "array",
|
|
50
|
-
"items": { "type": "string" },
|
|
51
|
-
"default": ["session.error", "model.unavailable", "model.rate_limited"]
|
|
52
|
-
},
|
|
53
|
-
"_doc": { "type": "string" }
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
"autonomy": {
|
|
60
|
-
"type": "object",
|
|
61
|
-
"description": "三档自主度默认(AGENTS.md C18)。命令行 --mode 优先生效。",
|
|
62
|
-
"additionalProperties": false,
|
|
63
|
-
"properties": {
|
|
64
|
-
"_doc": { "type": "string" },
|
|
65
|
-
"default_mode": {
|
|
66
|
-
"type": "string",
|
|
67
|
-
"enum": ["step", "semi", "full"],
|
|
68
|
-
"default": "semi",
|
|
69
|
-
"description": "step=每步确认 / semi=危险工具确认 / full=全自动(强制 worktree)"
|
|
70
|
-
},
|
|
71
|
-
"downgrade_on_risky": {
|
|
72
|
-
"type": "boolean",
|
|
73
|
-
"default": true,
|
|
74
|
-
"description": "检测到破坏性命令是否自动降级到 semi(不可关)"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
"runtime": {
|
|
80
|
-
"type": "object",
|
|
81
|
-
"description": "全局运行时安全开关(v1 占位;写入但 plugin 默认仍为 hardcoded 安全值,下个版本接入)",
|
|
82
|
-
"additionalProperties": false,
|
|
83
|
-
"properties": {
|
|
84
|
-
"_doc": { "type": "string" },
|
|
85
|
-
"worktree_isolation": {
|
|
86
|
-
"type": "boolean",
|
|
87
|
-
"default": true,
|
|
88
|
-
"description": "subtasks 在独立 worktree 跑(C22)。v1:subtasks plugin 已默认开,此字段暂未读取。"
|
|
89
|
-
},
|
|
90
|
-
"workspace_snapshot": {
|
|
91
|
-
"type": "boolean",
|
|
92
|
-
"default": true,
|
|
93
|
-
"description": "每步前对工作区做 shadow git 快照。v1:plugin 已默认开,此字段暂未读取。"
|
|
94
|
-
},
|
|
95
|
-
"auto_commit": {
|
|
96
|
-
"type": "boolean",
|
|
97
|
-
"default": false,
|
|
98
|
-
"description": "step 完成后自动 commit(C23)。v1:plugin 已默认开,此字段暂未读取。"
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
"tools": {
|
|
104
|
-
"type": "object",
|
|
105
|
-
"description": "工具开关(已接 plugins/codeforge-tools.ts)",
|
|
106
|
-
"additionalProperties": false,
|
|
107
|
-
"properties": {
|
|
108
|
-
"_doc": { "type": "string" },
|
|
109
|
-
"browser": {
|
|
110
|
-
"type": "object",
|
|
111
|
-
"additionalProperties": false,
|
|
112
|
-
"properties": {
|
|
113
|
-
"enabled": {
|
|
114
|
-
"type": "boolean",
|
|
115
|
-
"default": false,
|
|
116
|
-
"description": "Browser Control 工具开关(AGENTS.md C20 默认禁用)。开启会注册 6 个 browser_* 工具。"
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
"context": {
|
|
124
|
-
"type": "object",
|
|
125
|
-
"description": "Implicit Reasoning + Condenser(已接 plugins/token-manager.ts)",
|
|
126
|
-
"additionalProperties": false,
|
|
127
|
-
"properties": {
|
|
128
|
-
"_doc": { "type": "string" },
|
|
129
|
-
"condenser_threshold_ratio": {
|
|
130
|
-
"type": "number",
|
|
131
|
-
"minimum": 0.1,
|
|
132
|
-
"maximum": 0.95,
|
|
133
|
-
"default": 0.7,
|
|
134
|
-
"description": "Token 使用率超过此比例自动压缩上下文。"
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
"update": {
|
|
140
|
-
"type": "object",
|
|
141
|
-
"description": "自动更新检查(已接 plugins/update-checker.ts)。仿 oh-my-opencode:opencode 启动时后台拉 GitHub Releases,发现新版只通知不自动重装。",
|
|
142
|
-
"additionalProperties": false,
|
|
143
|
-
"properties": {
|
|
144
|
-
"_doc": { "type": "string" },
|
|
145
|
-
"auto_check_enabled": {
|
|
146
|
-
"type": "boolean",
|
|
147
|
-
"default": true,
|
|
148
|
-
"description": "是否启用启动时自动检查"
|
|
149
|
-
},
|
|
150
|
-
"interval_hours": {
|
|
151
|
-
"type": "integer",
|
|
152
|
-
"minimum": 1,
|
|
153
|
-
"maximum": 720,
|
|
154
|
-
"default": 24,
|
|
155
|
-
"description": "两次检查之间的最短间隔(小时)。命中缓存就不打 GitHub API。"
|
|
156
|
-
},
|
|
157
|
-
"repo": {
|
|
158
|
-
"type": "string",
|
|
159
|
-
"pattern": "^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$",
|
|
160
|
-
"default": "andy-personal/code-forge",
|
|
161
|
-
"description": "GitHub 仓库 <owner>/<repo>,私仓需要 GITHUB_TOKEN 环境变量"
|
|
162
|
-
},
|
|
163
|
-
"channel": {
|
|
164
|
-
"type": "string",
|
|
165
|
-
"enum": ["stable", "prerelease"],
|
|
166
|
-
"default": "stable",
|
|
167
|
-
"description": "stable=只看 latest release;prerelease=允许 pre-release(v1 仅声明,未实现)"
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
"$defs": {
|
|
175
|
-
"ProviderModelId": {
|
|
176
|
-
"type": "string",
|
|
177
|
-
"pattern": "^[a-z0-9-]+/[a-zA-Z0-9._-]+$",
|
|
178
|
-
"description": "Format: <provider>/<model-id>, e.g. anthropic/claude-opus-4-7"
|
|
179
|
-
},
|
|
180
|
-
"Thinking": {
|
|
181
|
-
"type": "object",
|
|
182
|
-
"additionalProperties": true,
|
|
183
|
-
"properties": {
|
|
184
|
-
"type": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
185
|
-
"budget_tokens": { "type": "integer", "minimum": 0 }
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
"AgentBinding": {
|
|
189
|
-
"type": "object",
|
|
190
|
-
"required": ["model"],
|
|
191
|
-
"additionalProperties": false,
|
|
192
|
-
"properties": {
|
|
193
|
-
"model": { "$ref": "#/$defs/ProviderModelId" },
|
|
194
|
-
"variant": { "type": "string" },
|
|
195
|
-
"category": { "type": "string" },
|
|
196
|
-
"
|
|
197
|
-
|
|
198
|
-
"
|
|
199
|
-
"
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
},
|
|
203
|
-
"
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
},
|
|
220
|
-
"
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://codeforge/schemas/codeforge.schema.json",
|
|
4
|
+
"title": "CodeForge Configuration",
|
|
5
|
+
"description": "Single source of truth for CodeForge: agent ↔ model mapping + global runtime preferences.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": true,
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": { "type": "string" },
|
|
10
|
+
"_doc": { "type": "string" },
|
|
11
|
+
|
|
12
|
+
"models": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"description": "Agent ↔ model bindings + reusable categories + runtime fallback policy. Synced to agents/*.md frontmatter via `npm run sync:models`.",
|
|
15
|
+
"required": ["agents"],
|
|
16
|
+
"additionalProperties": true,
|
|
17
|
+
"properties": {
|
|
18
|
+
"_doc": { "type": "string" },
|
|
19
|
+
"default": {
|
|
20
|
+
"$ref": "#/$defs/ProviderModelId",
|
|
21
|
+
"description": "Fallback for any agent that omits `model` and is not bound by category."
|
|
22
|
+
},
|
|
23
|
+
"agents": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"description": "Per-agent model binding. Key = agent name (matches agents/<name>.md).",
|
|
26
|
+
"patternProperties": {
|
|
27
|
+
"^[a-z][a-z0-9-]*$": { "$ref": "#/$defs/AgentBinding" }
|
|
28
|
+
},
|
|
29
|
+
"additionalProperties": false,
|
|
30
|
+
"minProperties": 1
|
|
31
|
+
},
|
|
32
|
+
"categories": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"description": "Reusable model presets shared by multiple agents.",
|
|
35
|
+
"patternProperties": {
|
|
36
|
+
"^[a-z][a-z0-9-]*$": { "$ref": "#/$defs/CategoryBinding" }
|
|
37
|
+
},
|
|
38
|
+
"additionalProperties": false
|
|
39
|
+
},
|
|
40
|
+
"runtime_fallback": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"description": "Behavior of plugins/model-fallback.ts when primary model fails.",
|
|
43
|
+
"additionalProperties": true,
|
|
44
|
+
"properties": {
|
|
45
|
+
"enabled": { "type": "boolean", "default": true },
|
|
46
|
+
"max_fallback_attempts": { "type": "integer", "minimum": 1, "default": 3 },
|
|
47
|
+
"notify_on_fallback": { "type": "boolean", "default": true },
|
|
48
|
+
"trigger_events": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": { "type": "string" },
|
|
51
|
+
"default": ["session.error", "model.unavailable", "model.rate_limited"]
|
|
52
|
+
},
|
|
53
|
+
"_doc": { "type": "string" }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
"autonomy": {
|
|
60
|
+
"type": "object",
|
|
61
|
+
"description": "三档自主度默认(AGENTS.md C18)。命令行 --mode 优先生效。",
|
|
62
|
+
"additionalProperties": false,
|
|
63
|
+
"properties": {
|
|
64
|
+
"_doc": { "type": "string" },
|
|
65
|
+
"default_mode": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"enum": ["step", "semi", "full"],
|
|
68
|
+
"default": "semi",
|
|
69
|
+
"description": "step=每步确认 / semi=危险工具确认 / full=全自动(强制 worktree)"
|
|
70
|
+
},
|
|
71
|
+
"downgrade_on_risky": {
|
|
72
|
+
"type": "boolean",
|
|
73
|
+
"default": true,
|
|
74
|
+
"description": "检测到破坏性命令是否自动降级到 semi(不可关)"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
"runtime": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"description": "全局运行时安全开关(v1 占位;写入但 plugin 默认仍为 hardcoded 安全值,下个版本接入)",
|
|
82
|
+
"additionalProperties": false,
|
|
83
|
+
"properties": {
|
|
84
|
+
"_doc": { "type": "string" },
|
|
85
|
+
"worktree_isolation": {
|
|
86
|
+
"type": "boolean",
|
|
87
|
+
"default": true,
|
|
88
|
+
"description": "subtasks 在独立 worktree 跑(C22)。v1:subtasks plugin 已默认开,此字段暂未读取。"
|
|
89
|
+
},
|
|
90
|
+
"workspace_snapshot": {
|
|
91
|
+
"type": "boolean",
|
|
92
|
+
"default": true,
|
|
93
|
+
"description": "每步前对工作区做 shadow git 快照。v1:plugin 已默认开,此字段暂未读取。"
|
|
94
|
+
},
|
|
95
|
+
"auto_commit": {
|
|
96
|
+
"type": "boolean",
|
|
97
|
+
"default": false,
|
|
98
|
+
"description": "step 完成后自动 commit(C23)。v1:plugin 已默认开,此字段暂未读取。"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
"tools": {
|
|
104
|
+
"type": "object",
|
|
105
|
+
"description": "工具开关(已接 plugins/codeforge-tools.ts)",
|
|
106
|
+
"additionalProperties": false,
|
|
107
|
+
"properties": {
|
|
108
|
+
"_doc": { "type": "string" },
|
|
109
|
+
"browser": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"additionalProperties": false,
|
|
112
|
+
"properties": {
|
|
113
|
+
"enabled": {
|
|
114
|
+
"type": "boolean",
|
|
115
|
+
"default": false,
|
|
116
|
+
"description": "Browser Control 工具开关(AGENTS.md C20 默认禁用)。开启会注册 6 个 browser_* 工具。"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
"context": {
|
|
124
|
+
"type": "object",
|
|
125
|
+
"description": "Implicit Reasoning + Condenser(已接 plugins/token-manager.ts)",
|
|
126
|
+
"additionalProperties": false,
|
|
127
|
+
"properties": {
|
|
128
|
+
"_doc": { "type": "string" },
|
|
129
|
+
"condenser_threshold_ratio": {
|
|
130
|
+
"type": "number",
|
|
131
|
+
"minimum": 0.1,
|
|
132
|
+
"maximum": 0.95,
|
|
133
|
+
"default": 0.7,
|
|
134
|
+
"description": "Token 使用率超过此比例自动压缩上下文。"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
"update": {
|
|
140
|
+
"type": "object",
|
|
141
|
+
"description": "自动更新检查(已接 plugins/update-checker.ts)。仿 oh-my-opencode:opencode 启动时后台拉 GitHub Releases,发现新版只通知不自动重装。",
|
|
142
|
+
"additionalProperties": false,
|
|
143
|
+
"properties": {
|
|
144
|
+
"_doc": { "type": "string" },
|
|
145
|
+
"auto_check_enabled": {
|
|
146
|
+
"type": "boolean",
|
|
147
|
+
"default": true,
|
|
148
|
+
"description": "是否启用启动时自动检查"
|
|
149
|
+
},
|
|
150
|
+
"interval_hours": {
|
|
151
|
+
"type": "integer",
|
|
152
|
+
"minimum": 1,
|
|
153
|
+
"maximum": 720,
|
|
154
|
+
"default": 24,
|
|
155
|
+
"description": "两次检查之间的最短间隔(小时)。命中缓存就不打 GitHub API。"
|
|
156
|
+
},
|
|
157
|
+
"repo": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"pattern": "^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$",
|
|
160
|
+
"default": "andy-personal/code-forge",
|
|
161
|
+
"description": "GitHub 仓库 <owner>/<repo>,私仓需要 GITHUB_TOKEN 环境变量"
|
|
162
|
+
},
|
|
163
|
+
"channel": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"enum": ["stable", "prerelease"],
|
|
166
|
+
"default": "stable",
|
|
167
|
+
"description": "stable=只看 latest release;prerelease=允许 pre-release(v1 仅声明,未实现)"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
"$defs": {
|
|
175
|
+
"ProviderModelId": {
|
|
176
|
+
"type": "string",
|
|
177
|
+
"pattern": "^[a-z0-9-]+/[a-zA-Z0-9._-]+$",
|
|
178
|
+
"description": "Format: <provider>/<model-id>, e.g. anthropic/claude-opus-4-7"
|
|
179
|
+
},
|
|
180
|
+
"Thinking": {
|
|
181
|
+
"type": "object",
|
|
182
|
+
"additionalProperties": true,
|
|
183
|
+
"properties": {
|
|
184
|
+
"type": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
185
|
+
"budget_tokens": { "type": "integer", "minimum": 0 }
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
"AgentBinding": {
|
|
189
|
+
"type": "object",
|
|
190
|
+
"required": ["model"],
|
|
191
|
+
"additionalProperties": false,
|
|
192
|
+
"properties": {
|
|
193
|
+
"model": { "$ref": "#/$defs/ProviderModelId" },
|
|
194
|
+
"variant": { "type": "string" },
|
|
195
|
+
"category": { "type": "string" },
|
|
196
|
+
"tier": {
|
|
197
|
+
"type": "string",
|
|
198
|
+
"enum": ["quick", "balanced", "deep", "ultra"],
|
|
199
|
+
"description": "任务难度档位,与 lib/model-tier.ts 的 TierLevel 对应"
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
"thinking": { "$ref": "#/$defs/Thinking" },
|
|
203
|
+
"fallback_models": {
|
|
204
|
+
"type": "array",
|
|
205
|
+
"items": { "$ref": "#/$defs/ProviderModelId" },
|
|
206
|
+
"uniqueItems": true,
|
|
207
|
+
"default": []
|
|
208
|
+
},
|
|
209
|
+
"_doc": { "type": "string" }
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
"CategoryBinding": {
|
|
213
|
+
"type": "object",
|
|
214
|
+
"required": ["model"],
|
|
215
|
+
"additionalProperties": false,
|
|
216
|
+
"properties": {
|
|
217
|
+
"model": { "$ref": "#/$defs/ProviderModelId" },
|
|
218
|
+
"variant": { "type": "string" },
|
|
219
|
+
"thinking": { "$ref": "#/$defs/Thinking" },
|
|
220
|
+
"fallback_models": {
|
|
221
|
+
"type": "array",
|
|
222
|
+
"items": { "$ref": "#/$defs/ProviderModelId" },
|
|
223
|
+
"uniqueItems": true,
|
|
224
|
+
"default": []
|
|
225
|
+
},
|
|
226
|
+
"_doc": { "type": "string" }
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -7,12 +7,19 @@
|
|
|
7
7
|
* 行为:
|
|
8
8
|
* - 对每个 agent:
|
|
9
9
|
* * 找不到 agents/<name>.md → 报警告(不创建)
|
|
10
|
-
* * 找到 → 在 frontmatter 中写入/更新:model / fallback_models / category / thinking
|
|
10
|
+
* * 找到 → 在 frontmatter 中写入/更新:model / fallback_models / category / thinking / tier
|
|
11
11
|
* * 删除老字段 preferred_model(统一改名为 model,对齐 opencode 标准)
|
|
12
12
|
* - --check 模式:只校验,不写盘;任何漂移则 exit(1)
|
|
13
13
|
* - --dry 模式:打印会改什么,不写盘
|
|
14
14
|
*
|
|
15
|
-
* 设计原则:保留 frontmatter
|
|
15
|
+
* 设计原则:保留 frontmatter 中其他字段不动,仅替换目标 key。
|
|
16
|
+
*
|
|
17
|
+
* 关于 tier:
|
|
18
|
+
* - tier 是 ADR-0060 模型难度分级字段(quick / balanced / deep / ultra)
|
|
19
|
+
* - 变体 agent(名字含 -quick / -deep / -ultra 后缀)不在 codeforge.json 的 agents 里,
|
|
20
|
+
* 本脚本只同步 base agent;变体由人工维护或后续 sync 脚本扩展生成。
|
|
21
|
+
* - 当 codeforge.json 未声明 tier 时,保留 .md 中现有 tier 值(不删),
|
|
22
|
+
* 避免变体 agent 的 tier 在 sync 时被静默清除。
|
|
16
23
|
*/
|
|
17
24
|
|
|
18
25
|
import { promises as fs } from "node:fs"
|
|
@@ -28,7 +35,7 @@ const CONFIG_FILE = "codeforge.json"
|
|
|
28
35
|
const CONFIG_PATH = path.join(ROOT, CONFIG_FILE)
|
|
29
36
|
const AGENTS_DIR = path.join(ROOT, "agents")
|
|
30
37
|
|
|
31
|
-
const TARGET_KEYS = ["model", "fallback_models", "model_category", "model_thinking"]
|
|
38
|
+
const TARGET_KEYS = ["model", "fallback_models", "model_category", "model_thinking", "tier"]
|
|
32
39
|
const REMOVE_KEYS = ["preferred_model"]
|
|
33
40
|
|
|
34
41
|
async function main() {
|
|
@@ -108,6 +115,13 @@ function applyToMarkdown(text, agentCfg) {
|
|
|
108
115
|
|
|
109
116
|
const lines = fmRaw.split(/\r?\n/)
|
|
110
117
|
|
|
118
|
+
// 在删除前先解析现有 frontmatter 里的 tier 值(顶层 key,单行)。
|
|
119
|
+
// 用途:当 codeforge.json 未声明 tier 时(如变体 agent),保留 .md 中已有 tier,
|
|
120
|
+
// 避免被本次 sync 静默清除。
|
|
121
|
+
const existingTier = lines
|
|
122
|
+
.map((line) => line.match(/^tier\s*:\s*(.+?)\s*$/)?.[1]?.trim())
|
|
123
|
+
.find(Boolean)
|
|
124
|
+
|
|
111
125
|
// 删除目标 + REMOVE_KEYS。
|
|
112
126
|
// 关键:YAML 子结构(list/object)以「行首空白」为续行标志;
|
|
113
127
|
// 一旦遇到下一个顶层 key(行首非空白且不是注释/空行)就结束 skipping。
|
|
@@ -134,9 +148,14 @@ function applyToMarkdown(text, agentCfg) {
|
|
|
134
148
|
// 末尾保证空行清洁
|
|
135
149
|
while (stripped.length > 0 && stripped[stripped.length - 1].trim() === "") stripped.pop()
|
|
136
150
|
|
|
151
|
+
// tier 写入策略:优先用 agentCfg.tier(codeforge.json 声明),
|
|
152
|
+
// 否则 fallback 到 .md 中现有 tier;都没有就不写(保持空)。
|
|
153
|
+
const tier = typeof agentCfg.tier === "string" ? agentCfg.tier : existingTier
|
|
154
|
+
|
|
137
155
|
const newLines = []
|
|
138
156
|
newLines.push(`model: ${agentCfg.model}`)
|
|
139
157
|
if (agentCfg.category) newLines.push(`model_category: ${agentCfg.category}`)
|
|
158
|
+
if (tier) newLines.push(`tier: ${tier}`)
|
|
140
159
|
if (agentCfg.thinking) {
|
|
141
160
|
newLines.push(`model_thinking:`)
|
|
142
161
|
newLines.push(` type: ${agentCfg.thinking.type}`)
|