@fitlab-ai/agent-infra 0.9.0 → 0.9.2

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.
Files changed (327) hide show
  1. package/README.md +22 -5
  2. package/README.zh-CN.md +21 -5
  3. package/bin/cli.ts +12 -0
  4. package/dist/bin/cli.js +14 -0
  5. package/dist/bin/internal-cli.js +20 -0
  6. package/dist/lib/agent-client.js +163 -0
  7. package/dist/lib/agent-clients/adapter.js +294 -0
  8. package/dist/lib/agent-clients/adapters/claude-code.js +62 -0
  9. package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
  10. package/dist/lib/agent-clients/adapters/codex.js +54 -0
  11. package/dist/lib/agent-clients/adapters/gemini-cli.js +64 -0
  12. package/dist/lib/agent-clients/adapters/index.js +20 -0
  13. package/dist/lib/agent-clients/adapters/opencode.js +64 -0
  14. package/dist/lib/agent-clients/config.js +177 -0
  15. package/dist/lib/agent-clients/custom-tuis.js +99 -0
  16. package/dist/lib/agent-clients/invocation.js +9 -0
  17. package/dist/lib/agent-clients/next-steps.js +38 -0
  18. package/dist/lib/agent-clients/project-assets.js +45 -0
  19. package/dist/lib/agent-clients/reconcile.js +235 -0
  20. package/dist/lib/agent-clients/registry.js +72 -0
  21. package/dist/lib/agent-clients/schema.js +57 -0
  22. package/dist/lib/agent-clients/types.js +29 -0
  23. package/dist/lib/builtin-tuis.js +9 -14
  24. package/dist/lib/defaults.json +85 -73
  25. package/dist/lib/git/review-snapshot.js +25 -10
  26. package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
  27. package/dist/lib/init.js +47 -91
  28. package/dist/lib/internal/agent-client.js +117 -0
  29. package/dist/lib/internal/git-workflow.js +1 -1
  30. package/dist/lib/internal/platform-release-notes.js +53 -0
  31. package/dist/lib/internal/release-workflow.js +175 -17
  32. package/dist/lib/internal/task-orchestration.js +151 -0
  33. package/dist/lib/internal/task-review.js +65 -0
  34. package/dist/lib/merge.js +2 -1
  35. package/dist/lib/platform/adapters.js +38 -1
  36. package/dist/lib/platform/change-request-git-evidence.js +113 -0
  37. package/dist/lib/platform/github-release-notes.js +96 -0
  38. package/dist/lib/platform/issues.js +4 -2
  39. package/dist/lib/platform/merged-pr-equivalence.js +84 -0
  40. package/dist/lib/platform/pr-checks.js +43 -15
  41. package/dist/lib/platform/pull-requests.js +113 -7
  42. package/dist/lib/platform/release-notes.js +143 -0
  43. package/dist/lib/platform/releases.js +1 -1
  44. package/dist/lib/platform/verification-required.js +31 -9
  45. package/dist/lib/prompt.js +15 -3
  46. package/dist/lib/release/channels.js +4 -1
  47. package/dist/lib/release/workflow.js +4 -2
  48. package/dist/lib/remove-dir.js +25 -0
  49. package/dist/lib/run/tui.js +8 -2
  50. package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
  51. package/dist/lib/sandbox/build-proxy.js +63 -0
  52. package/dist/lib/sandbox/clipboard/linux.js +2 -1
  53. package/dist/lib/sandbox/commands/create.js +133 -189
  54. package/dist/lib/sandbox/commands/enter.js +17 -1
  55. package/dist/lib/sandbox/commands/prune.js +2 -2
  56. package/dist/lib/sandbox/commands/rebuild.js +24 -7
  57. package/dist/lib/sandbox/commands/rm.js +3 -2
  58. package/dist/lib/sandbox/config.js +21 -4
  59. package/dist/lib/sandbox/constants.js +3 -0
  60. package/dist/lib/sandbox/dockerfile.js +2 -1
  61. package/dist/lib/sandbox/image-build.js +2 -1
  62. package/dist/lib/sandbox/managed-fs.js +10 -5
  63. package/dist/lib/sandbox/recovery.js +52 -36
  64. package/dist/lib/sandbox/runtimes/ai-tools.dockerfile +24 -3
  65. package/dist/lib/sandbox/runtimes/base.dockerfile +8 -1
  66. package/dist/lib/sandbox/runtimes/java17.dockerfile +8 -1
  67. package/dist/lib/sandbox/runtimes/java21.dockerfile +8 -1
  68. package/dist/lib/sandbox/runtimes/node20.dockerfile +8 -1
  69. package/dist/lib/sandbox/runtimes/node22.dockerfile +8 -1
  70. package/dist/lib/sandbox/runtimes/python3.dockerfile +8 -1
  71. package/dist/lib/sandbox/shell.js +3 -2
  72. package/dist/lib/sandbox/tool-types.js +8 -0
  73. package/dist/lib/sandbox/tools.js +2 -126
  74. package/dist/lib/task/artifact-lifecycle.js +1 -49
  75. package/dist/lib/task/commands/decisions.js +50 -20
  76. package/dist/lib/task/commands/issue-body.js +10 -5
  77. package/dist/lib/task/delegation-receipts.js +107 -0
  78. package/dist/lib/task/events.js +101 -2
  79. package/dist/lib/task/issue-form.js +2 -0
  80. package/dist/lib/task/orchestration.js +420 -0
  81. package/dist/lib/task/review-artifacts.js +143 -59
  82. package/dist/lib/task/review-finalization.js +166 -0
  83. package/dist/lib/task/review-fingerprint.js +13 -0
  84. package/dist/lib/task/verification-checks.js +2 -1
  85. package/dist/lib/task/verification-engine.js +168 -23
  86. package/dist/lib/task/verification-review.js +1 -1
  87. package/dist/lib/task/verification.js +4 -2
  88. package/dist/lib/task/workspace-snapshot.js +34 -0
  89. package/dist/lib/update.js +42 -161
  90. package/lib/agent-client.ts +214 -0
  91. package/lib/agent-clients/adapter.ts +461 -0
  92. package/lib/agent-clients/adapters/claude-code.ts +70 -0
  93. package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
  94. package/lib/agent-clients/adapters/codex.ts +58 -0
  95. package/lib/agent-clients/adapters/gemini-cli.ts +65 -0
  96. package/lib/agent-clients/adapters/index.ts +27 -0
  97. package/lib/agent-clients/adapters/opencode.ts +66 -0
  98. package/lib/agent-clients/config.ts +278 -0
  99. package/lib/agent-clients/custom-tuis.ts +149 -0
  100. package/lib/agent-clients/invocation.ts +19 -0
  101. package/lib/agent-clients/next-steps.ts +72 -0
  102. package/lib/agent-clients/project-assets.ts +96 -0
  103. package/lib/agent-clients/reconcile.ts +324 -0
  104. package/lib/agent-clients/registry.ts +144 -0
  105. package/lib/agent-clients/schema.ts +62 -0
  106. package/lib/agent-clients/types.ts +78 -0
  107. package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
  108. package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
  109. package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
  110. package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
  111. package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
  112. package/lib/builtin-tuis.ts +16 -15
  113. package/lib/defaults.json +24 -12
  114. package/lib/git/review-snapshot.ts +39 -9
  115. package/lib/git/reviewed-commit-equivalence.ts +135 -0
  116. package/lib/init.ts +53 -121
  117. package/lib/internal/agent-client.ts +131 -0
  118. package/lib/internal/git-workflow.ts +1 -1
  119. package/lib/internal/platform-release-notes.ts +55 -0
  120. package/lib/internal/release-workflow.ts +172 -18
  121. package/lib/internal/task-orchestration.ts +132 -0
  122. package/lib/internal/task-review.ts +65 -0
  123. package/lib/merge.ts +2 -1
  124. package/lib/platform/adapters.ts +142 -3
  125. package/lib/platform/change-request-git-evidence.ts +159 -0
  126. package/lib/platform/github-release-notes.ts +132 -0
  127. package/lib/platform/issues.ts +6 -4
  128. package/lib/platform/merged-pr-equivalence.ts +107 -0
  129. package/lib/platform/pr-checks.ts +57 -28
  130. package/lib/platform/pull-requests.ts +140 -25
  131. package/lib/platform/release-notes.ts +167 -0
  132. package/lib/platform/releases.ts +1 -1
  133. package/lib/platform/verification-required.ts +37 -9
  134. package/lib/prompt.ts +16 -3
  135. package/lib/release/channels.ts +4 -1
  136. package/lib/release/workflow.ts +4 -3
  137. package/lib/remove-dir.ts +28 -0
  138. package/lib/run/tui.ts +9 -1
  139. package/lib/sandbox/agent-client-reconciler.ts +378 -0
  140. package/lib/sandbox/build-proxy.ts +94 -0
  141. package/lib/sandbox/clipboard/linux.ts +2 -1
  142. package/lib/sandbox/commands/create.ts +188 -203
  143. package/lib/sandbox/commands/enter.ts +23 -1
  144. package/lib/sandbox/commands/prune.ts +2 -2
  145. package/lib/sandbox/commands/rebuild.ts +29 -7
  146. package/lib/sandbox/commands/rm.ts +3 -2
  147. package/lib/sandbox/config.ts +31 -4
  148. package/lib/sandbox/constants.ts +6 -0
  149. package/lib/sandbox/dockerfile.ts +2 -1
  150. package/lib/sandbox/image-build.ts +4 -1
  151. package/lib/sandbox/managed-fs.ts +18 -5
  152. package/lib/sandbox/recovery.ts +98 -67
  153. package/lib/sandbox/runtimes/ai-tools.dockerfile +24 -3
  154. package/lib/sandbox/runtimes/base.dockerfile +8 -1
  155. package/lib/sandbox/runtimes/java17.dockerfile +8 -1
  156. package/lib/sandbox/runtimes/java21.dockerfile +8 -1
  157. package/lib/sandbox/runtimes/node20.dockerfile +8 -1
  158. package/lib/sandbox/runtimes/node22.dockerfile +8 -1
  159. package/lib/sandbox/runtimes/python3.dockerfile +8 -1
  160. package/lib/sandbox/shell.ts +4 -2
  161. package/lib/sandbox/tool-types.ts +143 -0
  162. package/lib/sandbox/tools.ts +5 -157
  163. package/lib/task/artifact-lifecycle.ts +1 -38
  164. package/lib/task/commands/decisions.ts +53 -20
  165. package/lib/task/commands/issue-body.ts +10 -5
  166. package/lib/task/delegation-receipts.ts +170 -0
  167. package/lib/task/events.ts +111 -3
  168. package/lib/task/issue-form.ts +4 -0
  169. package/lib/task/orchestration.ts +543 -0
  170. package/lib/task/review-artifacts.ts +201 -69
  171. package/lib/task/review-finalization.ts +275 -0
  172. package/lib/task/review-fingerprint.ts +15 -1
  173. package/lib/task/verification-checks.ts +2 -1
  174. package/lib/task/verification-engine.ts +190 -25
  175. package/lib/task/verification-review.ts +2 -0
  176. package/lib/task/verification.ts +6 -3
  177. package/lib/task/workspace-snapshot.ts +36 -0
  178. package/lib/update.ts +48 -184
  179. package/package.json +2 -2
  180. package/templates/.agents/README.en.md +21 -20
  181. package/templates/.agents/README.zh-CN.md +21 -20
  182. package/templates/.agents/hooks/lifecycle-delegation.js +64 -0
  183. package/templates/.agents/rules/README.en.md +2 -0
  184. package/templates/.agents/rules/README.zh-CN.md +2 -0
  185. package/templates/.agents/rules/commit-and-pr.en.md +1 -0
  186. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
  187. package/templates/.agents/rules/human-decision-context.en.md +14 -12
  188. package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
  189. package/templates/.agents/rules/lifecycle-orchestration.en.md +21 -0
  190. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +21 -0
  191. package/templates/.agents/rules/next-step-output.en.md +16 -0
  192. package/templates/.agents/rules/next-step-output.zh-CN.md +16 -0
  193. package/templates/.agents/rules/no-mid-flow-questions.en.md +2 -0
  194. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +2 -0
  195. package/templates/.agents/rules/release-commands.en.md +2 -2
  196. package/templates/.agents/rules/release-commands.github.en.md +15 -39
  197. package/templates/.agents/rules/release-commands.github.zh-CN.md +14 -38
  198. package/templates/.agents/rules/release-commands.zh-CN.md +2 -2
  199. package/templates/.agents/rules/review-handshake.en.md +4 -3
  200. package/templates/.agents/rules/review-handshake.zh-CN.md +4 -3
  201. package/templates/.agents/rules/review-method.en.md +113 -0
  202. package/templates/.agents/rules/review-method.zh-CN.md +98 -0
  203. package/templates/.agents/rules/testing-discipline.en.md +20 -2
  204. package/templates/.agents/rules/testing-discipline.zh-CN.md +20 -2
  205. package/templates/.agents/skills/analyze-task/SKILL.en.md +9 -6
  206. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +9 -6
  207. package/templates/.agents/skills/block-task/SKILL.en.md +4 -4
  208. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +4 -4
  209. package/templates/.agents/skills/cancel-task/SKILL.en.md +4 -4
  210. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +5 -5
  211. package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
  212. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
  213. package/templates/.agents/skills/close-codescan/SKILL.en.md +4 -4
  214. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +4 -4
  215. package/templates/.agents/skills/close-dependabot/SKILL.en.md +4 -4
  216. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +4 -4
  217. package/templates/.agents/skills/code-task/SKILL.en.md +1 -1
  218. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -2
  219. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
  220. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
  221. package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
  222. package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
  223. package/templates/.agents/skills/commit/SKILL.en.md +11 -1
  224. package/templates/.agents/skills/commit/SKILL.zh-CN.md +11 -1
  225. package/templates/.agents/skills/commit/reference/task-status-update.en.md +24 -28
  226. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
  227. package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
  228. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
  229. package/templates/.agents/skills/complete-task/config/verify.en.json +0 -1
  230. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +0 -1
  231. package/templates/.agents/skills/create-pr/SKILL.en.md +10 -10
  232. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +10 -10
  233. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
  234. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
  235. package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -38
  236. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +16 -37
  237. package/templates/.agents/skills/create-task/SKILL.en.md +15 -11
  238. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +15 -11
  239. package/templates/.agents/skills/create-task/reference/context-capture.en.md +29 -0
  240. package/templates/.agents/skills/create-task/reference/context-capture.zh-CN.md +29 -0
  241. package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
  242. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
  243. package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
  244. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
  245. package/templates/.agents/skills/import-issue/SKILL.en.md +5 -5
  246. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -5
  247. package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
  248. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
  249. package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
  250. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
  251. package/templates/.agents/skills/plan-task/SKILL.en.md +5 -5
  252. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -5
  253. package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
  254. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
  255. package/templates/.agents/skills/release/SKILL.en.md +1 -1
  256. package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -2
  257. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -3
  258. package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
  259. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
  260. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
  261. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
  262. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
  263. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
  264. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
  265. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
  266. package/templates/.agents/skills/review-code/SKILL.en.md +28 -8
  267. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +28 -8
  268. package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
  269. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
  270. package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
  271. package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
  272. package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
  273. package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
  274. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
  275. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
  276. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
  277. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
  278. package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
  279. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
  280. package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
  281. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
  282. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
  283. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
  284. package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
  285. package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
  286. package/templates/.agents/skills/review-plan/SKILL.en.md +13 -2
  287. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -3
  288. package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
  289. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
  290. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
  291. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
  292. package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
  293. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
  294. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
  295. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
  296. package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
  297. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
  298. package/templates/.agents/skills/run-task/config/verify.en.json +9 -0
  299. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +9 -0
  300. package/templates/.agents/skills/test/SKILL.en.md +4 -4
  301. package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
  302. package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
  303. package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
  304. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
  305. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
  306. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +647 -203
  307. package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
  308. package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
  309. package/templates/.agents/skills/watch-pr/SKILL.en.md +8 -8
  310. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +8 -8
  311. package/templates/.agents/templates/task.en.md +18 -0
  312. package/templates/.agents/templates/task.zh-CN.md +18 -0
  313. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
  314. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
  315. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
  316. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
  317. package/templates/.claude/commands/run-task.en.md +8 -0
  318. package/templates/.claude/commands/run-task.zh-CN.md +8 -0
  319. package/templates/.claude/settings.json +24 -0
  320. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
  321. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
  322. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
  323. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
  324. package/templates/.gemini/commands/_project_/run-task.en.toml +8 -0
  325. package/templates/.gemini/commands/_project_/run-task.zh-CN.toml +8 -0
  326. package/templates/.opencode/commands/run-task.en.md +11 -0
  327. package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
