agent-devkit 0.1.5 → 0.2.0

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 (606) hide show
  1. package/README.md +14 -2
  2. package/package.json +1 -1
  3. package/runtime/README.md +127 -6
  4. package/runtime/agent +5 -0
  5. package/runtime/agents/README.md +34 -0
  6. package/runtime/agents/agent-devkit-agent-builder/AGENTS.md +24 -0
  7. package/runtime/agents/agent-devkit-agent-builder/README.md +37 -0
  8. package/runtime/agents/agent-devkit-agent-builder/agent.yaml +46 -0
  9. package/runtime/agents/agent-devkit-agent-builder/capabilities/plan-agent/capability.yaml +29 -0
  10. package/runtime/agents/agent-devkit-agent-builder/capabilities/plan-agent/decision-rules.md +7 -0
  11. package/runtime/agents/agent-devkit-agent-builder/capabilities/plan-agent/runner.py +33 -0
  12. package/runtime/agents/agent-devkit-agent-builder/capabilities/plan-agent/workflow.md +8 -0
  13. package/runtime/agents/agent-devkit-agent-builder/capabilities/scaffold-agent/capability.yaml +31 -0
  14. package/runtime/agents/agent-devkit-agent-builder/capabilities/scaffold-agent/decision-rules.md +9 -0
  15. package/runtime/agents/agent-devkit-agent-builder/capabilities/scaffold-agent/runner.py +39 -0
  16. package/runtime/agents/agent-devkit-agent-builder/capabilities/scaffold-agent/workflow.md +8 -0
  17. package/runtime/agents/agent-devkit-agent-builder/capabilities/validate-agent-contract/capability.yaml +28 -0
  18. package/runtime/agents/agent-devkit-agent-builder/capabilities/validate-agent-contract/decision-rules.md +6 -0
  19. package/runtime/agents/agent-devkit-agent-builder/capabilities/validate-agent-contract/runner.py +33 -0
  20. package/runtime/agents/agent-devkit-agent-builder/capabilities/validate-agent-contract/workflow.md +7 -0
  21. package/runtime/agents/agent-devkit-agent-builder/infra/integrations/agent-devkit/agent_builder_repository.py +527 -0
  22. package/runtime/agents/agent-devkit-agent-builder/knowledge/context.md +15 -0
  23. package/runtime/agents/agent-devkit-agent-builder/knowledge/policies.yaml +11 -0
  24. package/runtime/agents/agent-devkit-agent-builder/knowledge/system.md +11 -0
  25. package/runtime/agents/agent-devkit-agent-builder/templates/agent-plan-output.md +20 -0
  26. package/runtime/agents/agent-devkit-agent-builder/templates/scaffold-plan-output.md +13 -0
  27. package/runtime/agents/agent-devkit-agent-builder/templates/validation-report-output.md +13 -0
  28. package/runtime/agents/agent-devkit-agent-builder/tests/test_runners.py +188 -0
  29. package/runtime/agents/automation-architect/AGENTS.md +11 -0
  30. package/runtime/agents/automation-architect/README.md +27 -0
  31. package/runtime/agents/automation-architect/agent.yaml +57 -0
  32. package/runtime/agents/automation-architect/capabilities/classify-automation-request/capability.yaml +35 -0
  33. package/runtime/agents/automation-architect/capabilities/classify-automation-request/decision-rules.md +10 -0
  34. package/runtime/agents/automation-architect/capabilities/classify-automation-request/runner.py +37 -0
  35. package/runtime/agents/automation-architect/capabilities/classify-automation-request/workflow.md +7 -0
  36. package/runtime/agents/automation-architect/capabilities/delegate-automation-build/capability.yaml +34 -0
  37. package/runtime/agents/automation-architect/capabilities/delegate-automation-build/decision-rules.md +7 -0
  38. package/runtime/agents/automation-architect/capabilities/delegate-automation-build/runner.py +37 -0
  39. package/runtime/agents/automation-architect/capabilities/delegate-automation-build/workflow.md +6 -0
  40. package/runtime/agents/automation-architect/capabilities/plan-automation-solution/capability.yaml +35 -0
  41. package/runtime/agents/automation-architect/capabilities/plan-automation-solution/decision-rules.md +7 -0
  42. package/runtime/agents/automation-architect/capabilities/plan-automation-solution/runner.py +37 -0
  43. package/runtime/agents/automation-architect/capabilities/plan-automation-solution/workflow.md +7 -0
  44. package/runtime/agents/automation-architect/capabilities/review-automation-solution/capability.yaml +36 -0
  45. package/runtime/agents/automation-architect/capabilities/review-automation-solution/decision-rules.md +7 -0
  46. package/runtime/agents/automation-architect/capabilities/review-automation-solution/runner.py +39 -0
  47. package/runtime/agents/automation-architect/capabilities/review-automation-solution/workflow.md +7 -0
  48. package/runtime/agents/automation-architect/infra/integrations/automation-architecture/automation_architecture_repository.py +481 -0
  49. package/runtime/agents/automation-architect/knowledge/context.md +22 -0
  50. package/runtime/agents/automation-architect/knowledge/policies.yaml +20 -0
  51. package/runtime/agents/automation-architect/knowledge/system.md +8 -0
  52. package/runtime/agents/automation-architect/templates/automation-classification.md +6 -0
  53. package/runtime/agents/automation-architect/templates/automation-plan.md +5 -0
  54. package/runtime/agents/automation-architect/tests/test_runners.py +135 -0
  55. package/runtime/agents/aws-architecture-analyst/agent.yaml +17 -4
  56. package/runtime/agents/aws-cloudwatch-log-analyzer/agent.yaml +12 -2
  57. package/runtime/agents/aws-cloudwatch-log-analyzer/capabilities/analyze-service-error/capability.yaml +16 -0
  58. package/runtime/agents/aws-lambda-builder/AGENTS.md +27 -0
  59. package/runtime/agents/aws-lambda-builder/README.md +21 -0
  60. package/runtime/agents/aws-lambda-builder/agent.yaml +46 -0
  61. package/runtime/agents/aws-lambda-builder/capabilities/deploy-lambda-plan/capability.yaml +18 -0
  62. package/runtime/agents/aws-lambda-builder/capabilities/deploy-lambda-plan/decision-rules.md +6 -0
  63. package/runtime/agents/aws-lambda-builder/capabilities/deploy-lambda-plan/runner.py +33 -0
  64. package/runtime/agents/aws-lambda-builder/capabilities/deploy-lambda-plan/workflow.md +6 -0
  65. package/runtime/agents/aws-lambda-builder/capabilities/generate-lambda-project/capability.yaml +20 -0
  66. package/runtime/agents/aws-lambda-builder/capabilities/generate-lambda-project/decision-rules.md +6 -0
  67. package/runtime/agents/aws-lambda-builder/capabilities/generate-lambda-project/runner.py +39 -0
  68. package/runtime/agents/aws-lambda-builder/capabilities/generate-lambda-project/workflow.md +7 -0
  69. package/runtime/agents/aws-lambda-builder/capabilities/package-lambda/capability.yaml +22 -0
  70. package/runtime/agents/aws-lambda-builder/capabilities/package-lambda/decision-rules.md +6 -0
  71. package/runtime/agents/aws-lambda-builder/capabilities/package-lambda/runner.py +41 -0
  72. package/runtime/agents/aws-lambda-builder/capabilities/package-lambda/workflow.md +6 -0
  73. package/runtime/agents/aws-lambda-builder/capabilities/plan-lambda/capability.yaml +18 -0
  74. package/runtime/agents/aws-lambda-builder/capabilities/plan-lambda/decision-rules.md +7 -0
  75. package/runtime/agents/aws-lambda-builder/capabilities/plan-lambda/runner.py +33 -0
  76. package/runtime/agents/aws-lambda-builder/capabilities/plan-lambda/workflow.md +6 -0
  77. package/runtime/agents/aws-lambda-builder/capabilities/review-lambda-security/capability.yaml +18 -0
  78. package/runtime/agents/aws-lambda-builder/capabilities/review-lambda-security/decision-rules.md +7 -0
  79. package/runtime/agents/aws-lambda-builder/capabilities/review-lambda-security/runner.py +33 -0
  80. package/runtime/agents/aws-lambda-builder/capabilities/review-lambda-security/workflow.md +5 -0
  81. package/runtime/agents/aws-lambda-builder/infra/integrations/aws-lambda/aws_lambda_repository.py +688 -0
  82. package/runtime/agents/aws-lambda-builder/knowledge/context.md +12 -0
  83. package/runtime/agents/aws-lambda-builder/knowledge/policies.yaml +23 -0
  84. package/runtime/agents/aws-lambda-builder/knowledge/system.md +10 -0
  85. package/runtime/agents/aws-lambda-builder/templates/lambda-deploy-plan.md +3 -0
  86. package/runtime/agents/aws-lambda-builder/templates/lambda-package.md +3 -0
  87. package/runtime/agents/aws-lambda-builder/templates/lambda-plan.md +3 -0
  88. package/runtime/agents/aws-lambda-builder/templates/lambda-readme.md +3 -0
  89. package/runtime/agents/aws-lambda-builder/templates/lambda-security-review.md +3 -0
  90. package/runtime/agents/aws-lambda-builder/tests/test_runners.py +355 -0
  91. package/runtime/agents/aws-operations-operator/agent.yaml +18 -6
  92. package/runtime/agents/aws-security-governance-auditor/agent.yaml +17 -5
  93. package/runtime/agents/azure-devops-orchestrator/agent.yaml +15 -2
  94. package/runtime/agents/azure-devops-orchestrator/capabilities/read-card/capability.yaml +29 -0
  95. package/runtime/agents/bpo-analyser/agent.yaml +12 -2
  96. package/runtime/agents/bpo-analyser/knowledge/policies.yaml +2 -2
  97. package/runtime/agents/data-scientist-analyst/agent.yaml +16 -4
  98. package/runtime/agents/data-scientist-analyst/capabilities/generate-data-report/capability.yaml +1 -1
  99. package/runtime/agents/data-scientist-analyst/capabilities/generate-reconciliation-report/capability.yaml +1 -1
  100. package/runtime/agents/data-scientist-analyst/capabilities/run-data-pipeline/capability.yaml +1 -1
  101. package/runtime/agents/data-scientist-analyst/infra/integrations/agent-bridge/methods/analyze-sql-source.yaml +1 -1
  102. package/runtime/agents/data-scientist-analyst/knowledge/policies.yaml +4 -4
  103. package/runtime/agents/data-scientist-analyst/knowledge/system.md +1 -1
  104. package/runtime/agents/data-scientist-analyst/tests/test_runners.py +1 -1
  105. package/runtime/agents/database-change-operator/agent.yaml +12 -1
  106. package/runtime/agents/docker-container-builder/AGENTS.md +27 -0
  107. package/runtime/agents/docker-container-builder/README.md +21 -0
  108. package/runtime/agents/docker-container-builder/agent.yaml +52 -0
  109. package/runtime/agents/docker-container-builder/capabilities/analyze-containerization-target/capability.yaml +18 -0
  110. package/runtime/agents/docker-container-builder/capabilities/analyze-containerization-target/decision-rules.md +6 -0
  111. package/runtime/agents/docker-container-builder/capabilities/analyze-containerization-target/runner.py +32 -0
  112. package/runtime/agents/docker-container-builder/capabilities/analyze-containerization-target/workflow.md +6 -0
  113. package/runtime/agents/docker-container-builder/capabilities/generate-compose/capability.yaml +18 -0
  114. package/runtime/agents/docker-container-builder/capabilities/generate-compose/decision-rules.md +7 -0
  115. package/runtime/agents/docker-container-builder/capabilities/generate-compose/runner.py +32 -0
  116. package/runtime/agents/docker-container-builder/capabilities/generate-compose/workflow.md +6 -0
  117. package/runtime/agents/docker-container-builder/capabilities/generate-container-project-files/capability.yaml +20 -0
  118. package/runtime/agents/docker-container-builder/capabilities/generate-container-project-files/decision-rules.md +7 -0
  119. package/runtime/agents/docker-container-builder/capabilities/generate-container-project-files/runner.py +38 -0
  120. package/runtime/agents/docker-container-builder/capabilities/generate-container-project-files/workflow.md +7 -0
  121. package/runtime/agents/docker-container-builder/capabilities/generate-dockerfile/capability.yaml +18 -0
  122. package/runtime/agents/docker-container-builder/capabilities/generate-dockerfile/decision-rules.md +6 -0
  123. package/runtime/agents/docker-container-builder/capabilities/generate-dockerfile/runner.py +32 -0
  124. package/runtime/agents/docker-container-builder/capabilities/generate-dockerfile/workflow.md +7 -0
  125. package/runtime/agents/docker-container-builder/capabilities/plan-image-build/capability.yaml +18 -0
  126. package/runtime/agents/docker-container-builder/capabilities/plan-image-build/decision-rules.md +6 -0
  127. package/runtime/agents/docker-container-builder/capabilities/plan-image-build/runner.py +32 -0
  128. package/runtime/agents/docker-container-builder/capabilities/plan-image-build/workflow.md +6 -0
  129. package/runtime/agents/docker-container-builder/capabilities/review-docker-security/capability.yaml +21 -0
  130. package/runtime/agents/docker-container-builder/capabilities/review-docker-security/decision-rules.md +6 -0
  131. package/runtime/agents/docker-container-builder/capabilities/review-docker-security/runner.py +43 -0
  132. package/runtime/agents/docker-container-builder/capabilities/review-docker-security/workflow.md +5 -0
  133. package/runtime/agents/docker-container-builder/infra/integrations/docker-container/docker_container_repository.py +837 -0
  134. package/runtime/agents/docker-container-builder/knowledge/context.md +21 -0
  135. package/runtime/agents/docker-container-builder/knowledge/policies.yaml +13 -0
  136. package/runtime/agents/docker-container-builder/knowledge/system.md +21 -0
  137. package/runtime/agents/docker-container-builder/templates/container-plan.md +4 -0
  138. package/runtime/agents/docker-container-builder/templates/container-review.md +4 -0
  139. package/runtime/agents/docker-container-builder/templates/docker-compose.md +5 -0
  140. package/runtime/agents/docker-container-builder/templates/docker-readme.md +3 -0
  141. package/runtime/agents/docker-container-builder/templates/dockerfile.md +5 -0
  142. package/runtime/agents/docker-container-builder/tests/test_runners.py +255 -0
  143. package/runtime/agents/drawio-diagram-builder/agent.yaml +11 -2
  144. package/runtime/agents/drawio-diagram-builder/capabilities/execute-diagram-delivery/capability.yaml +1 -1
  145. package/runtime/agents/drawio-diagram-builder/capabilities/read-azure-card-context/capability.yaml +1 -1
  146. package/runtime/agents/elasticsearch-log-analyzer/agent.yaml +14 -2
  147. package/runtime/agents/elasticsearch-log-analyzer/capabilities/analyze-service-errors/capability.yaml +14 -0
  148. package/runtime/agents/excel-workbook-builder/agent.yaml +10 -0
  149. package/runtime/agents/excel-workbook-builder/capabilities/create-template/capability.yaml +1 -1
  150. package/runtime/agents/excel-workbook-builder/capabilities/create-template/workflow.md +1 -1
  151. package/runtime/agents/excel-workbook-builder/capabilities/create-template-version/capability.yaml +1 -1
  152. package/runtime/agents/excel-workbook-builder/capabilities/generate-template-input-file/capability.yaml +1 -2
  153. package/runtime/agents/excel-workbook-builder/capabilities/refine-template/capability.yaml +1 -1
  154. package/runtime/agents/excel-workbook-builder/capabilities/register-template/capability.yaml +1 -2
  155. package/runtime/agents/excel-workbook-builder/capabilities/register-template/workflow.md +1 -1
  156. package/runtime/agents/execution-loop-builder/AGENTS.md +24 -0
  157. package/runtime/agents/execution-loop-builder/README.md +19 -0
  158. package/runtime/agents/execution-loop-builder/agent.yaml +49 -0
  159. package/runtime/agents/execution-loop-builder/capabilities/generate-loop-project-files/capability.yaml +20 -0
  160. package/runtime/agents/execution-loop-builder/capabilities/generate-loop-project-files/decision-rules.md +6 -0
  161. package/runtime/agents/execution-loop-builder/capabilities/generate-loop-project-files/runner.py +38 -0
  162. package/runtime/agents/execution-loop-builder/capabilities/generate-loop-project-files/workflow.md +7 -0
  163. package/runtime/agents/execution-loop-builder/capabilities/generate-loop-runner/capability.yaml +18 -0
  164. package/runtime/agents/execution-loop-builder/capabilities/generate-loop-runner/decision-rules.md +5 -0
  165. package/runtime/agents/execution-loop-builder/capabilities/generate-loop-runner/runner.py +32 -0
  166. package/runtime/agents/execution-loop-builder/capabilities/generate-loop-runner/workflow.md +6 -0
  167. package/runtime/agents/execution-loop-builder/capabilities/plan-execution-loop/capability.yaml +18 -0
  168. package/runtime/agents/execution-loop-builder/capabilities/plan-execution-loop/decision-rules.md +6 -0
  169. package/runtime/agents/execution-loop-builder/capabilities/plan-execution-loop/runner.py +32 -0
  170. package/runtime/agents/execution-loop-builder/capabilities/plan-execution-loop/workflow.md +6 -0
  171. package/runtime/agents/execution-loop-builder/capabilities/register-loop-task/capability.yaml +19 -0
  172. package/runtime/agents/execution-loop-builder/capabilities/register-loop-task/decision-rules.md +6 -0
  173. package/runtime/agents/execution-loop-builder/capabilities/register-loop-task/runner.py +36 -0
  174. package/runtime/agents/execution-loop-builder/capabilities/register-loop-task/workflow.md +6 -0
  175. package/runtime/agents/execution-loop-builder/capabilities/review-loop-safety/capability.yaml +19 -0
  176. package/runtime/agents/execution-loop-builder/capabilities/review-loop-safety/decision-rules.md +6 -0
  177. package/runtime/agents/execution-loop-builder/capabilities/review-loop-safety/runner.py +39 -0
  178. package/runtime/agents/execution-loop-builder/capabilities/review-loop-safety/workflow.md +5 -0
  179. package/runtime/agents/execution-loop-builder/infra/integrations/execution-loop/execution_loop_repository.py +608 -0
  180. package/runtime/agents/execution-loop-builder/knowledge/context.md +26 -0
  181. package/runtime/agents/execution-loop-builder/knowledge/policies.yaml +13 -0
  182. package/runtime/agents/execution-loop-builder/knowledge/system.md +19 -0
  183. package/runtime/agents/execution-loop-builder/templates/loop-plan.md +3 -0
  184. package/runtime/agents/execution-loop-builder/templates/loop-readme.md +3 -0
  185. package/runtime/agents/execution-loop-builder/templates/loop-review.md +3 -0
  186. package/runtime/agents/execution-loop-builder/templates/loop-runner.py +2 -0
  187. package/runtime/agents/execution-loop-builder/tests/test_runners.py +274 -0
  188. package/runtime/agents/execution-reviewer/AGENTS.md +8 -0
  189. package/runtime/agents/execution-reviewer/README.md +13 -0
  190. package/runtime/agents/execution-reviewer/agent.yaml +27 -0
  191. package/runtime/agents/execution-reviewer/capabilities/review-agent-result/capability.yaml +14 -0
  192. package/runtime/agents/execution-reviewer/capabilities/review-agent-result/decision-rules.md +6 -0
  193. package/runtime/agents/execution-reviewer/capabilities/review-agent-result/workflow.md +7 -0
  194. package/runtime/agents/execution-reviewer/capabilities/review-final-output/capability.yaml +14 -0
  195. package/runtime/agents/execution-reviewer/capabilities/review-final-output/decision-rules.md +6 -0
  196. package/runtime/agents/execution-reviewer/capabilities/review-final-output/workflow.md +7 -0
  197. package/runtime/agents/execution-reviewer/capabilities/review-plan/capability.yaml +14 -0
  198. package/runtime/agents/execution-reviewer/capabilities/review-plan/decision-rules.md +6 -0
  199. package/runtime/agents/execution-reviewer/capabilities/review-plan/workflow.md +7 -0
  200. package/runtime/agents/execution-reviewer/infra/README.md +4 -0
  201. package/runtime/agents/execution-reviewer/knowledge/context.md +6 -0
  202. package/runtime/agents/execution-reviewer/knowledge/system.md +18 -0
  203. package/runtime/agents/execution-reviewer/templates/README.md +4 -0
  204. package/runtime/agents/figma-ui-ux-product-designer/agent.yaml +17 -5
  205. package/runtime/agents/figma-ui-ux-product-designer/capabilities/analyze-product-context/capability.yaml +1 -1
  206. package/runtime/agents/figma-ui-ux-product-designer/capabilities/conduct-design-interview/capability.yaml +1 -1
  207. package/runtime/agents/figma-ui-ux-product-designer/capabilities/conduct-design-review-session/capability.yaml +1 -1
  208. package/runtime/agents/figma-ui-ux-product-designer/capabilities/generate-dev-handoff/capability.yaml +1 -1
  209. package/runtime/agents/figma-ui-ux-product-designer/capabilities/generate-user-journey-diagram/capability.yaml +1 -1
  210. package/runtime/agents/figma-ui-ux-product-designer/capabilities/ingest-design-source/capability.yaml +1 -1
  211. package/runtime/agents/figma-ui-ux-product-designer/capabilities/triage-design-feedback/capability.yaml +1 -1
  212. package/runtime/agents/generic-agent-builder/AGENTS.md +20 -0
  213. package/runtime/agents/generic-agent-builder/README.md +40 -0
  214. package/runtime/agents/generic-agent-builder/agent.yaml +43 -0
  215. package/runtime/agents/generic-agent-builder/capabilities/generate-agent-instructions/capability.yaml +18 -0
  216. package/runtime/agents/generic-agent-builder/capabilities/generate-agent-instructions/decision-rules.md +5 -0
  217. package/runtime/agents/generic-agent-builder/capabilities/generate-agent-instructions/runner.py +33 -0
  218. package/runtime/agents/generic-agent-builder/capabilities/generate-agent-instructions/workflow.md +6 -0
  219. package/runtime/agents/generic-agent-builder/capabilities/generate-project-agent-files/capability.yaml +20 -0
  220. package/runtime/agents/generic-agent-builder/capabilities/generate-project-agent-files/decision-rules.md +6 -0
  221. package/runtime/agents/generic-agent-builder/capabilities/generate-project-agent-files/runner.py +39 -0
  222. package/runtime/agents/generic-agent-builder/capabilities/generate-project-agent-files/workflow.md +7 -0
  223. package/runtime/agents/generic-agent-builder/capabilities/generate-skill/capability.yaml +18 -0
  224. package/runtime/agents/generic-agent-builder/capabilities/generate-skill/decision-rules.md +5 -0
  225. package/runtime/agents/generic-agent-builder/capabilities/generate-skill/runner.py +33 -0
  226. package/runtime/agents/generic-agent-builder/capabilities/generate-skill/workflow.md +5 -0
  227. package/runtime/agents/generic-agent-builder/capabilities/plan-generic-agent/capability.yaml +18 -0
  228. package/runtime/agents/generic-agent-builder/capabilities/plan-generic-agent/decision-rules.md +6 -0
  229. package/runtime/agents/generic-agent-builder/capabilities/plan-generic-agent/runner.py +33 -0
  230. package/runtime/agents/generic-agent-builder/capabilities/plan-generic-agent/workflow.md +6 -0
  231. package/runtime/agents/generic-agent-builder/capabilities/review-generic-agent/capability.yaml +20 -0
  232. package/runtime/agents/generic-agent-builder/capabilities/review-generic-agent/decision-rules.md +6 -0
  233. package/runtime/agents/generic-agent-builder/capabilities/review-generic-agent/runner.py +40 -0
  234. package/runtime/agents/generic-agent-builder/capabilities/review-generic-agent/workflow.md +7 -0
  235. package/runtime/agents/generic-agent-builder/infra/integrations/generic-agent/generic_agent_repository.py +445 -0
  236. package/runtime/agents/generic-agent-builder/knowledge/context.md +11 -0
  237. package/runtime/agents/generic-agent-builder/knowledge/policies.yaml +12 -0
  238. package/runtime/agents/generic-agent-builder/knowledge/system.md +17 -0
  239. package/runtime/agents/generic-agent-builder/templates/generic-agent-instructions.md +17 -0
  240. package/runtime/agents/generic-agent-builder/templates/generic-review-report.md +13 -0
  241. package/runtime/agents/generic-agent-builder/templates/generic-skill.md +14 -0
  242. package/runtime/agents/generic-agent-builder/tests/test_runners.py +220 -0
  243. package/runtime/agents/github-pr-reviewer/agent.yaml +17 -5
  244. package/runtime/agents/github-pr-reviewer/capabilities/create-review-automation/capability.yaml +1 -1
  245. package/runtime/agents/github-pr-reviewer/capabilities/inspect-pr/capability.yaml +1 -1
  246. package/runtime/agents/github-pr-reviewer/capabilities/list-review-requests/capability.yaml +1 -1
  247. package/runtime/agents/github-pr-reviewer/capabilities/review-pr-diff/capability.yaml +1 -1
  248. package/runtime/agents/knowledge-generator/agent.yaml +13 -3
  249. package/runtime/agents/knowledge-generator/capabilities/generate-knowledge/capability.yaml +1 -1
  250. package/runtime/agents/local-llm-operator/AGENTS.md +8 -0
  251. package/runtime/agents/local-llm-operator/README.md +12 -0
  252. package/runtime/agents/local-llm-operator/agent.yaml +28 -0
  253. package/runtime/agents/local-llm-operator/capabilities/delegate-operational-task/capability.yaml +14 -0
  254. package/runtime/agents/local-llm-operator/capabilities/delegate-operational-task/decision-rules.md +6 -0
  255. package/runtime/agents/local-llm-operator/capabilities/delegate-operational-task/workflow.md +7 -0
  256. package/runtime/agents/local-llm-operator/capabilities/inspect-local-models/capability.yaml +14 -0
  257. package/runtime/agents/local-llm-operator/capabilities/inspect-local-models/decision-rules.md +5 -0
  258. package/runtime/agents/local-llm-operator/capabilities/inspect-local-models/workflow.md +6 -0
  259. package/runtime/agents/local-llm-operator/capabilities/select-local-worker/capability.yaml +14 -0
  260. package/runtime/agents/local-llm-operator/capabilities/select-local-worker/decision-rules.md +6 -0
  261. package/runtime/agents/local-llm-operator/capabilities/select-local-worker/workflow.md +7 -0
  262. package/runtime/agents/local-llm-operator/infra/README.md +4 -0
  263. package/runtime/agents/local-llm-operator/knowledge/context.md +6 -0
  264. package/runtime/agents/local-llm-operator/knowledge/system.md +18 -0
  265. package/runtime/agents/local-llm-operator/templates/README.md +4 -0
  266. package/runtime/agents/n1-support-agent/agent.yaml +40 -1
  267. package/runtime/agents/n2-support-agent/agent.yaml +41 -2
  268. package/runtime/agents/n2-support-agent/knowledge/policies.yaml +2 -2
  269. package/runtime/agents/notification-operator/AGENTS.md +11 -0
  270. package/runtime/agents/notification-operator/README.md +15 -0
  271. package/runtime/agents/notification-operator/agent.yaml +43 -0
  272. package/runtime/agents/notification-operator/capabilities/configure-notification-channel/capability.yaml +19 -0
  273. package/runtime/agents/notification-operator/capabilities/configure-notification-channel/decision-rules.md +6 -0
  274. package/runtime/agents/notification-operator/capabilities/configure-notification-channel/runner.py +33 -0
  275. package/runtime/agents/notification-operator/capabilities/configure-notification-channel/workflow.md +6 -0
  276. package/runtime/agents/notification-operator/capabilities/format-task-completion-notification/capability.yaml +25 -0
  277. package/runtime/agents/notification-operator/capabilities/format-task-completion-notification/decision-rules.md +7 -0
  278. package/runtime/agents/notification-operator/capabilities/format-task-completion-notification/runner.py +49 -0
  279. package/runtime/agents/notification-operator/capabilities/format-task-completion-notification/workflow.md +6 -0
  280. package/runtime/agents/notification-operator/capabilities/send-task-completion-notification/capability.yaml +27 -0
  281. package/runtime/agents/notification-operator/capabilities/send-task-completion-notification/decision-rules.md +6 -0
  282. package/runtime/agents/notification-operator/capabilities/send-task-completion-notification/runner.py +68 -0
  283. package/runtime/agents/notification-operator/capabilities/send-task-completion-notification/workflow.md +7 -0
  284. package/runtime/agents/notification-operator/infra/README.md +6 -0
  285. package/runtime/agents/notification-operator/knowledge/context.md +10 -0
  286. package/runtime/agents/notification-operator/knowledge/policies.yaml +9 -0
  287. package/runtime/agents/notification-operator/knowledge/system.md +7 -0
  288. package/runtime/agents/notification-operator/templates/README.md +6 -0
  289. package/runtime/agents/notification-operator/tests/test_runners.py +108 -0
  290. package/runtime/agents/playwright-automation-builder/AGENTS.md +23 -0
  291. package/runtime/agents/playwright-automation-builder/README.md +43 -0
  292. package/runtime/agents/playwright-automation-builder/agent.yaml +48 -0
  293. package/runtime/agents/playwright-automation-builder/capabilities/generate-playwright-project-files/capability.yaml +20 -0
  294. package/runtime/agents/playwright-automation-builder/capabilities/generate-playwright-project-files/decision-rules.md +6 -0
  295. package/runtime/agents/playwright-automation-builder/capabilities/generate-playwright-project-files/runner.py +38 -0
  296. package/runtime/agents/playwright-automation-builder/capabilities/generate-playwright-project-files/workflow.md +6 -0
  297. package/runtime/agents/playwright-automation-builder/capabilities/generate-playwright-script/capability.yaml +18 -0
  298. package/runtime/agents/playwright-automation-builder/capabilities/generate-playwright-script/decision-rules.md +6 -0
  299. package/runtime/agents/playwright-automation-builder/capabilities/generate-playwright-script/runner.py +32 -0
  300. package/runtime/agents/playwright-automation-builder/capabilities/generate-playwright-script/workflow.md +6 -0
  301. package/runtime/agents/playwright-automation-builder/capabilities/plan-playwright-automation/capability.yaml +18 -0
  302. package/runtime/agents/playwright-automation-builder/capabilities/plan-playwright-automation/decision-rules.md +6 -0
  303. package/runtime/agents/playwright-automation-builder/capabilities/plan-playwright-automation/runner.py +32 -0
  304. package/runtime/agents/playwright-automation-builder/capabilities/plan-playwright-automation/workflow.md +6 -0
  305. package/runtime/agents/playwright-automation-builder/capabilities/review-playwright-artifacts/capability.yaml +19 -0
  306. package/runtime/agents/playwright-automation-builder/capabilities/review-playwright-artifacts/decision-rules.md +6 -0
  307. package/runtime/agents/playwright-automation-builder/capabilities/review-playwright-artifacts/runner.py +33 -0
  308. package/runtime/agents/playwright-automation-builder/capabilities/review-playwright-artifacts/workflow.md +6 -0
  309. package/runtime/agents/playwright-automation-builder/capabilities/run-playwright-check/capability.yaml +22 -0
  310. package/runtime/agents/playwright-automation-builder/capabilities/run-playwright-check/decision-rules.md +6 -0
  311. package/runtime/agents/playwright-automation-builder/capabilities/run-playwright-check/runner.py +40 -0
  312. package/runtime/agents/playwright-automation-builder/capabilities/run-playwright-check/workflow.md +6 -0
  313. package/runtime/agents/playwright-automation-builder/capabilities/wrap-playwright-as-capability/capability.yaml +22 -0
  314. package/runtime/agents/playwright-automation-builder/capabilities/wrap-playwright-as-capability/decision-rules.md +6 -0
  315. package/runtime/agents/playwright-automation-builder/capabilities/wrap-playwright-as-capability/runner.py +42 -0
  316. package/runtime/agents/playwright-automation-builder/capabilities/wrap-playwright-as-capability/workflow.md +6 -0
  317. package/runtime/agents/playwright-automation-builder/infra/integrations/playwright-automation/playwright_automation_repository.py +865 -0
  318. package/runtime/agents/playwright-automation-builder/knowledge/context.md +19 -0
  319. package/runtime/agents/playwright-automation-builder/knowledge/policies.yaml +25 -0
  320. package/runtime/agents/playwright-automation-builder/knowledge/system.md +19 -0
  321. package/runtime/agents/playwright-automation-builder/templates/capability-wrapper.md +4 -0
  322. package/runtime/agents/playwright-automation-builder/templates/playwright-automation.py +12 -0
  323. package/runtime/agents/playwright-automation-builder/templates/playwright-readme.md +13 -0
  324. package/runtime/agents/playwright-automation-builder/templates/playwright-review-report.md +9 -0
  325. package/runtime/agents/playwright-automation-builder/templates/playwright-test.py +2 -0
  326. package/runtime/agents/playwright-automation-builder/tests/test_runners.py +261 -0
  327. package/runtime/agents/postgres-data-analyzer/agent.yaml +13 -2
  328. package/runtime/agents/presentation-deck-builder/agent.yaml +14 -3
  329. package/runtime/agents/presentation-deck-builder/capabilities/create-template/capability.yaml +1 -1
  330. package/runtime/agents/presentation-deck-builder/capabilities/create-template-version/capability.yaml +1 -1
  331. package/runtime/agents/presentation-deck-builder/capabilities/generate-template-input-file/capability.yaml +1 -1
  332. package/runtime/agents/presentation-deck-builder/capabilities/refine-template/capability.yaml +1 -1
  333. package/runtime/agents/presentation-deck-builder/capabilities/register-template/capability.yaml +1 -1
  334. package/runtime/agents/presentation-deck-builder/knowledge/prompts/create-template.md +1 -1
  335. package/runtime/agents/presentation-deck-builder/knowledge/prompts/generate-template-input-file.md +1 -1
  336. package/runtime/agents/provider-configurator/AGENTS.md +8 -0
  337. package/runtime/agents/provider-configurator/README.md +5 -0
  338. package/runtime/agents/provider-configurator/agent.yaml +27 -0
  339. package/runtime/agents/provider-configurator/capabilities/collect-provider-credentials/capability.yaml +14 -0
  340. package/runtime/agents/provider-configurator/capabilities/collect-provider-credentials/decision-rules.md +6 -0
  341. package/runtime/agents/provider-configurator/capabilities/collect-provider-credentials/workflow.md +7 -0
  342. package/runtime/agents/provider-configurator/capabilities/configure-provider-source/capability.yaml +14 -0
  343. package/runtime/agents/provider-configurator/capabilities/configure-provider-source/decision-rules.md +6 -0
  344. package/runtime/agents/provider-configurator/capabilities/configure-provider-source/workflow.md +8 -0
  345. package/runtime/agents/provider-configurator/capabilities/validate-provider-readiness/capability.yaml +14 -0
  346. package/runtime/agents/provider-configurator/capabilities/validate-provider-readiness/decision-rules.md +6 -0
  347. package/runtime/agents/provider-configurator/capabilities/validate-provider-readiness/workflow.md +7 -0
  348. package/runtime/agents/provider-configurator/infra/README.md +5 -0
  349. package/runtime/agents/provider-configurator/knowledge/context.md +8 -0
  350. package/runtime/agents/provider-configurator/knowledge/system.md +19 -0
  351. package/runtime/agents/provider-configurator/templates/README.md +4 -0
  352. package/runtime/agents/pyautogui-automation-builder/AGENTS.md +32 -0
  353. package/runtime/agents/pyautogui-automation-builder/README.md +44 -0
  354. package/runtime/agents/pyautogui-automation-builder/agent.yaml +45 -0
  355. package/runtime/agents/pyautogui-automation-builder/capabilities/generate-pyautogui-project-files/capability.yaml +20 -0
  356. package/runtime/agents/pyautogui-automation-builder/capabilities/generate-pyautogui-project-files/decision-rules.md +6 -0
  357. package/runtime/agents/pyautogui-automation-builder/capabilities/generate-pyautogui-project-files/runner.py +39 -0
  358. package/runtime/agents/pyautogui-automation-builder/capabilities/generate-pyautogui-project-files/workflow.md +7 -0
  359. package/runtime/agents/pyautogui-automation-builder/capabilities/generate-pyautogui-script/capability.yaml +18 -0
  360. package/runtime/agents/pyautogui-automation-builder/capabilities/generate-pyautogui-script/decision-rules.md +7 -0
  361. package/runtime/agents/pyautogui-automation-builder/capabilities/generate-pyautogui-script/runner.py +33 -0
  362. package/runtime/agents/pyautogui-automation-builder/capabilities/generate-pyautogui-script/workflow.md +7 -0
  363. package/runtime/agents/pyautogui-automation-builder/capabilities/plan-desktop-automation/capability.yaml +18 -0
  364. package/runtime/agents/pyautogui-automation-builder/capabilities/plan-desktop-automation/decision-rules.md +8 -0
  365. package/runtime/agents/pyautogui-automation-builder/capabilities/plan-desktop-automation/runner.py +33 -0
  366. package/runtime/agents/pyautogui-automation-builder/capabilities/plan-desktop-automation/workflow.md +9 -0
  367. package/runtime/agents/pyautogui-automation-builder/capabilities/review-pyautogui-script/capability.yaml +20 -0
  368. package/runtime/agents/pyautogui-automation-builder/capabilities/review-pyautogui-script/decision-rules.md +8 -0
  369. package/runtime/agents/pyautogui-automation-builder/capabilities/review-pyautogui-script/runner.py +43 -0
  370. package/runtime/agents/pyautogui-automation-builder/capabilities/review-pyautogui-script/workflow.md +7 -0
  371. package/runtime/agents/pyautogui-automation-builder/capabilities/wrap-pyautogui-as-capability/capability.yaml +22 -0
  372. package/runtime/agents/pyautogui-automation-builder/capabilities/wrap-pyautogui-as-capability/decision-rules.md +6 -0
  373. package/runtime/agents/pyautogui-automation-builder/capabilities/wrap-pyautogui-as-capability/runner.py +43 -0
  374. package/runtime/agents/pyautogui-automation-builder/capabilities/wrap-pyautogui-as-capability/workflow.md +7 -0
  375. package/runtime/agents/pyautogui-automation-builder/infra/integrations/pyautogui-automation/pyautogui_automation_repository.py +856 -0
  376. package/runtime/agents/pyautogui-automation-builder/knowledge/context.md +17 -0
  377. package/runtime/agents/pyautogui-automation-builder/knowledge/policies.yaml +24 -0
  378. package/runtime/agents/pyautogui-automation-builder/knowledge/system.md +13 -0
  379. package/runtime/agents/pyautogui-automation-builder/templates/capability-wrapper.md +3 -0
  380. package/runtime/agents/pyautogui-automation-builder/templates/pyautogui-automation.py +12 -0
  381. package/runtime/agents/pyautogui-automation-builder/templates/pyautogui-readme.md +3 -0
  382. package/runtime/agents/pyautogui-automation-builder/templates/pyautogui-review-report.md +3 -0
  383. package/runtime/agents/pyautogui-automation-builder/templates/pyautogui-test.py +2 -0
  384. package/runtime/agents/pyautogui-automation-builder/tests/test_runners.py +376 -0
  385. package/runtime/agents/python-automation-builder/AGENTS.md +25 -0
  386. package/runtime/agents/python-automation-builder/README.md +43 -0
  387. package/runtime/agents/python-automation-builder/agent.yaml +45 -0
  388. package/runtime/agents/python-automation-builder/capabilities/generate-automation-project-files/capability.yaml +20 -0
  389. package/runtime/agents/python-automation-builder/capabilities/generate-automation-project-files/decision-rules.md +6 -0
  390. package/runtime/agents/python-automation-builder/capabilities/generate-automation-project-files/runner.py +39 -0
  391. package/runtime/agents/python-automation-builder/capabilities/generate-automation-project-files/workflow.md +7 -0
  392. package/runtime/agents/python-automation-builder/capabilities/generate-python-automation/capability.yaml +18 -0
  393. package/runtime/agents/python-automation-builder/capabilities/generate-python-automation/decision-rules.md +5 -0
  394. package/runtime/agents/python-automation-builder/capabilities/generate-python-automation/runner.py +33 -0
  395. package/runtime/agents/python-automation-builder/capabilities/generate-python-automation/workflow.md +5 -0
  396. package/runtime/agents/python-automation-builder/capabilities/plan-python-automation/capability.yaml +18 -0
  397. package/runtime/agents/python-automation-builder/capabilities/plan-python-automation/decision-rules.md +6 -0
  398. package/runtime/agents/python-automation-builder/capabilities/plan-python-automation/runner.py +33 -0
  399. package/runtime/agents/python-automation-builder/capabilities/plan-python-automation/workflow.md +6 -0
  400. package/runtime/agents/python-automation-builder/capabilities/review-python-automation/capability.yaml +20 -0
  401. package/runtime/agents/python-automation-builder/capabilities/review-python-automation/decision-rules.md +6 -0
  402. package/runtime/agents/python-automation-builder/capabilities/review-python-automation/runner.py +43 -0
  403. package/runtime/agents/python-automation-builder/capabilities/review-python-automation/workflow.md +5 -0
  404. package/runtime/agents/python-automation-builder/capabilities/wrap-automation-as-capability/capability.yaml +22 -0
  405. package/runtime/agents/python-automation-builder/capabilities/wrap-automation-as-capability/decision-rules.md +6 -0
  406. package/runtime/agents/python-automation-builder/capabilities/wrap-automation-as-capability/runner.py +43 -0
  407. package/runtime/agents/python-automation-builder/capabilities/wrap-automation-as-capability/workflow.md +6 -0
  408. package/runtime/agents/python-automation-builder/infra/integrations/python-automation/python_automation_repository.py +717 -0
  409. package/runtime/agents/python-automation-builder/knowledge/context.md +15 -0
  410. package/runtime/agents/python-automation-builder/knowledge/policies.yaml +12 -0
  411. package/runtime/agents/python-automation-builder/knowledge/system.md +19 -0
  412. package/runtime/agents/python-automation-builder/templates/automation-readme.md +13 -0
  413. package/runtime/agents/python-automation-builder/templates/automation-review-report.md +13 -0
  414. package/runtime/agents/python-automation-builder/templates/automation-test.py +9 -0
  415. package/runtime/agents/python-automation-builder/templates/automation.py +19 -0
  416. package/runtime/agents/python-automation-builder/templates/capability-wrapper.md +4 -0
  417. package/runtime/agents/python-automation-builder/tests/test_runners.py +292 -0
  418. package/runtime/agents/selenium-automation-builder/AGENTS.md +27 -0
  419. package/runtime/agents/selenium-automation-builder/README.md +40 -0
  420. package/runtime/agents/selenium-automation-builder/agent.yaml +45 -0
  421. package/runtime/agents/selenium-automation-builder/capabilities/generate-selenium-project-files/capability.yaml +20 -0
  422. package/runtime/agents/selenium-automation-builder/capabilities/generate-selenium-project-files/decision-rules.md +6 -0
  423. package/runtime/agents/selenium-automation-builder/capabilities/generate-selenium-project-files/runner.py +39 -0
  424. package/runtime/agents/selenium-automation-builder/capabilities/generate-selenium-project-files/workflow.md +7 -0
  425. package/runtime/agents/selenium-automation-builder/capabilities/generate-selenium-script/capability.yaml +18 -0
  426. package/runtime/agents/selenium-automation-builder/capabilities/generate-selenium-script/decision-rules.md +6 -0
  427. package/runtime/agents/selenium-automation-builder/capabilities/generate-selenium-script/runner.py +33 -0
  428. package/runtime/agents/selenium-automation-builder/capabilities/generate-selenium-script/workflow.md +6 -0
  429. package/runtime/agents/selenium-automation-builder/capabilities/plan-selenium-automation/capability.yaml +18 -0
  430. package/runtime/agents/selenium-automation-builder/capabilities/plan-selenium-automation/decision-rules.md +6 -0
  431. package/runtime/agents/selenium-automation-builder/capabilities/plan-selenium-automation/runner.py +33 -0
  432. package/runtime/agents/selenium-automation-builder/capabilities/plan-selenium-automation/workflow.md +6 -0
  433. package/runtime/agents/selenium-automation-builder/capabilities/review-selenium-script/capability.yaml +20 -0
  434. package/runtime/agents/selenium-automation-builder/capabilities/review-selenium-script/decision-rules.md +6 -0
  435. package/runtime/agents/selenium-automation-builder/capabilities/review-selenium-script/runner.py +40 -0
  436. package/runtime/agents/selenium-automation-builder/capabilities/review-selenium-script/workflow.md +6 -0
  437. package/runtime/agents/selenium-automation-builder/capabilities/wrap-selenium-as-capability/capability.yaml +22 -0
  438. package/runtime/agents/selenium-automation-builder/capabilities/wrap-selenium-as-capability/decision-rules.md +6 -0
  439. package/runtime/agents/selenium-automation-builder/capabilities/wrap-selenium-as-capability/runner.py +43 -0
  440. package/runtime/agents/selenium-automation-builder/capabilities/wrap-selenium-as-capability/workflow.md +6 -0
  441. package/runtime/agents/selenium-automation-builder/infra/integrations/selenium-automation/selenium_automation_repository.py +793 -0
  442. package/runtime/agents/selenium-automation-builder/knowledge/context.md +15 -0
  443. package/runtime/agents/selenium-automation-builder/knowledge/policies.yaml +17 -0
  444. package/runtime/agents/selenium-automation-builder/knowledge/system.md +18 -0
  445. package/runtime/agents/selenium-automation-builder/templates/capability-wrapper.md +4 -0
  446. package/runtime/agents/selenium-automation-builder/templates/selenium-automation.py +20 -0
  447. package/runtime/agents/selenium-automation-builder/templates/selenium-readme.md +13 -0
  448. package/runtime/agents/selenium-automation-builder/templates/selenium-review-report.md +13 -0
  449. package/runtime/agents/selenium-automation-builder/templates/selenium-test.py +9 -0
  450. package/runtime/agents/selenium-automation-builder/tests/test_runners.py +282 -0
  451. package/runtime/agents/software-specification-analyst/agent.yaml +17 -4
  452. package/runtime/agents/software-specification-analyst/capabilities/analyze-multiple-projects/capability.yaml +1 -1
  453. package/runtime/agents/software-specification-analyst/capabilities/analyze-project-context/capability.yaml +1 -1
  454. package/runtime/agents/software-specification-analyst/capabilities/conduct-requirements-interview/capability.yaml +1 -1
  455. package/runtime/agents/software-specification-analyst/capabilities/create-complete-spec/capability.yaml +1 -1
  456. package/runtime/agents/software-specification-analyst/capabilities/create-final-spec-from-analysis/capability.yaml +1 -1
  457. package/runtime/agents/software-specification-analyst/capabilities/create-functional-spec/capability.yaml +11 -0
  458. package/runtime/agents/software-specification-analyst/capabilities/create-technical-spec/capability.yaml +12 -0
  459. package/runtime/agents/software-specification-analyst/capabilities/refine-analysis-with-feedback/capability.yaml +1 -1
  460. package/runtime/agents/software-specification-analyst/capabilities/write-user-stories/capability.yaml +12 -0
  461. package/runtime/agents/sqlserver-change-operator/agent.yaml +12 -1
  462. package/runtime/agents/sqlserver-data-analyzer/agent.yaml +13 -2
  463. package/runtime/agents/supabase-project-analyst/AGENTS.md +29 -0
  464. package/runtime/agents/supabase-project-analyst/README.md +23 -0
  465. package/runtime/agents/supabase-project-analyst/agent.yaml +53 -0
  466. package/runtime/agents/supabase-project-analyst/capabilities/audit-auth-security/capability.yaml +18 -0
  467. package/runtime/agents/supabase-project-analyst/capabilities/audit-auth-security/decision-rules.md +5 -0
  468. package/runtime/agents/supabase-project-analyst/capabilities/audit-auth-security/runner.py +32 -0
  469. package/runtime/agents/supabase-project-analyst/capabilities/audit-auth-security/workflow.md +6 -0
  470. package/runtime/agents/supabase-project-analyst/capabilities/audit-rls-policies/capability.yaml +18 -0
  471. package/runtime/agents/supabase-project-analyst/capabilities/audit-rls-policies/decision-rules.md +6 -0
  472. package/runtime/agents/supabase-project-analyst/capabilities/audit-rls-policies/runner.py +32 -0
  473. package/runtime/agents/supabase-project-analyst/capabilities/audit-rls-policies/workflow.md +7 -0
  474. package/runtime/agents/supabase-project-analyst/capabilities/audit-storage-policies/capability.yaml +18 -0
  475. package/runtime/agents/supabase-project-analyst/capabilities/audit-storage-policies/decision-rules.md +5 -0
  476. package/runtime/agents/supabase-project-analyst/capabilities/audit-storage-policies/runner.py +32 -0
  477. package/runtime/agents/supabase-project-analyst/capabilities/audit-storage-policies/workflow.md +6 -0
  478. package/runtime/agents/supabase-project-analyst/capabilities/generate-supabase-report/capability.yaml +18 -0
  479. package/runtime/agents/supabase-project-analyst/capabilities/generate-supabase-report/decision-rules.md +6 -0
  480. package/runtime/agents/supabase-project-analyst/capabilities/generate-supabase-report/runner.py +32 -0
  481. package/runtime/agents/supabase-project-analyst/capabilities/generate-supabase-report/workflow.md +6 -0
  482. package/runtime/agents/supabase-project-analyst/capabilities/inspect-supabase-project/capability.yaml +19 -0
  483. package/runtime/agents/supabase-project-analyst/capabilities/inspect-supabase-project/decision-rules.md +6 -0
  484. package/runtime/agents/supabase-project-analyst/capabilities/inspect-supabase-project/runner.py +36 -0
  485. package/runtime/agents/supabase-project-analyst/capabilities/inspect-supabase-project/workflow.md +7 -0
  486. package/runtime/agents/supabase-project-analyst/capabilities/plan-supabase-fix/capability.yaml +18 -0
  487. package/runtime/agents/supabase-project-analyst/capabilities/plan-supabase-fix/decision-rules.md +6 -0
  488. package/runtime/agents/supabase-project-analyst/capabilities/plan-supabase-fix/runner.py +32 -0
  489. package/runtime/agents/supabase-project-analyst/capabilities/plan-supabase-fix/workflow.md +6 -0
  490. package/runtime/agents/supabase-project-analyst/capabilities/review-migrations/capability.yaml +18 -0
  491. package/runtime/agents/supabase-project-analyst/capabilities/review-migrations/decision-rules.md +6 -0
  492. package/runtime/agents/supabase-project-analyst/capabilities/review-migrations/runner.py +32 -0
  493. package/runtime/agents/supabase-project-analyst/capabilities/review-migrations/workflow.md +5 -0
  494. package/runtime/agents/supabase-project-analyst/infra/integrations/supabase-project/supabase_project_repository.py +589 -0
  495. package/runtime/agents/supabase-project-analyst/knowledge/context.md +11 -0
  496. package/runtime/agents/supabase-project-analyst/knowledge/policies.yaml +24 -0
  497. package/runtime/agents/supabase-project-analyst/knowledge/system.md +10 -0
  498. package/runtime/agents/supabase-project-analyst/templates/supabase-audit.md +3 -0
  499. package/runtime/agents/supabase-project-analyst/templates/supabase-fix-plan.md +3 -0
  500. package/runtime/agents/supabase-project-analyst/templates/supabase-inspection.md +3 -0
  501. package/runtime/agents/supabase-project-analyst/templates/supabase-report.md +3 -0
  502. package/runtime/agents/supabase-project-analyst/tests/test_runners.py +239 -0
  503. package/runtime/agents/task-orchestrator/AGENTS.md +8 -0
  504. package/runtime/agents/task-orchestrator/README.md +7 -0
  505. package/runtime/agents/task-orchestrator/agent.yaml +53 -0
  506. package/runtime/agents/task-orchestrator/capabilities/coordinate-execution/capability.yaml +15 -0
  507. package/runtime/agents/task-orchestrator/capabilities/coordinate-execution/decision-rules.md +6 -0
  508. package/runtime/agents/task-orchestrator/capabilities/coordinate-execution/workflow.md +7 -0
  509. package/runtime/agents/task-orchestrator/capabilities/plan-task/capability.yaml +14 -0
  510. package/runtime/agents/task-orchestrator/capabilities/plan-task/decision-rules.md +6 -0
  511. package/runtime/agents/task-orchestrator/capabilities/plan-task/workflow.md +8 -0
  512. package/runtime/agents/task-orchestrator/capabilities/select-specialists/capability.yaml +14 -0
  513. package/runtime/agents/task-orchestrator/capabilities/select-specialists/decision-rules.md +6 -0
  514. package/runtime/agents/task-orchestrator/capabilities/select-specialists/workflow.md +7 -0
  515. package/runtime/agents/task-orchestrator/infra/README.md +5 -0
  516. package/runtime/agents/task-orchestrator/knowledge/context.md +9 -0
  517. package/runtime/agents/task-orchestrator/knowledge/system.md +20 -0
  518. package/runtime/agents/task-orchestrator/templates/README.md +4 -0
  519. package/runtime/agents/technical-integration-analyst/agent.yaml +15 -2
  520. package/runtime/agents/topdesk-orchestrator/agent.yaml +10 -2
  521. package/runtime/cli/README.md +76 -11
  522. package/runtime/cli/aikit/__init__.py +1 -1
  523. package/runtime/cli/aikit/acceptance.py +166 -0
  524. package/runtime/cli/aikit/agent_executor.py +89 -0
  525. package/runtime/cli/aikit/agent_registry.py +319 -0
  526. package/runtime/cli/aikit/app_home.py +87 -2
  527. package/runtime/cli/aikit/architecture.py +84 -0
  528. package/runtime/cli/aikit/audit.py +216 -3
  529. package/runtime/cli/aikit/autonomy.py +237 -0
  530. package/runtime/cli/aikit/capability_runtime.py +522 -0
  531. package/runtime/cli/aikit/catalog.py +246 -0
  532. package/runtime/cli/aikit/cli_dispatch.py +1078 -0
  533. package/runtime/cli/aikit/cli_parser.py +409 -0
  534. package/runtime/cli/aikit/collaboration.py +359 -0
  535. package/runtime/cli/aikit/configuration_orchestrator.py +52 -26
  536. package/runtime/cli/aikit/contribution.py +105 -0
  537. package/runtime/cli/aikit/control_router.py +298 -0
  538. package/runtime/cli/aikit/core/__init__.py +1 -0
  539. package/runtime/cli/aikit/core/capability_contract.py +112 -0
  540. package/runtime/cli/aikit/core/requests.py +69 -0
  541. package/runtime/cli/aikit/core/runtime.py +64 -0
  542. package/runtime/cli/aikit/decision_store.py +17 -0
  543. package/runtime/cli/aikit/diagnostics.py +10 -3
  544. package/runtime/cli/aikit/doctor_runtime.py +79 -0
  545. package/runtime/cli/aikit/errors.py +7 -0
  546. package/runtime/cli/aikit/eval.py +158 -0
  547. package/runtime/cli/aikit/execution_reviewer.py +195 -0
  548. package/runtime/cli/aikit/extensions.py +140 -0
  549. package/runtime/cli/aikit/fallback.py +1 -0
  550. package/runtime/cli/aikit/github_pr.py +23 -0
  551. package/runtime/cli/aikit/guardrails.py +25 -10
  552. package/runtime/cli/aikit/human_output.py +1026 -0
  553. package/runtime/cli/aikit/impact_map.py +294 -0
  554. package/runtime/cli/aikit/install.py +4 -3
  555. package/runtime/cli/aikit/interactive_wizard.py +79 -0
  556. package/runtime/cli/aikit/local_llm_operator.py +146 -0
  557. package/runtime/cli/aikit/lock.py +4 -1
  558. package/runtime/cli/aikit/main.py +11 -2561
  559. package/runtime/cli/aikit/mcp_manifest.py +229 -0
  560. package/runtime/cli/aikit/mcp_server.py +132 -0
  561. package/runtime/cli/aikit/mcp_tools.py +262 -0
  562. package/runtime/cli/aikit/mini_brain.py +227 -0
  563. package/runtime/cli/aikit/model_router.py +193 -20
  564. package/runtime/cli/aikit/module_controller.py +335 -0
  565. package/runtime/cli/aikit/natural_prompt_runtime.py +538 -0
  566. package/runtime/cli/aikit/notifications.py +716 -2
  567. package/runtime/cli/aikit/ollama.py +1 -0
  568. package/runtime/cli/aikit/orchestrator.py +1225 -0
  569. package/runtime/cli/aikit/output.py +63 -2
  570. package/runtime/cli/aikit/permissions.py +14 -4
  571. package/runtime/cli/aikit/prompt_injection.py +57 -0
  572. package/runtime/cli/aikit/review_gate.py +38 -6
  573. package/runtime/cli/aikit/roadmap.py +195 -0
  574. package/runtime/cli/aikit/roadmap_cli.py +70 -0
  575. package/runtime/cli/aikit/router.py +41 -12
  576. package/runtime/cli/aikit/router_explain.py +152 -0
  577. package/runtime/cli/aikit/runtime_paths.py +11 -0
  578. package/runtime/cli/aikit/secrets.py +113 -0
  579. package/runtime/cli/aikit/sessions.py +125 -2
  580. package/runtime/cli/aikit/setup_wizard_payload.py +32 -0
  581. package/runtime/cli/aikit/sources.py +298 -46
  582. package/runtime/cli/aikit/tasks.py +449 -21
  583. package/runtime/cli/aikit/wizard_state.py +517 -0
  584. package/runtime/cli/aikit/workflows.py +115 -0
  585. package/runtime/cli/aikit/write_policy.py +108 -0
  586. package/runtime/plugins/claude-code-ai-devkit/README.md +17 -0
  587. package/runtime/plugins/claude-code-ai-devkit/agents/README.md +29 -2
  588. package/runtime/plugins/claude-code-ai-devkit/agents/agent-devkit-db-analyst.md +44 -0
  589. package/runtime/plugins/claude-code-ai-devkit/agents/agent-devkit-execution-reviewer.md +38 -0
  590. package/runtime/plugins/claude-code-ai-devkit/agents/agent-devkit-pr-reviewer.md +42 -0
  591. package/runtime/plugins/claude-code-ai-devkit/agents/agent-devkit-repo-explorer.md +40 -0
  592. package/runtime/plugins/claude-code-ai-devkit/agents/agent-devkit-support-triage.md +43 -0
  593. package/runtime/plugins/claude-code-ai-devkit/plugin.json +1 -1
  594. package/runtime/plugins/claude-code-ai-devkit/skills/ai-devkit-router/SKILL.md +16 -0
  595. package/runtime/plugins/claude-skill-ai-devkit/ai-devkit/SKILL.md +1 -0
  596. package/runtime/plugins/claude-skill-ai-devkit/ai-devkit/references/subagents.md +21 -0
  597. package/runtime/plugins/claude-skill-ai-devkit/plugin.json +1 -1
  598. package/runtime/providers/azure-devops.yaml +9 -0
  599. package/runtime/providers/github.yaml +4 -0
  600. package/runtime/providers/local-notification.yaml +5 -2
  601. package/runtime/providers/local-scheduler.yaml +1 -1
  602. package/runtime/providers/supabase.yaml +46 -0
  603. package/runtime/scripts/release-catalog-snapshot.json +543 -0
  604. package/runtime/scripts/release-gate.py +141 -1
  605. package/runtime/scripts/validate-repo.py +312 -0
  606. package/runtime/vendor/skills/napkin/napkin.md +15 -9
