@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,294 @@
1
+ import { AGENT_CLIENT_CAPABILITY_IDS, AGENT_CLIENT_SUPPORT_LEVELS, isAgentClientId } from './types.js';
2
+ import { SANDBOX_HOOK_PHASES } from '../sandbox/tool-types.js';
3
+ const PROJECT_ASSET_CATEGORIES = ['managed', 'merged', 'ejected'];
4
+ const MAX_SANDBOX_HOOK_TIMEOUT_MS = 300_000;
5
+ const TOOL_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
6
+ function freezeRecoveryProbe(id, checkId, value) {
7
+ if (!value
8
+ || typeof value.script !== 'string'
9
+ || value.script.trim() === ''
10
+ || !Array.isArray(value.args)
11
+ || value.args.some((arg) => typeof arg !== 'string')
12
+ || (value.user !== undefined && (typeof value.user !== 'string' || value.user === ''))) {
13
+ throw new Error(`Agent Client '${id}' recovery check '${checkId}' has an invalid probe`);
14
+ }
15
+ return Object.freeze({
16
+ script: value.script,
17
+ args: Object.freeze([...value.args]),
18
+ ...(value.user === undefined ? {} : { user: value.user })
19
+ });
20
+ }
21
+ function freezeTool(tool) {
22
+ if (typeof tool.id !== 'string' || !TOOL_ID_PATTERN.test(tool.id)) {
23
+ throw new Error(`Invalid sandbox tool id: ${String(tool.id)}`);
24
+ }
25
+ if (!tool.install?.cmd || !['npm', 'shell'].includes(tool.install.type)) {
26
+ throw new Error(`Sandbox tool '${tool.id}' has invalid install`);
27
+ }
28
+ if (!tool.containerMount.startsWith('/')) {
29
+ throw new Error(`Sandbox tool '${tool.id}' containerMount must be absolute`);
30
+ }
31
+ if (!tool.versionCmd) {
32
+ throw new Error(`Sandbox tool '${tool.id}' requires versionCmd`);
33
+ }
34
+ return Object.freeze({
35
+ ...tool,
36
+ install: Object.freeze({ ...tool.install }),
37
+ ...(tool.envVars ? { envVars: Object.freeze({ ...tool.envVars }) } : {}),
38
+ ...(tool.hostPreSeedFiles ? {
39
+ hostPreSeedFiles: Object.freeze(tool.hostPreSeedFiles.map((entry) => Object.freeze({ ...entry })))
40
+ } : {}),
41
+ ...(tool.hostPreSeedDirs ? {
42
+ hostPreSeedDirs: Object.freeze(tool.hostPreSeedDirs.map((entry) => Object.freeze({ ...entry })))
43
+ } : {}),
44
+ ...(tool.pathRewriteFiles ? { pathRewriteFiles: Object.freeze([...tool.pathRewriteFiles]) } : {}),
45
+ ...(tool.hostLiveMounts ? {
46
+ hostLiveMounts: Object.freeze(tool.hostLiveMounts.map((entry) => Object.freeze({ ...entry })))
47
+ } : {}),
48
+ ...(tool.postSetupCmds ? { postSetupCmds: Object.freeze([...tool.postSetupCmds]) } : {}),
49
+ ...(tool.tmpfs ? {
50
+ tmpfs: Object.freeze({
51
+ ...tool.tmpfs,
52
+ ...(tool.tmpfs.seed ? { seed: Object.freeze([...tool.tmpfs.seed]) } : {})
53
+ })
54
+ } : {})
55
+ });
56
+ }
57
+ function freezeAliases(id, aliases) {
58
+ const names = new Set();
59
+ return Object.freeze(aliases.map((alias) => {
60
+ if (!alias.name || !alias.command || names.has(alias.name)) {
61
+ throw new Error(`Agent Client '${id}' has invalid or duplicate sandbox alias '${alias.name}'`);
62
+ }
63
+ names.add(alias.name);
64
+ return Object.freeze({ ...alias });
65
+ }));
66
+ }
67
+ function isProjectRelativeLiteral(value) {
68
+ if (value.length === 0
69
+ || value.startsWith('/')
70
+ || /^[a-zA-Z]:/.test(value)
71
+ || value.includes('\\')
72
+ || /[*?[\]{}]/.test(value)) {
73
+ return false;
74
+ }
75
+ return !value.split('/').some((segment) => segment === '..');
76
+ }
77
+ function defineAgentClientAdapter(candidate) {
78
+ if (!isAgentClientId(candidate.id)) {
79
+ throw new Error(`Unknown Agent Client ID '${String(candidate.id)}'`);
80
+ }
81
+ if (typeof candidate.displayName !== 'string' || candidate.displayName.trim() === '') {
82
+ throw new Error(`Agent Client '${candidate.id}' requires a display name`);
83
+ }
84
+ if (typeof candidate.invocation !== 'string'
85
+ || candidate.invocation.trim() === ''
86
+ || /[\r\n]/.test(candidate.invocation)) {
87
+ throw new Error(`Agent Client '${candidate.id}' requires a single-line invocation`);
88
+ }
89
+ const invocationPlaceholders = [
90
+ ...candidate.invocation.matchAll(/\$\{([^}]+)\}/g)
91
+ ].map((match) => match[1]);
92
+ if (!invocationPlaceholders.includes('skillName')
93
+ || invocationPlaceholders.some((placeholder) => placeholder !== 'skillName' && placeholder !== 'projectName')
94
+ || candidate.invocation
95
+ .replaceAll('${skillName}', '')
96
+ .replaceAll('${projectName}', '')
97
+ .includes('${')) {
98
+ throw new Error(`Agent Client '${candidate.id}' has an invalid invocation`);
99
+ }
100
+ if (typeof candidate.capabilities !== 'object'
101
+ || candidate.capabilities === null
102
+ || Array.isArray(candidate.capabilities)) {
103
+ throw new Error(`Agent Client '${candidate.id}' has an invalid capability map`);
104
+ }
105
+ const capabilityKeys = Object.keys(candidate.capabilities);
106
+ if (capabilityKeys.length !== AGENT_CLIENT_CAPABILITY_IDS.length
107
+ || AGENT_CLIENT_CAPABILITY_IDS.some((capability) => !Object.prototype.hasOwnProperty.call(candidate.capabilities, capability))) {
108
+ throw new Error(`Agent Client '${candidate.id}' has an invalid capability map`);
109
+ }
110
+ const capabilities = Object.fromEntries(AGENT_CLIENT_CAPABILITY_IDS.map((capability) => {
111
+ const support = candidate.capabilities[capability];
112
+ if (typeof support !== 'object'
113
+ || support === null
114
+ || !AGENT_CLIENT_SUPPORT_LEVELS.includes(support.level)) {
115
+ throw new Error(`Agent Client '${candidate.id}' has invalid support for '${capability}'`);
116
+ }
117
+ return [capability, Object.freeze({ level: support.level })];
118
+ }));
119
+ if (typeof candidate.project !== 'object'
120
+ || candidate.project === null
121
+ || Array.isArray(candidate.project)) {
122
+ throw new Error(`Agent Client '${candidate.id}' has an invalid project descriptor`);
123
+ }
124
+ const ownedPathPrefixes = candidate.project.ownedPathPrefixes;
125
+ if (!Array.isArray(ownedPathPrefixes) || ownedPathPrefixes.length === 0) {
126
+ throw new Error(`Agent Client '${candidate.id}' requires owned path prefixes`);
127
+ }
128
+ const paths = ownedPathPrefixes.map((prefix) => {
129
+ if (typeof prefix !== 'string'
130
+ || !isProjectRelativeLiteral(prefix)
131
+ || !prefix.endsWith('/')) {
132
+ throw new Error(`Agent Client '${candidate.id}' has invalid owned path prefix '${String(prefix)}'`);
133
+ }
134
+ return prefix;
135
+ });
136
+ if (new Set(paths).size !== paths.length) {
137
+ throw new Error(`Agent Client '${candidate.id}' has duplicate owned path prefixes`);
138
+ }
139
+ const projectAssets = Object.fromEntries(PROJECT_ASSET_CATEGORIES.map((category) => {
140
+ const values = candidate.project[category];
141
+ if (!Array.isArray(values)) {
142
+ throw new Error(`Agent Client '${candidate.id}' has invalid '${category}' project assets`);
143
+ }
144
+ const assets = values.map((asset) => {
145
+ if (typeof asset !== 'string'
146
+ || !isProjectRelativeLiteral(asset)
147
+ || !paths.some((prefix) => asset === prefix.slice(0, -1) || asset.startsWith(prefix))) {
148
+ throw new Error(`Agent Client '${candidate.id}' has invalid '${category}' project asset '${String(asset)}'`);
149
+ }
150
+ return asset;
151
+ });
152
+ if (new Set(assets).size !== assets.length) {
153
+ throw new Error(`Agent Client '${candidate.id}' has duplicate '${category}' project assets`);
154
+ }
155
+ return [category, Object.freeze(assets)];
156
+ }));
157
+ const categorizedAssets = PROJECT_ASSET_CATEGORIES.flatMap((category) => projectAssets[category].map((asset) => ({ asset, category })));
158
+ const seenAssets = new Map();
159
+ for (const { asset, category } of categorizedAssets) {
160
+ const previous = seenAssets.get(asset);
161
+ if (previous) {
162
+ throw new Error(`Agent Client '${candidate.id}' project asset '${asset}' overlaps '${previous}' and '${category}'`);
163
+ }
164
+ seenAssets.set(asset, category);
165
+ }
166
+ if (!Array.isArray(candidate.project.seedCommands)) {
167
+ throw new Error(`Agent Client '${candidate.id}' has invalid seed commands`);
168
+ }
169
+ const seedTargets = new Set();
170
+ const seedCommands = candidate.project.seedCommands.map((seed) => {
171
+ if (!seed || typeof seed !== 'object') {
172
+ throw new Error(`Agent Client '${candidate.id}' has an invalid seed command`);
173
+ }
174
+ const placeholders = [
175
+ ...seed.target.matchAll(/\$\{([^}]+)\}/g)
176
+ ].map((match) => match[1]);
177
+ const targetProbe = seed.target.replaceAll('${projectName}', 'project');
178
+ if (placeholders.some((placeholder) => placeholder !== 'projectName')
179
+ || targetProbe.includes('${')
180
+ || !isProjectRelativeLiteral(targetProbe)
181
+ || !paths.some((prefix) => targetProbe === prefix.slice(0, -1) || targetProbe.startsWith(prefix))
182
+ || seedTargets.has(seed.target)) {
183
+ throw new Error(`Agent Client '${candidate.id}' has invalid seed target '${String(seed.target)}'`);
184
+ }
185
+ if (!seed.templates
186
+ || typeof seed.templates.en !== 'string'
187
+ || typeof seed.templates['zh-CN'] !== 'string'
188
+ || !isProjectRelativeLiteral(seed.templates.en)
189
+ || !isProjectRelativeLiteral(seed.templates['zh-CN'])) {
190
+ throw new Error(`Agent Client '${candidate.id}' has invalid seed templates`);
191
+ }
192
+ seedTargets.add(seed.target);
193
+ return Object.freeze({
194
+ templates: Object.freeze({ ...seed.templates }),
195
+ target: seed.target
196
+ });
197
+ });
198
+ if (!candidate.sandbox || typeof candidate.sandbox.createTool !== 'function') {
199
+ throw new Error(`Agent Client '${candidate.id}' requires a sandbox descriptor`);
200
+ }
201
+ const hookIds = new Set();
202
+ const hooks = Object.freeze(candidate.sandbox.hooks.map((hook) => {
203
+ if (!hook.id
204
+ || hookIds.has(hook.id)
205
+ || !SANDBOX_HOOK_PHASES.includes(hook.phase)
206
+ || typeof hook.run !== 'function') {
207
+ throw new Error(`Agent Client '${candidate.id}' has an invalid sandbox hook`);
208
+ }
209
+ if (hook.timeoutMs !== undefined
210
+ && (!Number.isInteger(hook.timeoutMs)
211
+ || hook.timeoutMs <= 0
212
+ || hook.timeoutMs > MAX_SANDBOX_HOOK_TIMEOUT_MS)) {
213
+ throw new Error(`Agent Client '${candidate.id}' hook '${hook.id}' has invalid timeoutMs`);
214
+ }
215
+ hookIds.add(hook.id);
216
+ return Object.freeze({ ...hook });
217
+ }));
218
+ const recoveryCheckIds = new Set();
219
+ if (candidate.sandbox.recoveryChecks !== undefined
220
+ && !Array.isArray(candidate.sandbox.recoveryChecks)) {
221
+ throw new Error(`Agent Client '${candidate.id}' has invalid recovery checks`);
222
+ }
223
+ const recoveryChecks = Object.freeze((candidate.sandbox.recoveryChecks ?? []).map((check) => {
224
+ if (!check
225
+ || typeof check.id !== 'string'
226
+ || !TOOL_ID_PATTERN.test(check.id)
227
+ || recoveryCheckIds.has(check.id)) {
228
+ throw new Error(`Agent Client '${candidate.id}' has an invalid recovery check`);
229
+ }
230
+ const probe = freezeRecoveryProbe(candidate.id, check.id, check.probe);
231
+ const when = check.when === undefined
232
+ ? undefined
233
+ : freezeRecoveryProbe(candidate.id, check.id, check.when);
234
+ if (!check.finding
235
+ || !['permissions', 'builtin-link', 'hard-failure'].includes(check.finding.repairKind)
236
+ || typeof check.finding.message !== 'string'
237
+ || check.finding.message.trim() === ''
238
+ || (check.finding.path !== undefined
239
+ && (typeof check.finding.path !== 'string' || !check.finding.path.startsWith('/')))
240
+ || (check.finding.repairKind === 'permissions'
241
+ && check.finding.path === undefined)) {
242
+ throw new Error(`Agent Client '${candidate.id}' recovery check '${check.id}' has an invalid finding`);
243
+ }
244
+ let repair;
245
+ if (check.repair !== undefined) {
246
+ if (typeof check.repair.user !== 'string'
247
+ || check.repair.user === ''
248
+ || typeof check.repair.command !== 'string'
249
+ || check.repair.command === ''
250
+ || !Array.isArray(check.repair.args)
251
+ || check.repair.args.some((arg) => typeof arg !== 'string')) {
252
+ throw new Error(`Agent Client '${candidate.id}' recovery check '${check.id}' has an invalid repair`);
253
+ }
254
+ repair = Object.freeze({
255
+ user: check.repair.user,
256
+ command: check.repair.command,
257
+ args: Object.freeze([...check.repair.args])
258
+ });
259
+ }
260
+ if (check.finding.repairKind === 'builtin-link' && repair === undefined) {
261
+ throw new Error(`Agent Client '${candidate.id}' recovery check '${check.id}' requires a repair`);
262
+ }
263
+ recoveryCheckIds.add(check.id);
264
+ return Object.freeze({
265
+ id: check.id,
266
+ ...(when === undefined ? {} : { when }),
267
+ probe,
268
+ finding: Object.freeze({ ...check.finding }),
269
+ ...(repair === undefined ? {} : { repair })
270
+ });
271
+ }));
272
+ const aliases = freezeAliases(candidate.id, candidate.sandbox.aliases);
273
+ const createTool = (context) => {
274
+ const tool = freezeTool(candidate.sandbox.createTool(context));
275
+ if (tool.id !== candidate.id) {
276
+ throw new Error(`Agent Client '${candidate.id}' sandbox tool id must match the adapter id`);
277
+ }
278
+ return tool;
279
+ };
280
+ return Object.freeze({
281
+ id: candidate.id,
282
+ displayName: candidate.displayName,
283
+ invocation: candidate.invocation,
284
+ capabilities: Object.freeze(capabilities),
285
+ project: Object.freeze({
286
+ ownedPathPrefixes: Object.freeze(paths),
287
+ ...projectAssets,
288
+ seedCommands: Object.freeze(seedCommands)
289
+ }),
290
+ sandbox: Object.freeze({ createTool, aliases, hooks, recoveryChecks })
291
+ });
292
+ }
293
+ export { defineAgentClientAdapter };
294
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1,62 @@
1
+ import { defineAgentClientAdapter } from '../adapter.js';
2
+ import { hostJoin } from '../../sandbox/engines/wsl2-paths.js';
3
+ const claudeCodeAdapter = defineAgentClientAdapter({
4
+ id: 'claude-code',
5
+ displayName: 'Claude Code',
6
+ invocation: '/${skillName}',
7
+ capabilities: {
8
+ instructions: { level: 'compatible' },
9
+ skills: { level: 'compatible' },
10
+ commands: { level: 'integrated' },
11
+ hooks: { level: 'integrated' },
12
+ subagents: { level: 'experimental' },
13
+ orchestration: { level: 'experimental' },
14
+ sandbox: { level: 'integrated' },
15
+ verification: { level: 'compatible' }
16
+ },
17
+ project: {
18
+ ownedPathPrefixes: ['.claude/'],
19
+ managed: ['.claude/commands/', '.claude/agents/'],
20
+ merged: ['.claude/settings.json'],
21
+ ejected: [],
22
+ seedCommands: [{
23
+ templates: {
24
+ en: '.claude/commands/update-agent-infra.en.md',
25
+ 'zh-CN': '.claude/commands/update-agent-infra.zh-CN.md'
26
+ },
27
+ target: '.claude/commands/update-agent-infra.md'
28
+ }]
29
+ },
30
+ sandbox: {
31
+ createTool: ({ home, project }) => ({
32
+ id: 'claude-code',
33
+ name: 'Claude Code',
34
+ install: { type: 'npm', cmd: '@anthropic-ai/claude-code@latest' },
35
+ sandboxBase: hostJoin(home, '.agent-infra', 'sandboxes', 'claude-code'),
36
+ containerMount: '/home/devuser/.claude',
37
+ versionCmd: 'claude --version',
38
+ setupHint: 'Authenticates via host credentials live-mounted at ~/.claude/.credentials.json',
39
+ envVars: { CLAUDE_CONFIG_DIR: '/home/devuser/.claude' },
40
+ hostPreSeedDirs: [
41
+ { hostDir: hostJoin(home, '.claude', 'plugins'), sandboxSubdir: 'plugins' }
42
+ ],
43
+ pathRewriteFiles: [
44
+ 'plugins/installed_plugins.json',
45
+ 'plugins/known_marketplaces.json'
46
+ ],
47
+ hostLiveMounts: [
48
+ {
49
+ hostPath: hostJoin(home, '.agent-infra', 'credentials', project, 'claude-code', '.credentials.json'),
50
+ containerSubpath: '.credentials.json'
51
+ }
52
+ ]
53
+ }),
54
+ aliases: [
55
+ { name: 'claude-yolo', command: 'claude --dangerously-skip-permissions; tput ed' },
56
+ { name: 'cy', command: 'claude --dangerously-skip-permissions; tput ed' }
57
+ ],
58
+ hooks: []
59
+ }
60
+ });
61
+ export { claudeCodeAdapter };
62
+ //# sourceMappingURL=claude-code.js.map
@@ -0,0 +1,210 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import * as toml from 'smol-toml';
4
+ function isJsonObjectRecord(value) {
5
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
6
+ }
7
+ function resolveHostCatalogPath(value, hostHomeDir) {
8
+ if (typeof value !== 'string' || value === '') {
9
+ return null;
10
+ }
11
+ let resolved;
12
+ if (value === '~' || value.startsWith('~/') || value.startsWith('~\\')) {
13
+ resolved = path.join(hostHomeDir, value.slice(1).replace(/^[/\\]+/, ''));
14
+ }
15
+ else if (path.isAbsolute(value)) {
16
+ resolved = value;
17
+ }
18
+ else {
19
+ resolved = path.join(hostHomeDir, '.codex', value);
20
+ }
21
+ try {
22
+ if (!fs.statSync(resolved).isFile()) {
23
+ return null;
24
+ }
25
+ fs.accessSync(resolved, fs.constants.R_OK);
26
+ return resolved;
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ const CODEX_DISABLED_FEATURE_FLAGS = ['apps', 'enable_mcp_apps'];
33
+ function removeCodexMcpServers(sandboxParsed) {
34
+ if (!Object.hasOwn(sandboxParsed, 'mcp_servers')) {
35
+ return false;
36
+ }
37
+ delete sandboxParsed.mcp_servers;
38
+ return true;
39
+ }
40
+ function inheritDisabledCodexFeatureFlags(sandboxParsed, hostParsed) {
41
+ if (!isJsonObjectRecord(hostParsed.features)) {
42
+ return false;
43
+ }
44
+ if (Object.hasOwn(sandboxParsed, 'features') && !isJsonObjectRecord(sandboxParsed.features)) {
45
+ return false;
46
+ }
47
+ let sandboxFeatures = sandboxParsed.features;
48
+ let changed = false;
49
+ for (const key of CODEX_DISABLED_FEATURE_FLAGS) {
50
+ if (hostParsed.features[key] !== false) {
51
+ continue;
52
+ }
53
+ if (!sandboxFeatures) {
54
+ sandboxFeatures = {};
55
+ sandboxParsed.features = sandboxFeatures;
56
+ }
57
+ if (sandboxFeatures[key] !== false) {
58
+ sandboxFeatures[key] = false;
59
+ changed = true;
60
+ }
61
+ }
62
+ return changed;
63
+ }
64
+ function ensureCodexModelInheritance(toolDir, hostHomeDir, containerCodexDir = '/home/devuser/.codex') {
65
+ if (!hostHomeDir) {
66
+ return;
67
+ }
68
+ const hostConfigPath = path.join(hostHomeDir, '.codex', 'config.toml');
69
+ if (!fs.existsSync(hostConfigPath)) {
70
+ return;
71
+ }
72
+ let hostParsed;
73
+ try {
74
+ hostParsed = toml.parse(fs.readFileSync(hostConfigPath, 'utf8'));
75
+ }
76
+ catch {
77
+ return;
78
+ }
79
+ const sandboxConfigPath = path.join(toolDir, 'config.toml');
80
+ // This rewrites sandbox-side TOML and drops comments; the host config stays untouched.
81
+ let sandboxParsed = {};
82
+ if (fs.existsSync(sandboxConfigPath)) {
83
+ try {
84
+ sandboxParsed = toml.parse(fs.readFileSync(sandboxConfigPath, 'utf8'));
85
+ }
86
+ catch {
87
+ return;
88
+ }
89
+ }
90
+ let changed = removeCodexMcpServers(sandboxParsed);
91
+ changed = inheritDisabledCodexFeatureFlags(sandboxParsed, hostParsed) || changed;
92
+ const inheritSpecs = [
93
+ ['model', 'string'],
94
+ ['model_reasoning_effort', 'string'],
95
+ ['model_auto_compact_token_limit', 'number']
96
+ ];
97
+ for (const [key, type] of inheritSpecs) {
98
+ if (Object.hasOwn(sandboxParsed, key)) {
99
+ continue;
100
+ }
101
+ const value = hostParsed[key];
102
+ if (type === 'string' && (typeof value !== 'string' || value === '')) {
103
+ continue;
104
+ }
105
+ if (type === 'number' && (typeof value !== 'number' || !Number.isFinite(value) || value <= 0)) {
106
+ continue;
107
+ }
108
+ sandboxParsed[key] = value;
109
+ changed = true;
110
+ }
111
+ if (!Object.hasOwn(sandboxParsed, 'model_catalog_json')) {
112
+ const hostCatalogPath = resolveHostCatalogPath(hostParsed['model_catalog_json'], hostHomeDir);
113
+ if (hostCatalogPath) {
114
+ try {
115
+ const basename = path.basename(hostCatalogPath);
116
+ const destDir = path.join(toolDir, 'model-catalogs');
117
+ fs.mkdirSync(destDir, { recursive: true });
118
+ fs.copyFileSync(hostCatalogPath, path.join(destDir, basename));
119
+ sandboxParsed['model_catalog_json'] = path.posix.join(containerCodexDir, 'model-catalogs', basename);
120
+ changed = true;
121
+ }
122
+ catch {
123
+ // Copy failed (e.g. permissions): skip catalog, keep scalar inheritance intact.
124
+ }
125
+ }
126
+ }
127
+ if (changed) {
128
+ fs.writeFileSync(sandboxConfigPath, `${toml.stringify(sandboxParsed)}\n`, 'utf8');
129
+ }
130
+ }
131
+ function ensureCodexWorkspaceTrust(toolDir) {
132
+ const configPath = path.join(toolDir, 'config.toml');
133
+ let content = '';
134
+ if (fs.existsSync(configPath)) {
135
+ content = fs.readFileSync(configPath, 'utf8');
136
+ }
137
+ if (!content.includes('[projects."/workspace"]')) {
138
+ const entry = '\n[projects."/workspace"]\ntrust_level = "trusted"\n';
139
+ fs.writeFileSync(configPath, content + entry, 'utf8');
140
+ }
141
+ }
142
+ const codexBeforeContainerCreateHook = {
143
+ id: 'codex-before-container-create',
144
+ phase: 'before-container-create',
145
+ async run(context) {
146
+ const create = context.create;
147
+ const entry = create?.resolvedTools.find(({ tool }) => tool.id === 'codex');
148
+ if (!create || !entry) {
149
+ return {
150
+ status: 'fatal',
151
+ message: 'Codex sandbox hook requires its resolved tool state.'
152
+ };
153
+ }
154
+ ensureCodexModelInheritance(entry.dir, create.hostHome, entry.tool.containerMount);
155
+ ensureCodexWorkspaceTrust(entry.dir);
156
+ return { status: 'ready' };
157
+ }
158
+ };
159
+ const codexRecoveryChecks = [
160
+ {
161
+ id: 'command-available',
162
+ probe: {
163
+ script: 'command -v "$1"',
164
+ args: ['codex']
165
+ },
166
+ finding: {
167
+ repairKind: 'hard-failure',
168
+ message: 'Codex is not available on PATH inside the sandbox.'
169
+ }
170
+ },
171
+ {
172
+ id: 'state-writable',
173
+ probe: {
174
+ script: 'probe="$1/.agent-infra-codex-state-$$"; trap \'rm -f -- "$probe"\' EXIT; : > "$probe"',
175
+ args: ['/home/devuser/.codex']
176
+ },
177
+ finding: {
178
+ repairKind: 'permissions',
179
+ message: 'Codex state directory is not writable by devuser.',
180
+ path: '/home/devuser/.codex'
181
+ }
182
+ },
183
+ {
184
+ id: 'prompts-link',
185
+ when: {
186
+ script: 'test -d "$1"',
187
+ args: ['/workspace/.codex/commands']
188
+ },
189
+ probe: {
190
+ script: 'test "$(readlink -- "$1")" = "$2"',
191
+ args: ['/home/devuser/.codex/prompts', '/workspace/.codex/commands']
192
+ },
193
+ finding: {
194
+ repairKind: 'builtin-link',
195
+ message: 'Codex prompts link does not point to the workspace commands directory.',
196
+ path: '/home/devuser/.codex/prompts'
197
+ },
198
+ repair: {
199
+ user: 'devuser',
200
+ command: 'ln',
201
+ args: [
202
+ '-sfn',
203
+ '/workspace/.codex/commands',
204
+ '/home/devuser/.codex/prompts'
205
+ ]
206
+ }
207
+ }
208
+ ];
209
+ export { codexBeforeContainerCreateHook, codexRecoveryChecks, ensureCodexModelInheritance, ensureCodexWorkspaceTrust };
210
+ //# sourceMappingURL=codex-sandbox.js.map
@@ -0,0 +1,54 @@
1
+ import { defineAgentClientAdapter } from '../adapter.js';
2
+ import { hostJoin } from '../../sandbox/engines/wsl2-paths.js';
3
+ import { codexBeforeContainerCreateHook, codexRecoveryChecks } from './codex-sandbox.js';
4
+ const codexAdapter = defineAgentClientAdapter({
5
+ id: 'codex',
6
+ displayName: 'Codex',
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: 'unsupported' },
15
+ sandbox: { level: 'integrated' },
16
+ verification: { level: 'compatible' }
17
+ },
18
+ project: {
19
+ ownedPathPrefixes: ['.codex/'],
20
+ managed: ['.codex/hooks.json', '.codex/agents/'],
21
+ merged: [],
22
+ ejected: [],
23
+ seedCommands: []
24
+ },
25
+ sandbox: {
26
+ createTool: ({ home }) => ({
27
+ id: 'codex',
28
+ name: 'Codex',
29
+ install: { type: 'npm', cmd: '@openai/codex' },
30
+ sandboxBase: hostJoin(home, '.agent-infra', 'sandboxes', 'codex'),
31
+ containerMount: '/home/devuser/.codex',
32
+ versionCmd: 'codex --version',
33
+ setupHint: 'Run codex once inside the container and choose Device Code login if needed.',
34
+ tmpfs: { size: '512m', seed: ['config.toml', 'model-catalogs'] },
35
+ hostLiveMounts: [
36
+ {
37
+ hostPath: hostJoin(home, '.codex', 'auth.json'),
38
+ containerSubpath: 'auth.json'
39
+ }
40
+ ],
41
+ postSetupCmds: [
42
+ 'test -d /workspace/.codex/commands && ln -sfn /workspace/.codex/commands /home/devuser/.codex/prompts || true'
43
+ ]
44
+ }),
45
+ aliases: [
46
+ { name: 'codex-yolo', command: 'codex --yolo; tput ed' },
47
+ { name: 'xy', command: 'codex --yolo; tput ed' }
48
+ ],
49
+ hooks: [codexBeforeContainerCreateHook],
50
+ recoveryChecks: codexRecoveryChecks
51
+ }
52
+ });
53
+ export { codexAdapter };
54
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1,64 @@
1
+ import { defineAgentClientAdapter } from '../adapter.js';
2
+ import { hostJoin } from '../../sandbox/engines/wsl2-paths.js';
3
+ const geminiCliAdapter = defineAgentClientAdapter({
4
+ id: 'gemini-cli',
5
+ displayName: 'Gemini CLI',
6
+ invocation: '/${projectName}:${skillName}',
7
+ capabilities: {
8
+ instructions: { level: 'compatible' },
9
+ skills: { level: 'compatible' },
10
+ commands: { level: 'integrated' },
11
+ hooks: { level: 'compatible' },
12
+ subagents: { level: 'unsupported' },
13
+ orchestration: { level: 'unsupported' },
14
+ sandbox: { level: 'integrated' },
15
+ verification: { level: 'compatible' }
16
+ },
17
+ project: {
18
+ ownedPathPrefixes: ['.gemini/'],
19
+ managed: ['.gemini/commands/'],
20
+ merged: ['.gemini/settings.json'],
21
+ ejected: [],
22
+ seedCommands: [{
23
+ templates: {
24
+ en: '.gemini/commands/_project_/update-agent-infra.en.toml',
25
+ 'zh-CN': '.gemini/commands/_project_/update-agent-infra.zh-CN.toml'
26
+ },
27
+ target: '.gemini/commands/${projectName}/update-agent-infra.toml'
28
+ }]
29
+ },
30
+ sandbox: {
31
+ createTool: ({ home }) => ({
32
+ id: 'gemini-cli',
33
+ name: 'Gemini CLI',
34
+ install: { type: 'npm', cmd: '@google/gemini-cli' },
35
+ sandboxBase: hostJoin(home, '.agent-infra', 'sandboxes', 'gemini-cli'),
36
+ containerMount: '/home/devuser/.gemini',
37
+ versionCmd: 'gemini --version',
38
+ setupHint: 'Run gemini inside the container to finish authentication.',
39
+ hostLiveMounts: [
40
+ {
41
+ hostPath: hostJoin(home, '.gemini', 'oauth_creds.json'),
42
+ containerSubpath: 'oauth_creds.json'
43
+ }
44
+ ],
45
+ hostPreSeedFiles: [
46
+ {
47
+ hostPath: hostJoin(home, '.gemini', 'settings.json'),
48
+ sandboxName: 'settings.json'
49
+ },
50
+ {
51
+ hostPath: hostJoin(home, '.gemini', 'google_accounts.json'),
52
+ sandboxName: 'google_accounts.json'
53
+ }
54
+ ]
55
+ }),
56
+ aliases: [
57
+ { name: 'gemini-yolo', command: 'gemini --yolo; tput ed' },
58
+ { name: 'gy', command: 'gemini --yolo; tput ed' }
59
+ ],
60
+ hooks: []
61
+ }
62
+ });
63
+ export { geminiCliAdapter };
64
+ //# sourceMappingURL=gemini-cli.js.map