@@ -1,15 +1,13 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ import { normalizeAgentClients } from './agent-clients/config.js';
4
+ import { applyAgentClientReconciliation, planAgentClientReconciliation } from './agent-clients/reconcile.js';
3
5
  import { info, ok, err } from './log.js';
4
6
  import { resolveTemplateDir } from './paths.js';
5
- import { renderFile, copySkillDir, KNOWN_PLATFORMS } from './render.js';
6
- import { isPathOwnedByDisabledTUI, resolveEnabledTUIs } from './builtin-tuis.js';
7
+ import { renderFile, copySkillDir } from './render.js';
7
8
  const defaults = JSON.parse(fs.readFileSync(new URL('./defaults.json', import.meta.url), 'utf8'));
8
9
  const CONFIG_DIR = '.agents';
9
10
  const CONFIG_PATH = path.join(CONFIG_DIR, '.airc.json');
10
- const AGENT_INFRA_SANDBOX_TOOL = 'agent-infra';
11
- const LEGACY_DEFAULT_SANDBOX_TOOLS = ['claude-code', 'codex', 'gemini-cli', 'opencode'];
12
- const DEFAULT_SANDBOX_TOOLS = [AGENT_INFRA_SANDBOX_TOOL, ...LEGACY_DEFAULT_SANDBOX_TOOLS];
13
11
  // One-time migration of the legacy project-level PR switch to the three-state