@@ -1,133 +1,16 @@
1
1
  #!/usr/bin/env python3
2
- """AI DevKit public command line interface."""
2
+ """AI DevKit public command line entrypoint."""
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
- import argparse
7
6
  import json
8
- import os
9
- import shutil
10
- import subprocess
11
7
  import sys
12
- from pathlib import Path
13
- from typing import Any
14
8
 
15
- from cli.aikit.aliases import add_alias, list_aliases, remove_alias, sync_aliases
16
- from cli.aikit import __version__
17
- from cli.aikit.audit import export_audit, list_audits, record_audit, show_audit
18
- from cli.aikit.calendar import calendar_list, calendar_summary, calendar_today, calendar_tomorrow, configure_calendar
19
- from cli.aikit.configuration_orchestrator import provider_wizard_from_requirement
20
- from cli.aikit.decision_store import list_decisions, reset_decisions, set_decision
21
- from cli.aikit.diagnostics import build_diagnostics
22
- from cli.aikit.fallback import evaluate_provider_requirements
23
- from cli.aikit.github_pr import pr_create_automation, pr_inspect, pr_list_review_requests, pr_review
24
- from cli.aikit.guardrails import evaluate_execution_guardrails
25
- from cli.aikit.identity import enforce_identity_response, is_identity_question, local_identity_response, public_name
26
- from cli.aikit.llm import (
27
- configure_backend,
28
- doctor_backends,
29
- invoke_agent_prompt,
30
- list_backends,
31
- llm_preference,
32
- set_default_backend,
33
- set_llm_preference,
34
- )
35
- from cli.aikit.memory import memory_path_payload, napkin_context, record_usage, reset_memory, show_memory
36
- from cli.aikit.model_router import build_model_plan
37
- from cli.aikit.ollama import ollama_models, ollama_pull, ollama_status, ollama_update
38
- from cli.aikit.personality import load_personality, reset_personality, setup_personality, update_personality
39
- from cli.aikit.permissions import grant_permission, revoke_permission, show_permissions
40
- from cli.aikit.provider_wizard import missing_source_wizard
41
- from cli.aikit.review_gate import build_review_gate, mark_reviewed
42
- from cli.aikit.sessions import (
43
- build_contextual_prompt,
44
- get_or_create_session,
45
- list_sessions,
46
- record_exchange,
47
- resume_session,
48
- show_session,
49
- )
50
- from cli.aikit.setup_wizard import setup_wizard
51
- from cli.aikit.scheduler import run_scheduler_once, scheduler_daemon_plan
52
- from cli.aikit.tasks import (
53
- create_task,
54
- delete_task,
55
- list_tasks,
56
- run_task,
57
- show_task,
58
- task_history,
59
- update_task_schedule,
60
- update_task_status,
61
- )
62
- from cli.aikit.toolchain import doctor_toolchain, install_toolchain, list_toolchain
63
- from cli.aikit.install import InstallError, install_runtime
64
- from cli.aikit.lock import lock_status, parse_profiles
65
- from cli.aikit.output import run_payload
66
- from cli.aikit.credentials import CredentialResolverError, credential_backends
67
- from cli.aikit.providers import (
68
- ProviderRegistryError,
69
- configure_provider,
70
- credential_resolution,
71
- list_providers,
72
- provider_status_with_credentials,
73
- unset_provider_config,
74
- )
75
- from cli.aikit.router import route_prompt
76
- from cli.aikit.sources import (
77
- SourceRegistryError,
78
- add_source,
79
- apply_source_to_args,
80
- extract_source_arg,
81
- list_sources,
82
- public_source,
83
- remove_source,
84
- resolve_source,
85
- source_env,
86
- source_status,
87
- )
88
-
89
-
90
- DEFAULT_ROOT = Path(__file__).resolve().parents[2]
91
- ROOT = Path(os.environ.get("AI_DEVKIT_ROOT", DEFAULT_ROOT)).resolve()
92
- AGENTS_DIR = ROOT / "agents"
93
-
94
- DETERMINISTIC_COMMANDS = (
95
- "agents",
96
- "capabilities",
97
- "inspect",
98
- "run",
99
- "doctor",
100
- "commands",
101
- "llm",
102
- "providers",
103
- "provider",
104
- "credential",
105
- "source",
106
- "memory",
107
- "personality",
108
- "setup",
109
- "alias",
110
- "session",
111
- "toolchain",
112
- "task",
113
- "scheduler",
114
- "calendar",
115
- "pr",
116
- "permissions",
117
- "audit",
118
- "config",
119
- "tools",
120
- "integrations",
121
- "skills",
122
- "decisions",
123
- "ollama",
124
- "install",
125
- )
126
- LLM_COMMANDS = ("agent",)
127
-
128
-
129
- class DevKitError(RuntimeError):
130
- """Raised for user-facing CLI errors."""
9
+ from cli.aikit.cli_dispatch import dispatch, format_audit_warning, is_audit_warning, maybe_record_cli_audit
10
+ from cli.aikit.cli_parser import DETERMINISTIC_COMMANDS, LLM_COMMANDS, build_parser
11
+ from cli.aikit.errors import DevKitError
12
+ from cli.aikit.human_output import print_human
13
+ from cli.aikit.interactive_wizard import maybe_run_interactive_wizard
131
14
 
