@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
@@ -0,0 +1,461 @@
1
+ import {
2
+ AGENT_CLIENT_CAPABILITY_IDS,
3
+ AGENT_CLIENT_SUPPORT_LEVELS,
4
+ isAgentClientId
5
+ } from './types.ts';
6
+ import type {
7
+ AgentClientCapabilityMap,
8
+ AgentClientId
9
+ } from './types.ts';
10
+ import {
11
+ SANDBOX_HOOK_PHASES
12
+ } from '../sandbox/tool-types.ts';
13
+ import type {
14
+ AgentClientSandboxRecoveryCheck,
15
+ AgentClientSandboxDescriptor,
16
+ SandboxAlias,
17
+ SandboxTool,
18
+ SandboxToolContext
19
+ } from '../sandbox/tool-types.ts';
20
+
21
+ type AgentClientCapabilities = AgentClientCapabilityMap;
22
+
23
+ type AgentClientSeedCommand = Readonly<{
24
+ templates: Readonly<{
25
+ en: string;
26
+ 'zh-CN': string;
27
+ }>;
28
+ target: string;
29
+ }>;
30
+
31
+ type AgentClientProjectDescriptor = Readonly<{
32
+ ownedPathPrefixes: readonly string[];
33
+ managed: readonly string[];
34
+ merged: readonly string[];
35
+ ejected: readonly string[];
36
+ seedCommands: readonly AgentClientSeedCommand[];
37
+ }>;
38
+
39
+ type AgentClientAdapter = Readonly<{
40
+ id: AgentClientId;
41
+ displayName: string;
42
+ invocation: string;
43
+ capabilities: AgentClientCapabilities;
44
+ project: AgentClientProjectDescriptor;
45
+ sandbox: AgentClientSandboxDescriptor;
46
+ }>;
47
+
48
+ type AgentClientRegistry = Readonly<
49
+ Record<AgentClientId, AgentClientAdapter>
50
+ >;
51
+
52
+ type AgentClientManifestEntry = Readonly<{
53
+ id: AgentClientId;
54
+ displayName: string;
55
+ invocation: string;
56
+ ownedPathPrefixes: readonly string[];
57
+ managed: readonly string[];
58
+ merged: readonly string[];
59
+ ejected: readonly string[];
60
+ }>;
61
+
62
+ const PROJECT_ASSET_CATEGORIES = ['managed', 'merged', 'ejected'] as const;
63
+ const MAX_SANDBOX_HOOK_TIMEOUT_MS = 300_000;
64
+ const TOOL_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
65
+
66
+ function freezeRecoveryProbe(
67
+ id: AgentClientId,
68
+ checkId: string,
69
+ value: AgentClientSandboxRecoveryCheck['probe']
70
+ ): AgentClientSandboxRecoveryCheck['probe'] {
71
+ if (
72
+ !value
73
+ || typeof value.script !== 'string'
74
+ || value.script.trim() === ''
75
+ || !Array.isArray(value.args)
76
+ || value.args.some((arg) => typeof arg !== 'string')
77
+ || (value.user !== undefined && (typeof value.user !== 'string' || value.user === ''))
78
+ ) {
79
+ throw new Error(`Agent Client '${id}' recovery check '${checkId}' has an invalid probe`);
80
+ }
81
+ return Object.freeze({
82
+ script: value.script,
83
+ args: Object.freeze([...value.args]),
84
+ ...(value.user === undefined ? {} : { user: value.user })
85
+ });
86
+ }
87
+
88
+ function freezeTool(tool: SandboxTool): SandboxTool {
89
+ if (typeof tool.id !== 'string' || !TOOL_ID_PATTERN.test(tool.id)) {
90
+ throw new Error(`Invalid sandbox tool id: ${String(tool.id)}`);
91
+ }
92
+ if (!tool.install?.cmd || !['npm', 'shell'].includes(tool.install.type)) {
93
+ throw new Error(`Sandbox tool '${tool.id}' has invalid install`);
94
+ }
95
+ if (!tool.containerMount.startsWith('/')) {
96
+ throw new Error(`Sandbox tool '${tool.id}' containerMount must be absolute`);
97
+ }
98
+ if (!tool.versionCmd) {
99
+ throw new Error(`Sandbox tool '${tool.id}' requires versionCmd`);
100
+ }
101
+ return Object.freeze({
102
+ ...tool,
103
+ install: Object.freeze({ ...tool.install }),
104
+ ...(tool.envVars ? { envVars: Object.freeze({ ...tool.envVars }) } : {}),
105
+ ...(tool.hostPreSeedFiles ? {
106
+ hostPreSeedFiles: Object.freeze(tool.hostPreSeedFiles.map((entry) => Object.freeze({ ...entry })))
107
+ } : {}),
108
+ ...(tool.hostPreSeedDirs ? {
109
+ hostPreSeedDirs: Object.freeze(tool.hostPreSeedDirs.map((entry) => Object.freeze({ ...entry })))
110
+ } : {}),
111
+ ...(tool.pathRewriteFiles ? { pathRewriteFiles: Object.freeze([...tool.pathRewriteFiles]) } : {}),
112
+ ...(tool.hostLiveMounts ? {
113
+ hostLiveMounts: Object.freeze(tool.hostLiveMounts.map((entry) => Object.freeze({ ...entry })))
114
+ } : {}),
115
+ ...(tool.postSetupCmds ? { postSetupCmds: Object.freeze([...tool.postSetupCmds]) } : {}),
116
+ ...(tool.tmpfs ? {
117
+ tmpfs: Object.freeze({
118
+ ...tool.tmpfs,
119
+ ...(tool.tmpfs.seed ? { seed: Object.freeze([...tool.tmpfs.seed]) } : {})
120
+ })
121
+ } : {})
122
+ }) as SandboxTool;
123
+ }
124
+
125
+ function freezeAliases(id: AgentClientId, aliases: readonly SandboxAlias[]): readonly SandboxAlias[] {
126
+ const names = new Set<string>();
127
+ return Object.freeze(aliases.map((alias) => {
128
+ if (!alias.name || !alias.command || names.has(alias.name)) {
129
+ throw new Error(`Agent Client '${id}' has invalid or duplicate sandbox alias '${alias.name}'`);
130
+ }
131
+ names.add(alias.name);
132
+ return Object.freeze({ ...alias });
133
+ }));
134
+ }
135
+
136
+ function isProjectRelativeLiteral(value: string): boolean {
137
+ if (
138
+ value.length === 0
139
+ || value.startsWith('/')
140
+ || /^[a-zA-Z]:/.test(value)
141
+ || value.includes('\\')
142
+ || /[*?[\]{}]/.test(value)
143
+ ) {
144
+ return false;
145
+ }
146
+ return !value.split('/').some((segment) => segment === '..');
147
+ }
148
+
149
+ function defineAgentClientAdapter(
150
+ candidate: AgentClientAdapter
151
+ ): AgentClientAdapter {
152
+ if (!isAgentClientId(candidate.id)) {
153
+ throw new Error(`Unknown Agent Client ID '${String(candidate.id)}'`);
154
+ }
155
+ if (typeof candidate.displayName !== 'string' || candidate.displayName.trim() === '') {
156
+ throw new Error(`Agent Client '${candidate.id}' requires a display name`);
157
+ }
158
+ if (
159
+ typeof candidate.invocation !== 'string'
160
+ || candidate.invocation.trim() === ''
161
+ || /[\r\n]/.test(candidate.invocation)
162
+ ) {
163
+ throw new Error(`Agent Client '${candidate.id}' requires a single-line invocation`);
164
+ }
165
+ const invocationPlaceholders = [
166
+ ...candidate.invocation.matchAll(/\$\{([^}]+)\}/g)
167
+ ].map((match) => match[1]);
168
+ if (
169
+ !invocationPlaceholders.includes('skillName')
170
+ || invocationPlaceholders.some((placeholder) =>
171
+ placeholder !== 'skillName' && placeholder !== 'projectName'
172
+ )
173
+ || candidate.invocation
174
+ .replaceAll('${skillName}', '')
175
+ .replaceAll('${projectName}', '')
176
+ .includes('${')
177
+ ) {
178
+ throw new Error(`Agent Client '${candidate.id}' has an invalid invocation`);
179
+ }
180
+
181
+ if (
182
+ typeof candidate.capabilities !== 'object'
183
+ || candidate.capabilities === null
184
+ || Array.isArray(candidate.capabilities)
185
+ ) {
186
+ throw new Error(`Agent Client '${candidate.id}' has an invalid capability map`);
187
+ }
188
+ const capabilityKeys = Object.keys(candidate.capabilities);
189
+ if (
190
+ capabilityKeys.length !== AGENT_CLIENT_CAPABILITY_IDS.length
191
+ || AGENT_CLIENT_CAPABILITY_IDS.some((capability) =>
192
+ !Object.prototype.hasOwnProperty.call(candidate.capabilities, capability)
193
+ )
194
+ ) {
195
+ throw new Error(`Agent Client '${candidate.id}' has an invalid capability map`);
196
+ }
197
+
198
+ const capabilities = Object.fromEntries(
199
+ AGENT_CLIENT_CAPABILITY_IDS.map((capability) => {
200
+ const support = candidate.capabilities[capability];
201
+ if (
202
+ typeof support !== 'object'
203
+ || support === null
204
+ || !AGENT_CLIENT_SUPPORT_LEVELS.includes(support.level)
205
+ ) {
206
+ throw new Error(
207
+ `Agent Client '${candidate.id}' has invalid support for '${capability}'`
208
+ );
209
+ }
210
+ return [capability, Object.freeze({ level: support.level })];
211
+ })
212
+ ) as AgentClientCapabilities;
213
+
214
+ if (
215
+ typeof candidate.project !== 'object'
216
+ || candidate.project === null
217
+ || Array.isArray(candidate.project)
218
+ ) {
219
+ throw new Error(`Agent Client '${candidate.id}' has an invalid project descriptor`);
220
+ }
221
+ const ownedPathPrefixes = candidate.project.ownedPathPrefixes;
222
+ if (!Array.isArray(ownedPathPrefixes) || ownedPathPrefixes.length === 0) {
223
+ throw new Error(`Agent Client '${candidate.id}' requires owned path prefixes`);
224
+ }
225
+
226
+ const paths = ownedPathPrefixes.map((prefix) => {
227
+ if (
228
+ typeof prefix !== 'string'
229
+ || !isProjectRelativeLiteral(prefix)
230
+ || !prefix.endsWith('/')
231
+ ) {
232
+ throw new Error(
233
+ `Agent Client '${candidate.id}' has invalid owned path prefix '${String(prefix)}'`
234
+ );
235
+ }
236
+ return prefix;
237
+ });
238
+ if (new Set(paths).size !== paths.length) {
239
+ throw new Error(`Agent Client '${candidate.id}' has duplicate owned path prefixes`);
240
+ }
241
+
242
+ const projectAssets = Object.fromEntries(
243
+ PROJECT_ASSET_CATEGORIES.map((category) => {
244
+ const values = candidate.project[category];
245
+ if (!Array.isArray(values)) {
246
+ throw new Error(
247
+ `Agent Client '${candidate.id}' has invalid '${category}' project assets`
248
+ );
249
+ }
250
+ const assets = values.map((asset) => {
251
+ if (
252
+ typeof asset !== 'string'
253
+ || !isProjectRelativeLiteral(asset)
254
+ || !paths.some((prefix) =>
255
+ asset === prefix.slice(0, -1) || asset.startsWith(prefix)
256
+ )
257
+ ) {
258
+ throw new Error(
259
+ `Agent Client '${candidate.id}' has invalid '${category}' project asset '${String(asset)}'`
260
+ );
261
+ }
262
+ return asset;
263
+ });
264
+ if (new Set(assets).size !== assets.length) {
265
+ throw new Error(
266
+ `Agent Client '${candidate.id}' has duplicate '${category}' project assets`
267
+ );
268
+ }
269
+ return [category, Object.freeze(assets)];
270
+ })
271
+ ) as Pick<AgentClientProjectDescriptor, 'managed' | 'merged' | 'ejected'>;
272
+
273
+ const categorizedAssets = PROJECT_ASSET_CATEGORIES.flatMap((category) =>
274
+ projectAssets[category].map((asset) => ({ asset, category }))
275
+ );
276
+ const seenAssets = new Map<string, string>();
277
+ for (const { asset, category } of categorizedAssets) {
278
+ const previous = seenAssets.get(asset);
279
+ if (previous) {
280
+ throw new Error(
281
+ `Agent Client '${candidate.id}' project asset '${asset}' overlaps '${previous}' and '${category}'`
282
+ );
283
+ }
284
+ seenAssets.set(asset, category);
285
+ }
286
+
287
+ if (!Array.isArray(candidate.project.seedCommands)) {
288
+ throw new Error(`Agent Client '${candidate.id}' has invalid seed commands`);
289
+ }
290
+ const seedTargets = new Set<string>();
291
+ const seedCommands = candidate.project.seedCommands.map((seed) => {
292
+ if (!seed || typeof seed !== 'object') {
293
+ throw new Error(`Agent Client '${candidate.id}' has an invalid seed command`);
294
+ }
295
+ const placeholders = [
296
+ ...seed.target.matchAll(/\$\{([^}]+)\}/g)
297
+ ].map((match) => match[1]);
298
+ const targetProbe = seed.target.replaceAll('${projectName}', 'project');
299
+ if (
300
+ placeholders.some((placeholder) => placeholder !== 'projectName')
301
+ || targetProbe.includes('${')
302
+ || !isProjectRelativeLiteral(targetProbe)
303
+ || !paths.some((prefix) =>
304
+ targetProbe === prefix.slice(0, -1) || targetProbe.startsWith(prefix)
305
+ )
306
+ || seedTargets.has(seed.target)
307
+ ) {
308
+ throw new Error(
309
+ `Agent Client '${candidate.id}' has invalid seed target '${String(seed.target)}'`
310
+ );
311
+ }
312
+ if (
313
+ !seed.templates
314
+ || typeof seed.templates.en !== 'string'
315
+ || typeof seed.templates['zh-CN'] !== 'string'
316
+ || !isProjectRelativeLiteral(seed.templates.en)
317
+ || !isProjectRelativeLiteral(seed.templates['zh-CN'])
318
+ ) {
319
+ throw new Error(`Agent Client '${candidate.id}' has invalid seed templates`);
320
+ }
321
+ seedTargets.add(seed.target);
322
+ return Object.freeze({
323
+ templates: Object.freeze({ ...seed.templates }),
324
+ target: seed.target
325
+ });
326
+ });
327
+
328
+ if (!candidate.sandbox || typeof candidate.sandbox.createTool !== 'function') {
329
+ throw new Error(`Agent Client '${candidate.id}' requires a sandbox descriptor`);
330
+ }
331
+ const hookIds = new Set<string>();
332
+ const hooks = Object.freeze(candidate.sandbox.hooks.map((hook) => {
333
+ if (
334
+ !hook.id
335
+ || hookIds.has(hook.id)
336
+ || !SANDBOX_HOOK_PHASES.includes(hook.phase)
337
+ || typeof hook.run !== 'function'
338
+ ) {
339
+ throw new Error(`Agent Client '${candidate.id}' has an invalid sandbox hook`);
340
+ }
341
+ if (
342
+ hook.timeoutMs !== undefined
343
+ && (
344
+ !Number.isInteger(hook.timeoutMs)
345
+ || hook.timeoutMs <= 0
346
+ || hook.timeoutMs > MAX_SANDBOX_HOOK_TIMEOUT_MS
347
+ )
348
+ ) {
349
+ throw new Error(`Agent Client '${candidate.id}' hook '${hook.id}' has invalid timeoutMs`);
350
+ }
351
+ hookIds.add(hook.id);
352
+ return Object.freeze({ ...hook });
353
+ }));
354
+ const recoveryCheckIds = new Set<string>();
355
+ if (
356
+ candidate.sandbox.recoveryChecks !== undefined
357
+ && !Array.isArray(candidate.sandbox.recoveryChecks)
358
+ ) {
359
+ throw new Error(`Agent Client '${candidate.id}' has invalid recovery checks`);
360
+ }
361
+ const recoveryChecks = Object.freeze(
362
+ (candidate.sandbox.recoveryChecks ?? []).map((check) => {
363
+ if (
364
+ !check
365
+ || typeof check.id !== 'string'
366
+ || !TOOL_ID_PATTERN.test(check.id)
367
+ || recoveryCheckIds.has(check.id)
368
+ ) {
369
+ throw new Error(`Agent Client '${candidate.id}' has an invalid recovery check`);
370
+ }
371
+ const probe = freezeRecoveryProbe(candidate.id, check.id, check.probe);
372
+ const when = check.when === undefined
373
+ ? undefined
374
+ : freezeRecoveryProbe(candidate.id, check.id, check.when);
375
+ if (
376
+ !check.finding
377
+ || !['permissions', 'builtin-link', 'hard-failure'].includes(check.finding.repairKind)
378
+ || typeof check.finding.message !== 'string'
379
+ || check.finding.message.trim() === ''
380
+ || (
381
+ check.finding.path !== undefined
382
+ && (typeof check.finding.path !== 'string' || !check.finding.path.startsWith('/'))
383
+ )
384
+ || (
385
+ check.finding.repairKind === 'permissions'
386
+ && check.finding.path === undefined
387
+ )
388
+ ) {
389
+ throw new Error(
390
+ `Agent Client '${candidate.id}' recovery check '${check.id}' has an invalid finding`
391
+ );
392
+ }
393
+ let repair: AgentClientSandboxRecoveryCheck['repair'];
394
+ if (check.repair !== undefined) {
395
+ if (
396
+ typeof check.repair.user !== 'string'
397
+ || check.repair.user === ''
398
+ || typeof check.repair.command !== 'string'
399
+ || check.repair.command === ''
400
+ || !Array.isArray(check.repair.args)
401
+ || check.repair.args.some((arg: unknown) => typeof arg !== 'string')
402
+ ) {
403
+ throw new Error(
404
+ `Agent Client '${candidate.id}' recovery check '${check.id}' has an invalid repair`
405
+ );
406
+ }
407
+ repair = Object.freeze({
408
+ user: check.repair.user,
409
+ command: check.repair.command,
410
+ args: Object.freeze([...check.repair.args])
411
+ });
412
+ }
413
+ if (check.finding.repairKind === 'builtin-link' && repair === undefined) {
414
+ throw new Error(
415
+ `Agent Client '${candidate.id}' recovery check '${check.id}' requires a repair`
416
+ );
417
+ }
418
+ recoveryCheckIds.add(check.id);
419
+ return Object.freeze({
420
+ id: check.id,
421
+ ...(when === undefined ? {} : { when }),
422
+ probe,
423
+ finding: Object.freeze({ ...check.finding }),
424
+ ...(repair === undefined ? {} : { repair })
425
+ });
426
+ })
427
+ );
428
+ const aliases = freezeAliases(candidate.id, candidate.sandbox.aliases);
429
+ const createTool = (context: SandboxToolContext): SandboxTool => {
430
+ const tool = freezeTool(candidate.sandbox.createTool(context));
431
+ if (tool.id !== candidate.id) {
432
+ throw new Error(
433
+ `Agent Client '${candidate.id}' sandbox tool id must match the adapter id`
434
+ );
435
+ }
436
+ return tool;
437
+ };
438
+
439
+ return Object.freeze({
440
+ id: candidate.id,
441
+ displayName: candidate.displayName,
442
+ invocation: candidate.invocation,
443
+ capabilities: Object.freeze(capabilities),
444
+ project: Object.freeze({
445
+ ownedPathPrefixes: Object.freeze(paths),
446
+ ...projectAssets,
447
+ seedCommands: Object.freeze(seedCommands)
448
+ }),
449
+ sandbox: Object.freeze({ createTool, aliases, hooks, recoveryChecks })
450
+ });
451
+ }
452
+
453
+ export { defineAgentClientAdapter };
454
+ export type {
455
+ AgentClientAdapter,
456
+ AgentClientCapabilities,
457
+ AgentClientManifestEntry,
458
+ AgentClientProjectDescriptor,
459
+ AgentClientSeedCommand,
460
+ AgentClientRegistry
461
+ };
@@ -0,0 +1,70 @@
1
+ import { defineAgentClientAdapter } from '../adapter.ts';
2
+ import { hostJoin } from '../../sandbox/engines/wsl2-paths.ts';
3
+
4
+ const claudeCodeAdapter = defineAgentClientAdapter({
5
+ id: 'claude-code',
6
+ displayName: 'Claude Code',
7
+ invocation: '/${skillName}',
8
+ capabilities: {
9
+ instructions: { level: 'compatible' },
10
+ skills: { level: 'compatible' },
11
+ commands: { level: 'integrated' },
12
+ hooks: { level: 'integrated' },
13
+ subagents: { level: 'experimental' },
14
+ orchestration: { level: 'experimental' },
15
+ sandbox: { level: 'integrated' },
16
+ verification: { level: 'compatible' }
17
+ },
18
+ project: {
19
+ ownedPathPrefixes: ['.claude/'],
20
+ managed: ['.claude/commands/', '.claude/agents/'],
21
+ merged: ['.claude/settings.json'],
22
+ ejected: [],
23
+ seedCommands: [{
24
+ templates: {
25
+ en: '.claude/commands/update-agent-infra.en.md',
26
+ 'zh-CN': '.claude/commands/update-agent-infra.zh-CN.md'
27
+ },
28
+ target: '.claude/commands/update-agent-infra.md'
29
+ }]
30
+ },
31
+ sandbox: {
32
+ createTool: ({ home, project }) => ({
33
+ id: 'claude-code',
34
+ name: 'Claude Code',
35
+ install: { type: 'npm', cmd: '@anthropic-ai/claude-code@latest' },
36
+ sandboxBase: hostJoin(home, '.agent-infra', 'sandboxes', 'claude-code'),
37
+ containerMount: '/home/devuser/.claude',
38
+ versionCmd: 'claude --version',
39
+ setupHint: 'Authenticates via host credentials live-mounted at ~/.claude/.credentials.json',
40
+ envVars: { CLAUDE_CONFIG_DIR: '/home/devuser/.claude' },
41
+ hostPreSeedDirs: [
42
+ { hostDir: hostJoin(home, '.claude', 'plugins'), sandboxSubdir: 'plugins' }
43
+ ],
44
+ pathRewriteFiles: [
45
+ 'plugins/installed_plugins.json',
46
+ 'plugins/known_marketplaces.json'
47
+ ],
48
+ hostLiveMounts: [
49
+ {
50
+ hostPath: hostJoin(
51
+ home,
52
+ '.agent-infra',
53
+ 'credentials',
54
+ project,
55
+ 'claude-code',
56
+ '.credentials.json'
57
+ ),
58
+ containerSubpath: '.credentials.json'
59
+ }
60
+ ]
61
+ }),
62
+ aliases: [
63
+ { name: 'claude-yolo', command: 'claude --dangerously-skip-permissions; tput ed' },
64
+ { name: 'cy', command: 'claude --dangerously-skip-permissions; tput ed' }
65
+ ],
66
+ hooks: []
67
+ }
68
+ });
69
+
70
+ export { claudeCodeAdapter };