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