@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
package/lib/init.ts CHANGED
@@ -8,13 +8,13 @@ import { resolveTemplateDir } from './paths.ts';
8
8
  import { renderFile, copySkillDir, KNOWN_PLATFORMS } from './render.ts';
9
9
  import { enginesForPlatform } from './sandbox/engines/index.ts';
10
10
  import { VERSION } from './version.ts';
11
+ import { listAgentClientAdapters } from './agent-clients/registry.ts';
12
+ import { serializeAgentClients } from './agent-clients/config.ts';
11
13
  import {
12
- BUILTIN_TUI_IDS,
13
- BUILTIN_TUI_DISPLAY,
14
- isPathOwnedByDisabledTUI,
15
- resolveEnabledTUIs
16
- } from './builtin-tuis.ts';
17
- import type { BuiltinTUIId } from './builtin-tuis.ts';
14
+ applyAgentClientReconciliation,
15
+ planAgentClientReconciliation
16
+ } from './agent-clients/reconcile.ts';
17
+ import type { AgentClientState } from './agent-clients/types.ts';
18
18
 
19
19
  type FileRegistry = {
20
20
  managed: string[];
@@ -28,6 +28,7 @@ type SourceEntry = {
28
28
  };
29
29
 
30
30
  type Defaults = {
31
+ agentClients: AgentConfig['agentClients'];
31
32
  files: FileRegistry;
32
33
  sandbox: Record<string, unknown>;
33
34
  task: { shortIdLength: number };
@@ -44,7 +45,7 @@ type AgentConfig = {
44
45
  task: { shortIdLength: number };
45
46
  labels: Record<string, unknown>;
46
47
  files: FileRegistry;
47
- tuis: string[];
48
+ agentClients: ReturnType<typeof serializeAgentClients>;
48
49
  templates?: { sources: SourceEntry[] };
49
50
  skills?: { sources: SourceEntry[] };
50
51
  };
@@ -59,28 +60,6 @@ const PLATFORM_DEFAULT_ENGINES = Object.freeze({
59
60
  win32: 'wsl2'
60
61
  });
61
62
 
62
- function isPathOwnedByOtherPlatform(relativePath: string, platformType: string): boolean {
63
- const top = String(relativePath || '').replace(/\\/g, '/').replace(/^\.\//, '').split('/')[0] ?? '';
64
- if (!top.startsWith('.')) return false;
65
-
66
- const candidate = top.slice(1);
67
- if (!KNOWN_PLATFORMS.has(candidate)) return false;
68
- return candidate !== platformType;
69
- }
70
-
71
- function buildDefaultFiles(platformType: string, enabledTUIs: Set<BuiltinTUIId>): FileRegistry {
72
- const ownedByDisabled = (entry: string) => isPathOwnedByDisabledTUI(entry, enabledTUIs);
73
- return {
74
- managed: (defaults.files.managed || []).filter(
75
- (entry) => !isPathOwnedByOtherPlatform(entry, platformType) && !ownedByDisabled(entry)
76
- ),
77
- merged: (defaults.files.merged || []).filter(
78
- (entry) => !isPathOwnedByOtherPlatform(entry, platformType) && !ownedByDisabled(entry)
79
- ),
80
- ejected: structuredClone(defaults.files.ejected || [])
81
- };
82
- }
83
-
84
63
  function detectProjectName(): string {
85
64
  try {
86
65
  const url = execSync('git remote get-url origin', { stdio: ['pipe', 'pipe', 'pipe'] })
@@ -222,11 +201,12 @@ async function cmdInit(): Promise<void> {
222
201
  );
223
202
  }
224
203
 
225
- let enabledTUIs: string[];
204
+ const adapters = listAgentClientAdapters();
205
+ let enabledClientIds: string[];
226
206
  try {
227
- enabledTUIs = await multiSelect(
228
- 'Built-in TUI command files to install/manage',
229
- BUILTIN_TUI_IDS.map((id) => ({ id, label: BUILTIN_TUI_DISPLAY[id] }))
207
+ enabledClientIds = await multiSelect(
208
+ 'Agent Client project integrations to enable',
209
+ adapters.map((adapter) => ({ id: adapter.id, label: adapter.displayName }))
230
210
  );
231
211
  } catch (e) {
232
212
  err(e instanceof Error ? e.message : String(e));
@@ -234,7 +214,7 @@ async function cmdInit(): Promise<void> {
234
214
  process.exitCode = 1;
235
215
  return;
236
216
  }
237
- const enabledTUISet = resolveEnabledTUIs(enabledTUIs);
217
+ const enabledClientSet = new Set(enabledClientIds);
238
218
 
239
219
  const templateSources = parseLocalSources(await prompt(
240
220
  'Template sources (optional, comma-separated local paths, e.g. ~/my-templates; Enter to skip)',
@@ -249,6 +229,39 @@ async function cmdInit(): Promise<void> {
249
229
  const project = projectName;
250
230
  const replacements = { project, org: orgName };
251
231
 
232
+ const defaultState = Object.fromEntries(defaults.agentClients.map((entry) => [
233
+ entry.id,
234
+ {
235
+ enabled: enabledClientSet.has(entry.id),
236
+ installInSandbox: entry.installInSandbox
237
+ }
238
+ ])) as AgentClientState;
239
+ const config: AgentConfig = {
240
+ project: projectName,
241
+ org: orgName,
242
+ language,
243
+ platform: { type: platformType },
244
+ templateVersion: VERSION,
245
+ sandbox: structuredClone(defaults.sandbox),
246
+ task: structuredClone(defaults.task),
247
+ labels: structuredClone(defaults.labels),
248
+ files: { managed: [], merged: [], ejected: [] },
249
+ agentClients: serializeAgentClients(defaultState)
250
+ };
251
+
252
+ if (sandboxEngine) config.sandbox.engine = sandboxEngine;
253
+ if (templateSources.length > 0) config.templates = { sources: templateSources };
254
+ if (skillSources.length > 0) config.skills = { sources: skillSources };
255
+
256
+ const workflowPlan = planAgentClientReconciliation({
257
+ config: config as unknown as Record<string, unknown>,
258
+ mutation: { type: 'none' },
259
+ projectRoot: process.cwd(),
260
+ templateRoot: templateDir,
261
+ platformType,
262
+ language
263
+ });
264
+
252
265
  console.log('');
253
266
  if (orgName) {
254
267
  info(`Installing update-agent-infra seed command for: ${projectName} (${orgName})`);
@@ -257,18 +270,6 @@ async function cmdInit(): Promise<void> {
257
270
  }
258
271
  console.log('');
259
272
 
260
- // select language-specific template filenames
261
- let claudeSrc, geminiSrc, opencodeSrc;
262
- if (language === 'zh-CN') {
263
- claudeSrc = 'update-agent-infra.zh-CN.md';
264
- geminiSrc = 'update-agent-infra.zh-CN.toml';
265
- opencodeSrc = 'update-agent-infra.zh-CN.md';
266
- } else {
267
- claudeSrc = 'update-agent-infra.en.md';
268
- geminiSrc = 'update-agent-infra.en.toml';
269
- opencodeSrc = 'update-agent-infra.en.md';
270
- }
271
-
272
273
  // install skill
273
274
  copySkillDir(
274
275
  path.join(templateDir, '.agents', 'skills', 'update-agent-infra'),
@@ -285,68 +286,8 @@ async function cmdInit(): Promise<void> {
285
286
  );
286
287
  ok('Installed .agents/scripts/lib/agent-infra-package.js');
287
288
 
288
- // install Claude command (only if enabled)
289
- if (enabledTUISet.has('claude-code')) {
290
- renderFile(
291
- path.join(templateDir, '.claude', 'commands', claudeSrc),
292
- path.join('.claude', 'commands', 'update-agent-infra.md'),
293
- replacements
294
- );
295
- ok('Installed .claude/commands/update-agent-infra.md');
296
- }
297
-
298
- // install Gemini command (only if enabled)
299
- if (enabledTUISet.has('gemini-cli')) {
300
- renderFile(
301
- path.join(templateDir, '.gemini', 'commands', '_project_', geminiSrc),
302
- path.join('.gemini', 'commands', project, 'update-agent-infra.toml'),
303
- replacements
304
- );
305
- ok(`Installed .gemini/commands/${project}/update-agent-infra.toml`);
306
- }
307
-
308
- // install OpenCode command (only if enabled)
309
- if (enabledTUISet.has('opencode')) {
310
- renderFile(
311
- path.join(templateDir, '.opencode', 'commands', opencodeSrc),
312
- path.join('.opencode', 'commands', 'update-agent-infra.md'),
313
- replacements
314
- );
315
- ok('Installed .opencode/commands/update-agent-infra.md');
316
- }
317
-
318
- // generate .agents/.airc.json
319
- const config: AgentConfig = {
320
- project: projectName,
321
- org: orgName,
322
- language,
323
- platform: { type: platformType },
324
- templateVersion: VERSION,
325
- sandbox: structuredClone(defaults.sandbox),
326
- task: structuredClone(defaults.task),
327
- labels: structuredClone(defaults.labels),
328
- files: buildDefaultFiles(platformType, enabledTUISet),
329
- tuis: enabledTUIs
330
- };
331
-
332
- if (sandboxEngine) {
333
- config.sandbox.engine = sandboxEngine;
334
- }
335
-
336
- if (templateSources.length > 0) {
337
- config.templates = {
338
- sources: templateSources
339
- };
340
- }
341
-
342
- if (skillSources.length > 0) {
343
- config.skills = {
344
- sources: skillSources
345
- };
346
- }
347
-
348
- fs.mkdirSync(path.dirname(configPath), { recursive: true });
349
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
289
+ const reconcileResult = applyAgentClientReconciliation(workflowPlan);
290
+ for (const target of reconcileResult.applied) ok(`Installed ${target}`);
350
291
  ok(`Generated ${configPath}`);
351
292
 
352
293
  // done
@@ -356,24 +297,15 @@ async function cmdInit(): Promise<void> {
356
297
  console.log(' If this init used npx, install agent-infra persistently before update or validation:');
357
298
  console.log(' npm install -g @fitlab-ai/agent-infra');
358
299
  console.log('');
359
- if (enabledTUISet.size === 0) {
360
- console.log(' No built-in TUI selected.');
300
+ if (workflowPlan.nextSteps.length === 0) {
301
+ console.log(' No Agent Client project integration enabled.');
361
302
  console.log(` Configure "customTUIs" in ${configPath} before running update-agent-infra.`);
362
303
  console.log('');
363
304
  } else {
364
305
  console.log(' Next step: open this project in any AI TUI and run:');
365
306
  console.log('');
366
- const claudeOrOpencode: string[] = [];
367
- if (enabledTUISet.has('claude-code')) claudeOrOpencode.push('Claude Code');
368
- if (enabledTUISet.has('opencode')) claudeOrOpencode.push('OpenCode');
369
- if (claudeOrOpencode.length > 0) {
370
- console.log(` ${claudeOrOpencode.join(' / ')}: /update-agent-infra`);
371
- }
372
- if (enabledTUISet.has('gemini-cli')) {
373
- console.log(` Gemini CLI: /${project}:update-agent-infra`);
374
- }
375
- if (enabledTUISet.has('codex')) {
376
- console.log(' Codex CLI: $update-agent-infra');
307
+ for (const nextStep of workflowPlan.nextSteps) {
308
+ console.log(` ${nextStep.displayName}: ${nextStep.command}`);
377
309
  }
378
310
  console.log('');
379
311
  console.log(' This will render all templates and set up the full');
@@ -0,0 +1,131 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ import {
5
+ AgentClientConfigError,
6
+ normalizeAgentClients
7
+ } from '../agent-clients/config.ts';
8
+ import { normalizeCustomTUIs } from '../agent-clients/custom-tuis.ts';
9
+ import { renderNextStepCommands } from '../agent-clients/next-steps.ts';
10
+
11
+ const USAGE = 'Usage: agent-infra-internal agent-client next-steps --skill <skill-name> [--task-ref <NN|TASK-id>] [--format text|json]\n';
12
+
13
+ type ParsedArgs = Readonly<{
14
+ skillName: string;
15
+ taskRef?: string;
16
+ format: 'text' | 'json';
17
+ }>;
18
+
19
+ function failure(code: string, message: string): void {
20
+ process.stdout.write(`${JSON.stringify({
21
+ status: 'failed',
22
+ changed: false,
23
+ commands: [],
24
+ diagnostics: [],
25
+ error: { code, message }
26
+ })}\n`);
27
+ process.exitCode = 1;
28
+ }
29
+
30
+ function parseArgs(args: string[]): ParsedArgs | null {
31
+ if (args[0] === '--help' || args[0] === '-h') {
32
+ process.stdout.write(USAGE);
33
+ return null;
34
+ }
35
+ if (args[0] !== 'next-steps') {
36
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', "operation must be 'next-steps'");
37
+ return null;
38
+ }
39
+ let skillName: string | undefined;
40
+ let taskRef: string | undefined;
41
+ let format: 'text' | 'json' = 'text';
42
+ const seen = new Set<string>();
43
+ for (let index = 1; index < args.length; index += 1) {
44
+ const flag = args[index]!;
45
+ if (!['--skill', '--task-ref', '--format'].includes(flag)) {
46
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', `unknown option '${flag}'`);
47
+ return null;
48
+ }
49
+ if (seen.has(flag)) {
50
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', `duplicate option '${flag}'`);
51
+ return null;
52
+ }
53
+ const value = args[++index];
54
+ if (!value || value.startsWith('--')) {
55
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', `option '${flag}' requires a value`);
56
+ return null;
57
+ }
58
+ seen.add(flag);
59
+ if (flag === '--skill') skillName = value;
60
+ if (flag === '--task-ref') taskRef = value;
61
+ if (flag === '--format') {
62
+ if (value !== 'text' && value !== 'json') {
63
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', "format must be 'text' or 'json'");
64
+ return null;
65
+ }
66
+ format = value;
67
+ }
68
+ }
69
+ if (!skillName) {
70
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', "option '--skill' is required");
71
+ return null;
72
+ }
73
+ return { skillName, ...(taskRef ? { taskRef } : {}), format };
74
+ }
75
+
76
+ function agentClient(args: string[] = []): void {
77
+ const parsed = parseArgs(args);
78
+ if (!parsed || process.exitCode) return;
79
+
80
+ let config: Record<string, unknown>;
81
+ try {
82
+ const configPath = path.join(process.cwd(), '.agents', '.airc.json');
83
+ const raw = JSON.parse(fs.readFileSync(configPath, 'utf8')) as unknown;
84
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
85
+ throw new Error('configuration root must be an object');
86
+ }
87
+ config = raw as Record<string, unknown>;
88
+ } catch (error) {
89
+ failure('AGENT_CLIENT_CONFIG_INVALID', String(error));
90
+ return;
91
+ }
92
+
93
+ try {
94
+ const clients = normalizeAgentClients(config);
95
+ const custom = normalizeCustomTUIs(process.cwd(), config.customTUIs ?? []);
96
+ const commands = renderNextStepCommands({
97
+ projectName: String(config.project ?? ''),
98
+ state: clients.state,
99
+ customTUIs: custom.items,
100
+ skillName: parsed.skillName,
101
+ ...(parsed.taskRef ? { taskRef: parsed.taskRef } : {})
102
+ });
103
+ if (parsed.format === 'json') {
104
+ process.stdout.write(`${JSON.stringify({
105
+ status: 'rendered',
106
+ changed: false,
107
+ commands,
108
+ diagnostics: custom.diagnostics,
109
+ error: null
110
+ })}\n`);
111
+ return;
112
+ }
113
+ for (const command of commands) {
114
+ process.stdout.write(` - ${command.displayName}: ${command.command}\n`);
115
+ }
116
+ for (const diagnostic of custom.diagnostics) {
117
+ process.stderr.write(`${diagnostic.code} at ${diagnostic.path}\n`);
118
+ }
119
+ } catch (error) {
120
+ if (error instanceof AgentClientConfigError) {
121
+ failure(error.code, error.message);
122
+ return;
123
+ }
124
+ failure(
125
+ 'AGENT_CLIENT_RENDER_INVALID',
126
+ error instanceof Error ? error.message : String(error)
127
+ );
128
+ }
129
+ }
130
+
131
+ export { agentClient };
@@ -27,7 +27,7 @@ function gitWorkflow(args: string[] = []): void {
27
27
  const inputIndex = rest.indexOf('--input');
28
28
  const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1]!, 'utf8')) : null;
29
29
  if (!input) result = { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
30
- else if (action === 'snapshot') result = { status: 'no-op', changed: false, snapshot: snapshotReview({ cwd: cwd ?? process.cwd(), mode: input.mode, baseline: input.baseline, globs: input.globs ?? resolvePostReviewGlobs({}, {}) }), error: null };
30
+ else if (action === 'snapshot') result = { status: 'no-op', changed: false, snapshot: snapshotReview({ cwd: cwd ?? process.cwd(), mode: input.mode, baseline: input.baseline, diffBase: input.diffBase, globs: input.globs ?? resolvePostReviewGlobs({}, {}) }), error: null };
31
31
  else result = { status: 'no-op', changed: false, comparison: compareReviewTrees({ cwd: cwd ?? process.cwd(), expected: input.expected, actual: input.actual }), error: null };
32
32
  } else result = { status: 'failed', changed: false, error: { code: 'GIT_ACTION_INVALID', message: `Unknown git-workflow action '${action ?? ''}'` } };
33
33
  output(result);
@@ -0,0 +1,55 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ import { publishReleaseNotes, releaseNoteContext } from '../platform/release-notes.ts';
5
+
6
+ function option(args: string[], name: string): string | null {
7
+ const index = args.indexOf(name);
8
+ return index >= 0 && args[index + 1] ? args[index + 1]! : null;
9
+ }
10
+
11
+ function finish(result: { status: string; [key: string]: unknown }): void {
12
+ process.stdout.write(`${JSON.stringify(result)}\n`);
13
+ process.exitCode = result.status === 'blocked' ? 2 : result.status === 'failed' ? 1 : 0;
14
+ }
15
+
16
+ function platformReleaseNotes(args: string[] = []): void {
17
+ const [action, ...rest] = args;
18
+ const cwd = path.resolve(option(rest, '--cwd') || process.cwd());
19
+ if (action === 'context') {
20
+ const historyRaw = option(rest, '--history-limit');
21
+ finish(releaseNoteContext({
22
+ fromTag: option(rest, '--from-tag') || '',
23
+ toTag: option(rest, '--to-tag') || '',
24
+ branch: option(rest, '--branch') || '',
25
+ historyLimit: historyRaw === null ? undefined : Number(historyRaw)
26
+ }, { cwd }));
27
+ return;
28
+ }
29
+ if (action === 'publish') {
30
+ const notesPath = option(rest, '--notes-file');
31
+ if (!notesPath) {
32
+ finish({ status: 'failed', changed: false, error: { code: 'RELEASE_NOTES_INPUT_INVALID', message: 'notes-file is required', retryable: false } });
33
+ return;
34
+ }
35
+ let resolvedNotesPath = notesPath;
36
+ if (notesPath === '-') {
37
+ resolvedNotesPath = path.join(process.env.TMPDIR || '/tmp', `agent-infra-release-notes-${process.pid}.md`);
38
+ fs.writeFileSync(resolvedNotesPath, fs.readFileSync(0));
39
+ }
40
+ try {
41
+ finish(publishReleaseNotes({
42
+ tag: option(rest, '--tag') || '',
43
+ title: option(rest, '--title') || option(rest, '--tag') || '',
44
+ notesFile: resolvedNotesPath,
45
+ dryRun: rest.includes('--dry-run')
46
+ }, { cwd }));
47
+ } finally {
48
+ if (notesPath === '-') fs.rmSync(resolvedNotesPath, { force: true });
49
+ }
50
+ return;
51
+ }
52
+ finish({ status: 'failed', changed: false, error: { code: 'RELEASE_NOTES_INPUT_INVALID', message: 'Usage: platform-release-notes context|publish', retryable: false } });
53
+ }
54
+
55
+ export { platformReleaseNotes };