@andyqiu/codeforge 0.3.7 → 0.3.9

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/install.sh CHANGED
@@ -155,6 +155,96 @@ opencode_cfg_path() {
155
155
  echo "$TARGET_ROOT/opencode.json"
156
156
  }
157
157
 
158
+ # 配置默认 agent → codeforge(ADR-0056 D5 / D2 实施细节)
159
+ #
160
+ # 在 ~/.config/opencode/opencode.json 顶层幂等合并 "default_agent": "codeforge"。
161
+ # 行为规则:
162
+ # - 字段不存在 → 写入 codeforge
163
+ # - 字段已是 codeforge → unchanged
164
+ # - 字段为其他值(用户自配) → 跳过不动 + 打 warn(绝不覆盖用户配置)
165
+ # 仅在 MODE=user/global 调用(项目级配置由用户自己管,不动)。
166
+ # 失败不阻塞 install 主流程(warn + return 0)。
167
+ # 用 node 处理 JSON(避免 sed/awk 处理 JSON 转义边界)。
168
+ configure_default_agent() {
169
+ local opencode_json="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/opencode.json"
170
+ local target_agent="codeforge"
171
+
172
+ if [[ ! -f "$opencode_json" ]]; then
173
+ warn "opencode.json 不存在,跳过 default_agent 配置(首次安装 opencode 后请手动重跑 codeforge install)"
174
+ return 0
175
+ fi
176
+
177
+ if ! command -v node >/dev/null 2>&1; then
178
+ warn "未找到 node,跳过 default_agent 配置(请安装 Node.js >= 20 后重跑 install)"
179
+ return 0
180
+ fi
181
+
182
+ if [[ $DRY_RUN -eq 1 ]]; then
183
+ printf " ${C_BLUE}[dry-run]${C_RESET} configure default_agent=%s in %s\n" "$target_agent" "$opencode_json"
184
+ return 0
185
+ fi
186
+
187
+ local result
188
+ result=$(CFG="$opencode_json" TARGET="$target_agent" node -e '
189
+ const fs = require("node:fs");
190
+ const path = process.env.CFG;
191
+ const target = process.env.TARGET;
192
+ let cfg;
193
+ try { cfg = JSON.parse(fs.readFileSync(path, "utf8")); }
194
+ catch (e) { console.log("ERROR: " + e.message); process.exit(0); }
195
+ const current = cfg.default_agent;
196
+ if (current === undefined) {
197
+ cfg.default_agent = target;
198
+ fs.writeFileSync(path, JSON.stringify(cfg, null, 2) + "\n", "utf8");
199
+ console.log("SET default_agent=" + target);
200
+ } else if (current === target) {
201
+ console.log("UNCHANGED (already " + target + ")");
202
+ } else {
203
+ console.log("SKIPPED: user has default_agent=\"" + current + "\", not touching");
204
+ }
205
+ ' 2>&1) || {
206
+ warn "default_agent 配置失败(不阻塞 install 主流程)"
207
+ return 0
208
+ }
209
+ ok "default_agent: $result"
210
+ }
211
+
212
+ # 卸载时还原 default_agent(仅当当前值是 codeforge 时移除字段)。
213
+ # 用户改成其他值的不动。
214
+ restore_default_agent() {
215
+ local opencode_json="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/opencode.json"
216
+ if [[ ! -f "$opencode_json" ]]; then
217
+ return 0
218
+ fi
219
+ if ! command -v node >/dev/null 2>&1; then
220
+ warn "未找到 node,跳过 default_agent 卸载还原"
221
+ return 0
222
+ fi
223
+ if [[ $DRY_RUN -eq 1 ]]; then
224
+ printf " ${C_BLUE}[dry-run]${C_RESET} restore default_agent in %s (remove if codeforge)\n" "$opencode_json"
225
+ return 0
226
+ fi
227
+
228
+ local result
229
+ result=$(CFG="$opencode_json" node -e '
230
+ const fs = require("node:fs");
231
+ const path = process.env.CFG;
232
+ let cfg;
233
+ try { cfg = JSON.parse(fs.readFileSync(path, "utf8")); }
234
+ catch { process.exit(0); }
235
+ if (cfg.default_agent === "codeforge") {
236
+ delete cfg.default_agent;
237
+ fs.writeFileSync(path, JSON.stringify(cfg, null, 2) + "\n", "utf8");
238
+ console.log("REMOVED default_agent (was codeforge)");
239
+ } else if (cfg.default_agent !== undefined) {
240
+ console.log("SKIPPED: default_agent=\"" + cfg.default_agent + "\" not set by codeforge");
241
+ } else {
242
+ console.log("NOOP (no default_agent)");
243
+ }
244
+ ' 2>&1) || return 0
245
+ ok "default_agent: $result"
246
+ }
247
+
158
248
  # 写 ~/.config/codeforge/kh.json 模板(仅 --global 调用)
159
249
  #
160
250
  # 硬约束 #2:API key 绝不能落盘,模板里**不写** token / apiKey 字段。
@@ -293,6 +383,10 @@ remove_plugin_entry() {
293
383
  uninstall() {
294
384
  log "卸载 CodeForge from: $TARGET_ROOT"
295
385
  remove_plugin_entry
386
+ # 还原 default_agent(仅 user/global mode;project mode 不动用户级配置)
387
+ if [[ "$MODE" != "project" ]]; then
388
+ restore_default_agent
389
+ fi
296
390
  for name in "${LEGACY_DIRS[@]}" "${MANAGED_DIRS[@]}"; do
297
391
  local p="$TARGET_ROOT/$name"
298
392
  if [[ -e "$p" || -L "$p" ]]; then
@@ -338,13 +432,13 @@ if [[ "$ACTION" == "uninstall" ]]; then
338
432
  exit 0
339
433
  fi
340
434
 
341
- # Step 1/7: 环境检测
342
- log "Step 1/7: 环境检测"
435
+ # Step 1/8: 环境检测
436
+ log "Step 1/8: 环境检测"
343
437
  detect_opencode
344
438
  detect_kh_mcp
345
439
 
346
- # Step 2/7: build dist bundle
347
- log "Step 2/7: 构建 dist/index.js 单 bundle"
440
+ # Step 2/8: build dist bundle
441
+ log "Step 2/8: 构建 dist/index.js 单 bundle"
348
442
  BUNDLE_SRC="$SOURCE_ROOT/$BUNDLE_SRC_REL"
349
443
  if [[ $SKIP_BUILD -eq 1 ]]; then
350
444
  warn "已跳过 build(--skip-build),使用现有 dist/index.js"
@@ -369,8 +463,8 @@ if [[ -f "$BUNDLE_SRC" ]]; then
369
463
  ok "bundle 已就绪: $BUNDLE_SRC (${size} bytes)"
370
464
  fi
371
465
 
372
- # Step 3/7: 准备目录 + 清理 legacy
373
- log "Step 3/7: 准备目标目录 + 清理 legacy 注入物"
466
+ # Step 3/8: 准备目录 + 清理 legacy
467
+ log "Step 3/8: 准备目标目录 + 清理 legacy 注入物"
374
468
  ensure_dir "$TARGET_ROOT"
375
469
  for legacy in "${LEGACY_DIRS[@]}"; do
376
470
  p="$TARGET_ROOT/$legacy"
@@ -380,8 +474,8 @@ for legacy in "${LEGACY_DIRS[@]}"; do
380
474
  fi
381
475
  done
382
476
 
383
- # Step 4/7: 装 bundle
384
- log "Step 4/7: 装入 dist/index.js bundle"
477
+ # Step 4/8: 装 bundle
478
+ log "Step 4/8: 装入 dist/index.js bundle"
385
479
  BUNDLE_DST="$TARGET_ROOT/$BUNDLE_DST_REL"
386
480
  ensure_dir "$(dirname "$BUNDLE_DST")"
387
481
  run "cp -f '$BUNDLE_SRC' '$BUNDLE_DST'"
@@ -396,8 +490,8 @@ if [[ $DRY_RUN -eq 0 ]]; then
396
490
  fi
397
491
  ok "VERSION → ${VERSION_FILE} (${CF_VERSION})"
398
492
 
399
- # Step 5/7: 装 agents / commands / workflows / context-templates
400
- log "Step 5/7: 装 agents / commands / workflows / context-templates"
493
+ # Step 5/8: 装 agents / commands / workflows / context-templates
494
+ log "Step 5/8: 装 agents / commands / workflows / context-templates"
401
495
  for entry in "${MD_COPY_DIRS[@]}"; do
402
496
  src_name="${entry%%:*}"; dst_name="${entry##*:}"
403
497
  src_path="$SOURCE_ROOT/$src_name"
@@ -430,8 +524,8 @@ for entry in "${COPY_DIRS[@]}"; do
430
524
  ok "$src_name/ → $dst_path (整目录拷贝)"
431
525
  done
432
526
 
433
- # Step 6/7: AGENTS.md 智能合并(仅项目模式)
434
- log "Step 6/7: AGENTS.md 智能合并"
527
+ # Step 6/8: AGENTS.md 智能合并(仅项目模式)
528
+ log "Step 6/8: AGENTS.md 智能合并"
435
529
  if [[ "$MODE" == "project" ]]; then
436
530
  agents_target="$(pwd)/AGENTS.md"
437
531
  template_path="$SOURCE_ROOT/$KH_TEMPLATE_REL"
@@ -440,14 +534,25 @@ else
440
534
  ok "全局模式:跳过项目 AGENTS.md 合并(context-templates 已装到 $TARGET_ROOT/context-templates)"
441
535
  fi
442
536
 
443
- # Step 7/7: KH 全局配置模板(仅 --global)
444
- log "Step 7/7: KH 全局配置模板"
537
+ # Step 7/8: KH 全局配置模板(仅 --global)
538
+ log "Step 7/8: KH 全局配置模板"
445
539
  if [[ "$MODE" == "global" ]]; then
446
540
  write_kh_template
447
541
  else
448
542
  ok "项目级安装,跳过 KH 全局模板(要装请加 --global)"
449
543
  fi
450
544
 
545
+ # Step 8/8: 配置默认 agent → codeforge(ADR-0056 D5)
546
+ # 仅 user/global mode 配置用户级 ~/.config/opencode/opencode.json
547
+ # project mode 不动用户级配置(项目应由用户自决是否覆盖)
548
+ # Windows 用户暂需手动配置(install.ps1 尚未实现该步骤,留待 ADR-0059)
549
+ log "Step 8/8: 配置默认 agent → codeforge"
550
+ if [[ "$MODE" == "global" ]]; then
551
+ configure_default_agent
552
+ else
553
+ ok "项目级安装,跳过用户级 default_agent 配置(要装请加 --global)"
554
+ fi
555
+
451
556
  # 验证清单
452
557
  hr
453
558
  ok "${C_BOLD}CodeForge v${CF_VERSION} 安装完成${C_RESET}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andyqiu/codeforge",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "description": "CodeForge — opencode 的零侵入扩展包",
5
5
  "type": "module",
6
6
  "private": false,
@@ -1,64 +1,29 @@
1
- # ──────────────────────────────────────────────────────────────
2
- # parallel-explore.yaml — N 路并行探索工作流(Phase 4 Task NN)
1
+ # DEPRECATED (ADR-0054 hotfix 2)
3
2
  #
4
- # 触发:用户输入 /parallel
5
- # 流程:
6
- # 1. planner 根据用户原始需求 + KH 历史,拆出 N 个独立子任务
7
- # 2. subtasks plugin 并发执行(每条子任务可分配独立 worktree)
8
- # 3. reviewer 看冲突报告 + 各子任务摘要,给最终建议
3
+ # /parallel 命令已由 plugins/subtasks.ts 直接拦截处理(command.execute.before hook),
4
+ # 提供 4 类文字反馈(派出/启动/完成/总结)+ /parallel-status 查询。
9
5
  #
10
- # 关键:第二步用 `tool: subtasks-dispatch` 间接触发 plugins/subtasks,
11
- # 它内部调 lib/parallel.schedule 真正并发跑。
12
- # ──────────────────────────────────────────────────────────────
6
+ # workflow 之前作为 fallback 路径存在,dry_run 模式会吐大段 plan JSON 污染父 session;
7
+ # 真跑模式又会和 plugin 路径冲突。当前实现下整个 workflow 已无用。
8
+ #
9
+ # 双保险禁用:
10
+ # 1. trigger 错位为 /parallel-DISABLED-DO-NOT-MATCH — 永远 match 不上 /parallel
11
+ # 2. 唯一 step 是 no-op smart_search,即使误触发也仅查询 KH,不会破坏任何东西
12
+ #
13
+ # schema 要求 steps ≥ 1 + 不识别 disabled 字段,所以无法用纯禁用语法;改用 trigger 错位兜底。
14
+ #
15
+ # 如未来 plugin 链路出问题,可恢复此文件(改回 trigger /parallel + 写真正 steps)。
13
16
 
14
17
  name: parallel-explore
15
- version: 1.0.0
16
- description: |
17
- 把一个含糊需求扔给 planner 拆成 N 路独立子任务,subtasks plugin 并发跑(每路独立
18
- worktree),reviewer 看冲突 + digest 给最终建议。灵感来自 Cursor Composer 的多路探索。
19
-
20
- trigger: /parallel
18
+ description: (已弃用 - 见 plugins/subtasks.ts)
19
+ trigger: /parallel-DISABLED-DO-NOT-MATCH
21
20
 
22
21
  steps:
23
- - name: 拆分
22
+ - name: no-op (workflow 已弃用)
24
23
  agent: planner
25
- description: 把 ${user_request} 拆成 2~4 个独立可并发的子任务
26
- inject_context:
27
- role_hint: |
28
- 请输出 2~4 条独立子任务(每条独立可跑,互相不冲突)。
29
- 每条用「-」开头,单行描述。
30
24
  actions:
31
25
  - tool: smart_search
32
26
  args:
33
- query: "${user_request}"
34
- limit: 3
35
- on_error: skip
36
- on_error: abort
37
-
38
- - name: 并发
39
- agent: coder
40
- description: 用 subtasks plugin 并发跑全部子任务
41
- requires_human_approval: false
42
- actions:
43
- - tool: subtasks-dispatch
44
- args:
45
- parentId: "${session_id}"
46
- # description 由 plugin 从上一步 planner 输出里抽(按行拆)
47
- description: "${planner_output}"
48
- maxConcurrency: 4
49
- on_error: abort
50
- on_error: abort
51
-
52
- - name: 汇总
53
- agent: reviewer
54
- description: 看冲突 + digest,给最终建议(合并 / 选其一 / 补救)
55
- actions:
56
- - tool: save_chat_insight
57
- args:
58
- insight: "${session_summary}"
59
- category: workflow
60
- tags:
61
- - "trigger:/parallel"
62
- - "workflow:parallel-explore"
27
+ query: "deprecated parallel-explore workflow no-op"
28
+ limit: 1
63
29
  on_error: skip
64
- on_error: skip