14
12
  // `prFlow` preference. `true` (the old default / "PR flow on") maps to the
15
13
  // strong constraint `required`; `false` maps to `disabled`. A missing or
@@ -28,80 +26,6 @@ function migratePrFlow(config) {
28
26
  }
29
27
  return null;
30
28
  }
31
- function isLegacyDefaultSandboxTools(value) {
32
- if (!Array.isArray(value) || value.length !== LEGACY_DEFAULT_SANDBOX_TOOLS.length) {
33
- return false;
34
- }
35
- const tools = new Set(value);
36
- return LEGACY_DEFAULT_SANDBOX_TOOLS.every((tool) => tools.has(tool));
37
- }
38
- function migrateSandboxTools(config) {
39
- const tools = config.sandbox?.tools;
40
- if (!isLegacyDefaultSandboxTools(tools)) {
41
- return false;
42
- }
43
- config.sandbox = {
44
- ...config.sandbox,
45
- tools: [...DEFAULT_SANDBOX_TOOLS]
46
- };
47
- return true;
48
- }
49
- function isPathOwnedByOtherPlatform(relativePath, platformType) {
50
- const top = String(relativePath || '').replace(/\\/g, '/').replace(/^\.\//, '').split('/')[0] ?? '';
51
- if (!top.startsWith('.'))
52
- return false;
53
- const candidate = top.slice(1);
54
- if (!KNOWN_PLATFORMS.has(candidate))
55
- return false;
56
- return candidate !== platformType;
57
- }
58
- function syncFileRegistry(config, platformType, enabledTUIs) {
59
- config.files ||= {};
60
- const before = JSON.stringify({
61
- files: {
62
- managed: config.files.managed || [],
63
- merged: config.files.merged || [],
64
- ejected: config.files.ejected || []
65
- }
66
- });
67
- config.files.managed = config.files.managed || [];
68
- config.files.merged = config.files.merged || [];
69
- config.files.ejected = config.files.ejected || [];
70
- const allExisting = [
71
- ...config.files.managed,
72
- ...config.files.merged,
73
- ...config.files.ejected
74
- ];
75
- const added = { managed: [], merged: [] };
76
- for (const entry of defaults.files.managed) {
77
- if (isPathOwnedByOtherPlatform(entry, platformType))
78
- continue;
79
- if (isPathOwnedByDisabledTUI(entry, enabledTUIs))
80
- continue;
81
- if (!allExisting.includes(entry)) {
82
- config.files.managed.push(entry);
83
- added.managed.push(entry);
84
- }
85
- }
86
- for (const entry of defaults.files.merged) {
87
- if (isPathOwnedByOtherPlatform(entry, platformType))
88
- continue;
89
- if (isPathOwnedByDisabledTUI(entry, enabledTUIs))
90
- continue;
91
- if (!allExisting.includes(entry)) {
92
- config.files.merged.push(entry);
93
- added.merged.push(entry);
94
- }
95
- }
96
- const after = JSON.stringify({
97
- files: {
98
- managed: config.files.managed,
99
- merged: config.files.merged,
100
- ejected: config.files.ejected
101
- }
102
- });
103
- return { added, changed: before !== after };
104
- }
105
29
  async function cmdUpdate() {
106
30
  console.log('');
107
31
  console.log(' ai update');
@@ -126,22 +50,36 @@ async function cmdUpdate() {
126
50
  const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
127
51
  const { project, org, language } = config;
128
52
  const platformType = config.platform?.type || defaults.platform.type;
129
- const enabledTUIs = resolveEnabledTUIs(config.tuis);
130
53
  const replacements = { project, org };
54
+ const normalizedOriginal = normalizeAgentClients(config);
55
+ const currentRegistry = {
56
+ managed: config.files?.managed || [],
57
+ merged: config.files?.merged || [],
58
+ ejected: config.files?.ejected || []
59
+ };
60
+ const platformAdded = !config.platform;
61
+ const sandboxAdded = !config.sandbox;
62
+ const taskAdded = !config.task;
63
+ const labelsAdded = !config.labels;
64
+ const prFlowMigrated = migratePrFlow(config);
65
+ if (platformAdded)
66
+ config.platform = structuredClone(defaults.platform);
67
+ if (sandboxAdded)
68
+ config.sandbox = structuredClone(defaults.sandbox);
69
+ if (taskAdded)
70
+ config.task = structuredClone(defaults.task);
71
+ if (labelsAdded)
72
+ config.labels = structuredClone(defaults.labels);
73
+ const workflowPlan = planAgentClientReconciliation({
74
+ config: config,
75
+ mutation: { type: 'replace-state', state: normalizedOriginal.state },
76
+ projectRoot: process.cwd(),
77
+ templateRoot: templateDir,
78
+ platformType,
79
+ language
80
+ });
131
81
  info(`Updating seed files for: ${project}`);
132
82
  console.log('');
133
- // select language-specific template filenames
134
- let claudeSrc, geminiSrc, opencodeSrc;
135
- if (language === 'zh-CN') {
136
- claudeSrc = 'update-agent-infra.zh-CN.md';
137
- geminiSrc = 'update-agent-infra.zh-CN.toml';
138
- opencodeSrc = 'update-agent-infra.zh-CN.md';
139
- }
140
- else {
141
- claudeSrc = 'update-agent-infra.en.md';
142
- geminiSrc = 'update-agent-infra.en.toml';
143
- opencodeSrc = 'update-agent-infra.en.md';
144
- }
145
83
  // update skill
146
84
  copySkillDir(path.join(templateDir, '.agents', 'skills', 'update-agent-infra'), path.join('.agents', 'skills', 'update-agent-infra'), replacements, language, platformType);
147
85
  ok('Updated .agents/skills/update-agent-infra/');
@@ -153,54 +91,15 @@ async function cmdUpdate() {
153
91
  catch {
154
92
  // Ignore missing legacy script from pre-ESM installs.
155
93
  }
156
- // update Claude command (only if enabled)
157
- if (enabledTUIs.has('claude-code')) {
158
- renderFile(path.join(templateDir, '.claude', 'commands', claudeSrc), path.join('.claude', 'commands', 'update-agent-infra.md'), replacements);
159
- ok('Updated .claude/commands/update-agent-infra.md');
160
- }
161
- // update Gemini command (only if enabled)
162
- if (enabledTUIs.has('gemini-cli')) {
163
- renderFile(path.join(templateDir, '.gemini', 'commands', '_project_', geminiSrc), path.join('.gemini', 'commands', project, 'update-agent-infra.toml'), replacements);
164
- ok(`Updated .gemini/commands/${project}/update-agent-infra.toml`);
165
- }
166
- // update OpenCode command (only if enabled)
167
- if (enabledTUIs.has('opencode')) {
168
- renderFile(path.join(templateDir, '.opencode', 'commands', opencodeSrc), path.join('.opencode', 'commands', 'update-agent-infra.md'), replacements);
169
- ok('Updated .opencode/commands/update-agent-infra.md');
170
- }
171
- // sync file registry
172
- const { added, changed } = syncFileRegistry(config, platformType, enabledTUIs);
94
+ const added = {
95
+ managed: workflowPlan.projectAssets.registry.managed.filter((entry) => !currentRegistry.managed.includes(entry)),
96
+ merged: workflowPlan.projectAssets.registry.merged.filter((entry) => !currentRegistry.merged.includes(entry))
97
+ };
173
98
  const hasNewEntries = added.managed.length > 0 || added.merged.length > 0;
174
- const platformAdded = !config.platform;
175
- const sandboxAdded = !config.sandbox;
176
- const taskAdded = !config.task;
177
- const labelsAdded = !config.labels;
178
- const prFlowMigrated = migratePrFlow(config);
179
- const sandboxToolsMigrated = !sandboxAdded && migrateSandboxTools(config);
180
- let configChanged = changed;
181
- if (platformAdded) {
182
- config.platform = structuredClone(defaults.platform);
183
- configChanged = true;
184
- }
185
- if (sandboxAdded) {
186
- config.sandbox = structuredClone(defaults.sandbox);
187
- configChanged = true;
188
- }
189
- if (taskAdded) {
190
- config.task = structuredClone(defaults.task);
191
- configChanged = true;
192
- }
193
- if (labelsAdded) {
194
- config.labels = structuredClone(defaults.labels);
195
- configChanged = true;
196
- }
197
- if (prFlowMigrated) {
198
- configChanged = true;
199
- }
200
- if (sandboxToolsMigrated) {
201
- configChanged = true;
202
- }
203
- if (configChanged) {
99
+ const reconcileResult = applyAgentClientReconciliation(workflowPlan);
100
+ for (const target of reconcileResult.applied)
101
+ ok(`Updated ${target}`);
102
+ if (reconcileResult.configUpdated) {
204
103
  console.log('');
205
104
  if (hasNewEntries) {
206
105
  info(`New file entries synced to ${CONFIG_PATH}:`);
@@ -227,9 +126,6 @@ async function cmdUpdate() {
227
126
  if (prFlowMigrated) {
228
127
  info(`Migrated legacy requiresPullRequest to prFlow="${prFlowMigrated}" in ${CONFIG_PATH}.`);
229
128
  }
230
- if (sandboxToolsMigrated) {
231
- info(`Migrated default sandbox.tools to include ${AGENT_INFRA_SANDBOX_TOOL} in ${CONFIG_PATH}.`);
232
- }
233
129
  }
234
130
  else {
235
131
  info(`File registry changed in ${CONFIG_PATH}.`);
@@ -249,37 +145,22 @@ async function cmdUpdate() {
249
145
  if (hasNewEntries && prFlowMigrated) {
250
146
  info(`Migrated legacy requiresPullRequest to prFlow="${prFlowMigrated}" in ${CONFIG_PATH}.`);
251
147
  }
252
- if (hasNewEntries && sandboxToolsMigrated) {
253
- info(`Migrated default sandbox.tools to include ${AGENT_INFRA_SANDBOX_TOOL} in ${CONFIG_PATH}.`);
254
- }
255
- fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n', 'utf8');
256
148
  ok(`Updated ${CONFIG_PATH}`);
257
149
  }
258
150
  // done
259
151
  console.log('');
260
152
  ok('Seed files updated successfully!');
261
153
  console.log('');
262
- if (enabledTUIs.size === 0) {
263
- console.log(' No built-in TUI enabled (tuis: []).');
154
+ if (workflowPlan.nextSteps.length === 0) {
155
+ console.log(' No Agent Client project integration enabled.');
264
156
  console.log(` Configure "customTUIs" in ${CONFIG_PATH} if needed.`);
265
157
  console.log('');
266
158
  }
267
159
  else {
268
160
  console.log(' Next step: run the full update in your AI TUI:');
269
161
  console.log('');
270
- const claudeOrOpencode = [];
271
- if (enabledTUIs.has('claude-code'))
272
- claudeOrOpencode.push('Claude Code');
273
- if (enabledTUIs.has('opencode'))
274
- claudeOrOpencode.push('OpenCode');
275
- if (claudeOrOpencode.length > 0) {
276
- console.log(` ${claudeOrOpencode.join(' / ')}: /update-agent-infra`);
277
- }
278
- if (enabledTUIs.has('gemini-cli')) {
279
- console.log(` Gemini CLI: /${project}:update-agent-infra`);
280
- }
281
- if (enabledTUIs.has('codex')) {
282
- console.log(' Codex CLI: $update-agent-infra');
162
+ for (const nextStep of workflowPlan.nextSteps) {
163
+ console.log(` ${nextStep.displayName}: ${nextStep.command}`);
283
164
  }
284
165
  console.log('');
285
166
  }
@@ -0,0 +1,214 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ import { AgentClientConfigError, normalizeAgentClients } from './agent-clients/config.ts';
5
+ import {
6
+ applyAgentClientReconciliation,
7
+ planAgentClientReconciliation
8
+ } from './agent-clients/reconcile.ts';
9
+ import { listAgentClientAdapters } from './agent-clients/registry.ts';
10
+ import { AGENT_CLIENT_IDS, isAgentClientId } from './agent-clients/types.ts';
11
+ import type { AgentClientState } from './agent-clients/types.ts';
12
+ import { closePrompt, multiSelect } from './prompt.ts';
13
+ import { resolveTemplateDir } from './paths.ts';
14
+
15
+ const USAGE = `Usage: ai agent-client <operation>
16
+
17
+ Operations:
18
+ list List built-in Agent Clients
19
+ status Show project integration and sandbox state
20
+ enable <client-id> Enable project integration only
21
+ disable <client-id> Disable project integration only
22
+ configure Configure integration and sandbox state interactively
23
+ `;
24
+
25
+ class AgentClientCommandError extends Error {
26
+ readonly code: string;
27
+
28
+ constructor(code: string, message: string) {
29
+ super(`${code}: ${message}`);
30
+ this.name = 'AgentClientCommandError';
31
+ this.code = code;
32
+ }
33
+ }
34
+
35
+ function readConfig(projectRoot: string): Record<string, unknown> {
36
+ const configPath = path.join(projectRoot, '.agents', '.airc.json');
37
+ if (!fs.existsSync(configPath)) {
38
+ throw new AgentClientCommandError(
39
+ 'AGENT_CLIENT_CONFIG_NOT_FOUND',
40
+ 'No .agents/.airc.json found. Run "ai init" first.'
41
+ );
42
+ }
43
+ let parsed: unknown;
44
+ try {
45
+ parsed = JSON.parse(fs.readFileSync(configPath, 'utf8'));
46
+ } catch (error) {
47
+ throw new AgentClientCommandError(
48
+ 'AGENT_CLIENT_CONFIG_INVALID',
49
+ error instanceof Error ? error.message : String(error)
50
+ );
51
+ }
52
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
53
+ throw new AgentClientCommandError(
54
+ 'AGENT_CLIENT_CONFIG_INVALID',
55
+ 'configuration root must be an object'
56
+ );
57
+ }
58
+ return parsed as Record<string, unknown>;
59
+ }
60
+
61
+ function choices() {
62
+ return listAgentClientAdapters().map((adapter) => ({
63
+ id: adapter.id,
64
+ label: adapter.displayName
65
+ }));
66
+ }
67
+
68
+ function selected(state: AgentClientState, field: 'enabled' | 'installInSandbox'): string[] {
69
+ return AGENT_CLIENT_IDS.filter((id) => state[id][field]);
70
+ }
71
+
72
+ function workflowPlan(
73
+ projectRoot: string,
74
+ config: Record<string, unknown>,
75
+ mutation: Parameters<typeof planAgentClientReconciliation>[0]['mutation']
76
+ ) {
77
+ const templateRoot = resolveTemplateDir();
78
+ if (!templateRoot) {
79
+ throw new AgentClientCommandError('AGENT_CLIENT_TEMPLATE_NOT_FOUND', 'Template directory not found');
80
+ }
81
+ const platform = config.platform;
82
+ const platformType = typeof platform === 'object' && platform !== null && 'type' in platform
83
+ ? String(platform.type ?? 'github')
84
+ : 'github';
85
+ return planAgentClientReconciliation({
86
+ config,
87
+ mutation,
88
+ projectRoot,
89
+ templateRoot,
90
+ platformType,
91
+ language: String(config.language ?? 'en')
92
+ });
93
+ }
94
+
95
+ function printState(state: AgentClientState): void {
96
+ for (const adapter of listAgentClientAdapters()) {
97
+ const value = state[adapter.id];
98
+ process.stdout.write(
99
+ ` ${adapter.id}: enabled=${String(value.enabled)} installInSandbox=${String(value.installInSandbox)}\n`
100
+ );
101
+ }
102
+ }
103
+
104
+ async function cmdAgentClient(args: string[]): Promise<number> {
105
+ const operation = args[0];
106
+ if (!operation || operation === '--help' || operation === '-h' || operation === 'help') {
107
+ process.stdout.write(USAGE);
108
+ return 0;
109
+ }
110
+
111
+ if (operation === 'list') {
112
+ if (args.length !== 1) {
113
+ throw new AgentClientCommandError('AGENT_CLIENT_ARGUMENT_INVALID', 'list accepts no arguments');
114
+ }
115
+ for (const adapter of listAgentClientAdapters()) {
116
+ process.stdout.write(
117
+ `${adapter.id}\t${adapter.displayName}\t${adapter.invocation}\tcommands=${adapter.capabilities.commands.level}\tsandbox=${adapter.capabilities.sandbox.level}\n`
118
+ );
119
+ }
120
+ return 0;
121
+ }
122
+
123
+ const projectRoot = process.cwd();
124
+ const config = readConfig(projectRoot);
125
+ try {
126
+ if (operation === 'status') {
127
+ if (args.length !== 1) {
128
+ throw new AgentClientCommandError('AGENT_CLIENT_ARGUMENT_INVALID', 'status accepts no arguments');
129
+ }
130
+ const plan = workflowPlan(projectRoot, config, { type: 'none' });
131
+ process.stdout.write(`source: ${plan.source}\n`);
132
+ printState(plan.desired);
133
+ for (const seed of plan.seedOperations) {
134
+ process.stdout.write(` seed ${seed.target}: ${seed.kind}\n`);
135
+ }
136
+ for (const diagnostic of plan.diagnostics) {
137
+ process.stdout.write(` diagnostic ${diagnostic.code} at ${diagnostic.path}\n`);
138
+ }
139
+ return 0;
140
+ }
141
+
142
+ if (operation === 'enable' || operation === 'disable') {
143
+ if (args.length !== 2) {
144
+ throw new AgentClientCommandError(
145
+ 'AGENT_CLIENT_ARGUMENT_INVALID',
146
+ `${operation} requires exactly one client id`
147
+ );
148
+ }
149
+ const id = args[1];
150
+ if (!isAgentClientId(id)) {
151
+ throw new AgentClientCommandError('UNKNOWN_AGENT_CLIENT', `Unknown Agent Client '${String(id)}'`);
152
+ }
153
+ const plan = workflowPlan(projectRoot, config, {
154
+ type: 'set-enabled',
155
+ id,
156
+ value: operation === 'enable'
157
+ });
158
+ process.stdout.write('Before:\n');
159
+ printState(plan.before);
160
+ const result = applyAgentClientReconciliation(plan);
161
+ process.stdout.write('After:\n');
162
+ printState(plan.desired);
163
+ process.stdout.write(
164
+ `Result: ${result.status}; applied=${result.applied.length}; protected=${result.protected.length}\n`
165
+ );
166
+ return 0;
167
+ }
168
+
169
+ if (operation === 'configure') {
170
+ if (args.length !== 1) {
171
+ throw new AgentClientCommandError('AGENT_CLIENT_ARGUMENT_INVALID', 'configure accepts no arguments');
172
+ }
173
+ const normalized = normalizeAgentClients(config);
174
+ let enabled: string[];
175
+ let installed: string[];
176
+ try {
177
+ enabled = await multiSelect(
178
+ 'Agent Client project integrations',
179
+ choices(),
180
+ selected(normalized.state, 'enabled')
181
+ );
182
+ installed = await multiSelect(
183
+ 'Agent Clients installed in sandbox',
184
+ choices(),
185
+ selected(normalized.state, 'installInSandbox')
186
+ );
187
+ } finally {
188
+ closePrompt();
189
+ }
190
+ const state = Object.fromEntries(AGENT_CLIENT_IDS.map((id) => [id, {
191
+ enabled: enabled.includes(id),
192
+ installInSandbox: installed.includes(id)
193
+ }])) as AgentClientState;
194
+ const plan = workflowPlan(projectRoot, config, { type: 'replace-state', state });
195
+ const result = applyAgentClientReconciliation(plan);
196
+ process.stdout.write(
197
+ `Result: ${result.status}; applied=${result.applied.length}; protected=${result.protected.length}\n`
198
+ );
199
+ return 0;
200
+ }
201
+
202
+ throw new AgentClientCommandError(
203
+ 'AGENT_CLIENT_OPERATION_INVALID',
204
+ `Unknown operation '${operation}'`
205
+ );
206
+ } catch (error) {
207
+ if (error instanceof AgentClientConfigError) {
208
+ throw new AgentClientCommandError(error.code, error.message);
209
+ }
210
+ throw error;
211
+ }
212
+ }
213
+
214
+ export { AgentClientCommandError, cmdAgentClient };