132
15
 
133
16
  def main(argv: list[str] | None = None, *, prog: str | None = None) -> int:
@@ -138,12 +21,16 @@ def main(argv: list[str] | None = None, *, prog: str | None = None) -> int:
138
21
  try:
139
22
  result = dispatch(args)
140
23
  except DevKitError as exc:
141
- maybe_record_cli_audit(args, result=None, error=str(exc))
24
+ audit_result = maybe_record_cli_audit(args, result=None, error=str(exc))
25
+ if is_audit_warning(audit_result):
26
+ print(format_audit_warning(audit_result), file=sys.stderr)
142
27
  print(f"error: {exc}", file=sys.stderr)
143
28
  return 1
144
29
 
145
30
  if result is None:
146
31
  return 0
32
+ if not getattr(args, "json", False):
33
+ result = maybe_run_interactive_wizard(result)
147
34
  maybe_record_cli_audit(args, result=result, error=None)
148
35
 
149
36
  if getattr(args, "json", False):
@@ -157,2442 +44,5 @@ def main(argv: list[str] | None = None, *, prog: str | None = None) -> int:
157
44
  return 0
158
45
 
159
46
 
160
- def build_parser(prog: str | None = None) -> argparse.ArgumentParser:
161
- parser = argparse.ArgumentParser(
162
- prog=prog or "aikit",
163
- description="AI DevKit CLI",
164
- )
165
- parser.add_argument("--json", action="store_true", help="print machine-readable JSON")
166
- parser.add_argument("--dry-run", dest="global_dry_run", action="store_true", help="show execution plan without external write effects")
167
- parser.add_argument("-v", "--version", action="store_true", help="print CLI version and exit")
168
- parser.add_argument(
169
- "-s",
170
- "--sessions",
171
- dest="sessions_shortcut",
172
- action="store_true",
173
- help="list local conversation sessions and exit",
174
- )
175
-
176
- subparsers = parser.add_subparsers(dest="command")
177
-
178
- agent_parser = subparsers.add_parser(
179
- "agent",
180
- help="handle a natural-language task using an LLM backend",
181
- )
182
- agent_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
183
- agent_parser.add_argument("--llm", help="LLM backend id to use")
184
- agent_parser.add_argument("--dry-run", action="store_true", help="show execution plan without invoking LLM or external writes")
185
- agent_parser.add_argument("--no-llm-fallback", action="store_true", help="disable automatic fallback to secondary LLM backends")
186
- agent_parser.add_argument("--session", dest="session_id", help="resume a local conversation session")
187
- agent_parser.add_argument("--new-session", action="store_true", help="start a new local conversation session")
188
- agent_parser.add_argument("prompt", nargs=argparse.REMAINDER)
189
-
190
- commands_parser = subparsers.add_parser("commands", help="list CLI command modes")
191
- commands_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
192
- commands_parser.add_argument("action", nargs="?", default="list", choices=["list"])
193
-
194
- providers_parser = subparsers.add_parser("providers", help="list provider registry entries")
195
- providers_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
196
- providers_parser.add_argument("action", nargs="?", default="list", choices=["list"])
197
-
198
- provider_parser = subparsers.add_parser("provider", help="inspect or configure one provider")
199
- provider_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
200
- provider_parser.add_argument("--env-file", action="append", default=[], help="credential env/JSON/YAML file to inspect without printing values")
201
- provider_parser.add_argument("--env", action="append", default=[], help="persist an environment variable reference for provider configuration")
202
- provider_parser.add_argument("--from-env", action="store_true", help="persist references for provider fields found in the current environment")
203
- provider_parser.add_argument("--session-only", action="store_true", help="validate configuration for this invocation without writing config")
204
- provider_parser.add_argument("action", nargs="?", default="status", choices=["status", "doctor", "configure", "unset"])
205
- provider_parser.add_argument("provider", nargs="?")
206
-
207
- credential_parser = subparsers.add_parser("credential", help="resolve provider credentials without exposing values")
208
- credential_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
209
- credential_parser.add_argument("--env-file", action="append", default=[], help="credential env/JSON/YAML file to inspect")
210
- credential_parser.add_argument("action", nargs="?", default="resolve", choices=["resolve", "backends"])
211
- credential_parser.add_argument("provider", nargs="?")
212
-
213
- source_parser = subparsers.add_parser("source", help="manage reusable provider/project sources")
214
- source_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
215
- source_parser.add_argument("action", nargs="?", default="list", choices=["list", "add", "status", "remove"])
216
- source_parser.add_argument("source_id", nargs="?")
217
- source_parser.add_argument("--provider", help="provider id used by this source")
218
- source_parser.add_argument("--label", help="human-readable source label")
219
- source_parser.add_argument("--config", action="append", default=[], help="source config as KEY=VALUE")
220
- source_parser.add_argument("--env", action="append", default=[], help="environment reference as PROVIDER_ENV=LOCAL_ENV")
221
- source_parser.add_argument("--env-file", action="append", default=[], help="credential file reference")
222
- source_parser.add_argument("--default-for", action="append", default=[], help="intent that should use this source by default")
223
- source_parser.add_argument("--default-for-agent", action="append", default=[], help="agent id that should use this source by default")
224
- source_parser.add_argument("--set-default", action="store_true", help="set as default source for its provider")
225
-
226
- memory_parser = subparsers.add_parser("memory", help="inspect or reset local AI DevKit memory")
227
- memory_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
228
- memory_parser.add_argument("action", nargs="?", default="show", choices=["show", "path", "reset"])
229
- memory_parser.add_argument("--agent", dest="agent_id")
230
- memory_parser.add_argument("--source", dest="source_id")
231
- memory_parser.add_argument("--all", action="store_true", help="reset all local memory")
232
- memory_parser.add_argument("--sessions", action="store_true", help="reset local conversation sessions")
233
- memory_parser.add_argument("--tasks", action="store_true", help="reset local task schedules")
234
- memory_parser.add_argument("--cache", action="store_true", help="reset local cache")
235
-
236
- personality_parser = subparsers.add_parser("personality", help="inspect or update local Agent DevKit personality")
237
- personality_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
238
- personality_parser.add_argument("action", nargs="?", default="show", choices=["show", "edit", "reset"])
239
- personality_parser.add_argument("--name", dest="agent_name", help="public agent name")
240
- personality_parser.add_argument("--user-name", help="user name")
241
- personality_parser.add_argument("--language", help="default response language")
242
- personality_parser.add_argument("--tone", help="response tone")
243
- personality_parser.add_argument("--detail-level", help="response detail level")
244
-
245
- setup_parser = subparsers.add_parser("setup", help="run setup helpers")
246
- setup_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
247
- setup_parser.add_argument("--dry-run", action="store_true", help="show setup plan without installing external tools")
248
- setup_parser.add_argument("--yes", action="store_true", help="confirm setup actions")
249
- setup_parser.add_argument("action", nargs="?", default="plan", choices=["plan", "personality"])
250
-
251
- alias_parser = subparsers.add_parser("alias", help="manage local command aliases for agent")
252
- alias_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
253
- alias_parser.add_argument("action", nargs="?", default="list", choices=["add", "list", "remove", "sync"])
254
- alias_parser.add_argument("name", nargs="?")
255
- alias_parser.add_argument("--force", action="store_true", help="allow replacing an existing local alias file")
256
-
257
- session_parser = subparsers.add_parser("session", help="manage local conversation sessions")
258
- session_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
259
- session_parser.add_argument("action", nargs="?", default="list", choices=["list", "show", "resume"])
260
- session_parser.add_argument("session_id", nargs="?")
261
-
262
- toolchain_parser = subparsers.add_parser("toolchain", help="inspect or install external tools")
263
- toolchain_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
264
- toolchain_parser.add_argument("action", nargs="?", default="list", choices=["list", "doctor", "install"])
265
- toolchain_parser.add_argument("tool", nargs="?", default="all")
266
- toolchain_parser.add_argument("--dry-run", action="store_true", help="show install plan without executing it")
267
- toolchain_parser.add_argument("--yes", action="store_true", help="confirm external tool installation")
268
-
269
- task_parser = subparsers.add_parser("task", help="manage local scheduled tasks")
270
- task_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
271
- task_parser.add_argument("action", nargs="?", default="list", choices=["create", "list", "show", "history", "run", "pause", "resume", "update", "enable", "disable", "delete"])
272
- task_parser.add_argument("task_id", nargs="?")
273
- task_parser.add_argument("--title")
274
- task_parser.add_argument("--prompt")
275
- task_parser.add_argument("--every")
276
- task_parser.add_argument("--cron")
277
- task_parser.add_argument("--dry-run", action="store_true")
278
- task_parser.add_argument("--yes", action="store_true")
279
-
280
- scheduler_parser = subparsers.add_parser("scheduler", help="run local scheduler")
281
- scheduler_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
282
- scheduler_parser.add_argument("action", nargs="?", default="run-once", choices=["run-once", "daemon"])
283
- scheduler_parser.add_argument("--dry-run", action="store_true")
284
-
285
- calendar_parser = subparsers.add_parser("calendar", help="inspect configured calendar")
286
- calendar_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
287
- calendar_parser.add_argument("action", nargs="?", default="today", choices=["today", "tomorrow", "list", "configure"])
288
- calendar_parser.add_argument("--from", dest="date_from")
289
- calendar_parser.add_argument("--to", dest="date_to")
290
- calendar_parser.add_argument("--ics")
291
- calendar_parser.add_argument("--timezone")
292
-
293
- pr_parser = subparsers.add_parser("pr", help="review GitHub pull requests")
294
- pr_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
295
- pr_parser.add_argument("action", nargs="?", default="list-review-requests", choices=["list-review-requests", "inspect", "review", "automation"])
296
- pr_parser.add_argument("pr_ref", nargs="?")
297
- pr_parser.add_argument("automation_action", nargs="?")
298
- pr_parser.add_argument("--approve", action="store_true")
299
- pr_parser.add_argument("--request-changes", action="store_true")
300
- pr_parser.add_argument("--comment")
301
- pr_parser.add_argument("--allow-write", action="store_true")
302
- pr_parser.add_argument("--dry-run", action="store_true")
303
- pr_parser.add_argument("--time", default="09:00")
304
-
305
- permissions_parser = subparsers.add_parser("permissions", help="manage local permission policies")
306
- permissions_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
307
- permissions_parser.add_argument("action", nargs="?", default="show", choices=["show", "grant", "revoke"])
308
- permissions_parser.add_argument("agent", nargs="?")
309
- permissions_parser.add_argument("provider", nargs="?")
310
- permissions_parser.add_argument("level", nargs="?")
311
- permissions_parser.add_argument("--project")
312
- permissions_parser.add_argument("--task", dest="task_id")
313
-
314
- audit_parser = subparsers.add_parser("audit", help="inspect local execution audit trail")
315
- audit_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
316
- audit_parser.add_argument("action", nargs="?", default="list", choices=["list", "show", "export"])
317
- audit_parser.add_argument("execution_id", nargs="?")
318
- audit_parser.add_argument("--limit", type=int, default=20)
319
- audit_parser.add_argument("--format", default="md", choices=["md", "json"])
320
-
321
- config_parser = subparsers.add_parser("config", help="inspect local Agent DevKit configuration")
322
- config_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
323
- config_parser.add_argument("action", nargs="?", default="show", choices=["show", "path"])
324
-
325
- for command_name, help_text in (
326
- ("tools", "manage enabled local tools"),
327
- ("integrations", "manage provider integration decisions"),
328
- ("skills", "manage local skill decisions"),
329
- ):
330
- control_parser = subparsers.add_parser(command_name, help=help_text)
331
- control_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
332
- control_parser.add_argument("action", nargs="?", default="list", choices=["list", "enable", "disable"])
333
- control_parser.add_argument("item_id", nargs="?")
334
-
335
- decisions_parser = subparsers.add_parser("decisions", help="inspect or reset local opt-in and opt-out decisions")
336
- decisions_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
337
- decisions_parser.add_argument("action", nargs="?", default="list", choices=["list", "forget", "reset"])
338
- decisions_parser.add_argument("item_id", nargs="?")
339
- decisions_parser.add_argument("--category", choices=["tools", "integrations", "skills", "llms"])
340
-
341
- ollama_parser = subparsers.add_parser("ollama", help="inspect and manage local Ollama models")
342
- ollama_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
343
- ollama_parser.add_argument("action", nargs="?", default="status", choices=["status", "models", "pull", "update"])
344
- ollama_parser.add_argument("model", nargs="?")
345
- ollama_parser.add_argument("--yes", action="store_true", help="confirm Ollama model or update operation")
346
- ollama_parser.add_argument("--dry-run", action="store_true", help="show Ollama operation without executing it")
347
-
348
- llm_parser = subparsers.add_parser("llm", help="manage LLM backends")
349
- llm_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
350
- llm_parser.add_argument(
351
- "action",
352
- nargs="?",
353
- default="list",
354
- choices=["list", "doctor", "configure", "set-default", "default", "enable", "disable", "preference"],
355
- )
356
- llm_parser.add_argument("backend", nargs="?")
357
- llm_parser.add_argument("preference_value", nargs="?")
358
- llm_parser.add_argument("--api-key-env", help="environment variable that stores the API key")
359
- llm_parser.add_argument("--base-url", help="OpenAI-compatible base URL")
360
- llm_parser.add_argument("--model", help="default model id")
361
- llm_parser.add_argument("--command", dest="host_command", help="host CLI command name or path")
362
- llm_parser.add_argument("--set-default", action="store_true", help="set backend as the default LLM")
363
- llm_parser.add_argument("--primary", help="primary backend for LLM preference")
364
- llm_parser.add_argument("--order", help="comma-separated fallback order")
365
-
366
- install_parser = subparsers.add_parser("install", help="install AI DevKit host artifacts")
367
- install_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
368
- install_parser.add_argument("scope", nargs="?", default="project", choices=["project", "global"])
369
- install_parser.add_argument("--target", help="project directory for project installs")
370
- install_parser.add_argument("--home", help="home directory override for global installs")
371
- install_parser.add_argument(
372
- "--host",
373
- default="all",
374
- choices=["all", "codex", "claude-code", "claude-desktop", "claude-ai"],
375
- help="host adapter to install",
376
- )
377
- install_parser.add_argument("--profiles", help="comma-separated project profiles to record in the lock")
378
- install_parser.add_argument("--dry-run", action="store_true", help="print planned writes without creating files")
379
-
380
- agents_parser = subparsers.add_parser("agents", aliases=["a"], help="list available agents")
381
- agents_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
382
- agents_parser.add_argument("action", nargs="?", default="list", choices=["list"])
383
-
384
- capabilities_parser = subparsers.add_parser(
385
- "capabilities",
386
- aliases=["c"],
387
- help="list capabilities",
388
- )
389
- capabilities_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
390
- capabilities_parser.add_argument("action_or_agent", nargs="?", default="list")
391
- capabilities_parser.add_argument("legacy_agent", nargs="?")
392
- capabilities_parser.add_argument("--agent", dest="agent")
393
-
394
- inspect_parser = subparsers.add_parser(
395
- "inspect",
396
- aliases=["i"],
397
- help="inspect an agent capability",
398
- )
399
- inspect_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
400
- inspect_parser.add_argument("agent")
401
- inspect_parser.add_argument("capability")
402
-
403
- run_parser = subparsers.add_parser(
404
- "run",
405
- aliases=["r"],
406
- help="run an agent capability",
407
- )
408
- run_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
409
- run_parser.add_argument("agent")
410
- run_parser.add_argument("capability")
411
- run_parser.add_argument("capability_args", nargs=argparse.REMAINDER)
412
-
413
- doctor_parser = subparsers.add_parser("doctor", help="run local diagnostics")
414
- doctor_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
415
- doctor_parser.add_argument("--scope", default="auto", choices=["auto", "project", "global"], help="diagnostic scope")
416
- doctor_parser.add_argument("--project", help="project directory whose AI DevKit lock should be checked")
417
- doctor_parser.add_argument("--home", help="home directory override for global lock checks")
418
- return parser
419
-
420
-
421
- def dispatch(args: argparse.Namespace) -> dict[str, Any] | None:
422
- if args.version:
423
- return {"kind": "version", "program": getattr(args, "prog_name", "aikit"), "version": __version__}
424
- if args.sessions_shortcut:
425
- return list_sessions()
426
-
427
- if not args.command:
428
- raise DevKitError("missing command. Use --help for usage.")
429
-
430
- command = canonical_command(args.command)
431
- if command == "agent":
432
- return agent_requires_llm(args)
433
- if command == "commands":
434
- return list_command_modes()
435
- if command == "providers":
436
- return dispatch_providers(args)
437
- if command == "provider":
438
- return dispatch_provider(args)
439
- if command == "credential":
440
- return dispatch_credential(args)
441
- if command == "source":
442
- return dispatch_source(args)
443
- if command == "memory":
444
- return dispatch_memory(args)
445
- if command == "personality":
446
- return dispatch_personality(args)
447
- if command == "setup":
448
- return dispatch_setup(args)
449
- if command == "alias":
450
- return dispatch_alias(args)
451
- if command == "session":
452
- return dispatch_session(args)
453
- if command == "toolchain":
454
- return dispatch_toolchain(args)
455
- if command == "task":
456
- return dispatch_task(args)
457
- if command == "scheduler":
458
- return dispatch_scheduler(args)
459
- if command == "calendar":
460
- return dispatch_calendar(args)
461
- if command == "pr":
462
- return dispatch_pr(args)
463
- if command == "permissions":
464
- return dispatch_permissions(args)
465
- if command == "audit":
466
- return dispatch_audit(args)
467
- if command == "config":
468
- return dispatch_config(args)
469
- if command in {"tools", "integrations", "skills"}:
470
- return dispatch_control_category(command, args)
471
- if command == "decisions":
472
- return dispatch_decisions(args)
473
- if command == "ollama":
474
- return dispatch_ollama(args)
475
- if command == "llm":
476
- return dispatch_llm(args)
477
- if command == "install":
478
- return dispatch_install(args)
479
- if command == "agents":
480
- return {"kind": "agents", "items": list_agents()}
481
- if command == "capabilities":
482
- agent_id = resolve_capabilities_agent(args)
483
- if agent_id:
484
- agent = load_agent(agent_id)
485
- return {
486
- "kind": "capabilities",
487
- "agent": agent["id"],
488
- "items": list_capabilities(agent["path"]),
489
- }
490
- return {
491
- "kind": "capabilities",
492
- "agent": None,
493
- "items": list_all_capabilities(),
494
- }
495
- if command == "inspect":
496
- agent = load_agent(args.agent)
497
- capability = load_capability(agent["path"], args.capability)
498
- return {
499
- "kind": "capability",
500
- "agent": summarize_agent(agent),
501
- "capability": capability,
502
- }
503
- if command == "run":
504
- agent = load_agent(args.agent)
505
- return run_capability(
506
- agent,
507
- args.capability,
508
- args.capability_args,
509
- capture_output=args.json,
510
- )
511
- if command == "doctor":
512
- return doctor(args.project, args.home, args.scope)
513
- raise DevKitError(f"unsupported command: {args.command}")
514
-
515
-
516
- def canonical_command(command: str) -> str:
517
- aliases = {
518
- "a": "agents",
519
- "c": "capabilities",
520
- "i": "inspect",
521
- "r": "run",
522
- }
523
- return aliases.get(command, command)
524
-
525
-
526
- def list_command_modes() -> dict[str, Any]:
527
- return {
528
- "kind": "commands",
529
- "deterministic": [
530
- {
531
- "command": command,
532
- "requires_llm": False,
533
- }
534
- for command in DETERMINISTIC_COMMANDS
535
- ],
536
- "llm": [
537
- {
538
- "command": command,
539
- "requires_llm": True,
540
- }
541
- for command in LLM_COMMANDS
542
- ],
543
- }
544
-
545
-
546
- def maybe_record_cli_audit(args: argparse.Namespace, *, result: dict[str, Any] | None, error: str | None) -> None:
547
- command = canonical_command(getattr(args, "command", None) or "")
548
- if command in {"", "audit"} or getattr(args, "version", False):
549
- return
550
- try:
551
- audit = record_audit(command=command, args=vars(args), result=result, error=error)
552
- except Exception:
553
- return
554
- if result is not None:
555
- result["audit"] = audit
556
-
557
-
558
- def dispatch_llm(args: argparse.Namespace) -> dict[str, Any]:
559
- try:
560
- if args.action != "preference" and args.preference_value:
561
- raise DevKitError(f"llm {args.action} received an unexpected argument: {args.preference_value}")
562
- if args.action == "list":
563
- if args.backend:
564
- raise DevKitError("llm list does not accept a backend argument")
565
- return list_backends()
566
- if args.action == "doctor":
567
- return doctor_backends(args.backend)
568
- if args.action == "configure":
569
- if not args.backend:
570
- raise DevKitError("llm configure requires a backend")
571
- return configure_backend(
572
- args.backend,
573
- api_key_env=args.api_key_env,
574
- base_url=args.base_url,
575
- model=args.model,
576
- command=args.host_command,
577
- set_default=args.set_default,
578
- )
579
- if args.action in {"set-default", "default"}:
580
- if not args.backend:
581
- raise DevKitError(f"llm {args.action} requires a backend")
582
- return set_default_backend(args.backend)
583
- if args.action in {"enable", "disable"}:
584
- if not args.backend:
585
- raise DevKitError(f"llm {args.action} requires a backend")
586
- state = "enabled" if args.action == "enable" else "disabled_by_user"
587
- return set_decision("llms", args.backend, state, reason=f"llm {args.action} command")
588
- if args.action == "preference":
589
- if args.backend in {None, "show"}:
590
- return llm_preference()
591
- if args.backend == "set":
592
- if not args.primary and not args.order:
593
- raise DevKitError("llm preference set requires --primary or --order")
594
- return set_llm_preference(primary=args.primary, order=args.order)
595
- if args.backend == "reorder":
596
- order = args.preference_value or args.order
597
- if not order:
598
- raise DevKitError("llm preference reorder requires an order value or --order")
599
- return set_llm_preference(order=order)
600
- raise DevKitError("llm preference action must be show, set or reorder")
601
- except ValueError as exc:
602
- raise DevKitError(str(exc)) from exc
603
- raise DevKitError(f"unsupported llm action: {args.action}")
604
-
605
-
606
- def dispatch_config(args: argparse.Namespace) -> dict[str, Any]:
607
- from cli.aikit.llm import config_path
608
-
609
- if args.action == "path":
610
- return {"kind": "config", "status": "ok", "path": str(config_path())}
611
- if args.action == "show":
612
- return {
613
- "kind": "config",
614
- "status": "ok",
615
- "path": str(config_path()),
616
- "decisions": list_decisions(),
617
- "llm": llm_preference(),
618
- "ollama": ollama_status(),
619
- }
620
- raise DevKitError(f"unsupported config action: {args.action}")
621
-
622
-
623
- def dispatch_control_category(command: str, args: argparse.Namespace) -> dict[str, Any]:
624
- try:
625
- category = command
626
- if args.action == "list":
627
- if args.item_id:
628
- raise DevKitError(f"{command} list does not accept an item id")
629
- payload = list_decisions(category)
630
- payload["kind"] = command
631
- return payload
632
- if args.action in {"enable", "disable"}:
633
- if not args.item_id:
634
- raise DevKitError(f"{command} {args.action} requires an item id")
635
- state = "enabled" if args.action == "enable" else "disabled_by_user"
636
- payload = set_decision(category, args.item_id, state, reason=f"{command} {args.action} command")
637
- payload["kind"] = command[:-1] if command.endswith("s") else command
638
- return payload
639
- except ValueError as exc:
640
- raise DevKitError(str(exc)) from exc
641
- raise DevKitError(f"unsupported {command} action: {args.action}")
642
-
643
-
644
- def dispatch_decisions(args: argparse.Namespace) -> dict[str, Any]:
645
- try:
646
- if args.action == "list":
647
- if args.item_id:
648
- raise DevKitError("decisions list does not accept an item id")
649
- return list_decisions(args.category)
650
- if args.action == "reset":
651
- if args.item_id:
652
- raise DevKitError("decisions reset does not accept an item id")
653
- return reset_decisions(args.category)
654
- if args.action == "forget":
655
- if not args.item_id:
656
- raise DevKitError("decisions forget requires an item id")
657
- category = args.category or "tools"
658
- return set_decision(category, args.item_id, "available", reason="decision forgotten")
659
- except ValueError as exc:
660
- raise DevKitError(str(exc)) from exc
661
- raise DevKitError(f"unsupported decisions action: {args.action}")
662
-
663
-
664
- def dispatch_ollama(args: argparse.Namespace) -> dict[str, Any]:
665
- try:
666
- if args.action == "status":
667
- if args.model:
668
- raise DevKitError("ollama status does not accept a model")
669
- return ollama_status()
670
- if args.action == "models":
671
- if args.model:
672
- raise DevKitError("ollama models does not accept a model")
673
- return ollama_models()
674
- if args.action == "pull":
675
- return ollama_pull(args.model, yes=args.yes, dry_run=effective_dry_run(args))
676
- if args.action == "update":
677
- if args.model:
678
- raise DevKitError("ollama update does not accept a model")
679
- return ollama_update(yes=args.yes, dry_run=effective_dry_run(args))
680
- except ValueError as exc:
681
- raise DevKitError(str(exc)) from exc
682
- raise DevKitError(f"unsupported ollama action: {args.action}")
683
-
684
-
685
- def dispatch_install(args: argparse.Namespace) -> dict[str, Any]:
686
- try:
687
- return install_runtime(
688
- ROOT,
689
- scope=args.scope,
690
- host=args.host,
691
- target=Path(args.target) if args.target else None,
692
- home=Path(args.home) if args.home else None,
693
- dry_run=effective_dry_run(args),
694
- profiles=parse_profiles(args.profiles),
695
- )
696
- except InstallError as exc:
697
- raise DevKitError(str(exc)) from exc
698
-
699
-
700
- def dispatch_providers(args: argparse.Namespace) -> dict[str, Any]:
701
- if args.action != "list":
702
- raise DevKitError(f"unsupported providers action: {args.action}")
703
- try:
704
- return list_providers(ROOT)
705
- except ProviderRegistryError as exc:
706
- raise DevKitError(str(exc)) from exc
707
-
708
-
709
- def dispatch_provider(args: argparse.Namespace) -> dict[str, Any]:
710
- try:
711
- if args.action in {"status", "doctor"}:
712
- return provider_status_with_credentials(ROOT, args.provider, env_files=[Path(item) for item in args.env_file])
713
- if args.action == "configure":
714
- if not args.provider:
715
- raise DevKitError("provider configure requires a provider id")
716
- return configure_provider(
717
- ROOT,
718
- args.provider,
719
- env_refs=args.env,
720
- env_files=[Path(item) for item in args.env_file],
721
- from_env=args.from_env,
722
- session_only=args.session_only,
723
- )
724
- if args.action == "unset":
725
- if not args.provider:
726
- raise DevKitError("provider unset requires a provider id")
727
- return unset_provider_config(ROOT, args.provider)
728
- except ProviderRegistryError as exc:
729
- raise DevKitError(str(exc)) from exc
730
- except CredentialResolverError as exc:
731
- raise DevKitError(str(exc)) from exc
732
- raise DevKitError(f"unsupported provider action: {args.action}")
733
-
734
-
735
- def dispatch_credential(args: argparse.Namespace) -> dict[str, Any]:
736
- if args.action == "backends":
737
- if args.provider:
738
- raise DevKitError("credential backends does not accept a provider argument")
739
- return credential_backends()
740
- if args.action == "resolve":
741
- if not args.provider:
742
- raise DevKitError("credential resolve requires a provider id")
743
- try:
744
- return credential_resolution(ROOT, args.provider, env_files=[Path(item) for item in args.env_file])
745
- except (ProviderRegistryError, CredentialResolverError) as exc:
746
- raise DevKitError(str(exc)) from exc
747
- raise DevKitError(f"unsupported credential action: {args.action}")
748
-
749
-
750
- def dispatch_source(args: argparse.Namespace) -> dict[str, Any]:
751
- try:
752
- if args.action == "list":
753
- return list_sources()
754
- if args.action == "add":
755
- if not args.source_id:
756
- raise DevKitError("source add requires a source id")
757
- return add_source(
758
- args.source_id,
759
- provider=args.provider,
760
- label=args.label,
761
- config_pairs=args.config,
762
- env_refs=args.env,
763
- env_files=args.env_file,
764
- default_for=args.default_for,
765
- default_for_agent=args.default_for_agent,
766
- set_default=args.set_default,
767
- )
768
- if args.action == "status":
769
- return source_status(args.source_id)
770
- if args.action == "remove":
771
- if not args.source_id:
772
- raise DevKitError("source remove requires a source id")
773
- return remove_source(args.source_id)
774
- except SourceRegistryError as exc:
775
- raise DevKitError(str(exc)) from exc
776
- raise DevKitError(f"unsupported source action: {args.action}")
777
-
778
-
779
- def dispatch_memory(args: argparse.Namespace) -> dict[str, Any]:
780
- if args.action == "show":
781
- return show_memory(ROOT, agent_id=args.agent_id, source_id=args.source_id)
782
- if args.action == "path":
783
- return memory_path_payload()
784
- if args.action == "reset":
785
- return reset_memory(
786
- all_memory=args.all,
787
- agent_id=args.agent_id,
788
- source_id=args.source_id,
789
- reset_sessions=args.sessions,
790
- reset_tasks=args.tasks,
791
- reset_cache=args.cache,
792
- )
793
- raise DevKitError(f"unsupported memory action: {args.action}")
794
-
795
-
796
- def dispatch_personality(args: argparse.Namespace) -> dict[str, Any]:
797
- if args.action == "show":
798
- return load_personality()
799
- if args.action == "edit":
800
- if not any([args.agent_name, args.user_name, args.language, args.tone, args.detail_level]):
801
- payload = load_personality()
802
- payload["status"] = "needs-input"
803
- payload["message"] = "Use --name, --user-name, --language, --tone or --detail-level to edit non-interactively."
804
- return payload
805
- return update_personality(
806
- agent_name=args.agent_name,
807
- user_name=args.user_name,
808
- language=args.language,
809
- tone=args.tone,
810
- detail_level=args.detail_level,
811
- )
812
- if args.action == "reset":
813
- return reset_personality()
814
- raise DevKitError(f"unsupported personality action: {args.action}")
815
-
816
-
817
- def dispatch_setup(args: argparse.Namespace) -> dict[str, Any]:
818
- if args.action == "personality":
819
- return setup_personality()
820
- if args.action == "plan":
821
- return setup_wizard(ROOT, dry_run=effective_dry_run(args), yes=args.yes)
822
- raise DevKitError(f"unsupported setup action: {args.action}")
823
-
824
-
825
- def dispatch_toolchain(args: argparse.Namespace) -> dict[str, Any]:
826
- try:
827
- if args.action == "list":
828
- if args.tool != "all":
829
- raise DevKitError("toolchain list does not accept a tool argument")
830
- return list_toolchain(ROOT)
831
- if args.action == "doctor":
832
- return doctor_toolchain(ROOT, None if args.tool == "all" else args.tool)
833
- if args.action == "install":
834
- return install_toolchain(ROOT, None if args.tool == "all" else args.tool, dry_run=effective_dry_run(args), yes=args.yes)
835
- except ValueError as exc:
836
- raise DevKitError(str(exc)) from exc
837
- raise DevKitError(f"unsupported toolchain action: {args.action}")
838
-
839
-
840
- def dispatch_task(args: argparse.Namespace) -> dict[str, Any]:
841
- try:
842
- if args.action == "list":
843
- return list_tasks()
844
- if args.action == "create":
845
- schedule = {"type": "manual"}
846
- if args.every:
847
- schedule = {"type": "interval", "every": args.every}
848
- if args.cron:
849
- schedule = {"type": "cron", "cron": args.cron}
850
- return create_task(task_id=args.task_id, title=args.title, prompt=args.prompt, schedule=schedule)
851
- if args.action == "show":
852
- require_id(args.task_id, "task show")
853
- return show_task(args.task_id)
854
- if args.action == "history":
855
- require_id(args.task_id, "task history")
856
- return task_history(args.task_id)
857
- if args.action == "run":
858
- require_id(args.task_id, "task run")
859
- return run_task(args.task_id, dry_run=effective_dry_run(args))
860
- if args.action in {"pause", "disable"}:
861
- require_id(args.task_id, f"task {args.action}")
862
- return update_task_status(args.task_id, "paused" if args.action == "pause" else "disabled")
863
- if args.action in {"resume", "enable"}:
864
- require_id(args.task_id, f"task {args.action}")
865
- return update_task_status(args.task_id, "enabled")
866
- if args.action == "update":
867
- require_id(args.task_id, "task update")
868
- return update_task_schedule(args.task_id, every=args.every, cron=args.cron)
869
- if args.action == "delete":
870
- require_id(args.task_id, "task delete")
871
- return delete_task(args.task_id, yes=args.yes)
872
- except ValueError as exc:
873
- raise DevKitError(str(exc)) from exc
874
- raise DevKitError(f"unsupported task action: {args.action}")
875
-
876
-
877
- def dispatch_scheduler(args: argparse.Namespace) -> dict[str, Any]:
878
- if args.action == "run-once":
879
- return run_scheduler_once(dry_run=effective_dry_run(args))
880
- if args.action == "daemon":
881
- return scheduler_daemon_plan()
882
- raise DevKitError(f"unsupported scheduler action: {args.action}")
883
-
884
-
885
- def dispatch_calendar(args: argparse.Namespace) -> dict[str, Any]:
886
- try:
887
- if args.action == "configure":
888
- return configure_calendar(ics_path=args.ics, timezone=args.timezone)
889
- if args.action == "today":
890
- return calendar_today()
891
- if args.action == "tomorrow":
892
- return calendar_tomorrow()
893
- if args.action == "list":
894
- return calendar_list(args.date_from, args.date_to)
895
- except ValueError as exc:
896
- raise DevKitError(str(exc)) from exc
897
- raise DevKitError(f"unsupported calendar action: {args.action}")
898
-
899
-
900
- def dispatch_pr(args: argparse.Namespace) -> dict[str, Any]:
901
- if args.action == "list-review-requests":
902
- if effective_dry_run(args):
903
- return pr_read_dry_run("list-review-requests")
904
- return pr_list_review_requests()
905
- if args.action == "inspect":
906
- require_id(args.pr_ref, "pr inspect")
907
- if effective_dry_run(args):
908
- return pr_read_dry_run("inspect", pr_ref=args.pr_ref)
909
- return pr_inspect(args.pr_ref)
910
- if args.action == "review":
911
- require_id(args.pr_ref, "pr review")
912
- return pr_review(
913
- args.pr_ref,
914
- approve=args.approve,
915
- request_changes=args.request_changes,
916
- comment=args.comment,
917
- allow_write=args.allow_write,
918
- dry_run=effective_dry_run(args),
919
- )
920
- if args.action == "automation":
921
- if args.automation_action not in {None, "create"}:
922
- raise DevKitError("pr automation action must be create")
923
- if effective_dry_run(args):
924
- return pr_automation_dry_run(time=args.time)
925
- return pr_create_automation(time=args.time)
926
- raise DevKitError(f"unsupported pr action: {args.action}")
927
-
928
-
929
- def dispatch_permissions(args: argparse.Namespace) -> dict[str, Any]:
930
- try:
931
- if args.action == "show":
932
- return show_permissions()
933
- if args.action == "grant":
934
- if not args.agent or not args.provider or not args.level:
935
- raise DevKitError("permissions grant requires agent, provider and level")
936
- return grant_permission(args.agent, args.provider, args.level, project=args.project, task_id=args.task_id)
937
- if args.action == "revoke":
938
- if not args.agent or not args.provider:
939
- raise DevKitError("permissions revoke requires agent and provider")
940
- return revoke_permission(args.agent, args.provider, args.level, project=args.project, task_id=args.task_id)
941
- except ValueError as exc:
942
- raise DevKitError(str(exc)) from exc
943
- raise DevKitError(f"unsupported permissions action: {args.action}")
944
-
945
-
946
- def dispatch_audit(args: argparse.Namespace) -> dict[str, Any]:
947
- try:
948
- if args.action == "list":
949
- if args.execution_id:
950
- raise DevKitError("audit list does not accept an execution id")
951
- return list_audits(limit=max(1, int(args.limit or 20)))
952
- if args.action == "show":
953
- require_id(args.execution_id, "audit show")
954
- return show_audit(args.execution_id)
955
- if args.action == "export":
956
- require_id(args.execution_id, "audit export")
957
- return export_audit(args.execution_id, fmt=args.format)
958
- except ValueError as exc:
959
- raise DevKitError(str(exc)) from exc
960
- raise DevKitError(f"unsupported audit action: {args.action}")
961
-
962
-
963
- def pr_read_dry_run(action: str, *, pr_ref: str | None = None) -> dict[str, Any]:
964
- return {
965
- "kind": "pr",
966
- "status": "planned",
967
- "ok": True,
968
- "dry_run": True,
969
- "mode": "report-only",
970
- "provider": "github",
971
- "action": action,
972
- "pr_ref": pr_ref,
973
- "commands": planned_pr_commands(action, pr_ref=pr_ref),
974
- "summary": "Dry-run only. GitHub would be read through gh; no PR write action would be submitted.",
975
- }
976
-
977
-
978
- def pr_automation_dry_run(*, time: str) -> dict[str, Any]:
979
- return {
980
- "kind": "pr-automation",
981
- "status": "planned",
982
- "ok": True,
983
- "dry_run": True,
984
- "mode": "report-only",
985
- "provider": "github",
986
- "task": {
987
- "id": "daily-pr-review",
988
- "title": "Revisar PRs pendentes diariamente",
989
- "schedule": {"type": "daily", "time": time},
990
- "action": {
991
- "type": "capability",
992
- "agent": "github-pr-reviewer",
993
- "capability": "list-review-requests",
994
- "external_writes": False,
995
- },
996
- "permissions": {"mode": "report-only", "comment": False, "approve": False, "request_changes": False},
997
- },
998
- "summary": "Dry-run only. A local report-only PR review task would be created.",
999
- }
1000
-
1001
-
1002
- def planned_pr_commands(action: str, *, pr_ref: str | None = None) -> list[list[str]]:
1003
- if action == "list-review-requests":
1004
- return [["gh", "pr", "list", "--review-requested", "@me", "--json", "number,title,url,author,headRefName,baseRefName,isDraft"]]
1005
- if action == "inspect":
1006
- return [["gh", "pr", "view", str(pr_ref), "--json", "number,title,url,author,body,headRefName,baseRefName,state,isDraft,reviewDecision,mergeable"]]
1007
- return []
1008
-
1009
-
1010
- def require_id(value: str | None, command: str) -> None:
1011
- if not value:
1012
- raise DevKitError(f"{command} requires an id")
1013
-
1014
-
1015
- def effective_dry_run(args: argparse.Namespace) -> bool:
1016
- return bool(getattr(args, "dry_run", False) or getattr(args, "global_dry_run", False))
1017
-
1018
-
1019
- def dispatch_alias(args: argparse.Namespace) -> dict[str, Any]:
1020
- try:
1021
- if args.action == "list":
1022
- if args.name:
1023
- raise DevKitError("alias list does not accept a name")
1024
- return list_aliases()
1025
- if args.action == "add":
1026
- if not args.name:
1027
- raise DevKitError("alias add requires a name")
1028
- return add_alias(args.name, force=args.force)
1029
- if args.action == "remove":
1030
- if not args.name:
1031
- raise DevKitError("alias remove requires a name")
1032
- return remove_alias(args.name)
1033
- if args.action == "sync":
1034
- if args.name:
1035
- raise DevKitError("alias sync does not accept a name")
1036
- return sync_aliases()
1037
- except ValueError as exc:
1038
- raise DevKitError(str(exc)) from exc
1039
- raise DevKitError(f"unsupported alias action: {args.action}")
1040
-
1041
-
1042
- def dispatch_session(args: argparse.Namespace) -> dict[str, Any]:
1043
- try:
1044
- if args.action == "list":
1045
- if args.session_id:
1046
- raise DevKitError("session list does not accept a session id")
1047
- return list_sessions()
1048
- if args.action == "show":
1049
- if not args.session_id:
1050
- raise DevKitError("session show requires a session id")
1051
- return show_session(args.session_id)
1052
- if args.action == "resume":
1053
- if not args.session_id:
1054
- raise DevKitError("session resume requires a session id")
1055
- return resume_session(args.session_id)
1056
- except ValueError as exc:
1057
- raise DevKitError(str(exc)) from exc
1058
- raise DevKitError(f"unsupported session action: {args.action}")
1059
-
1060
-
1061
- def agent_requires_llm(args: argparse.Namespace) -> dict[str, Any]:
1062
- prompt = " ".join(args.prompt).strip()
1063
- if not prompt:
1064
- raise DevKitError("agent requires a natural-language prompt")
1065
- if effective_dry_run(args):
1066
- return build_agent_dry_run_plan(prompt, args)
1067
- try:
1068
- session = get_or_create_session(
1069
- session_id=args.session_id,
1070
- force_new=args.new_session,
1071
- prompt=prompt,
1072
- project=str(Path.cwd()),
1073
- backend=args.llm,
1074
- )
1075
- except ValueError as exc:
1076
- raise DevKitError(str(exc)) from exc
1077
- personality = load_personality()
1078
- name = public_name(personality=personality, invoked_as=getattr(args, "prog_name", "agent"))
1079
- if is_identity_question(prompt):
1080
- result = {
1081
- "kind": "agent",
1082
- "status": "ok",
1083
- "ok": True,
1084
- "requires_llm": False,
1085
- "prompt_received": True,
1086
- "prompt_length": len(prompt),
1087
- "identity": {"name": name, "source": "local"},
1088
- "response": local_identity_response(prompt, name=name),
1089
- }
1090
- return finalize_agent_session(result, session, prompt, backend=args.llm)
1091
- natural_result = dispatch_natural_operational_prompt(prompt)
1092
- if natural_result:
1093
- return finalize_agent_session(natural_result, session, prompt, backend=args.llm)
1094
- route = route_prompt(prompt)
1095
- if route:
1096
- result = invoke_deterministic_route(prompt, route)
1097
- return finalize_agent_session(result, session, prompt, backend=args.llm)
1098
- contextual_prompt = build_contextual_prompt(str(session["id"]), prompt)
1099
- model_plan = build_model_plan(prompt)
1100
- result = invoke_agent_prompt(
1101
- contextual_prompt,
1102
- args.llm,
1103
- public_name=name,
1104
- allow_fallback=not args.no_llm_fallback,
1105
- )
1106
- review_gate = build_review_gate(prompt, model_plan=model_plan)
1107
- if result.get("ok"):
1108
- review_gate = mark_reviewed(review_gate, reviewer=str(result.get("llm_backend") or "coordinator"))
1109
- result["model_plan"] = model_plan
1110
- result["review_gate"] = review_gate
1111
- result["prompt_length"] = len(prompt)
1112
- result["session_context_applied"] = contextual_prompt != prompt
1113
- if result.get("response"):
1114
- result["response"] = enforce_identity_response(str(result["response"]), prompt, name=name)
1115
- result["identity"] = {"name": name, "source": "local"}
1116
- return finalize_agent_session(result, session, prompt, backend=result.get("llm_backend") or args.llm)
1117
-
1118
-
1119
- def dispatch_natural_operational_prompt(prompt: str) -> dict[str, Any] | None:
1120
- normalized = " ".join(prompt.lower().split())
1121
- control_result = dispatch_natural_control_prompt(normalized)
1122
- if control_result:
1123
- control_result["prompt_received"] = True
1124
- control_result["prompt_length"] = len(prompt)
1125
- return control_result
1126
- if "agenda" in normalized:
1127
- if "amanha" in normalized or "amanhã" in normalized:
1128
- payload = calendar_tomorrow()
1129
- else:
1130
- payload = calendar_today()
1131
- payload = dict(payload)
1132
- payload["kind"] = "agent"
1133
- payload["mode"] = "calendar-route"
1134
- payload["requires_llm"] = False
1135
- payload["prompt_received"] = True
1136
- payload["prompt_length"] = len(prompt)
1137
- payload["response"] = calendar_summary(payload)
1138
- if payload.get("status") == "needs-input":
1139
- payload["ok"] = False
1140
- else:
1141
- payload["ok"] = True
1142
- return payload
1143
- if has_pr_intent(normalized):
1144
- if any(marker in normalized for marker in ("diariamente", "todo dia", "diaria", "diária", "recorrente")):
1145
- payload = pr_create_automation()
1146
- return {
1147
- "kind": "agent",
1148
- "status": payload.get("status"),
1149
- "ok": True,
1150
- "mode": "pr-automation-route",
1151
- "requires_llm": False,
1152
- "prompt_received": True,
1153
- "prompt_length": len(prompt),
1154
- "response": "Automacao diaria de revisao de PRs criada em modo report-only.",
1155
- "result": payload,
1156
- }
1157
- payload = pr_list_review_requests()
1158
- return {
1159
- "kind": "agent",
1160
- "status": payload.get("status"),
1161
- "ok": payload.get("status") == "ok",
1162
- "mode": "pr-route",
1163
- "requires_llm": False,
1164
- "prompt_received": True,
1165
- "prompt_length": len(prompt),
1166
- "response": summarize_pr_list(payload),
1167
- "result": payload,
1168
- "exit_code": payload.get("exit_code", 0 if payload.get("status") == "ok" else 2),
1169
- }
1170
- return None
1171
-
1172
-
1173
- def dispatch_natural_control_prompt(normalized_prompt: str) -> dict[str, Any] | None:
1174
- if "decis" in normalized_prompt and any(marker in normalized_prompt for marker in ("mostre", "liste", "ver", "mostrar", "listar")):
1175
- return {
1176
- "kind": "agent",
1177
- "status": "ok",
1178
- "ok": True,
1179
- "mode": "control-center-route",
1180
- "requires_llm": False,
1181
- "response": "Estas sao as decisoes locais registradas.",
1182
- "result": list_decisions(),
1183
- }
1184
- control_targets = {
1185
- "ollama": ("tools", "ollama"),
1186
- "azure devops": ("tools", "azure-devops"),
1187
- "azure": ("tools", "azure-devops"),
1188
- "github": ("integrations", "github"),
1189
- "figma": ("tools", "figma"),
1190
- }
1191
- action: str | None = None
1192
- if any(marker in normalized_prompt for marker in ("desative", "desabilite", "disable", "bloqueie")):
1193
- action = "disable"
1194
- if any(marker in normalized_prompt for marker in ("reative", "ative", "habilite", "enable")):
1195
- action = "enable"
1196
- if not action:
1197
- return None
1198
- for marker, (category, item_id) in control_targets.items():
1199
- if marker in normalized_prompt:
1200
- state = "enabled" if action == "enable" else "disabled_by_user"
1201
- result = set_decision(category, item_id, state, reason=f"natural prompt: {action}")
1202
- return {
1203
- "kind": "agent",
1204
- "status": "ok",
1205
- "ok": True,
1206
- "mode": "control-center-route",
1207
- "requires_llm": False,
1208
- "response": f"{item_id} foi {'ativado' if state == 'enabled' else 'desativado'} para {category}.",
1209
- "result": {
1210
- "category": category,
1211
- "id": item_id,
1212
- "state": state,
1213
- "decision": result.get("item"),
1214
- },
1215
- }
1216
- if any(marker in normalized_prompt for marker in ("ferramentas", "tools")) and any(
1217
- marker in normalized_prompt for marker in ("mostre", "liste", "ver", "mostrar", "listar")
1218
- ):
1219
- return {
1220
- "kind": "agent",
1221
- "status": "ok",
1222
- "ok": True,
1223
- "mode": "control-center-route",
1224
- "requires_llm": False,
1225
- "response": "Estas sao as ferramentas com decisoes locais registradas.",
1226
- "result": list_decisions("tools"),
1227
- }
1228
- return None
1229
-
1230
-
1231
- def build_agent_dry_run_plan(prompt: str, args: argparse.Namespace) -> dict[str, Any]:
1232
- normalized = " ".join(prompt.lower().split())
1233
- route = route_prompt(prompt)
1234
- model_plan = build_model_plan(prompt, route=route)
1235
- review_gate = build_review_gate(prompt, route=route, model_plan=model_plan)
1236
- plan: dict[str, Any] = {
1237
- "kind": "agent",
1238
- "status": "planned",
1239
- "ok": True,
1240
- "dry_run": True,
1241
- "requires_llm": False,
1242
- "prompt_received": True,
1243
- "prompt_length": len(prompt),
1244
- "mode": "dry-run",
1245
- "intent": "llm" if not route else route.get("intent"),
1246
- "route": route,
1247
- "llm_backend": getattr(args, "llm", None),
1248
- "external_writes": False,
1249
- "providers": {"used": [], "missing": [], "skipped": []},
1250
- "commands": [],
1251
- "permissions": [],
1252
- "model_plan": model_plan,
1253
- "review_gate": review_gate,
1254
- "response": "Dry-run: nenhuma chamada LLM ou escrita externa foi executada.",
1255
- }
1256
- if "agenda" in normalized:
1257
- plan.update(
1258
- {
1259
- "intent": "calendar",
1260
- "mode": "calendar-dry-run",
1261
- "providers": {"used": ["calendar"], "missing": [], "skipped": []},
1262
- "data_reads": ["configured calendar provider, if present"],
1263
- "response": "Dry-run: o calendario seria consultado localmente se configurado.",
1264
- }
1265
- )
1266
- return plan
1267
- if has_pr_intent(normalized):
1268
- recurring = any(marker in normalized for marker in ("diariamente", "todo dia", "diaria", "diária", "recorrente"))
1269
- plan.update(
1270
- {
1271
- "intent": "github-pr-review",
1272
- "mode": "pr-dry-run",
1273
- "providers": {"used": ["github"], "missing": [], "skipped": []},
1274
- "commands": planned_pr_commands("list-review-requests"),
1275
- "external_writes": False,
1276
- "permissions": [{"agent": "github-pr-reviewer", "provider": "github", "required_level": "read-only"}],
1277
- "response": (
1278
- "Dry-run: a automacao diaria de PR seria planejada em modo report-only."
1279
- if recurring
1280
- else "Dry-run: PRs aguardando revisao seriam listadas via gh em modo report-only."
1281
- ),
1282
- }
1283
- )
1284
- return plan
1285
- if route:
1286
- plan["providers"] = {"used": [route.get("provider")], "missing": [], "skipped": []}
1287
- plan["response"] = "Dry-run: a capability roteada seria executada somente apos validar source/provider."
1288
- return plan
1289
- plan["response"] = "Dry-run: o prompt exigiria LLM configurada; nenhuma chamada foi feita."
1290
- return plan
1291
-
1292
-
1293
- def has_pr_intent(normalized_prompt: str) -> bool:
1294
- tokens = {token.strip(".,;:!?()[]{}\"'") for token in normalized_prompt.split()}
1295
- return bool({"pr", "prs"} & tokens) or "pull request" in normalized_prompt or "pull requests" in normalized_prompt
1296
-
1297
-
1298
- def summarize_pr_list(payload: dict[str, Any]) -> str:
1299
- if payload.get("status") != "ok":
1300
- return str(payload.get("message") or "Nao foi possivel listar PRs.")
1301
- items = payload.get("items") or []
1302
- if not items:
1303
- return "Nenhuma PR aguardando sua revisao foi encontrada."
1304
- lines = []
1305
- for item in items:
1306
- number = item.get("number")
1307
- title = item.get("title") or "-"
1308
- url = item.get("url") or ""
1309
- lines.append(f"- #{number} {title} {url}".strip())
1310
- return "\n".join(lines)
1311
-
1312
-
1313
- def finalize_agent_session(
1314
- result: dict[str, Any],
1315
- session: dict[str, Any],
1316
- prompt: str,
1317
- *,
1318
- backend: str | None = None,
1319
- ) -> dict[str, Any]:
1320
- try:
1321
- result["session"] = record_exchange(str(session["id"]), prompt=prompt, result=result, backend=backend)
1322
- except ValueError as exc:
1323
- raise DevKitError(str(exc)) from exc
1324
- return result
1325
-
1326
-
1327
- def invoke_deterministic_route(prompt: str, route: dict[str, Any]) -> dict[str, Any]:
1328
- try:
1329
- source = resolve_source(
1330
- provider=route.get("provider"),
1331
- intent=route.get("intent"),
1332
- agent_id=route.get("agent_id"),
1333
- )
1334
- except SourceRegistryError as exc:
1335
- raise DevKitError(str(exc)) from exc
1336
-
1337
- if not source:
1338
- wizard = missing_source_wizard(prompt, route, root=ROOT)
1339
- return {
1340
- "kind": "agent",
1341
- "status": "needs-input",
1342
- "ok": False,
1343
- "requires_source": True,
1344
- "provider": route.get("provider"),
1345
- "source_provider": route.get("provider"),
1346
- "prompt_received": True,
1347
- "prompt_length": len(prompt),
1348
- "route": route,
1349
- "napkin": napkin_context(ROOT, agent_id=route.get("agent_id")),
1350
- "setup_wizard": wizard,
1351
- "next_question": wizard.get("next_question"),
1352
- "message": wizard.get("message"),
1353
- "next_steps": [
1354
- "Responda a pergunta do wizard para autorizar ou negar a configuracao desta fonte.",
1355
- "Se preferir teste local, configure uma source com fixture sem armazenar segredos.",
1356
- "O prompt original sera retomado apos a fonte reutilizavel ser configurada.",
1357
- ],
1358
- "exit_code": 2,
1359
- }
1360
-
1361
- agent = load_agent(str(route["agent_id"]))
1362
- capability_args = [*route.get("args", []), "--source", str(source["id"])]
1363
- result = run_capability(agent, str(route["capability_id"]), capability_args, capture_output=True)
1364
- response = result.get("stdout") or result.get("error") or ""
1365
- record_usage(prompt, route=route, source_id=str(source["id"]))
1366
- model_plan = build_model_plan(prompt, route=route)
1367
- review_gate = build_review_gate(prompt, route=route, model_plan=model_plan)
1368
- if result.get("ok"):
1369
- review_gate = mark_reviewed(review_gate, reviewer="deterministic-coordinator")
1370
- return {
1371
- "kind": "agent",
1372
- "status": result.get("status"),
1373
- "ok": result.get("ok", False),
1374
- "mode": "deterministic-route",
1375
- "prompt_received": True,
1376
- "prompt_length": len(prompt),
1377
- "route": route,
1378
- "source": public_source(source),
1379
- "napkin": napkin_context(ROOT, agent_id=route.get("agent_id"), source_id=str(source["id"])),
1380
- "model_plan": model_plan,
1381
- "review_gate": review_gate,
1382
- "response": response,
1383
- "result": result,
1384
- "exit_code": result.get("exit_code", 0 if result.get("ok") else 1),
1385
- }
1386
-
1387
-
1388
- def resolve_capabilities_agent(args: argparse.Namespace) -> str | None:
1389
- if args.agent:
1390
- return args.agent
1391
-
1392
- action_or_agent = args.action_or_agent
1393
- if action_or_agent == "list":
1394
- return args.legacy_agent
1395
-
1396
- # Backward compatibility: `ai-devkit capabilities <agent>`.
1397
- if args.legacy_agent:
1398
- raise DevKitError("unexpected extra argument for capabilities")
1399
- return action_or_agent
1400
-
1401
-
1402
- def runner_timeout_seconds() -> int:
1403
- raw = os.environ.get("AI_DEVKIT_RUN_TIMEOUT", "300")
1404
- return int(raw) if raw.isdigit() and int(raw) > 0 else 300
1405
-
1406
-
1407
- def list_agents() -> list[dict[str, Any]]:
1408
- if not AGENTS_DIR.exists():
1409
- return []
1410
-
1411
- agents = []
1412
- for path in sorted(AGENTS_DIR.iterdir()):
1413
- if not path.is_dir():
1414
- continue
1415
- manifest = path / "agent.yaml"
1416
- if not manifest.exists():
1417
- continue
1418
- data = load_manifest(manifest)
1419
- capabilities = list_capabilities(path)
1420
- agents.append(
1421
- {
1422
- "id": data.get("id", path.name),
1423
- "name": data.get("name", path.name),
1424
- "status": data.get("status"),
1425
- "version": data.get("version"),
1426
- "path": str(path.relative_to(ROOT)),
1427
- "purpose": compact_text(data.get("purpose")),
1428
- "capabilities": len(capabilities),
1429
- }
1430
- )
1431
- return agents
1432
-
1433
-
1434
- def load_agent(agent_id: str) -> dict[str, Any]:
1435
- path = AGENTS_DIR / agent_id
1436
- manifest = path / "agent.yaml"
1437
- if not manifest.exists():
1438
- available = ", ".join(item["id"] for item in list_agents()) or "none"
1439
- raise DevKitError(f"agent not found: {agent_id}. available: {available}")
1440
-
1441
- data = load_manifest(manifest)
1442
- data["path"] = path
1443
- data["manifest_path"] = manifest
1444
- return data
1445
-
1446
-
1447
- def summarize_agent(agent: dict[str, Any]) -> dict[str, Any]:
1448
- return {
1449
- "id": agent.get("id"),
1450
- "name": agent.get("name"),
1451
- "status": agent.get("status"),
1452
- "version": agent.get("version"),
1453
- "path": str(agent["path"].relative_to(ROOT)),
1454
- }
1455
-
1456
-
1457
- def list_all_capabilities() -> list[dict[str, Any]]:
1458
- capabilities: list[dict[str, Any]] = []
1459
- for agent in list_agents():
1460
- agent_path = AGENTS_DIR / agent["id"]
1461
- for capability in list_capabilities(agent_path):
1462
- item = dict(capability)
1463
- item["agent"] = agent["id"]
1464
- capabilities.append(item)
1465
- return capabilities
1466
-
1467
-
1468
- def list_capabilities(agent_path: Path) -> list[dict[str, Any]]:
1469
- capabilities_dir = agent_path / "capabilities"
1470
- if not capabilities_dir.exists():
1471
- return []
1472
-
1473
- capabilities = []
1474
- for path in sorted(capabilities_dir.iterdir()):
1475
- if not path.is_dir():
1476
- continue
1477
- manifest = path / "capability.yaml"
1478
- if not manifest.exists():
1479
- continue
1480
- data = load_manifest(manifest)
1481
- runner = ((data.get("entrypoint", {}) or {}).get("runner"))
1482
- capabilities.append(
1483
- {
1484
- "id": data.get("id", path.name),
1485
- "name": data.get("name", path.name),
1486
- "status": data.get("status"),
1487
- "version": data.get("version"),
1488
- "path": str(path.relative_to(ROOT)),
1489
- "purpose": compact_text(data.get("purpose")),
1490
- "write_policy": data.get("write_policy"),
1491
- "runner": runner,
1492
- "has_runner": bool(runner),
1493
- "has_workflow": (path / "workflow.md").exists(),
1494
- "has_decision_rules": (path / "decision-rules.md").exists(),
1495
- }
1496
- )
1497
- return capabilities
1498
-
1499
-
1500
- def load_capability(agent_path: Path, capability_id: str) -> dict[str, Any]:
1501
- path = agent_path / "capabilities" / capability_id
1502
- manifest = path / "capability.yaml"
1503
- if not manifest.exists():
1504
- available = ", ".join(item["id"].split(".")[-1] for item in list_capabilities(agent_path))
1505
- raise DevKitError(
1506
- f"capability not found: {capability_id}. available: {available or 'none'}"
1507
- )
1508
-
1509
- data = load_manifest(manifest)
1510
- return {
1511
- "id": data.get("id", capability_id),
1512
- "name": data.get("name", capability_id),
1513
- "status": data.get("status"),
1514
- "version": data.get("version"),
1515
- "path": str(path.relative_to(ROOT)),
1516
- "purpose": compact_text(data.get("purpose")),
1517
- "inputs": data.get("inputs", {}),
1518
- "outputs": data.get("outputs", {}),
1519
- "entrypoint": resolve_refs(path, data.get("entrypoint", {})),
1520
- "integration": resolve_integration_refs(path, data.get("integration", {})),
1521
- "write_policy": data.get("write_policy"),
1522
- }
1523
-
1524
-
1525
- def run_capability(
1526
- agent: dict[str, Any],
1527
- capability_id: str,
1528
- capability_args: list[str],
1529
- capture_output: bool = True,
1530
- ) -> dict[str, Any]:
1531
- agent_path = agent["path"]
1532
- capability_path = agent_path / "capabilities" / capability_id
1533
- manifest = capability_path / "capability.yaml"
1534
- if not manifest.exists():
1535
- available = ", ".join(item["id"].split(".")[-1] for item in list_capabilities(agent_path))
1536
- raise DevKitError(
1537
- f"capability not found: {capability_id}. available: {available or 'none'}"
1538
- )
1539
-
1540
- data = load_manifest(manifest)
1541
- try:
1542
- source = None
1543
- if supports_runtime_source(str(agent.get("id")), capability_id):
1544
- source_id, capability_args = extract_source_arg(capability_args)
1545
- source = resolve_source(source_id=source_id) if source_id else None
1546
- capability_args = apply_source_to_args(source, str(agent.get("id")), capability_id, capability_args)
1547
- runtime_env = os.environ | source_env(source)
1548
- except SourceRegistryError as exc:
1549
- return run_payload(
1550
- status="blocked",
1551
- agent=summarize_agent(agent),
1552
- capability=data.get("id", capability_id),
1553
- runner=None,
1554
- returncode=2,
1555
- error=str(exc),
1556
- risks=["Source configuration could not be resolved."],
1557
- next_steps=["Inspect available sources with `agent source list` or configure one with `agent source add`."],
1558
- exit_code=2,
1559
- )
1560
- guardrail = evaluate_execution_guardrails(data, capability_args)
1561
- capability_args = guardrail["args"]
1562
- if not guardrail["ready"]:
1563
- return run_payload(
1564
- status="blocked",
1565
- agent=summarize_agent(agent),
1566
- capability=data.get("id", capability_id),
1567
- runner=None,
1568
- returncode=2,
1569
- guardrail={
1570
- "reason": guardrail["reason"],
1571
- "write_policy": guardrail["write_policy"],
1572
- "execute_requested": True,
1573
- },
1574
- risks=guardrail["risks"],
1575
- next_steps=guardrail["next_steps"],
1576
- exit_code=2,
1577
- )
1578
- readiness = evaluate_provider_requirements(ROOT, data, capability_args)
1579
- if not readiness["ready"]:
1580
- payload = run_payload(
1581
- status=readiness["status"],
1582
- agent=summarize_agent(agent),
1583
- capability=data.get("id", capability_id),
1584
- runner=None,
1585
- returncode=readiness.get("exit_code") or 0,
1586
- providers=readiness["providers"],
1587
- fallback_applied=readiness["fallback_applied"],
1588
- evidence=readiness["evidence"],
1589
- risks=readiness["risks"],
1590
- next_steps=readiness["next_steps"],
1591
- artifacts=readiness["artifacts"],
1592
- exit_code=readiness.get("exit_code"),
1593
- )
1594
- wizard = setup_wizard_from_readiness(readiness, agent=summarize_agent(agent), capability_id=str(data.get("id", capability_id)))
1595
- if wizard:
1596
- payload["setup_wizard"] = wizard
1597
- payload["next_question"] = wizard.get("next_question")
1598
- payload["configuration_agent"] = wizard.get("owner_agent")
1599
- payload["next_steps"] = [
1600
- "Responda a pergunta do wizard para autorizar ou negar a configuracao deste provider.",
1601
- "Informe uma referencia segura de credencial por variavel de ambiente, arquivo ou cadeia nativa quando solicitado.",
1602
- "Reexecute ou retome a mesma capability depois que a configuracao estiver salva.",
1603
- ]
1604
- return payload
1605
-
1606
- runner_ref = (data.get("entrypoint", {}) or {}).get("runner")
1607
- if not runner_ref:
1608
- if capture_output:
1609
- return run_payload(
1610
- status="failed",
1611
- agent=summarize_agent(agent),
1612
- capability=data.get("id", capability_id),
1613
- runner=None,
1614
- returncode=2,
1615
- providers=readiness["providers"],
1616
- error=f"capability has no runner: {capability_id}",
1617
- risks=["Capability cannot be executed by the runtime because no runner is declared."],
1618
- next_steps=["Add `entrypoint.runner` to the capability manifest or use a capability with an executable runner."],
1619
- exit_code=2,
1620
- )
1621
- raise DevKitError(f"capability has no runner: {capability_id}")
1622
-
1623
- runner_path = (capability_path / runner_ref).resolve()
1624
- if not runner_path.exists():
1625
- if capture_output:
1626
- relative_runner = str(runner_path.relative_to(ROOT))
1627
- return run_payload(
1628
- status="failed",
1629
- agent=summarize_agent(agent),
1630
- capability=data.get("id", capability_id),
1631
- runner=relative_runner,
1632
- returncode=2,
1633
- providers=readiness["providers"],
1634
- error=f"runner not found: {relative_runner}",
1635
- risks=["Capability runner declared in the manifest does not exist on disk."],
1636
- next_steps=["Fix `entrypoint.runner` in the capability manifest or restore the missing runner file."],
1637
- exit_code=2,
1638
- )
1639
- raise DevKitError(f"runner not found: {runner_path.relative_to(ROOT)}")
1640
-
1641
- timeout_seconds = runner_timeout_seconds()
1642
- try:
1643
- if capture_output:
1644
- process = subprocess.run(
1645
- [sys.executable, str(runner_path), *capability_args],
1646
- cwd=ROOT,
1647
- check=False,
1648
- text=True,
1649
- stdout=subprocess.PIPE,
1650
- stderr=subprocess.PIPE,
1651
- env=runtime_env,
1652
- timeout=timeout_seconds,
1653
- )
1654
- else:
1655
- process = subprocess.run(
1656
- [sys.executable, str(runner_path), *capability_args],
1657
- cwd=ROOT,
1658
- check=False,
1659
- text=True,
1660
- env=runtime_env,
1661
- timeout=timeout_seconds,
1662
- )
1663
- except subprocess.TimeoutExpired as exc:
1664
- if capture_output:
1665
- stdout = exc.stdout or ""
1666
- stderr = exc.stderr or ""
1667
- if isinstance(stdout, bytes):
1668
- stdout = stdout.decode(errors="replace")
1669
- if isinstance(stderr, bytes):
1670
- stderr = stderr.decode(errors="replace")
1671
- return run_payload(
1672
- status="failed",
1673
- agent=summarize_agent(agent),
1674
- capability=data.get("id", capability_id),
1675
- runner=str(runner_path.relative_to(ROOT)),
1676
- stdout=stdout,
1677
- stderr=stderr,
1678
- returncode=124,
1679
- providers=readiness["providers"],
1680
- error=f"runner timed out after {timeout_seconds}s: {agent.get('id')}/{capability_id}",
1681
- risks=["Capability runner exceeded the configured timeout."],
1682
- next_steps=["Review runner performance, inputs, provider latency, or increase `AI_DEVKIT_RUN_TIMEOUT` for this execution."],
1683
- exit_code=124,
1684
- )
1685
- raise DevKitError(f"runner timed out after {timeout_seconds}s: {agent.get('id')}/{capability_id}") from exc
1686
- if process.returncode != 0:
1687
- stderr = process.stderr if capture_output else ""
1688
- if capture_output:
1689
- stdout = process.stdout or ""
1690
- message = (stderr or stdout or f"runner failed: {process.returncode}").strip()
1691
- return run_payload(
1692
- status="failed",
1693
- agent=summarize_agent(agent),
1694
- capability=data.get("id", capability_id),
1695
- runner=str(runner_path.relative_to(ROOT)),
1696
- stdout=stdout,
1697
- stderr=stderr,
1698
- returncode=process.returncode,
1699
- providers=readiness["providers"],
1700
- error=message,
1701
- risks=["Capability runner returned a non-zero exit code."],
1702
- next_steps=["Review stdout/stderr and rerun after correcting the capability inputs or environment."],
1703
- exit_code=process.returncode,
1704
- )
1705
- raise DevKitError((stderr or "").strip() or f"runner failed: {process.returncode}")
1706
-
1707
- return run_payload(
1708
- status="ok",
1709
- agent=summarize_agent(agent),
1710
- capability=data.get("id", capability_id),
1711
- runner=str(runner_path.relative_to(ROOT)),
1712
- stdout=process.stdout if capture_output else "",
1713
- stderr=process.stderr if capture_output else "",
1714
- returncode=process.returncode,
1715
- providers=readiness["providers"],
1716
- )
1717
-
1718
-
1719
- def supports_runtime_source(agent_id: str, capability_id: str) -> bool:
1720
- return agent_id == "azure-devops-orchestrator" and capability_id == "read-card"
1721
-
1722
-
1723
- def setup_wizard_from_readiness(readiness: dict[str, Any], *, agent: dict[str, Any], capability_id: str) -> dict[str, Any] | None:
1724
- providers = readiness.get("providers") if isinstance(readiness.get("providers"), dict) else {}
1725
- missing = providers.get("missing") or []
1726
- if not missing:
1727
- return None
1728
- provider_id = str(missing[0])
1729
- details = providers.get("details") or []
1730
- detail = next((item for item in details if isinstance(item, dict) and item.get("id") == provider_id), {})
1731
- try:
1732
- return provider_wizard_from_requirement(
1733
- ROOT,
1734
- provider_id,
1735
- agent_id=str(agent.get("id") or ""),
1736
- capability_id=capability_id,
1737
- reason=str(detail.get("purpose") or "Provider is required but not configured."),
1738
- )
1739
- except Exception:
1740
- return None
1741
-
1742
-
1743
- def doctor(project: str | None = None, home: str | None = None, scope: str = "auto") -> dict[str, Any]:
1744
- agents = list_agents()
1745
- capabilities = list_all_capabilities()
1746
- declared_runners = sum(1 for item in capabilities if item.get("has_runner"))
1747
- workflows = sum(1 for item in capabilities if item.get("has_workflow"))
1748
- decision_rules = sum(1 for item in capabilities if item.get("has_decision_rules"))
1749
- validator = ROOT / "scripts" / "validate-repo.py"
1750
- errors: list[str] = []
1751
- warnings: list[str] = []
1752
-
1753
- if not ROOT.exists():
1754
- errors.append(f"root not found: {ROOT}")
1755
- if not AGENTS_DIR.is_dir():
1756
- errors.append(f"agents directory not found: {AGENTS_DIR}")
1757
- if not validator.exists():
1758
- warnings.append("scripts/validate-repo.py not found")
1759
- project_path = doctor_project_path(project, scope)
1760
- home_path = Path(home) if home else None
1761
- locks = lock_status(project_path, home_path)
1762
- if project and locks["status"] == "diverged":
1763
- warnings.append("lock divergence between global runtime.lock and project ai-devkit.lock")
1764
- checks = {
1765
- "root_exists": ROOT.exists(),
1766
- "agents_dir_exists": AGENTS_DIR.is_dir(),
1767
- "validator_exists": validator.exists(),
1768
- "agent_command_exists": (ROOT / "agent").exists(),
1769
- "aikit_command_exists": (ROOT / "aikit").exists(),
1770
- "ai_devkit_command_exists": (ROOT / "ai-devkit").exists(),
1771
- "agent_on_path": shutil.which("agent") is not None,
1772
- }
1773
- diagnostics = build_diagnostics(
1774
- ROOT,
1775
- project=project_path,
1776
- home=home_path,
1777
- runtime_checks=checks,
1778
- runtime_status="ok" if not errors else "error",
1779
- locks=locks,
1780
- )
1781
-
1782
- return {
1783
- "kind": "doctor",
1784
- "status": "ok" if not errors else "error",
1785
- "scope": scope,
1786
- "root": str(ROOT),
1787
- "summary": {
1788
- "agents": len(agents),
1789
- "capabilities": len(capabilities),
1790
- "declared_runners": declared_runners,
1791
- "workflows": workflows,
1792
- "decision_rules": decision_rules,
1793
- },
1794
- "checks": checks,
1795
- "errors": errors,
1796
- "warnings": warnings,
1797
- "locks": locks,
1798
- "diagnostics": diagnostics,
1799
- }
1800
-
1801
-
1802
- def doctor_project_path(project: str | None, scope: str) -> Path | None:
1803
- if project:
1804
- return Path(project)
1805
- if scope == "project":
1806
- return Path.cwd()
1807
- return None
1808
-
1809
-
1810
- def resolve_refs(base: Path, refs: dict[str, Any]) -> dict[str, Any]:
1811
- resolved = {}
1812
- for key, value in refs.items():
1813
- if isinstance(value, str):
1814
- resolved[key] = {
1815
- "ref": value,
1816
- "path": str((base / value).resolve().relative_to(ROOT)),
1817
- "exists": (base / value).resolve().exists(),
1818
- }
1819
- else:
1820
- resolved[key] = value
1821
- return resolved
1822
-
1823
-
1824
- def resolve_integration_refs(base: Path, integration: dict[str, Any]) -> dict[str, Any]:
1825
- if not integration:
1826
- return {}
1827
-
1828
- resolved: dict[str, Any] = {}
1829
- repository = integration.get("repository")
1830
- if repository:
1831
- repository_path = (base / repository).resolve()
1832
- resolved["repository"] = {
1833
- "ref": repository,
1834
- "path": str(repository_path.relative_to(ROOT)),
1835
- "exists": repository_path.exists(),
1836
- }
1837
-
1838
- methods = []
1839
- for method in integration.get("methods", []) or []:
1840
- method_path = (base / method).resolve()
1841
- methods.append(
1842
- {
1843
- "ref": method,
1844
- "path": str(method_path.relative_to(ROOT)),
1845
- "exists": method_path.exists(),
1846
- }
1847
- )
1848
- resolved["methods"] = methods
1849
- return resolved
1850
-
1851
-
1852
- def load_manifest(path: Path) -> dict[str, Any]:
1853
- try:
1854
- import yaml # type: ignore
1855
- except ImportError:
1856
- return load_simple_yaml(path)
1857
-
1858
- with path.open(encoding="utf-8") as file:
1859
- data = yaml.safe_load(file) or {}
1860
- if not isinstance(data, dict):
1861
- raise DevKitError(f"manifest must be a mapping: {path}")
1862
- return data
1863
-
1864
-
1865
- def load_simple_yaml(path: Path) -> dict[str, Any]:
1866
- # Fallback parser for simple top-level YAML used by the CLI when PyYAML is
1867
- # unavailable. It is intentionally narrow; install PyYAML for full support.
1868
- data: dict[str, Any] = {}
1869
- current_key: str | None = None
1870
- current_list: list[str] | None = None
1871
- for raw_line in path.read_text(encoding="utf-8").splitlines():
1872
- line = raw_line.rstrip()
1873
- stripped = line.strip()
1874
- if not stripped or stripped.startswith("#"):
1875
- continue
1876
- if not line.startswith(" ") and ":" in line:
1877
- key, value = line.split(":", 1)
1878
- current_key = key.strip()
1879
- value = value.strip()
1880
- if value:
1881
- data[current_key] = parse_scalar(value)
1882
- current_list = None
1883
- else:
1884
- current_list = []
1885
- data[current_key] = current_list
1886
- continue
1887
- if current_key and current_list is not None and stripped.startswith("- "):
1888
- current_list.append(stripped[2:].strip())
1889
- return data
1890
-
1891
-
1892
- def parse_scalar(value: str) -> Any:
1893
- if value in {"true", "false"}:
1894
- return value == "true"
1895
- return value.strip('"').strip("'")
1896
-
1897
-
1898
- def compact_text(value: Any) -> str | None:
1899
- if value is None:
1900
- return None
1901
- return " ".join(str(value).split())
1902
-
1903
-
1904
- def print_human(result: dict[str, Any]) -> None:
1905
- kind = result["kind"]
1906
- if kind == "version":
1907
- print(f"{result.get('program', 'aikit')} {result['version']}")
1908
- elif kind == "agents":
1909
- print_agents(result["items"])
1910
- elif kind == "capabilities":
1911
- print_capabilities(result["agent"], result["items"])
1912
- elif kind == "capability":
1913
- print_capability(result)
1914
- elif kind == "run":
1915
- print_run(result)
1916
- elif kind == "doctor":
1917
- print_doctor(result)
1918
- elif kind == "commands":
1919
- print_command_modes(result)
1920
- elif kind == "agent":
1921
- print_agent_response(result)
1922
- elif kind == "llm-backends":
1923
- print_llm_backends(result)
1924
- elif kind == "llm-doctor":
1925
- print_llm_doctor(result)
1926
- elif kind == "llm-configure":
1927
- print_llm_configure(result)
1928
- elif kind == "llm-default":
1929
- print_llm_default(result)
1930
- elif kind == "llm-preference":
1931
- print_llm_preference(result)
1932
- elif kind == "providers":
1933
- print_providers(result)
1934
- elif kind == "provider-status":
1935
- print_provider_status(result)
1936
- elif kind == "provider-configure":
1937
- print_provider_configure(result)
1938
- elif kind == "provider-unset":
1939
- print_provider_unset(result)
1940
- elif kind == "credential-resolution":
1941
- print_credential_resolution(result)
1942
- elif kind == "credential-backends":
1943
- print_credential_backends(result)
1944
- elif kind == "sources":
1945
- print_sources(result)
1946
- elif kind == "source-status":
1947
- print_source_status(result)
1948
- elif kind == "source-configure":
1949
- print_source_configure(result)
1950
- elif kind == "source-remove":
1951
- print_source_remove(result)
1952
- elif kind == "memory":
1953
- print_memory(result)
1954
- elif kind == "memory-path":
1955
- print_memory_path(result)
1956
- elif kind == "memory-reset":
1957
- print_memory_reset(result)
1958
- elif kind == "personality":
1959
- print_personality(result)
1960
- elif kind == "aliases":
1961
- print_aliases(result)
1962
- elif kind == "alias":
1963
- print_alias(result)
1964
- elif kind == "sessions":
1965
- print_sessions(result)
1966
- elif kind == "session":
1967
- print_session(result)
1968
- elif kind == "setup":
1969
- print_setup(result)
1970
- elif kind == "toolchain":
1971
- print_toolchain(result)
1972
- elif kind == "toolchain-doctor":
1973
- print_toolchain_doctor(result)
1974
- elif kind == "toolchain-install":
1975
- print_toolchain_install(result)
1976
- elif kind == "tasks":
1977
- print_tasks(result)
1978
- elif kind == "task":
1979
- print_task(result)
1980
- elif kind == "task-history":
1981
- print_task_history(result)
1982
- elif kind == "task-run":
1983
- print_task_run(result)
1984
- elif kind == "scheduler":
1985
- print_scheduler(result)
1986
- elif kind == "calendar":
1987
- print_calendar(result)
1988
- elif kind == "calendar-configure":
1989
- print_calendar_configure(result)
1990
- elif kind in {"pr", "pr-review", "pr-automation"}:
1991
- print_pr(result)
1992
- elif kind == "permissions":
1993
- print_permissions(result)
1994
- elif kind in {"audit", "audit-entry", "audit-export"}:
1995
- print_audit(result)
1996
- elif kind == "config":
1997
- print_config(result)
1998
- elif kind in {"tools", "tool", "integrations", "integration", "skills", "skill", "decisions", "decision", "decisions-reset"}:
1999
- print_control(result)
2000
- elif kind in {"ollama-status", "ollama-models", "ollama-pull", "ollama-update"}:
2001
- print_ollama(result)
2002
- elif kind == "install":
2003
- print_install(result)
2004
- else:
2005
- print(json.dumps(result, ensure_ascii=False, indent=2))
2006
-
2007
-
2008
- def print_agents(items: list[dict[str, Any]]) -> None:
2009
- if not items:
2010
- print("No agents found.")
2011
- return
2012
- for item in items:
2013
- count = item.get("capabilities", 0)
2014
- print(f"{item['id']} {item.get('status') or '-'} {count} capabilities")
2015
- if item.get("purpose"):
2016
- print(f" {item['purpose']}")
2017
-
2018
-
2019
- def print_capabilities(agent: str | None, items: list[dict[str, Any]]) -> None:
2020
- if not items:
2021
- suffix = f" for {agent}" if agent else ""
2022
- print(f"No capabilities found{suffix}.")
2023
- return
2024
- if agent:
2025
- print(f"{agent}:")
2026
- for item in items:
2027
- short_id = item["id"].split(".")[-1]
2028
- prefix = "" if agent else f"{item.get('agent', '-')}/"
2029
- runner = "runner" if item.get("has_runner") else "no-runner"
2030
- workflow = "workflow" if item.get("has_workflow") else "no-workflow"
2031
- rules = "rules" if item.get("has_decision_rules") else "no-rules"
2032
- print(f"- {prefix}{short_id} {item.get('write_policy') or '-'} {item.get('status') or '-'} {runner} {workflow} {rules}")
2033
- if item.get("purpose"):
2034
- print(f" {item['purpose']}")
2035
-
2036
-
2037
- def print_capability(result: dict[str, Any]) -> None:
2038
- agent = result["agent"]
2039
- capability = result["capability"]
2040
- print(f"{agent['id']} / {capability['id'].split('.')[-1]}")
2041
- print(f"Status: {capability.get('status') or '-'}")
2042
- print(f"Version: {capability.get('version') or '-'}")
2043
- print(f"Write policy: {capability.get('write_policy') or '-'}")
2044
- if capability.get("purpose"):
2045
- print(f"\n{capability['purpose']}")
2046
- print("\nEntrypoints:")
2047
- for key, value in capability.get("entrypoint", {}).items():
2048
- if isinstance(value, dict):
2049
- marker = "ok" if value["exists"] else "missing"
2050
- print(f"- {key}: {value['path']} [{marker}]")
2051
- integration = capability.get("integration", {})
2052
- if integration:
2053
- print("\nIntegration:")
2054
- repo = integration.get("repository")
2055
- if repo:
2056
- marker = "ok" if repo["exists"] else "missing"
2057
- print(f"- repository: {repo['path']} [{marker}]")
2058
- for method in integration.get("methods", []):
2059
- marker = "ok" if method["exists"] else "missing"
2060
- print(f"- method: {method['path']} [{marker}]")
2061
-
2062
-
2063
- def print_run(result: dict[str, Any]) -> None:
2064
- if result.get("status") in {None, "ok"}:
2065
- print(result.get("stdout", ""), end="")
2066
- return
2067
-
2068
- print(f"Run {result['status']}: {result['agent']['id']} / {result['capability'].split('.')[-1]}")
2069
- if result.get("fallback_applied"):
2070
- print(f"Fallback: {result['fallback_applied']}")
2071
- providers = result.get("providers") or {}
2072
- missing = providers.get("missing") or []
2073
- if missing:
2074
- print(f"Missing providers: {', '.join(missing)}")
2075
- if result.get("risks"):
2076
- print("\nRisks:")
2077
- for risk in result["risks"]:
2078
- print(f"- {risk}")
2079
- if result.get("next_steps"):
2080
- print("\nNext steps:")
2081
- for step in result["next_steps"]:
2082
- print(f"- {step}")
2083
-
2084
-
2085
- def print_doctor(result: dict[str, Any]) -> None:
2086
- print(f"AI DevKit doctor: {result['status']}")
2087
- print(f"Root: {result['root']}")
2088
- summary = result["summary"]
2089
- print(f"Agents: {summary['agents']}")
2090
- print(f"Capabilities: {summary['capabilities']}")
2091
- print(f"Declared runners: {summary['declared_runners']}")
2092
- print(f"Workflows: {summary['workflows']}")
2093
- print(f"Decision rules: {summary['decision_rules']}")
2094
- diagnostics = result.get("diagnostics") or {}
2095
- if diagnostics:
2096
- providers = diagnostics.get("providers") or {}
2097
- llm = diagnostics.get("llm") or {}
2098
- plugins = diagnostics.get("plugins") or {}
2099
- locks = diagnostics.get("locks") or {}
2100
- print("\nDiagnostics:")
2101
- print(f"- Locks: {locks.get('status', '-')}")
2102
- print(f"- Plugins: {plugins.get('status', '-')}")
2103
- print(f"- Providers: {providers.get('status', '-')} ({providers.get('ok', 0)} ok, {providers.get('missing', 0)} missing)")
2104
- print(f"- LLM: {llm.get('status', '-')} ({llm.get('ok', 0)} ok, {llm.get('missing', 0)} missing)")
2105
- if result["warnings"]:
2106
- print("\nWarnings:")
2107
- for warning in result["warnings"]:
2108
- print(f"- {warning}")
2109
- if result["errors"]:
2110
- print("\nErrors:")
2111
- for error in result["errors"]:
2112
- print(f"- {error}")
2113
-
2114
-
2115
- def print_command_modes(result: dict[str, Any]) -> None:
2116
- print("Deterministic commands (no LLM required):")
2117
- for item in result["deterministic"]:
2118
- print(f"- {item['command']}")
2119
- print("\nLLM commands:")
2120
- for item in result["llm"]:
2121
- print(f"- {item['command']}")
2122
-
2123
-
2124
- def print_agent_response(result: dict[str, Any]) -> None:
2125
- if result.get("status") == "ok":
2126
- print(result.get("response", ""))
2127
- return
2128
- print(result.get("message") or result.get("response") or "Agent execution did not complete.")
2129
- question = result.get("next_question") or ((result.get("setup_wizard") or {}).get("next_question") if isinstance(result.get("setup_wizard"), dict) else None)
2130
- if isinstance(question, dict) and question.get("text"):
2131
- print(f"\nPergunta: {question['text']}")
2132
- if question.get("type") == "confirm":
2133
- print("[s/N]")
2134
- if result.get("llm_backend"):
2135
- print(f"Requested backend: {result['llm_backend']}")
2136
- if result.get("next_steps"):
2137
- print("\nNext steps:")
2138
- for step in result["next_steps"]:
2139
- print(f"- {step}")
2140
-
2141
-
2142
- def print_sources(result: dict[str, Any]) -> None:
2143
- print(f"Sources config: {result['config_path']}")
2144
- if not result["items"]:
2145
- print("No sources configured.")
2146
- return
2147
- for item in result["items"]:
2148
- print(f"- {item['id']} {item['provider']} {item.get('label') or '-'}")
2149
-
2150
-
2151
- def print_source_status(result: dict[str, Any]) -> None:
2152
- print(f"Source status: {result['status']}")
2153
- for item in result["items"]:
2154
- print(f"- {item['id']}: {item['status']}")
2155
- missing = item.get("missing_env_refs") or []
2156
- if missing:
2157
- print(f" Missing env refs: {', '.join(missing)}")
2158
-
2159
-
2160
- def print_source_configure(result: dict[str, Any]) -> None:
2161
- source = result["source"]
2162
- print(f"Source configured: {source['id']}")
2163
- print(f"Provider: {source['provider']}")
2164
- print(f"Config: {result['config_path']}")
2165
- print("Stored secret: no")
2166
-
2167
-
2168
- def print_source_remove(result: dict[str, Any]) -> None:
2169
- print(f"Source removed: {result['source']['id']}")
2170
- print(f"Config: {result['config_path']}")
2171
-
2172
-
2173
- def print_memory(result: dict[str, Any]) -> None:
2174
- print(f"Memory home: {result['memory_home']}")
2175
- if result.get("files"):
2176
- print("\nFiles:")
2177
- for item in result["files"]:
2178
- print(f"- {item['name']}: {item['path']}")
2179
- for bucket in ("prompts", "routes", "sources"):
2180
- print(f"\n{bucket.title()}:")
2181
- items = result["usage"].get(bucket) or []
2182
- if not items:
2183
- print("- none")
2184
- continue
2185
- for item in items:
2186
- print(f"- {item['key']} ({item.get('count', 0)})")
2187
-
2188
-
2189
- def print_memory_reset(result: dict[str, Any]) -> None:
2190
- print("Memory reset.")
2191
- print(f"Config: {result['config_path']}")
2192
-
2193
-
2194
- def print_memory_path(result: dict[str, Any]) -> None:
2195
- print(f"Memory home: {result['home']}")
2196
- if result.get("created"):
2197
- print("Created:")
2198
- for path in result["created"]:
2199
- print(f"- {path}")
2200
- print("Files:")
2201
- for item in result["files"]:
2202
- print(f"- {item['name']}: {item['path']}")
2203
-
2204
-
2205
- def print_personality(result: dict[str, Any]) -> None:
2206
- print(f"Personality: {result.get('status', 'ok')}")
2207
- print(f"Path: {result['path']}")
2208
- print(f"Agent name: {result.get('agent_name') or '-'}")
2209
- print(f"User name: {result.get('user_name') or '-'}")
2210
- print(f"Language: {result.get('language') or '-'}")
2211
- print(f"Tone: {result.get('tone') or '-'}")
2212
- print(f"Detail level: {result.get('detail_level') or '-'}")
2213
- if result.get("message"):
2214
- print(result["message"])
2215
- if result.get("questions"):
2216
- print("Setup questions:")
2217
- for question in result["questions"]:
2218
- print(f"- {question}")
2219
-
2220
-
2221
- def print_aliases(result: dict[str, Any]) -> None:
2222
- print(f"Aliases config: {result['config_path']}")
2223
- if not result["items"]:
2224
- print("No aliases configured.")
2225
- return
2226
- for item in result["items"]:
2227
- print(f"- {item['name']}: {item['path']}")
2228
-
2229
-
2230
- def print_alias(result: dict[str, Any]) -> None:
2231
- print(f"Alias {result['status']}: {result['name']}")
2232
- if result.get("path"):
2233
- print(f"Path: {result['path']}")
2234
- if result.get("removed_paths"):
2235
- print("Removed:")
2236
- for path in result["removed_paths"]:
2237
- print(f"- {path}")
2238
- print(f"Config: {result['config_path']}")
2239
-
2240
-
2241
- def print_sessions(result: dict[str, Any]) -> None:
2242
- print(f"Sessions home: {result['home']}")
2243
- if result.get("active_session_id"):
2244
- print(f"Active: {result['active_session_id']}")
2245
- if not result["items"]:
2246
- print("No sessions found.")
2247
- return
2248
- for item in result["items"]:
2249
- marker = " active" if item.get("active") else ""
2250
- print(
2251
- f"- {item['id']}{marker} {item.get('title') or '-'} "
2252
- f"{item.get('exchange_count', 0)} exchanges ~{item.get('token_estimate', 0)} tokens"
2253
- )
2254
- if item.get("project"):
2255
- print(f" Project: {item['project']}")
2256
-
2257
-
2258
- def print_session(result: dict[str, Any]) -> None:
2259
- session = result["session"]
2260
- print(f"Session {result['status']}: {session['id']}")
2261
- print(f"Title: {session.get('title') or '-'}")
2262
- print(f"Path: {session.get('path') or '-'}")
2263
- print(f"Project: {session.get('project') or '-'}")
2264
- print(f"Exchanges: {session.get('exchange_count', 0)}")
2265
- print(f"Token estimate: {session.get('token_estimate', 0)}")
2266
-
2267
-
2268
- def print_setup(result: dict[str, Any]) -> None:
2269
- print(f"Setup: {result['status']}")
2270
- print(f"Dry-run: {result.get('dry_run', False)}")
2271
- toolchain = result.get("toolchain") or {}
2272
- print(f"Toolchain: {toolchain.get('status', '-')}")
2273
- missing = (toolchain.get("required_missing") or []) + (toolchain.get("optional_missing") or [])
2274
- if missing:
2275
- print(f"Missing: {', '.join(missing)}")
2276
- if result.get("next_steps"):
2277
- print("Next steps:")
2278
- for step in result["next_steps"]:
2279
- print(f"- {step}")
2280
-
2281
-
2282
- def print_toolchain(result: dict[str, Any]) -> None:
2283
- print(f"Toolchain: {result['status']}")
2284
- print(f"Platform: {result['platform']}")
2285
- for item in result["items"]:
2286
- print(f"- {item['id']} {item['command']} required={item['required']}")
2287
-
2288
-
2289
- def print_toolchain_doctor(result: dict[str, Any]) -> None:
2290
- print(f"Toolchain doctor: {result['status']}")
2291
- print(f"Platform: {result['platform']}")
2292
- for item in result["items"]:
2293
- print(f"- {item['id']}: {item['status']}")
2294
- if item.get("binary"):
2295
- print(f" {item['binary']}")
2296
- if item.get("install"):
2297
- print(f" Install: {item['install']}")
2298
-
2299
-
2300
- def print_toolchain_install(result: dict[str, Any]) -> None:
2301
- print(f"Toolchain install: {result['status']}")
2302
- if result.get("message"):
2303
- print(result["message"])
2304
- for plan in result["plans"]:
2305
- print(f"- {plan['id']}: {plan.get('command') or '-'}")
2306
-
2307
-
2308
- def print_tasks(result: dict[str, Any]) -> None:
2309
- print(f"Tasks: {len(result['items'])}")
2310
- for item in result["items"]:
2311
- print(f"- {item['id']} {item['status']} {item.get('title') or '-'}")
2312
-
2313
-
2314
- def print_task(result: dict[str, Any]) -> None:
2315
- if result.get("message"):
2316
- print(result["message"])
2317
- task = result.get("task") or {}
2318
- if task:
2319
- print(f"Task {result['status']}: {task.get('id')}")
2320
- print(f"Title: {task.get('title') or '-'}")
2321
- print(f"Status: {task.get('status') or '-'}")
2322
-
2323
-
2324
- def print_task_history(result: dict[str, Any]) -> None:
2325
- print(result.get("history") or "No history.")
2326
-
2327
-
2328
- def print_task_run(result: dict[str, Any]) -> None:
2329
- print(f"Task run: {result['status']}")
2330
- if result.get("message"):
2331
- print(result["message"])
2332
-
2333
-
2334
- def print_scheduler(result: dict[str, Any]) -> None:
2335
- print(f"Scheduler: {result['status']}")
2336
- if result.get("message"):
2337
- print(result["message"])
2338
- if "due_count" in result:
2339
- print(f"Due tasks: {result['due_count']}")
2340
-
2341
-
2342
- def print_calendar(result: dict[str, Any]) -> None:
2343
- if result.get("status") != "ok":
2344
- print(result.get("message") or "Calendar is not available.")
2345
- for step in result.get("next_steps") or []:
2346
- print(f"- {step}")
2347
- return
2348
- print(calendar_summary(result))
2349
-
2350
-
2351
- def print_calendar_configure(result: dict[str, Any]) -> None:
2352
- print(f"Calendar configured: {result['provider']}")
2353
- print(f"Source: {result['source_ref']}")
2354
- print("Stored secret: no")
2355
-
2356
-
2357
- def print_pr(result: dict[str, Any]) -> None:
2358
- if result.get("message"):
2359
- print(result["message"])
2360
- if result.get("items") is not None:
2361
- print(summarize_pr_list(result))
2362
- elif result.get("summary"):
2363
- print(result["summary"])
2364
- elif result.get("task"):
2365
- task = result["task"]
2366
- print(f"PR automation {result['status']}: {task.get('id')}")
2367
-
2368
-
2369
- def print_permissions(result: dict[str, Any]) -> None:
2370
- print(f"Permissions: {result['status']}")
2371
- if result.get("default_level"):
2372
- print(f"Default: {result['default_level']}")
2373
- if result.get("grant"):
2374
- grant = result["grant"]
2375
- print(f"Grant: {grant.get('agent')} / {grant.get('provider')} -> {grant.get('level')}")
2376
- if result.get("removed") is not None:
2377
- print(f"Removed: {len(result.get('removed') or [])}")
2378
- grants = result.get("grants")
2379
- if grants is not None:
2380
- if not grants:
2381
- print("No explicit grants.")
2382
- for grant in grants:
2383
- print(f"- {grant.get('agent')} / {grant.get('provider')} -> {grant.get('level')}")
2384
- if result.get("json_path"):
2385
- print(f"Policy: {result['json_path']}")
2386
-
2387
-
2388
- def print_audit(result: dict[str, Any]) -> None:
2389
- if result["kind"] == "audit":
2390
- print(f"Audit home: {result['home']}")
2391
- for item in result.get("items") or []:
2392
- print(f"- {item.get('id')} {item.get('created_at')} {item.get('command')} {item.get('status')}")
2393
- return
2394
- if result["kind"] == "audit-entry":
2395
- entry = result.get("entry") or {}
2396
- print(f"Audit: {entry.get('id')}")
2397
- print(f"Created: {entry.get('created_at')}")
2398
- print(f"Command: {entry.get('command')}")
2399
- print(f"Status: {(entry.get('result') or {}).get('status')}")
2400
- print(f"JSON: {result.get('json_path')}")
2401
- print(f"Markdown: {result.get('markdown_path')}")
2402
- return
2403
- print(result.get("content") or "")
2404
-
2405
-
2406
- def print_llm_backends(result: dict[str, Any]) -> None:
2407
- print(f"LLM config: {result['config_path']}")
2408
- print(f"Default: {result.get('default') or '-'}")
2409
- for item in result["items"]:
2410
- markers = []
2411
- if item.get("configured"):
2412
- markers.append("configured")
2413
- if item.get("default"):
2414
- markers.append("default")
2415
- suffix = f" [{' '.join(markers)}]" if markers else ""
2416
- print(f"- {item['id']} {item['kind']} {item['auth']}{suffix}")
2417
- if item.get("notes"):
2418
- print(f" {item['notes']}")
2419
-
2420
-
2421
- def print_llm_doctor(result: dict[str, Any]) -> None:
2422
- print(f"LLM doctor: {result['status']}")
2423
- print(f"Config: {result['config_path']}")
2424
- print(f"Default: {result.get('default') or '-'}")
2425
- for item in result["items"]:
2426
- print(f"- {item['id']}: {item['status']}")
2427
- if item.get("message"):
2428
- print(f" {item['message']}")
2429
-
2430
-
2431
- def print_llm_configure(result: dict[str, Any]) -> None:
2432
- print(f"LLM backend configured: {result['backend']}")
2433
- print(f"Config: {result['config_path']}")
2434
- print(f"Default: {result.get('default') or '-'}")
2435
- print("Stored secret: no")
2436
-
2437
-
2438
- def print_llm_default(result: dict[str, Any]) -> None:
2439
- print(f"Default LLM backend: {result['default']}")
2440
- print(f"Config: {result['config_path']}")
2441
-
2442
-
2443
- def print_llm_preference(result: dict[str, Any]) -> None:
2444
- print(f"LLM preference: {result.get('status', 'ok')}")
2445
- print(f"Primary: {result.get('primary') or '-'}")
2446
- print(f"Fallback enabled: {result.get('fallback_enabled', True)}")
2447
- print("Order:")
2448
- for backend_id in result.get("order") or []:
2449
- print(f"- {backend_id}")
2450
- print(f"Config: {result['config_path']}")
2451
-
2452
-
2453
- def print_providers(result: dict[str, Any]) -> None:
2454
- if not result["items"]:
2455
- print("No providers found.")
2456
- return
2457
- for item in result["items"]:
2458
- write_marker = "writes" if item.get("writes") else "read"
2459
- print(f"- {item['id']} {item['kind']} {item['status']} {write_marker}")
2460
- if item.get("description"):
2461
- print(f" {item['description']}")
2462
-
2463
-
2464
- def print_provider_status(result: dict[str, Any]) -> None:
2465
- print(f"Provider status: {result['status']}")
2466
- for item in result["items"]:
2467
- print(f"- {item['id']}: {item['status']}")
2468
- if item.get("message"):
2469
- print(f" {item['message']}")
2470
- missing = item.get("missing_required_fields") or []
2471
- if missing:
2472
- print(f" Missing config: {', '.join(missing)}")
2473
- auth = item.get("auth") or {}
2474
- missing_secret_fields = auth.get("missing_secret_fields") or []
2475
- if missing_secret_fields:
2476
- print(f" Missing secret refs: {', '.join(missing_secret_fields)}")
2477
- detected_env_file = item.get("detected_env_file") or []
2478
- if detected_env_file:
2479
- print(f" Detected in env-file: {', '.join(detected_env_file)}")
2480
-
2481
-
2482
- def print_provider_configure(result: dict[str, Any]) -> None:
2483
- print(result.get("message") or f"Provider configuration {result['status']}.")
2484
- print(f"Provider: {result['provider']}")
2485
- if result.get("status") == "configured":
2486
- print(f"Config: {result['config_path']}")
2487
- print("Stored secret: no")
2488
- return
2489
- if result.get("status") == "session-only":
2490
- print("Session-only: yes")
2491
- print("Stored secret: no")
2492
- return
2493
- if result.get("required_config_fields"):
2494
- print("Required config fields:")
2495
- for field in result["required_config_fields"]:
2496
- print(f"- {field}")
2497
- print("Next steps:")
2498
- for step in result["next_steps"]:
2499
- print(f"- {step}")
2500
-
2501
-
2502
- def print_provider_unset(result: dict[str, Any]) -> None:
2503
- print(f"Provider config {result['status']}: {result['provider']}")
2504
- print(f"Config: {result['config_path']}")
2505
-
2506
-
2507
- def print_credential_resolution(result: dict[str, Any]) -> None:
2508
- print(f"Credential resolution for {result['provider']}: {result['status']}")
2509
- if result.get("detected_env"):
2510
- print(f"Detected in env: {', '.join(result['detected_env'])}")
2511
- if result.get("detected_env_file"):
2512
- print(f"Detected in env-file: {', '.join(result['detected_env_file'])}")
2513
- if result.get("missing_required_fields"):
2514
- print(f"Missing required fields: {', '.join(result['missing_required_fields'])}")
2515
- auth = result.get("auth") or {}
2516
- if auth.get("missing_secret_fields"):
2517
- print(f"Missing secret refs: {', '.join(auth['missing_secret_fields'])}")
2518
- print("Secret values returned: no")
2519
-
2520
-
2521
- def print_credential_backends(result: dict[str, Any]) -> None:
2522
- print("Credential resolver backends:")
2523
- for item in result["items"]:
2524
- print(f"- {item}")
2525
-
2526
-
2527
- def print_config(result: dict[str, Any]) -> None:
2528
- print(f"Config: {result.get('path')}")
2529
- if result.get("llm"):
2530
- print(f"Primary LLM: {(result['llm'] or {}).get('primary') or '-'}")
2531
- if result.get("ollama"):
2532
- print(f"Ollama: {(result['ollama'] or {}).get('status')}")
2533
-
2534
-
2535
- def print_control(result: dict[str, Any]) -> None:
2536
- kind = result.get("kind")
2537
- if kind == "decisions-reset":
2538
- print(f"Decisions reset: {result.get('category') or 'all'}")
2539
- print(f"Path: {result.get('path')}")
2540
- return
2541
- if "items" in result:
2542
- print(f"{kind}:")
2543
- for item in result.get("items") or []:
2544
- print(f"- {item.get('category')}:{item.get('id')} {item.get('state')}")
2545
- if not result.get("items"):
2546
- print("- none")
2547
- return
2548
- item = result.get("item") or result
2549
- print(f"{item.get('category') or result.get('category')}:{item.get('id') or result.get('id')} {item.get('state') or result.get('state')}")
2550
-
2551
-
2552
- def print_ollama(result: dict[str, Any]) -> None:
2553
- kind = result.get("kind")
2554
- if kind == "ollama-status":
2555
- print(f"Ollama: {result.get('status')}")
2556
- print(f"Binary: {result.get('binary') or '-'}")
2557
- print(f"Version: {result.get('version') or '-'}")
2558
- daemon = result.get("daemon") or {}
2559
- print(f"Daemon: {daemon.get('status') or '-'}")
2560
- print(f"Models: {result.get('model_count', 0)}")
2561
- if result.get("install_plan"):
2562
- print(f"Install: {(result['install_plan'] or {}).get('command')}")
2563
- return
2564
- if kind == "ollama-models":
2565
- print(f"Ollama models: {result.get('status')}")
2566
- for item in result.get("items") or []:
2567
- print(f"- {item.get('name')} {item.get('size') or '-'}")
2568
- if not result.get("items"):
2569
- print("- none")
2570
- return
2571
- print(f"{kind}: {result.get('status')}")
2572
- if result.get("command"):
2573
- command = result["command"]
2574
- print("Command: " + (" ".join(command) if isinstance(command, list) else str(command)))
2575
- if result.get("message"):
2576
- print(result["message"])
2577
-
2578
-
2579
- def print_install(result: dict[str, Any]) -> None:
2580
- print(f"AI DevKit install: {result['status']}")
2581
- print(f"Scope: {result['scope']}")
2582
- print(f"Target: {result['target']}")
2583
- print(f"Hosts: {', '.join(result['hosts'])}")
2584
- print("Stored secret: no")
2585
- paths = result["planned"] if result.get("dry_run") else result["written"]
2586
- if paths:
2587
- label = "Planned writes" if result.get("dry_run") else "Written files"
2588
- print(f"\n{label}:")
2589
- for path in paths:
2590
- print(f"- {path}")
2591
- if result.get("next_steps"):
2592
- print("\nNext steps:")
2593
- for step in result["next_steps"]:
2594
- print(f"- {step}")
2595
-
2596
-
2597
47
  if __name__ == "__main__":
2598
48
  raise SystemExit(main())