@bluefly/openstandardagents 0.4.2 → 0.4.4
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/.version.json +7 -0
- package/CHANGELOG.md +488 -0
- package/README.md +106 -417
- package/bin/ossa +3 -0
- package/dist/adapters/agent-skills/exporter.d.ts +98 -0
- package/dist/adapters/agent-skills/exporter.d.ts.map +1 -0
- package/dist/adapters/agent-skills/exporter.js +453 -0
- package/dist/adapters/agent-skills/exporter.js.map +1 -0
- package/dist/adapters/agent-skills/index.d.ts +7 -0
- package/dist/adapters/agent-skills/index.d.ts.map +1 -0
- package/dist/adapters/agent-skills/index.js +6 -0
- package/dist/adapters/agent-skills/index.js.map +1 -0
- package/dist/adapters/anthropic/claude-optimizations.d.ts +44 -0
- package/dist/adapters/anthropic/claude-optimizations.d.ts.map +1 -0
- package/dist/adapters/anthropic/claude-optimizations.js +180 -0
- package/dist/adapters/anthropic/claude-optimizations.js.map +1 -0
- package/dist/adapters/base/adapter.interface.d.ts +4 -0
- package/dist/adapters/base/adapter.interface.d.ts.map +1 -1
- package/dist/adapters/base/adapter.interface.js +7 -0
- package/dist/adapters/base/adapter.interface.js.map +1 -1
- package/dist/adapters/base/common-file-generator.d.ts +160 -0
- package/dist/adapters/base/common-file-generator.d.ts.map +1 -0
- package/dist/adapters/base/common-file-generator.js +584 -0
- package/dist/adapters/base/common-file-generator.js.map +1 -0
- package/dist/adapters/base/index.d.ts +21 -0
- package/dist/adapters/base/index.d.ts.map +1 -0
- package/dist/adapters/base/index.js +25 -0
- package/dist/adapters/base/index.js.map +1 -0
- package/dist/adapters/base/manifest-validator.d.ts +84 -0
- package/dist/adapters/base/manifest-validator.d.ts.map +1 -0
- package/dist/adapters/base/manifest-validator.js +266 -0
- package/dist/adapters/base/manifest-validator.js.map +1 -0
- package/dist/adapters/base/template-engine.d.ts +52 -0
- package/dist/adapters/base/template-engine.d.ts.map +1 -0
- package/dist/adapters/base/template-engine.js +157 -0
- package/dist/adapters/base/template-engine.js.map +1 -0
- package/dist/adapters/crewai/adapter.d.ts +53 -1
- package/dist/adapters/crewai/adapter.d.ts.map +1 -1
- package/dist/adapters/crewai/adapter.js +1457 -31
- package/dist/adapters/crewai/adapter.js.map +1 -1
- package/dist/adapters/crewai/converter.d.ts +8 -0
- package/dist/adapters/crewai/converter.d.ts.map +1 -1
- package/dist/adapters/crewai/converter.js +56 -24
- package/dist/adapters/crewai/converter.js.map +1 -1
- package/dist/adapters/docker/docker-exporter.d.ts +38 -0
- package/dist/adapters/docker/docker-exporter.d.ts.map +1 -0
- package/dist/adapters/docker/docker-exporter.js +648 -0
- package/dist/adapters/docker/docker-exporter.js.map +1 -0
- package/dist/adapters/docker/generators.d.ts +73 -7
- package/dist/adapters/docker/generators.d.ts.map +1 -1
- package/dist/adapters/docker/generators.js +728 -43
- package/dist/adapters/docker/generators.js.map +1 -1
- package/dist/adapters/docker/index.d.ts +4 -3
- package/dist/adapters/docker/index.d.ts.map +1 -1
- package/dist/adapters/docker/index.js +3 -2
- package/dist/adapters/docker/index.js.map +1 -1
- package/dist/adapters/docker/types.d.ts +70 -0
- package/dist/adapters/docker/types.d.ts.map +1 -1
- package/dist/adapters/drupal/adapter.d.ts.map +1 -1
- package/dist/adapters/drupal/adapter.js +2 -2
- package/dist/adapters/drupal/adapter.js.map +1 -1
- package/dist/adapters/drupal/generator.d.ts.map +1 -1
- package/dist/adapters/drupal/generator.js +14 -9
- package/dist/adapters/drupal/generator.js.map +1 -1
- package/dist/adapters/drupal/index.d.ts +3 -1
- package/dist/adapters/drupal/index.d.ts.map +1 -1
- package/dist/adapters/drupal/index.js +5 -1
- package/dist/adapters/drupal/index.js.map +1 -1
- package/dist/adapters/drupal/manifest-exporter.d.ts +77 -0
- package/dist/adapters/drupal/manifest-exporter.d.ts.map +1 -0
- package/dist/adapters/drupal/manifest-exporter.js +360 -0
- package/dist/adapters/drupal/manifest-exporter.js.map +1 -0
- package/dist/adapters/drupal/production-exporter.legacy.d.ts +131 -0
- package/dist/adapters/drupal/production-exporter.legacy.d.ts.map +1 -0
- package/dist/adapters/drupal/production-exporter.legacy.js +2537 -0
- package/dist/adapters/drupal/production-exporter.legacy.js.map +1 -0
- package/dist/adapters/gitlab/agent-generator.d.ts +103 -0
- package/dist/adapters/gitlab/agent-generator.d.ts.map +1 -0
- package/dist/adapters/gitlab/agent-generator.js +898 -0
- package/dist/adapters/gitlab/agent-generator.js.map +1 -0
- package/dist/adapters/gitlab/converter.d.ts +12 -2
- package/dist/adapters/gitlab/converter.d.ts.map +1 -1
- package/dist/adapters/gitlab/converter.js +19 -2
- package/dist/adapters/gitlab/converter.js.map +1 -1
- package/dist/adapters/gitlab/external-agent-generator.d.ts +70 -0
- package/dist/adapters/gitlab/external-agent-generator.d.ts.map +1 -0
- package/dist/adapters/gitlab/external-agent-generator.js +338 -0
- package/dist/adapters/gitlab/external-agent-generator.js.map +1 -0
- package/dist/adapters/gitlab/flow-generator.d.ts +73 -0
- package/dist/adapters/gitlab/flow-generator.d.ts.map +1 -0
- package/dist/adapters/gitlab/flow-generator.js +669 -0
- package/dist/adapters/gitlab/flow-generator.js.map +1 -0
- package/dist/adapters/gitlab/index.d.ts +10 -2
- package/dist/adapters/gitlab/index.d.ts.map +1 -1
- package/dist/adapters/gitlab/index.js +6 -1
- package/dist/adapters/gitlab/index.js.map +1 -1
- package/dist/adapters/gitlab/package-generator.d.ts +167 -0
- package/dist/adapters/gitlab/package-generator.d.ts.map +1 -0
- package/dist/adapters/gitlab/package-generator.js +2426 -0
- package/dist/adapters/gitlab/package-generator.js.map +1 -0
- package/dist/adapters/gitlab/router-generator.d.ts +113 -0
- package/dist/adapters/gitlab/router-generator.d.ts.map +1 -0
- package/dist/adapters/gitlab/router-generator.js +541 -0
- package/dist/adapters/gitlab/router-generator.js.map +1 -0
- package/dist/adapters/gitlab/trigger-generator.d.ts +154 -0
- package/dist/adapters/gitlab/trigger-generator.d.ts.map +1 -0
- package/dist/adapters/gitlab/trigger-generator.js +279 -0
- package/dist/adapters/gitlab/trigger-generator.js.map +1 -0
- package/dist/adapters/gitlab/types.d.ts +98 -0
- package/dist/adapters/gitlab/types.d.ts.map +1 -1
- package/dist/adapters/kubernetes/generator.d.ts +93 -5
- package/dist/adapters/kubernetes/generator.d.ts.map +1 -1
- package/dist/adapters/kubernetes/generator.js +1292 -33
- package/dist/adapters/kubernetes/generator.js.map +1 -1
- package/dist/adapters/kubernetes/index.d.ts +2 -2
- package/dist/adapters/kubernetes/index.d.ts.map +1 -1
- package/dist/adapters/kubernetes/index.js +1 -1
- package/dist/adapters/kubernetes/kagent-crd-generator.d.ts +72 -0
- package/dist/adapters/kubernetes/kagent-crd-generator.d.ts.map +1 -0
- package/dist/adapters/kubernetes/kagent-crd-generator.js +237 -0
- package/dist/adapters/kubernetes/kagent-crd-generator.js.map +1 -0
- package/dist/adapters/kubernetes/types.d.ts +45 -0
- package/dist/adapters/kubernetes/types.d.ts.map +1 -1
- package/dist/adapters/langchain/adapter.d.ts +1 -9
- package/dist/adapters/langchain/adapter.d.ts.map +1 -1
- package/dist/adapters/langchain/adapter.js +35 -131
- package/dist/adapters/langchain/adapter.js.map +1 -1
- package/dist/adapters/langchain/converter.d.ts.map +1 -1
- package/dist/adapters/langchain/converter.js +16 -4
- package/dist/adapters/langchain/converter.js.map +1 -1
- package/dist/adapters/langfuse.adapter.d.ts +1 -1
- package/dist/adapters/langsmith.adapter.d.ts +1 -1
- package/dist/adapters/mcp/adapter.d.ts.map +1 -1
- package/dist/adapters/mcp/adapter.js +4 -1
- package/dist/adapters/mcp/adapter.js.map +1 -1
- package/dist/adapters/mcp/converter.d.ts.map +1 -1
- package/dist/adapters/mcp/converter.js.map +1 -1
- package/dist/adapters/npm/adapter.d.ts +1 -5
- package/dist/adapters/npm/adapter.d.ts.map +1 -1
- package/dist/adapters/npm/adapter.js +41 -84
- package/dist/adapters/npm/adapter.js.map +1 -1
- package/dist/adapters/npm/converter.d.ts.map +1 -1
- package/dist/adapters/npm/converter.js +28 -15
- package/dist/adapters/npm/converter.js.map +1 -1
- package/dist/adapters/npm/type-aware-dependencies.d.ts +19 -0
- package/dist/adapters/npm/type-aware-dependencies.d.ts.map +1 -0
- package/dist/adapters/npm/type-aware-dependencies.js +158 -0
- package/dist/adapters/npm/type-aware-dependencies.js.map +1 -0
- package/dist/adapters/opentelemetry.adapter.js.map +1 -1
- package/dist/adapters/phoenix.adapter.d.ts +1 -1
- package/dist/cli/banner.d.ts.map +1 -1
- package/dist/cli/banner.js +10 -3
- package/dist/cli/banner.js.map +1 -1
- package/dist/cli/commands/agent-wizard.command.d.ts.map +1 -1
- package/dist/cli/commands/agent-wizard.command.js +6 -1
- package/dist/cli/commands/agent-wizard.command.js.map +1 -1
- package/dist/cli/commands/agents/persona.command.d.ts +10 -0
- package/dist/cli/commands/agents/persona.command.d.ts.map +1 -0
- package/dist/cli/commands/agents/persona.command.js +519 -0
- package/dist/cli/commands/agents/persona.command.js.map +1 -0
- package/dist/cli/commands/agents.command.d.ts.map +1 -1
- package/dist/cli/commands/agents.command.js +6 -0
- package/dist/cli/commands/agents.command.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +26 -9
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/build.command.d.ts.map +1 -1
- package/dist/cli/commands/build.command.js +6 -5
- package/dist/cli/commands/build.command.js.map +1 -1
- package/dist/cli/commands/catalog/pull.command.d.ts.map +1 -1
- package/dist/cli/commands/catalog/pull.command.js +25 -5
- package/dist/cli/commands/catalog/pull.command.js.map +1 -1
- package/dist/cli/commands/catalog/push.command.d.ts.map +1 -1
- package/dist/cli/commands/catalog/push.command.js +29 -7
- package/dist/cli/commands/catalog/push.command.js.map +1 -1
- package/dist/cli/commands/catalog/sync.command.d.ts.map +1 -1
- package/dist/cli/commands/catalog/sync.command.js +23 -6
- package/dist/cli/commands/catalog/sync.command.js.map +1 -1
- package/dist/cli/commands/deploy-enhanced.command.d.ts +15 -0
- package/dist/cli/commands/deploy-enhanced.command.d.ts.map +1 -0
- package/dist/cli/commands/deploy-enhanced.command.js +335 -0
- package/dist/cli/commands/deploy-enhanced.command.js.map +1 -0
- package/dist/cli/commands/deploy.command.d.ts.map +1 -1
- package/dist/cli/commands/deploy.command.js +4 -3
- package/dist/cli/commands/deploy.command.js.map +1 -1
- package/dist/cli/commands/deploy.d.ts.map +1 -1
- package/dist/cli/commands/deploy.js +6 -5
- package/dist/cli/commands/deploy.js.map +1 -1
- package/dist/cli/commands/discover.d.ts +15 -0
- package/dist/cli/commands/discover.d.ts.map +1 -0
- package/dist/cli/commands/discover.js +215 -0
- package/dist/cli/commands/discover.js.map +1 -0
- package/dist/cli/commands/estimate.command.js +1 -1
- package/dist/cli/commands/estimate.command.js.map +1 -1
- package/dist/cli/commands/export.command.js +260 -86
- package/dist/cli/commands/export.command.js.map +1 -1
- package/dist/cli/commands/generate-gaid.command.d.ts +14 -0
- package/dist/cli/commands/generate-gaid.command.d.ts.map +1 -0
- package/dist/cli/commands/generate-gaid.command.js +141 -0
- package/dist/cli/commands/generate-gaid.command.js.map +1 -0
- package/dist/cli/commands/governance.command.d.ts +11 -0
- package/dist/cli/commands/governance.command.d.ts.map +1 -0
- package/dist/cli/commands/governance.command.js +166 -0
- package/dist/cli/commands/governance.command.js.map +1 -0
- package/dist/cli/commands/import.command.js.map +1 -1
- package/dist/cli/commands/init.command.d.ts.map +1 -1
- package/dist/cli/commands/init.command.js +11 -13
- package/dist/cli/commands/init.command.js.map +1 -1
- package/dist/cli/commands/lint.command.js +3 -1
- package/dist/cli/commands/lint.command.js.map +1 -1
- package/dist/cli/commands/migrate-langchain.command.js +3 -3
- package/dist/cli/commands/migrate-langchain.command.js.map +1 -1
- package/dist/cli/commands/migrate.command.js.map +1 -1
- package/dist/cli/commands/publish.command.d.ts.map +1 -1
- package/dist/cli/commands/publish.command.js.map +1 -1
- package/dist/cli/commands/quickstart.command.d.ts.map +1 -1
- package/dist/cli/commands/quickstart.command.js +32 -49
- package/dist/cli/commands/quickstart.command.js.map +1 -1
- package/dist/cli/commands/register.d.ts +12 -0
- package/dist/cli/commands/register.d.ts.map +1 -0
- package/dist/cli/commands/register.js +263 -0
- package/dist/cli/commands/register.js.map +1 -0
- package/dist/cli/commands/rollback.command.d.ts +13 -0
- package/dist/cli/commands/rollback.command.d.ts.map +1 -0
- package/dist/cli/commands/rollback.command.js +156 -0
- package/dist/cli/commands/rollback.command.js.map +1 -0
- package/dist/cli/commands/run.command.d.ts.map +1 -1
- package/dist/cli/commands/run.command.js +19 -4
- package/dist/cli/commands/run.command.js.map +1 -1
- package/dist/cli/commands/standardize.command.js +3 -6
- package/dist/cli/commands/standardize.command.js.map +1 -1
- package/dist/cli/commands/test.command.d.ts.map +1 -1
- package/dist/cli/commands/test.command.js +1 -1
- package/dist/cli/commands/test.command.js.map +1 -1
- package/dist/cli/commands/types/wizard-config.types.d.ts.map +1 -1
- package/dist/cli/commands/types/wizard-config.types.js.map +1 -1
- package/dist/cli/commands/upgrade.command.js.map +1 -1
- package/dist/cli/commands/validate.command.js +1 -3
- package/dist/cli/commands/validate.command.js.map +1 -1
- package/dist/cli/commands/verify.d.ts +15 -0
- package/dist/cli/commands/verify.d.ts.map +1 -0
- package/dist/cli/commands/verify.js +274 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/commands/wizard-api-first.command.d.ts.map +1 -1
- package/dist/cli/commands/wizard-api-first.command.js +1 -2
- package/dist/cli/commands/wizard-api-first.command.js.map +1 -1
- package/dist/cli/commands/wizard-interactive.command.d.ts.map +1 -1
- package/dist/cli/commands/wizard-interactive.command.js +1339 -28
- package/dist/cli/commands/wizard-interactive.command.js.map +1 -1
- package/dist/cli/index.js +136 -70
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/schema-driven/schema-loader.d.ts.map +1 -1
- package/dist/cli/schema-driven/schema-loader.js +2 -2
- package/dist/cli/schema-driven/schema-loader.js.map +1 -1
- package/dist/cli/schema-driven/ui-generator.d.ts.map +1 -1
- package/dist/cli/schema-driven/ui-generator.js +13 -4
- package/dist/cli/schema-driven/ui-generator.js.map +1 -1
- package/dist/cli/templates/enhanced-templates.d.ts.map +1 -1
- package/dist/cli/templates/enhanced-templates.js +2 -1
- package/dist/cli/templates/enhanced-templates.js.map +1 -1
- package/dist/cli/utils/index.d.ts +1 -0
- package/dist/cli/utils/index.d.ts.map +1 -1
- package/dist/cli/utils/index.js +2 -0
- package/dist/cli/utils/index.js.map +1 -1
- package/dist/cli/utils/logo.d.ts +10 -0
- package/dist/cli/utils/logo.d.ts.map +1 -0
- package/dist/cli/utils/logo.js +49 -0
- package/dist/cli/utils/logo.js.map +1 -0
- package/dist/cli/utils/standard-options.d.ts +21 -0
- package/dist/cli/utils/standard-options.d.ts.map +1 -1
- package/dist/cli/utils/standard-options.js +31 -0
- package/dist/cli/utils/standard-options.js.map +1 -1
- package/dist/cli/utils/validation-builder.d.ts +121 -0
- package/dist/cli/utils/validation-builder.d.ts.map +1 -0
- package/dist/cli/utils/validation-builder.js +322 -0
- package/dist/cli/utils/validation-builder.js.map +1 -0
- package/dist/cli/wizard/data/taxonomy.d.ts.map +1 -1
- package/dist/cli/wizard/data/taxonomy.js +5 -1
- package/dist/cli/wizard/data/taxonomy.js.map +1 -1
- package/dist/cli/wizard/interactive-wizard.d.ts.map +1 -1
- package/dist/cli/wizard/interactive-wizard.js +24 -11
- package/dist/cli/wizard/interactive-wizard.js.map +1 -1
- package/dist/cli/wizard/steps/04a-persona.d.ts +16 -0
- package/dist/cli/wizard/steps/04a-persona.d.ts.map +1 -0
- package/dist/cli/wizard/steps/04a-persona.js +297 -0
- package/dist/cli/wizard/steps/04a-persona.js.map +1 -0
- package/dist/cli/wizard/steps/05-tools.d.ts.map +1 -1
- package/dist/cli/wizard/steps/05-tools.js +10 -1
- package/dist/cli/wizard/steps/05-tools.js.map +1 -1
- package/dist/cli/wizard/steps/06-autonomy.js +1 -1
- package/dist/cli/wizard/steps/07-observability.js +1 -1
- package/dist/cli/wizard/steps/08-deployment.js +1 -1
- package/dist/cli/wizard/steps/09-advanced.js +1 -1
- package/dist/cli/wizard/steps/09-advanced.js.map +1 -1
- package/dist/cli/wizard/steps/10-review.d.ts.map +1 -1
- package/dist/cli/wizard/steps/10-review.js +6 -4
- package/dist/cli/wizard/steps/10-review.js.map +1 -1
- package/dist/cli/wizard/steps/12-agents-folder.d.ts.map +1 -1
- package/dist/cli/wizard/steps/12-agents-folder.js +14 -10
- package/dist/cli/wizard/steps/12-agents-folder.js.map +1 -1
- package/dist/cli/wizard/steps/13-openapi-generation.d.ts.map +1 -1
- package/dist/cli/wizard/steps/13-openapi-generation.js +10 -2
- package/dist/cli/wizard/steps/13-openapi-generation.js.map +1 -1
- package/dist/cli/wizard/steps/14-workspace-registration.d.ts.map +1 -1
- package/dist/cli/wizard/steps/14-workspace-registration.js +10 -2
- package/dist/cli/wizard/steps/14-workspace-registration.js.map +1 -1
- package/dist/cli/wizard/steps/15-cost-estimation.d.ts.map +1 -1
- package/dist/cli/wizard/steps/15-cost-estimation.js +27 -11
- package/dist/cli/wizard/steps/15-cost-estimation.js.map +1 -1
- package/dist/cli/wizard/steps/16-best-practices.d.ts.map +1 -1
- package/dist/cli/wizard/steps/16-best-practices.js +14 -13
- package/dist/cli/wizard/steps/16-best-practices.js.map +1 -1
- package/dist/cli/wizard/ui/banner.d.ts +20 -0
- package/dist/cli/wizard/ui/banner.d.ts.map +1 -0
- package/dist/cli/wizard/ui/banner.js +66 -0
- package/dist/cli/wizard/ui/banner.js.map +1 -0
- package/dist/cli/wizard/ui/console.d.ts.map +1 -1
- package/dist/cli/wizard/ui/console.js +21 -23
- package/dist/cli/wizard/ui/console.js.map +1 -1
- package/dist/cli/wizard/ui/wizard-ui.d.ts.map +1 -1
- package/dist/cli/wizard/ui/wizard-ui.js +54 -75
- package/dist/cli/wizard/ui/wizard-ui.js.map +1 -1
- package/dist/cli/wizard/use-cases.d.ts.map +1 -1
- package/dist/cli/wizard/use-cases.js.map +1 -1
- package/dist/config/defaults.d.ts +59 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +72 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/deploy/cloud/aws-driver.d.ts +75 -0
- package/dist/deploy/cloud/aws-driver.d.ts.map +1 -0
- package/dist/deploy/cloud/aws-driver.js +344 -0
- package/dist/deploy/cloud/aws-driver.js.map +1 -0
- package/dist/deploy/cloud/azure-driver.d.ts +54 -0
- package/dist/deploy/cloud/azure-driver.d.ts.map +1 -0
- package/dist/deploy/cloud/azure-driver.js +221 -0
- package/dist/deploy/cloud/azure-driver.js.map +1 -0
- package/dist/deploy/cloud/gcp-driver.d.ts +56 -0
- package/dist/deploy/cloud/gcp-driver.d.ts.map +1 -0
- package/dist/deploy/cloud/gcp-driver.js +212 -0
- package/dist/deploy/cloud/gcp-driver.js.map +1 -0
- package/dist/dev-cli/commands/version.command.js +18 -18
- package/dist/dev-cli/commands/version.command.js.map +1 -1
- package/dist/dev-cli/services/version-check.service.d.ts.map +1 -1
- package/dist/dev-cli/services/version-check.service.js +2 -1
- package/dist/dev-cli/services/version-check.service.js.map +1 -1
- package/dist/di-container.d.ts.map +1 -1
- package/dist/di-container.js +13 -5
- package/dist/di-container.js.map +1 -1
- package/dist/errors/index.d.ts +154 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +327 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/generated/types.d.ts +91 -91
- package/dist/generated/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/governance-provider.interface.d.ts +98 -0
- package/dist/interfaces/governance-provider.interface.d.ts.map +1 -0
- package/dist/interfaces/governance-provider.interface.js +20 -0
- package/dist/interfaces/governance-provider.interface.js.map +1 -0
- package/dist/mesh/advanced-routing.d.ts +181 -0
- package/dist/mesh/advanced-routing.d.ts.map +1 -0
- package/dist/mesh/advanced-routing.js +473 -0
- package/dist/mesh/advanced-routing.js.map +1 -0
- package/dist/mesh/agent-graph.d.ts +218 -0
- package/dist/mesh/agent-graph.d.ts.map +1 -0
- package/dist/mesh/agent-graph.js +487 -0
- package/dist/mesh/agent-graph.js.map +1 -0
- package/dist/mesh/discovery-providers.d.ts +162 -0
- package/dist/mesh/discovery-providers.d.ts.map +1 -0
- package/dist/mesh/discovery-providers.js +514 -0
- package/dist/mesh/discovery-providers.js.map +1 -0
- package/dist/mesh/index.d.ts +3 -0
- package/dist/mesh/index.d.ts.map +1 -1
- package/dist/mesh/index.js +6 -0
- package/dist/mesh/index.js.map +1 -1
- package/dist/messenger/Commands/MessengerConsumeCommand.d.ts +57 -0
- package/dist/messenger/Commands/MessengerConsumeCommand.d.ts.map +1 -0
- package/dist/messenger/Commands/MessengerConsumeCommand.js +49 -0
- package/dist/messenger/Commands/MessengerConsumeCommand.js.map +1 -0
- package/dist/messenger/Commands/MessengerFailedCommand.d.ts +76 -0
- package/dist/messenger/Commands/MessengerFailedCommand.d.ts.map +1 -0
- package/dist/messenger/Commands/MessengerFailedCommand.js +120 -0
- package/dist/messenger/Commands/MessengerFailedCommand.js.map +1 -0
- package/dist/messenger/Commands/MessengerStatsCommand.d.ts +61 -0
- package/dist/messenger/Commands/MessengerStatsCommand.d.ts.map +1 -0
- package/dist/messenger/Commands/MessengerStatsCommand.js +80 -0
- package/dist/messenger/Commands/MessengerStatsCommand.js.map +1 -0
- package/dist/messenger/Commands/index.d.ts +10 -0
- package/dist/messenger/Commands/index.d.ts.map +1 -0
- package/dist/messenger/Commands/index.js +10 -0
- package/dist/messenger/Commands/index.js.map +1 -0
- package/dist/messenger/EventSubscriber/FailedMessageSubscriber.d.ts +44 -0
- package/dist/messenger/EventSubscriber/FailedMessageSubscriber.d.ts.map +1 -0
- package/dist/messenger/EventSubscriber/FailedMessageSubscriber.js +64 -0
- package/dist/messenger/EventSubscriber/FailedMessageSubscriber.js.map +1 -0
- package/dist/messenger/Handler/AgentBatchHandler.d.ts +80 -0
- package/dist/messenger/Handler/AgentBatchHandler.d.ts.map +1 -0
- package/dist/messenger/Handler/AgentBatchHandler.js +207 -0
- package/dist/messenger/Handler/AgentBatchHandler.js.map +1 -0
- package/dist/messenger/Handler/AgentExecutionHandler.d.ts +76 -0
- package/dist/messenger/Handler/AgentExecutionHandler.d.ts.map +1 -0
- package/dist/messenger/Handler/AgentExecutionHandler.js +131 -0
- package/dist/messenger/Handler/AgentExecutionHandler.js.map +1 -0
- package/dist/messenger/Handler/index.d.ts +9 -0
- package/dist/messenger/Handler/index.d.ts.map +1 -0
- package/dist/messenger/Handler/index.js +9 -0
- package/dist/messenger/Handler/index.js.map +1 -0
- package/dist/messenger/Message/AgentBatchMessage.d.ts +115 -0
- package/dist/messenger/Message/AgentBatchMessage.d.ts.map +1 -0
- package/dist/messenger/Message/AgentBatchMessage.js +100 -0
- package/dist/messenger/Message/AgentBatchMessage.js.map +1 -0
- package/dist/messenger/Message/AgentExecutionMessage.d.ts +98 -0
- package/dist/messenger/Message/AgentExecutionMessage.d.ts.map +1 -0
- package/dist/messenger/Message/AgentExecutionMessage.js +77 -0
- package/dist/messenger/Message/AgentExecutionMessage.js.map +1 -0
- package/dist/messenger/Message/index.d.ts +9 -0
- package/dist/messenger/Message/index.d.ts.map +1 -0
- package/dist/messenger/Message/index.js +9 -0
- package/dist/messenger/Message/index.js.map +1 -0
- package/dist/messenger/Middleware/AuthenticationMiddleware.d.ts +41 -0
- package/dist/messenger/Middleware/AuthenticationMiddleware.d.ts.map +1 -0
- package/dist/messenger/Middleware/AuthenticationMiddleware.js +85 -0
- package/dist/messenger/Middleware/AuthenticationMiddleware.js.map +1 -0
- package/dist/messenger/Middleware/LoggingMiddleware.d.ts +30 -0
- package/dist/messenger/Middleware/LoggingMiddleware.d.ts.map +1 -0
- package/dist/messenger/Middleware/LoggingMiddleware.js +57 -0
- package/dist/messenger/Middleware/LoggingMiddleware.js.map +1 -0
- package/dist/messenger/Middleware/RateLimitMiddleware.d.ts +67 -0
- package/dist/messenger/Middleware/RateLimitMiddleware.d.ts.map +1 -0
- package/dist/messenger/Middleware/RateLimitMiddleware.js +90 -0
- package/dist/messenger/Middleware/RateLimitMiddleware.js.map +1 -0
- package/dist/messenger/Middleware/ValidationMiddleware.d.ts +39 -0
- package/dist/messenger/Middleware/ValidationMiddleware.d.ts.map +1 -0
- package/dist/messenger/Middleware/ValidationMiddleware.js +91 -0
- package/dist/messenger/Middleware/ValidationMiddleware.js.map +1 -0
- package/dist/messenger/Middleware/index.d.ts +11 -0
- package/dist/messenger/Middleware/index.d.ts.map +1 -0
- package/dist/messenger/Middleware/index.js +11 -0
- package/dist/messenger/Middleware/index.js.map +1 -0
- package/dist/messenger/Monitoring/MetricsCollector.d.ts +107 -0
- package/dist/messenger/Monitoring/MetricsCollector.d.ts.map +1 -0
- package/dist/messenger/Monitoring/MetricsCollector.js +80 -0
- package/dist/messenger/Monitoring/MetricsCollector.js.map +1 -0
- package/dist/messenger/Monitoring/QueueMonitor.d.ts +74 -0
- package/dist/messenger/Monitoring/QueueMonitor.d.ts.map +1 -0
- package/dist/messenger/Monitoring/QueueMonitor.js +157 -0
- package/dist/messenger/Monitoring/QueueMonitor.js.map +1 -0
- package/dist/messenger/Monitoring/index.d.ts +9 -0
- package/dist/messenger/Monitoring/index.d.ts.map +1 -0
- package/dist/messenger/Monitoring/index.js +9 -0
- package/dist/messenger/Monitoring/index.js.map +1 -0
- package/dist/messenger/index.d.ts +38 -0
- package/dist/messenger/index.d.ts.map +1 -0
- package/dist/messenger/index.js +44 -0
- package/dist/messenger/index.js.map +1 -0
- package/dist/observability/index.d.ts +13 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +14 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/metrics.d.ts +131 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +308 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/middleware.d.ts +64 -0
- package/dist/observability/middleware.d.ts.map +1 -0
- package/dist/observability/middleware.js +225 -0
- package/dist/observability/middleware.js.map +1 -0
- package/dist/package.json +17 -12
- package/dist/runtime/agent-runner.d.ts.map +1 -1
- package/dist/runtime/agent-runner.js +23 -23
- package/dist/runtime/agent-runner.js.map +1 -1
- package/dist/sdks/kagent/crd-generator.d.ts +63 -1
- package/dist/sdks/kagent/crd-generator.d.ts.map +1 -1
- package/dist/sdks/kagent/crd-generator.js +769 -20
- package/dist/sdks/kagent/crd-generator.js.map +1 -1
- package/dist/sdks/kagent/index.d.ts +1 -1
- package/dist/sdks/kagent/index.d.ts.map +1 -1
- package/dist/sdks/kagent/k8s-resources-generator.d.ts.map +1 -1
- package/dist/sdks/kagent/k8s-resources-generator.js.map +1 -1
- package/dist/sdks/kagent/types.d.ts +30 -0
- package/dist/sdks/kagent/types.d.ts.map +1 -1
- package/dist/sdks/shared/validation.d.ts +4 -4
- package/dist/services/agent-protocol-client.d.ts +541 -0
- package/dist/services/agent-protocol-client.d.ts.map +1 -0
- package/dist/services/agent-protocol-client.js +166 -0
- package/dist/services/agent-protocol-client.js.map +1 -0
- package/dist/services/ai-architect.service.js.map +1 -1
- package/dist/services/cost-estimation/token-counter.service.js +1 -1
- package/dist/services/cost-estimation/token-counter.service.js.map +1 -1
- package/dist/services/dev-server/websocket-server.d.ts.map +1 -1
- package/dist/services/dev-server/websocket-server.js +2 -1
- package/dist/services/dev-server/websocket-server.js.map +1 -1
- package/dist/services/export/anthropic/anthropic-exporter.d.ts.map +1 -1
- package/dist/services/export/anthropic/anthropic-exporter.js +8 -3
- package/dist/services/export/anthropic/anthropic-exporter.js.map +1 -1
- package/dist/services/export/anthropic/index.d.ts +1 -1
- package/dist/services/export/anthropic/index.d.ts.map +1 -1
- package/dist/services/export/anthropic/index.js +1 -1
- package/dist/services/export/anthropic/index.js.map +1 -1
- package/dist/services/export/langchain/callbacks-generator.d.ts.map +1 -1
- package/dist/services/export/langchain/callbacks-generator.js +16 -8
- package/dist/services/export/langchain/callbacks-generator.js.map +1 -1
- package/dist/services/export/langchain/error-handling-generator.d.ts.map +1 -1
- package/dist/services/export/langchain/error-handling-generator.js +9 -5
- package/dist/services/export/langchain/error-handling-generator.js.map +1 -1
- package/dist/services/export/langchain/langchain-exporter.d.ts.map +1 -1
- package/dist/services/export/langchain/langchain-exporter.js +16 -8
- package/dist/services/export/langchain/langchain-exporter.js.map +1 -1
- package/dist/services/export/langchain/langgraph-generator.d.ts.map +1 -1
- package/dist/services/export/langchain/langgraph-generator.js +34 -20
- package/dist/services/export/langchain/langgraph-generator.js.map +1 -1
- package/dist/services/export/langchain/langserve-generator.d.ts.map +1 -1
- package/dist/services/export/langchain/langserve-generator.js +7 -1
- package/dist/services/export/langchain/langserve-generator.js.map +1 -1
- package/dist/services/export/langchain/memory-generator.d.ts.map +1 -1
- package/dist/services/export/langchain/memory-generator.js.map +1 -1
- package/dist/services/export/langchain/plan-execute-generator.d.ts.map +1 -1
- package/dist/services/export/langchain/plan-execute-generator.js.map +1 -1
- package/dist/services/export/langchain/streaming-generator.d.ts.map +1 -1
- package/dist/services/export/langchain/streaming-generator.js +12 -6
- package/dist/services/export/langchain/streaming-generator.js.map +1 -1
- package/dist/services/export/langchain/tools-generator.d.ts.map +1 -1
- package/dist/services/export/langchain/tools-generator.js.map +1 -1
- package/dist/services/export/npm/npm-exporter.d.ts +40 -0
- package/dist/services/export/npm/npm-exporter.d.ts.map +1 -1
- package/dist/services/export/npm/npm-exporter.js +1294 -1
- package/dist/services/export/npm/npm-exporter.js.map +1 -1
- package/dist/services/export/npm/package-json-generator.js +3 -1
- package/dist/services/export/npm/package-json-generator.js.map +1 -1
- package/dist/services/export/npm/typescript-generator.d.ts.map +1 -1
- package/dist/services/export/npm/typescript-generator.js +7 -3
- package/dist/services/export/npm/typescript-generator.js.map +1 -1
- package/dist/services/export/testing/index.d.ts +1 -1
- package/dist/services/export/testing/index.d.ts.map +1 -1
- package/dist/services/export/testing/test-generator.d.ts.map +1 -1
- package/dist/services/export/testing/test-generator.js +5 -1
- package/dist/services/export/testing/test-generator.js.map +1 -1
- package/dist/services/governance-client.service.d.ts +39 -0
- package/dist/services/governance-client.service.d.ts.map +1 -0
- package/dist/services/governance-client.service.js +124 -0
- package/dist/services/governance-client.service.js.map +1 -0
- package/dist/services/migration/langchain-migration.service.js +2 -2
- package/dist/services/migration/langchain-migration.service.js.map +1 -1
- package/dist/services/release-automation/release.service.d.ts +4 -4
- package/dist/services/release-automation/schemas/release.schema.d.ts +5 -5
- package/dist/services/release-automation/tag.service.d.ts +3 -3
- package/dist/services/taxonomy-service.d.ts +3 -3
- package/dist/services/test-runner/mock-llm.service.d.ts.map +1 -1
- package/dist/services/test-runner/mock-llm.service.js +1 -2
- package/dist/services/test-runner/mock-llm.service.js.map +1 -1
- package/dist/services/test-runner/scenarios.d.ts.map +1 -1
- package/dist/services/test-runner/scenarios.js +9 -3
- package/dist/services/test-runner/scenarios.js.map +1 -1
- package/dist/services/test-runner/test-runner.service.d.ts.map +1 -1
- package/dist/services/test-runner/test-runner.service.js.map +1 -1
- package/dist/services/validation/best-practices-validator.d.ts.map +1 -1
- package/dist/services/validation/best-practices-validator.js.map +1 -1
- package/dist/services/validation/cost-estimator.d.ts.map +1 -1
- package/dist/services/validation/cost-estimator.js +4 -2
- package/dist/services/validation/cost-estimator.js.map +1 -1
- package/dist/services/validation/enhanced-validator.d.ts.map +1 -1
- package/dist/services/validation/enhanced-validator.js +2 -4
- package/dist/services/validation/enhanced-validator.js.map +1 -1
- package/dist/services/validation/security-validator.d.ts.map +1 -1
- package/dist/services/validation/security-validator.js +3 -1
- package/dist/services/validation/security-validator.js.map +1 -1
- package/dist/services/validation-zod.service.js +1 -1
- package/dist/services/validation-zod.service.js.map +1 -1
- package/dist/services/validation.service.d.ts +7 -2
- package/dist/services/validation.service.d.ts.map +1 -1
- package/dist/services/validation.service.js +7 -4
- package/dist/services/validation.service.js.map +1 -1
- package/dist/services/validators/a2a.validator.js.map +1 -1
- package/dist/services/validators/autogen.validator.js.map +1 -1
- package/dist/services/validators/contract.validator.js.map +1 -1
- package/dist/services/validators/crewai.validator.js.map +1 -1
- package/dist/services/validators/dependencies.validator.d.ts +1 -1
- package/dist/services/validators/dependencies.validator.d.ts.map +1 -1
- package/dist/services/validators/kagent.validator.js.map +1 -1
- package/dist/services/validators/langchain.validator.js.map +1 -1
- package/dist/services/validators/langgraph.validator.js.map +1 -1
- package/dist/services/validators/mcp.validator.js.map +1 -1
- package/dist/services/wizard/prompts.d.ts.map +1 -1
- package/dist/services/wizard/prompts.js +12 -5
- package/dist/services/wizard/prompts.js.map +1 -1
- package/dist/services/wizard/wizard.service.d.ts.map +1 -1
- package/dist/services/wizard/wizard.service.js +9 -4
- package/dist/services/wizard/wizard.service.js.map +1 -1
- package/dist/spec/extensions/knowledge-graph/knowledge-graph.schema.json +386 -0
- package/dist/spec/v0.4/agent.schema.json +154 -1
- package/dist/spec/v0.4/validator.schema.json +282 -0
- package/dist/transports/websocket.d.ts +1 -0
- package/dist/transports/websocket.d.ts.map +1 -1
- package/dist/transports/websocket.js +9 -1
- package/dist/transports/websocket.js.map +1 -1
- package/dist/types/architect.d.ts +2 -2
- package/dist/types/architect.d.ts.map +1 -1
- package/dist/types/identity.zod.d.ts +21 -21
- package/dist/types/index.d.ts +65 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/personality.zod.d.ts +65 -65
- package/dist/types/prompts.zod.d.ts +2 -2
- package/dist/utils/logger.d.ts +82 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +250 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/validation/index.d.ts +3 -0
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +6 -0
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/progressive-scorer.d.ts +123 -0
- package/dist/validation/progressive-scorer.d.ts.map +1 -0
- package/dist/validation/progressive-scorer.js +340 -0
- package/dist/validation/progressive-scorer.js.map +1 -0
- package/dist/validation/validation-context.d.ts +86 -0
- package/dist/validation/validation-context.d.ts.map +1 -0
- package/dist/validation/validation-context.js +138 -0
- package/dist/validation/validation-context.js.map +1 -0
- package/dist/validation/validator-registry.d.ts +158 -0
- package/dist/validation/validator-registry.d.ts.map +1 -0
- package/dist/validation/validator-registry.js +245 -0
- package/dist/validation/validator-registry.js.map +1 -0
- package/dist/version-management/api/server.d.ts.map +1 -1
- package/dist/version-management/api/server.js.map +1 -1
- package/dist/version-management/cli/index.js +8 -1
- package/dist/version-management/cli/index.js.map +1 -1
- package/dist/version-management/core/version-manager.d.ts.map +1 -1
- package/dist/version-management/core/version-manager.js +5 -2
- package/dist/version-management/core/version-manager.js.map +1 -1
- package/dist/version-management/core/version-manager.test.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +4 -6
- package/dist/version.js.map +1 -1
- package/examples/agent-mesh/DISCOVERY.md +679 -0
- package/examples/agent-mesh/discovery-system.ts +670 -0
- package/examples/agent-taxonomy-example.ossa.yaml +89 -0
- package/examples/agents/02-code-review-agent/agent.ossa.yaml +49 -0
- package/examples/agents/03-data-analysis-agent/agent.ossa.yaml +55 -0
- package/examples/agents/06-devops-agent/agent.ossa.yaml +47 -0
- package/examples/agents/07-research-assistant/agent.ossa.yaml +61 -1
- package/examples/agents/09-security-scanner/agent.ossa.yaml +46 -0
- package/examples/deployment-workflow.md +601 -0
- package/examples/gitlab-agents/DEPLOYMENT.md +331 -0
- package/examples/gitlab-agents/daily-code-scan/.env.example +11 -0
- package/examples/gitlab-agents/daily-code-scan/.gitlab-ci.yml +34 -0
- package/examples/gitlab-agents/daily-code-scan/Dockerfile +18 -0
- package/examples/gitlab-agents/daily-code-scan/README.md +80 -0
- package/examples/gitlab-agents/daily-code-scan/package.json +28 -0
- package/examples/gitlab-agents/daily-code-scan/src/gitlab-client.ts +59 -0
- package/examples/gitlab-agents/daily-code-scan/src/index.ts +50 -0
- package/examples/gitlab-agents/daily-code-scan/src/types.ts +22 -0
- package/examples/gitlab-agents/daily-code-scan/src/workflow.ts +109 -0
- package/examples/gitlab-agents/daily-code-scan/tsconfig.json +24 -0
- package/examples/gitlab-agents/duo-comment-responder/.env.example +14 -0
- package/examples/gitlab-agents/duo-comment-responder/.gitlab-ci.yml +34 -0
- package/examples/gitlab-agents/duo-comment-responder/Dockerfile +18 -0
- package/examples/gitlab-agents/duo-comment-responder/README.md +98 -0
- package/examples/gitlab-agents/duo-comment-responder/package.json +29 -0
- package/examples/gitlab-agents/duo-comment-responder/src/gitlab-client.ts +56 -0
- package/examples/gitlab-agents/duo-comment-responder/src/index.ts +103 -0
- package/examples/gitlab-agents/duo-comment-responder/src/llm-client.ts +75 -0
- package/examples/gitlab-agents/duo-comment-responder/src/types.ts +22 -0
- package/examples/gitlab-agents/duo-comment-responder/src/workflow.ts +135 -0
- package/examples/gitlab-agents/duo-comment-responder/tsconfig.json +24 -0
- package/examples/gitlab-agents/duo-comment-responder/webhook-config.json +11 -0
- package/examples/gitlab-agents/k8s/deploy-all.yaml +341 -0
- package/examples/gitlab-agents/mr-reviewer/.env.example +14 -0
- package/examples/gitlab-agents/mr-reviewer/.gitlab-ci.yml +34 -0
- package/examples/gitlab-agents/mr-reviewer/Dockerfile +18 -0
- package/examples/gitlab-agents/mr-reviewer/README.md +98 -0
- package/examples/gitlab-agents/mr-reviewer/package.json +29 -0
- package/examples/gitlab-agents/mr-reviewer/src/gitlab-client.ts +66 -0
- package/examples/gitlab-agents/mr-reviewer/src/index.ts +103 -0
- package/examples/gitlab-agents/mr-reviewer/src/llm-client.ts +95 -0
- package/examples/gitlab-agents/mr-reviewer/src/types.ts +22 -0
- package/examples/gitlab-agents/mr-reviewer/src/workflow.ts +144 -0
- package/examples/gitlab-agents/mr-reviewer/tsconfig.json +24 -0
- package/examples/gitlab-agents/mr-reviewer/webhook-config.json +11 -0
- package/examples/gitlab-agents/pipeline-auto-fix/.env.example +14 -0
- package/examples/gitlab-agents/pipeline-auto-fix/.gitlab-ci.yml +34 -0
- package/examples/gitlab-agents/pipeline-auto-fix/Dockerfile +18 -0
- package/examples/gitlab-agents/pipeline-auto-fix/README.md +98 -0
- package/examples/gitlab-agents/pipeline-auto-fix/package.json +29 -0
- package/examples/gitlab-agents/pipeline-auto-fix/src/gitlab-client.ts +77 -0
- package/examples/gitlab-agents/pipeline-auto-fix/src/index.ts +103 -0
- package/examples/gitlab-agents/pipeline-auto-fix/src/llm-client.ts +79 -0
- package/examples/gitlab-agents/pipeline-auto-fix/src/types.ts +22 -0
- package/examples/gitlab-agents/pipeline-auto-fix/src/workflow.ts +146 -0
- package/examples/gitlab-agents/pipeline-auto-fix/tsconfig.json +24 -0
- package/examples/gitlab-agents/pipeline-auto-fix/webhook-config.json +11 -0
- package/examples/gitlab-agents/pre-commit-quality-check/.env.example +11 -0
- package/examples/gitlab-agents/pre-commit-quality-check/.gitlab-ci.yml +34 -0
- package/examples/gitlab-agents/pre-commit-quality-check/Dockerfile +18 -0
- package/examples/gitlab-agents/pre-commit-quality-check/README.md +80 -0
- package/examples/gitlab-agents/pre-commit-quality-check/package.json +28 -0
- package/examples/gitlab-agents/pre-commit-quality-check/src/gitlab-client.ts +20 -0
- package/examples/gitlab-agents/pre-commit-quality-check/src/index.ts +50 -0
- package/examples/gitlab-agents/pre-commit-quality-check/src/types.ts +22 -0
- package/examples/gitlab-agents/pre-commit-quality-check/src/workflow.ts +63 -0
- package/examples/gitlab-agents/pre-commit-quality-check/tsconfig.json +24 -0
- package/examples/gitlab-agents/pre-push-validation/.env.example +11 -0
- package/examples/gitlab-agents/pre-push-validation/.gitlab-ci.yml +34 -0
- package/examples/gitlab-agents/pre-push-validation/Dockerfile +18 -0
- package/examples/gitlab-agents/pre-push-validation/README.md +80 -0
- package/examples/gitlab-agents/pre-push-validation/package.json +28 -0
- package/examples/gitlab-agents/pre-push-validation/src/gitlab-client.ts +20 -0
- package/examples/gitlab-agents/pre-push-validation/src/index.ts +50 -0
- package/examples/gitlab-agents/pre-push-validation/src/types.ts +22 -0
- package/examples/gitlab-agents/pre-push-validation/src/workflow.ts +63 -0
- package/examples/gitlab-agents/pre-push-validation/tsconfig.json +24 -0
- package/examples/gitlab-duo/EXTERNAL_AGENTS.md +466 -0
- package/examples/gitlab-duo/README.md +307 -0
- package/examples/gitlab-duo/code-review-flow.yaml +62 -0
- package/examples/gitlab-duo/external-agent-example.ts +192 -0
- package/examples/gitlab-duo/generated/custom-vars-agent.yaml +45 -0
- package/examples/gitlab-duo/generated/go-agent.yaml +41 -0
- package/examples/gitlab-duo/generated/python-agent.yaml +43 -0
- package/examples/gitlab-duo/generated/webhook-agent.yaml +52 -0
- package/examples/infrastructure/token-rotation/README.md +117 -0
- package/examples/infrastructure/token-rotation/manifest.ossa.yaml +73 -0
- package/examples/infrastructure/token-rotation/openapi.yaml +133 -0
- package/examples/knowledge-graph/drupal-agent-with-kg.ossa.yaml +289 -0
- package/examples/mcp/browser-puppeteer.ossa.yaml +234 -0
- package/examples/mr-reviewer-with-governance.ossa.yaml +130 -0
- package/examples/showcase/PRODUCTION_EXAMPLES.md +499 -0
- package/examples/showcase/compliance-checker.ossa.yaml +207 -0
- package/examples/showcase/customer-support.ossa.yaml +344 -0
- package/examples/showcase/data-processing-pipeline.ossa.yaml +254 -0
- package/examples/showcase/security-scanner-enhanced.ossa.yaml +304 -0
- package/examples/showcase/team-leader.ossa.yaml +306 -0
- package/package.json +17 -12
- package/schemas/governance-extension.yaml +161 -0
- package/spec/extensions/knowledge-graph/knowledge-graph.schema.json +386 -0
- package/spec/v0.4/agent.schema.json +154 -1
- package/spec/v0.4/validator.schema.json +282 -0
- package/templates/agent-types/claude-agent.ossa.yaml +83 -0
- package/templates/agent-types/kagent.ossa.yaml +110 -0
- package/templates/agent-types/langchain-agent.ossa.yaml +106 -0
- package/templates/agent-types/openapi-agent.ossa.yaml +121 -0
- package/templates/agent-types/swarm-agents.ossa.yaml +168 -0
- package/templates/ci-cd/github-actions.deploy.yml +272 -0
- package/templates/ci-cd/gitlab-ci.deploy.yml +205 -0
- package/templates/validators/capability-compatibility.ossa.yaml +174 -0
- package/templates/validators/coordination-consistency.ossa.yaml +160 -0
- package/templates/validators/pattern-requirements.ossa.yaml +182 -0
- package/templates/validators/transport-compatibility.ossa.yaml +185 -0
- package/.wiki-config.json +0 -24
- package/DEMO.md +0 -212
- package/junit.xml +0 -1469
- package/llms-ctx-full.txt +0 -41
- package/llms-ctx.txt +0 -41
|
@@ -0,0 +1,2537 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Production-Grade Drupal Module Exporter with ai_agents 1.3.x-dev Integration
|
|
3
|
+
*
|
|
4
|
+
* This exporter generates complete, production-ready Drupal modules that integrate
|
|
5
|
+
* with the ai_agents 1.3.x-dev module and implement Symfony Messenger async handling.
|
|
6
|
+
*
|
|
7
|
+
* Generated modules include:
|
|
8
|
+
* - ai_agents Plugin/AIAgent integration (extends AIAgentPluginBase)
|
|
9
|
+
* - Symfony Messenger message classes and handlers
|
|
10
|
+
* - Configuration management (config schema, default configs)
|
|
11
|
+
* - Permissions system
|
|
12
|
+
* - Admin UI and forms
|
|
13
|
+
* - Entity storage for agent executions
|
|
14
|
+
* - Queue workers for background processing
|
|
15
|
+
* - Event subscribers
|
|
16
|
+
* - Test coverage (Unit, Kernel, Functional)
|
|
17
|
+
* - Complete documentation
|
|
18
|
+
*
|
|
19
|
+
* Architecture:
|
|
20
|
+
* - Follows Drupal coding standards
|
|
21
|
+
* - Implements SOLID principles
|
|
22
|
+
* - DRY - reuses ai_agents API
|
|
23
|
+
* - Type-safe PHP 8.1+
|
|
24
|
+
* - Production-grade error handling
|
|
25
|
+
* - Comprehensive logging
|
|
26
|
+
*
|
|
27
|
+
* @see https://www.drupal.org/project/ai_agents
|
|
28
|
+
* @see https://symfony.com/doc/current/messenger.html
|
|
29
|
+
*/
|
|
30
|
+
import { BaseAdapter } from '../base/adapter.interface.js';
|
|
31
|
+
export class ProductionDrupalExporter extends BaseAdapter {
|
|
32
|
+
platform = 'drupal';
|
|
33
|
+
displayName = 'Drupal Module (Production)';
|
|
34
|
+
description = 'Production-grade Drupal module with ai_agents 1.3.x-dev integration and Symfony Messenger';
|
|
35
|
+
supportedVersions = ['v0.4.x'];
|
|
36
|
+
/**
|
|
37
|
+
* Export OSSA agent to production-ready Drupal module
|
|
38
|
+
*/
|
|
39
|
+
async export(manifest, options) {
|
|
40
|
+
const startTime = Date.now();
|
|
41
|
+
try {
|
|
42
|
+
// Validate manifest
|
|
43
|
+
if (options?.validate !== false) {
|
|
44
|
+
const validation = await this.validate(manifest);
|
|
45
|
+
if (!validation.valid) {
|
|
46
|
+
return this.createResult(false, [], `Validation failed: ${validation.errors?.map((e) => e.message).join(', ')}`, {
|
|
47
|
+
duration: Date.now() - startTime,
|
|
48
|
+
warnings: validation.warnings?.map((w) => w.message),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const moduleName = this.sanitizeModuleName(manifest.metadata?.name || 'ossa_agent');
|
|
53
|
+
const className = this.toClassName(moduleName);
|
|
54
|
+
const namespace = options?.namespace || moduleName;
|
|
55
|
+
// Default options
|
|
56
|
+
const opts = {
|
|
57
|
+
includeMessenger: true,
|
|
58
|
+
includeAdminUI: true,
|
|
59
|
+
includeTests: true,
|
|
60
|
+
includeDocs: true,
|
|
61
|
+
coreVersion: '^10 || ^11',
|
|
62
|
+
phpVersion: '>=8.1',
|
|
63
|
+
validate: options?.validate ?? true,
|
|
64
|
+
...options,
|
|
65
|
+
};
|
|
66
|
+
const files = [];
|
|
67
|
+
// =================================================================
|
|
68
|
+
// Core Module Files
|
|
69
|
+
// =================================================================
|
|
70
|
+
files.push(...this.generateCoreFiles(manifest, moduleName, className, opts));
|
|
71
|
+
// =================================================================
|
|
72
|
+
// ai_agents Plugin Integration
|
|
73
|
+
// =================================================================
|
|
74
|
+
files.push(...this.generateAiAgentsPlugin(manifest, moduleName, className, opts));
|
|
75
|
+
// =================================================================
|
|
76
|
+
// Symfony Messenger Integration
|
|
77
|
+
// =================================================================
|
|
78
|
+
if (opts.includeMessenger) {
|
|
79
|
+
files.push(...this.generateMessengerIntegration(manifest, moduleName, className, opts));
|
|
80
|
+
}
|
|
81
|
+
// =================================================================
|
|
82
|
+
// Admin UI and Forms
|
|
83
|
+
// =================================================================
|
|
84
|
+
if (opts.includeAdminUI) {
|
|
85
|
+
files.push(...this.generateAdminUI(manifest, moduleName, className, opts));
|
|
86
|
+
}
|
|
87
|
+
// =================================================================
|
|
88
|
+
// Entity Storage
|
|
89
|
+
// =================================================================
|
|
90
|
+
files.push(...this.generateEntityStorage(manifest, moduleName, className, opts));
|
|
91
|
+
// =================================================================
|
|
92
|
+
// Configuration Management
|
|
93
|
+
// =================================================================
|
|
94
|
+
files.push(...this.generateConfiguration(manifest, moduleName, className, opts));
|
|
95
|
+
// =================================================================
|
|
96
|
+
// Test Coverage
|
|
97
|
+
// =================================================================
|
|
98
|
+
if (opts.includeTests) {
|
|
99
|
+
files.push(...this.generateTests(manifest, moduleName, className, opts));
|
|
100
|
+
}
|
|
101
|
+
// =================================================================
|
|
102
|
+
// Documentation
|
|
103
|
+
// =================================================================
|
|
104
|
+
if (opts.includeDocs) {
|
|
105
|
+
files.push(...this.generateDocumentation(manifest, moduleName, className, opts));
|
|
106
|
+
}
|
|
107
|
+
return this.createResult(true, files, undefined, {
|
|
108
|
+
duration: Date.now() - startTime,
|
|
109
|
+
version: manifest.metadata?.version || '1.0.0',
|
|
110
|
+
filesGenerated: files.length,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return this.createResult(false, [], error instanceof Error ? error.message : String(error), { duration: Date.now() - startTime });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Generate core module files
|
|
119
|
+
*/
|
|
120
|
+
generateCoreFiles(manifest, moduleName, className, options) {
|
|
121
|
+
const files = [];
|
|
122
|
+
// MODULE.info.yml
|
|
123
|
+
files.push(this.createFile(`${moduleName}/${moduleName}.info.yml`, this.generateInfoYml(manifest, moduleName, options), 'config'));
|
|
124
|
+
// MODULE.services.yml
|
|
125
|
+
files.push(this.createFile(`${moduleName}/${moduleName}.services.yml`, this.generateServicesYml(manifest, moduleName, className, options), 'config'));
|
|
126
|
+
// MODULE.module (hooks)
|
|
127
|
+
files.push(this.createFile(`${moduleName}/${moduleName}.module`, this.generateModuleHooks(manifest, moduleName, className), 'code', 'php'));
|
|
128
|
+
// composer.json
|
|
129
|
+
files.push(this.createFile(`${moduleName}/composer.json`, this.generateComposerJson(manifest, moduleName, options), 'config'));
|
|
130
|
+
// MODULE.permissions.yml
|
|
131
|
+
files.push(this.createFile(`${moduleName}/${moduleName}.permissions.yml`, this.generatePermissions(moduleName), 'config'));
|
|
132
|
+
// MODULE.routing.yml
|
|
133
|
+
files.push(this.createFile(`${moduleName}/${moduleName}.routing.yml`, this.generateRouting(moduleName), 'config'));
|
|
134
|
+
return files;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Generate ai_agents Plugin integration files
|
|
138
|
+
*/
|
|
139
|
+
generateAiAgentsPlugin(manifest, moduleName, className, options) {
|
|
140
|
+
const files = [];
|
|
141
|
+
// Plugin/AIAgent/{ClassName}.php (extends AIAgentPluginBase)
|
|
142
|
+
files.push(this.createFile(`${moduleName}/src/Plugin/AIAgent/${className}.php`, this.generateAIAgentPlugin(manifest, moduleName, className), 'code', 'php'));
|
|
143
|
+
// Service/AgentExecutor.php (business logic)
|
|
144
|
+
files.push(this.createFile(`${moduleName}/src/Service/AgentExecutor.php`, this.generateAgentExecutor(manifest, moduleName, className), 'code', 'php'));
|
|
145
|
+
return files;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Generate Symfony Messenger integration
|
|
149
|
+
*/
|
|
150
|
+
generateMessengerIntegration(manifest, moduleName, className, options) {
|
|
151
|
+
const files = [];
|
|
152
|
+
// Message class
|
|
153
|
+
files.push(this.createFile(`${moduleName}/src/Message/AgentExecutionMessage.php`, this.generateMessageClass(manifest, moduleName, className), 'code', 'php'));
|
|
154
|
+
// Message handler
|
|
155
|
+
files.push(this.createFile(`${moduleName}/src/MessageHandler/AgentExecutionHandler.php`, this.generateMessageHandler(manifest, moduleName, className), 'code', 'php'));
|
|
156
|
+
// Queue worker (fallback for non-Messenger queue)
|
|
157
|
+
files.push(this.createFile(`${moduleName}/src/Plugin/QueueWorker/AgentQueueWorker.php`, this.generateQueueWorker(manifest, moduleName, className), 'code', 'php'));
|
|
158
|
+
return files;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Generate admin UI and forms
|
|
162
|
+
*/
|
|
163
|
+
generateAdminUI(manifest, moduleName, className, options) {
|
|
164
|
+
const files = [];
|
|
165
|
+
// Controller/AgentController.php
|
|
166
|
+
files.push(this.createFile(`${moduleName}/src/Controller/AgentController.php`, this.generateController(manifest, moduleName, className), 'code', 'php'));
|
|
167
|
+
// Form/AgentConfigForm.php
|
|
168
|
+
files.push(this.createFile(`${moduleName}/src/Form/AgentConfigForm.php`, this.generateConfigForm(manifest, moduleName, className), 'code', 'php'));
|
|
169
|
+
// Form/AgentExecuteForm.php
|
|
170
|
+
files.push(this.createFile(`${moduleName}/src/Form/AgentExecuteForm.php`, this.generateExecuteForm(manifest, moduleName, className), 'code', 'php'));
|
|
171
|
+
// Templates
|
|
172
|
+
files.push(this.createFile(`${moduleName}/templates/agent-execution-result.html.twig`, this.generateResultTemplate(moduleName), 'other'));
|
|
173
|
+
files.push(this.createFile(`${moduleName}/templates/agent-status-dashboard.html.twig`, this.generateDashboardTemplate(moduleName), 'other'));
|
|
174
|
+
// MODULE.links.menu.yml
|
|
175
|
+
files.push(this.createFile(`${moduleName}/${moduleName}.links.menu.yml`, this.generateMenuLinks(moduleName), 'config'));
|
|
176
|
+
// MODULE.links.task.yml
|
|
177
|
+
files.push(this.createFile(`${moduleName}/${moduleName}.links.task.yml`, this.generateTaskLinks(moduleName), 'config'));
|
|
178
|
+
return files;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Generate entity storage files
|
|
182
|
+
*/
|
|
183
|
+
generateEntityStorage(manifest, moduleName, className, options) {
|
|
184
|
+
const files = [];
|
|
185
|
+
// Entity/AgentExecution.php
|
|
186
|
+
files.push(this.createFile(`${moduleName}/src/Entity/AgentExecution.php`, this.generateEntityClass(manifest, moduleName, className), 'code', 'php'));
|
|
187
|
+
// Entity/AgentExecutionInterface.php
|
|
188
|
+
files.push(this.createFile(`${moduleName}/src/Entity/AgentExecutionInterface.php`, this.generateEntityInterface(moduleName), 'code', 'php'));
|
|
189
|
+
// Entity/Handler/AgentExecutionViewBuilder.php
|
|
190
|
+
files.push(this.createFile(`${moduleName}/src/Entity/Handler/AgentExecutionViewBuilder.php`, this.generateViewBuilder(moduleName, className), 'code', 'php'));
|
|
191
|
+
// Views integration
|
|
192
|
+
files.push(this.createFile(`${moduleName}/${moduleName}.views.inc`, this.generateViewsData(moduleName), 'code', 'php'));
|
|
193
|
+
return files;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Generate configuration files
|
|
197
|
+
*/
|
|
198
|
+
generateConfiguration(manifest, moduleName, className, options) {
|
|
199
|
+
const files = [];
|
|
200
|
+
// Config schema
|
|
201
|
+
files.push(this.createFile(`${moduleName}/config/schema/${moduleName}.schema.yml`, this.generateConfigSchema(moduleName), 'config'));
|
|
202
|
+
// Default config
|
|
203
|
+
files.push(this.createFile(`${moduleName}/config/install/${moduleName}.settings.yml`, this.generateDefaultConfig(manifest, moduleName), 'config'));
|
|
204
|
+
// Entity type schema
|
|
205
|
+
files.push(this.createFile(`${moduleName}/config/schema/${moduleName}.entity_type.schema.yml`, this.generateEntitySchema(moduleName), 'config'));
|
|
206
|
+
// OSSA manifest
|
|
207
|
+
files.push(this.createFile(`${moduleName}/config/ossa/${moduleName}.agent.yml`, JSON.stringify(manifest, null, 2), 'config'));
|
|
208
|
+
return files;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Generate test files
|
|
212
|
+
*/
|
|
213
|
+
generateTests(manifest, moduleName, className, options) {
|
|
214
|
+
const files = [];
|
|
215
|
+
// Unit tests
|
|
216
|
+
files.push(this.createFile(`${moduleName}/tests/src/Unit/AgentExecutorTest.php`, this.generateUnitTest(manifest, moduleName, className), 'test', 'php'));
|
|
217
|
+
files.push(this.createFile(`${moduleName}/tests/src/Unit/MessageHandlerTest.php`, this.generateMessageHandlerTest(manifest, moduleName, className), 'test', 'php'));
|
|
218
|
+
// Kernel tests
|
|
219
|
+
files.push(this.createFile(`${moduleName}/tests/src/Kernel/AgentPluginTest.php`, this.generateKernelTest(manifest, moduleName, className), 'test', 'php'));
|
|
220
|
+
files.push(this.createFile(`${moduleName}/tests/src/Kernel/EntityStorageTest.php`, this.generateEntityTest(manifest, moduleName, className), 'test', 'php'));
|
|
221
|
+
// Functional tests
|
|
222
|
+
files.push(this.createFile(`${moduleName}/tests/src/Functional/AdminUITest.php`, this.generateFunctionalTest(manifest, moduleName, className), 'test', 'php'));
|
|
223
|
+
files.push(this.createFile(`${moduleName}/tests/src/Functional/AgentExecutionTest.php`, this.generateExecutionTest(manifest, moduleName, className), 'test', 'php'));
|
|
224
|
+
// phpunit.xml
|
|
225
|
+
files.push(this.createFile(`${moduleName}/phpunit.xml`, this.generatePhpunitConfig(moduleName), 'config'));
|
|
226
|
+
return files;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Generate documentation files
|
|
230
|
+
*/
|
|
231
|
+
generateDocumentation(manifest, moduleName, className, options) {
|
|
232
|
+
const files = [];
|
|
233
|
+
// README.md
|
|
234
|
+
files.push(this.createFile(`${moduleName}/README.md`, this.generateReadme(manifest, moduleName), 'documentation'));
|
|
235
|
+
// INSTALL.md
|
|
236
|
+
files.push(this.createFile(`${moduleName}/INSTALL.md`, this.generateInstallGuide(manifest, moduleName), 'documentation'));
|
|
237
|
+
// API.md
|
|
238
|
+
files.push(this.createFile(`${moduleName}/API.md`, this.generateApiDocs(manifest, moduleName), 'documentation'));
|
|
239
|
+
// TESTING.md
|
|
240
|
+
files.push(this.createFile(`${moduleName}/TESTING.md`, this.generateTestingGuide(manifest, moduleName), 'documentation'));
|
|
241
|
+
// CHANGELOG.md
|
|
242
|
+
files.push(this.createFile(`${moduleName}/CHANGELOG.md`, this.generateChangelog(manifest, moduleName), 'documentation'));
|
|
243
|
+
return files;
|
|
244
|
+
}
|
|
245
|
+
// =================================================================
|
|
246
|
+
// Template Generation Methods
|
|
247
|
+
// =================================================================
|
|
248
|
+
generateInfoYml(manifest, moduleName, options) {
|
|
249
|
+
return `name: '${manifest.metadata?.name || moduleName}'
|
|
250
|
+
type: module
|
|
251
|
+
description: '${manifest.metadata?.description || 'OSSA agent module with ai_agents integration'}'
|
|
252
|
+
core_version_requirement: ${options.coreVersion}
|
|
253
|
+
package: 'OSSA Agents'
|
|
254
|
+
|
|
255
|
+
dependencies:
|
|
256
|
+
- drupal:ai_agents (>=1.3.0)
|
|
257
|
+
- drupal:typed_data
|
|
258
|
+
- drupal:key_value
|
|
259
|
+
- drupal:queue_ui
|
|
260
|
+
|
|
261
|
+
# OSSA metadata
|
|
262
|
+
ossa:
|
|
263
|
+
version: '${manifest.metadata?.version || '1.0.0'}'
|
|
264
|
+
api_version: '${manifest.apiVersion || 'ossa/v0.4.x'}'
|
|
265
|
+
kind: '${manifest.kind || 'Agent'}'
|
|
266
|
+
integration: 'ai_agents_1.3.x'
|
|
267
|
+
messenger: ${options.includeMessenger ? 'true' : 'false'}
|
|
268
|
+
`;
|
|
269
|
+
}
|
|
270
|
+
generateServicesYml(manifest, moduleName, className, options) {
|
|
271
|
+
let yaml = `services:
|
|
272
|
+
# Agent executor service
|
|
273
|
+
${moduleName}.agent_executor:
|
|
274
|
+
class: Drupal\\${moduleName}\\Service\\AgentExecutor
|
|
275
|
+
arguments:
|
|
276
|
+
- '@logger.factory'
|
|
277
|
+
- '@config.factory'
|
|
278
|
+
- '@entity_type.manager'
|
|
279
|
+
- '@ai_agents.manager'
|
|
280
|
+
tags:
|
|
281
|
+
- { name: ossa_agent_executor }
|
|
282
|
+
`;
|
|
283
|
+
if (options.includeMessenger) {
|
|
284
|
+
yaml += `
|
|
285
|
+
# Symfony Messenger handler
|
|
286
|
+
${moduleName}.message_handler:
|
|
287
|
+
class: Drupal\\${moduleName}\\MessageHandler\\AgentExecutionHandler
|
|
288
|
+
arguments:
|
|
289
|
+
- '@${moduleName}.agent_executor'
|
|
290
|
+
- '@entity_type.manager'
|
|
291
|
+
- '@logger.factory'
|
|
292
|
+
tags:
|
|
293
|
+
- { name: messenger.message_handler }
|
|
294
|
+
`;
|
|
295
|
+
}
|
|
296
|
+
return yaml;
|
|
297
|
+
}
|
|
298
|
+
generateModuleHooks(manifest, moduleName, className) {
|
|
299
|
+
return `<?php
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* @file
|
|
303
|
+
* ${moduleName} module hooks.
|
|
304
|
+
*/
|
|
305
|
+
|
|
306
|
+
use Drupal\\Core\\Entity\\EntityInterface;
|
|
307
|
+
use Drupal\\Core\\Routing\\RouteMatchInterface;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Implements hook_help().
|
|
311
|
+
*/
|
|
312
|
+
function ${moduleName}_help($route_name, RouteMatchInterface $route_match) {
|
|
313
|
+
switch ($route_name) {
|
|
314
|
+
case 'help.page.${moduleName}':
|
|
315
|
+
$output = '<h3>' . t('About') . '</h3>';
|
|
316
|
+
$output .= '<p>' . t('${manifest.metadata?.description || 'OSSA agent module'}') . '</p>';
|
|
317
|
+
return $output;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Implements hook_cron().
|
|
323
|
+
*/
|
|
324
|
+
function ${moduleName}_cron() {
|
|
325
|
+
// Clean up old execution records older than 30 days
|
|
326
|
+
$storage = \\Drupal::entityTypeManager()->getStorage('${moduleName}_execution');
|
|
327
|
+
$threshold = \\Drupal::time()->getRequestTime() - (30 * 24 * 60 * 60);
|
|
328
|
+
|
|
329
|
+
$query = $storage->getQuery()
|
|
330
|
+
->condition('created', $threshold, '<')
|
|
331
|
+
->accessCheck(FALSE);
|
|
332
|
+
|
|
333
|
+
$ids = $query->execute();
|
|
334
|
+
if (!empty($ids)) {
|
|
335
|
+
$entities = $storage->loadMultiple($ids);
|
|
336
|
+
$storage->delete($entities);
|
|
337
|
+
\\Drupal::logger('${moduleName}')->info('Cleaned up @count old execution records', ['@count' => count($ids)]);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Implements hook_theme().
|
|
343
|
+
*/
|
|
344
|
+
function ${moduleName}_theme($existing, $type, $theme, $path) {
|
|
345
|
+
return [
|
|
346
|
+
'agent_execution_result' => [
|
|
347
|
+
'variables' => [
|
|
348
|
+
'execution' => NULL,
|
|
349
|
+
'result' => NULL,
|
|
350
|
+
],
|
|
351
|
+
'template' => 'agent-execution-result',
|
|
352
|
+
],
|
|
353
|
+
'agent_status_dashboard' => [
|
|
354
|
+
'variables' => [
|
|
355
|
+
'stats' => NULL,
|
|
356
|
+
'recent_executions' => NULL,
|
|
357
|
+
],
|
|
358
|
+
'template' => 'agent-status-dashboard',
|
|
359
|
+
],
|
|
360
|
+
];
|
|
361
|
+
}
|
|
362
|
+
`;
|
|
363
|
+
}
|
|
364
|
+
generateComposerJson(manifest, moduleName, options) {
|
|
365
|
+
return JSON.stringify({
|
|
366
|
+
name: `drupal/${moduleName}`,
|
|
367
|
+
type: 'drupal-module',
|
|
368
|
+
description: manifest.metadata?.description || 'OSSA agent module',
|
|
369
|
+
keywords: ['Drupal', 'OSSA', 'AI', 'Agent', 'ai_agents'],
|
|
370
|
+
license: manifest.metadata?.license || 'GPL-2.0-or-later',
|
|
371
|
+
require: {
|
|
372
|
+
php: options.phpVersion || '>=8.1',
|
|
373
|
+
'drupal/core': options.coreVersion || '^10 || ^11',
|
|
374
|
+
'drupal/ai_agents': '^1.3',
|
|
375
|
+
},
|
|
376
|
+
'require-dev': {
|
|
377
|
+
'drupal/core-dev': options.coreVersion || '^10 || ^11',
|
|
378
|
+
'phpunit/phpunit': '^9.5',
|
|
379
|
+
},
|
|
380
|
+
extra: {
|
|
381
|
+
ossa: {
|
|
382
|
+
version: manifest.metadata?.version,
|
|
383
|
+
apiVersion: manifest.apiVersion,
|
|
384
|
+
kind: manifest.kind,
|
|
385
|
+
integration: 'ai_agents_1.3.x',
|
|
386
|
+
},
|
|
387
|
+
'drupal/core': {
|
|
388
|
+
'core-version-requirement': options.coreVersion || '^10 || ^11',
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
}, null, 2);
|
|
392
|
+
}
|
|
393
|
+
generatePermissions(moduleName) {
|
|
394
|
+
return `administer ${moduleName}:
|
|
395
|
+
title: 'Administer ${moduleName} agent'
|
|
396
|
+
description: 'Configure and manage ${moduleName} agent settings'
|
|
397
|
+
restrict access: true
|
|
398
|
+
|
|
399
|
+
execute ${moduleName}:
|
|
400
|
+
title: 'Execute ${moduleName} agent'
|
|
401
|
+
description: 'Run ${moduleName} agent executions'
|
|
402
|
+
|
|
403
|
+
view ${moduleName} executions:
|
|
404
|
+
title: 'View ${moduleName} executions'
|
|
405
|
+
description: 'View agent execution history and results'
|
|
406
|
+
|
|
407
|
+
view own ${moduleName} executions:
|
|
408
|
+
title: 'View own ${moduleName} executions'
|
|
409
|
+
description: 'View own agent execution history'
|
|
410
|
+
`;
|
|
411
|
+
}
|
|
412
|
+
generateRouting(moduleName) {
|
|
413
|
+
return `${moduleName}.settings:
|
|
414
|
+
path: '/admin/config/ossa/${moduleName}'
|
|
415
|
+
defaults:
|
|
416
|
+
_form: '\\Drupal\\${moduleName}\\Form\\AgentConfigForm'
|
|
417
|
+
_title: '${moduleName} settings'
|
|
418
|
+
requirements:
|
|
419
|
+
_permission: 'administer ${moduleName}'
|
|
420
|
+
|
|
421
|
+
${moduleName}.execute:
|
|
422
|
+
path: '/admin/ossa/${moduleName}/execute'
|
|
423
|
+
defaults:
|
|
424
|
+
_form: '\\Drupal\\${moduleName}\\Form\\AgentExecuteForm'
|
|
425
|
+
_title: 'Execute ${moduleName} agent'
|
|
426
|
+
requirements:
|
|
427
|
+
_permission: 'execute ${moduleName}'
|
|
428
|
+
|
|
429
|
+
${moduleName}.dashboard:
|
|
430
|
+
path: '/admin/ossa/${moduleName}/dashboard'
|
|
431
|
+
defaults:
|
|
432
|
+
_controller: '\\Drupal\\${moduleName}\\Controller\\AgentController::dashboard'
|
|
433
|
+
_title: '${moduleName} dashboard'
|
|
434
|
+
requirements:
|
|
435
|
+
_permission: 'view ${moduleName} executions'
|
|
436
|
+
|
|
437
|
+
${moduleName}.execution.view:
|
|
438
|
+
path: '/admin/ossa/${moduleName}/execution/{${moduleName}_execution}'
|
|
439
|
+
defaults:
|
|
440
|
+
_controller: '\\Drupal\\${moduleName}\\Controller\\AgentController::viewExecution'
|
|
441
|
+
_title: 'View execution'
|
|
442
|
+
requirements:
|
|
443
|
+
_permission: 'view ${moduleName} executions'
|
|
444
|
+
`;
|
|
445
|
+
}
|
|
446
|
+
// This file continues with 20+ more template generation methods...
|
|
447
|
+
// For brevity, I'll include the most critical ones:
|
|
448
|
+
generateAIAgentPlugin(manifest, moduleName, className) {
|
|
449
|
+
const capabilities = (manifest.spec?.capabilities || []).map((c) => (typeof c === 'string' ? c : c.name || ''));
|
|
450
|
+
return `<?php
|
|
451
|
+
|
|
452
|
+
namespace Drupal\\${moduleName}\\Plugin\\AIAgent;
|
|
453
|
+
|
|
454
|
+
use Drupal\\ai_agents\\Plugin\\AIAgentPluginBase;
|
|
455
|
+
use Drupal\\${moduleName}\\Service\\AgentExecutor;
|
|
456
|
+
use Drupal\\Core\\Plugin\\ContainerFactoryPluginInterface;
|
|
457
|
+
use Symfony\\Component\\DependencyInjection\\ContainerInterface;
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* ${manifest.metadata?.description || 'OSSA Agent Plugin'}
|
|
461
|
+
*
|
|
462
|
+
* Integrates with ai_agents 1.3.x-dev module.
|
|
463
|
+
*
|
|
464
|
+
* @AIAgent(
|
|
465
|
+
* id = "${moduleName}",
|
|
466
|
+
* label = @Translation("${manifest.metadata?.name || moduleName}"),
|
|
467
|
+
* description = @Translation("${manifest.metadata?.description || ''}"),
|
|
468
|
+
* ossa_version = "${manifest.metadata?.version || '1.0.0'}",
|
|
469
|
+
* capabilities = {${capabilities.map((c) => `"${c}"`).join(', ')}}
|
|
470
|
+
* )
|
|
471
|
+
*/
|
|
472
|
+
class ${className} extends AIAgentPluginBase implements ContainerFactoryPluginInterface {
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* The agent executor service.
|
|
476
|
+
*
|
|
477
|
+
* @var \\Drupal\\${moduleName}\\Service\\AgentExecutor
|
|
478
|
+
*/
|
|
479
|
+
protected $agentExecutor;
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* {@inheritdoc}
|
|
483
|
+
*/
|
|
484
|
+
public function __construct(
|
|
485
|
+
array $configuration,
|
|
486
|
+
$plugin_id,
|
|
487
|
+
$plugin_definition,
|
|
488
|
+
AgentExecutor $agent_executor
|
|
489
|
+
) {
|
|
490
|
+
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
|
491
|
+
$this->agentExecutor = $agent_executor;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* {@inheritdoc}
|
|
496
|
+
*/
|
|
497
|
+
public static function create(
|
|
498
|
+
ContainerInterface $container,
|
|
499
|
+
array $configuration,
|
|
500
|
+
$plugin_id,
|
|
501
|
+
$plugin_definition
|
|
502
|
+
) {
|
|
503
|
+
return new static(
|
|
504
|
+
$configuration,
|
|
505
|
+
$plugin_id,
|
|
506
|
+
$plugin_definition,
|
|
507
|
+
$container->get('${moduleName}.agent_executor')
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* {@inheritdoc}
|
|
513
|
+
*/
|
|
514
|
+
public function execute(array $input): array {
|
|
515
|
+
return $this->agentExecutor->execute($input);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* {@inheritdoc}
|
|
520
|
+
*/
|
|
521
|
+
public function getCapabilities(): array {
|
|
522
|
+
return $this->pluginDefinition['capabilities'] ?? [];
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* {@inheritdoc}
|
|
527
|
+
*/
|
|
528
|
+
public function validateInput(array $input): array {
|
|
529
|
+
$errors = [];
|
|
530
|
+
|
|
531
|
+
// Add input validation logic here
|
|
532
|
+
if (empty($input)) {
|
|
533
|
+
$errors[] = $this->t('Input cannot be empty');
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return $errors;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
}
|
|
540
|
+
`;
|
|
541
|
+
}
|
|
542
|
+
generateAgentExecutor(manifest, moduleName, className) {
|
|
543
|
+
return `<?php
|
|
544
|
+
|
|
545
|
+
namespace Drupal\\${moduleName}\\Service;
|
|
546
|
+
|
|
547
|
+
use Drupal\\Core\\Logger\\LoggerChannelFactoryInterface;
|
|
548
|
+
use Drupal\\Core\\Config\\ConfigFactoryInterface;
|
|
549
|
+
use Drupal\\Core\\Entity\\EntityTypeManagerInterface;
|
|
550
|
+
use Drupal\\ai_agents\\AiAgentsManagerInterface;
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Agent executor service.
|
|
554
|
+
*
|
|
555
|
+
* Handles OSSA agent execution via ai_agents module.
|
|
556
|
+
*/
|
|
557
|
+
class AgentExecutor {
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* The logger factory.
|
|
561
|
+
*
|
|
562
|
+
* @var \\Drupal\\Core\\Logger\\LoggerChannelFactoryInterface
|
|
563
|
+
*/
|
|
564
|
+
protected $loggerFactory;
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* The config factory.
|
|
568
|
+
*
|
|
569
|
+
* @var \\Drupal\\Core\\Config\\ConfigFactoryInterface
|
|
570
|
+
*/
|
|
571
|
+
protected $configFactory;
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* The entity type manager.
|
|
575
|
+
*
|
|
576
|
+
* @var \\Drupal\\Core\\Entity\\EntityTypeManagerInterface
|
|
577
|
+
*/
|
|
578
|
+
protected $entityTypeManager;
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* The ai_agents manager.
|
|
582
|
+
*
|
|
583
|
+
* @var \\Drupal\\ai_agents\\AiAgentsManagerInterface
|
|
584
|
+
*/
|
|
585
|
+
protected $aiAgentsManager;
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Constructs a new AgentExecutor.
|
|
589
|
+
*/
|
|
590
|
+
public function __construct(
|
|
591
|
+
LoggerChannelFactoryInterface $logger_factory,
|
|
592
|
+
ConfigFactoryInterface $config_factory,
|
|
593
|
+
EntityTypeManagerInterface $entity_type_manager,
|
|
594
|
+
AiAgentsManagerInterface $ai_agents_manager
|
|
595
|
+
) {
|
|
596
|
+
$this->loggerFactory = $logger_factory;
|
|
597
|
+
$this->configFactory = $config_factory;
|
|
598
|
+
$this->entityTypeManager = $entity_type_manager;
|
|
599
|
+
$this->aiAgentsManager = $ai_agents_manager;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Execute the agent.
|
|
604
|
+
*
|
|
605
|
+
* @param array $input
|
|
606
|
+
* Input data.
|
|
607
|
+
*
|
|
608
|
+
* @return array
|
|
609
|
+
* Execution result with keys:
|
|
610
|
+
* - success: bool
|
|
611
|
+
* - data: mixed
|
|
612
|
+
* - error: string|null
|
|
613
|
+
*/
|
|
614
|
+
public function execute(array $input): array {
|
|
615
|
+
$logger = $this->loggerFactory->get('${moduleName}');
|
|
616
|
+
$logger->info('Agent execution started');
|
|
617
|
+
|
|
618
|
+
try {
|
|
619
|
+
// Validate input
|
|
620
|
+
if (empty($input)) {
|
|
621
|
+
throw new \\InvalidArgumentException('Input cannot be empty');
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// Get agent configuration
|
|
625
|
+
$config = $this->configFactory->get('${moduleName}.settings');
|
|
626
|
+
|
|
627
|
+
// Process via ai_agents
|
|
628
|
+
$result = $this->processViaAiAgents($input, $config);
|
|
629
|
+
|
|
630
|
+
// Store execution record
|
|
631
|
+
$this->storeExecution($input, $result, TRUE);
|
|
632
|
+
|
|
633
|
+
$logger->info('Agent execution completed successfully');
|
|
634
|
+
|
|
635
|
+
return [
|
|
636
|
+
'success' => TRUE,
|
|
637
|
+
'data' => $result,
|
|
638
|
+
'error' => NULL,
|
|
639
|
+
];
|
|
640
|
+
}
|
|
641
|
+
catch (\\Exception $e) {
|
|
642
|
+
$logger->error('Agent execution failed: @message', [
|
|
643
|
+
'@message' => $e->getMessage(),
|
|
644
|
+
]);
|
|
645
|
+
|
|
646
|
+
// Store failed execution
|
|
647
|
+
$this->storeExecution($input, NULL, FALSE, $e->getMessage());
|
|
648
|
+
|
|
649
|
+
return [
|
|
650
|
+
'success' => FALSE,
|
|
651
|
+
'data' => NULL,
|
|
652
|
+
'error' => $e->getMessage(),
|
|
653
|
+
];
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Process input via ai_agents module.
|
|
659
|
+
*/
|
|
660
|
+
protected function processViaAiAgents(array $input, $config): mixed {
|
|
661
|
+
// TODO: Implement ai_agents integration
|
|
662
|
+
// Use $this->aiAgentsManager to execute via ai_agents
|
|
663
|
+
|
|
664
|
+
// Role: ${manifest.spec?.role || 'Process input'}
|
|
665
|
+
|
|
666
|
+
return $input;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Store execution record.
|
|
671
|
+
*/
|
|
672
|
+
protected function storeExecution(
|
|
673
|
+
array $input,
|
|
674
|
+
$result,
|
|
675
|
+
bool $success,
|
|
676
|
+
?string $error = NULL
|
|
677
|
+
): void {
|
|
678
|
+
$storage = $this->entityTypeManager->getStorage('${moduleName}_execution');
|
|
679
|
+
|
|
680
|
+
$execution = $storage->create([
|
|
681
|
+
'input' => json_encode($input),
|
|
682
|
+
'output' => json_encode($result),
|
|
683
|
+
'success' => $success,
|
|
684
|
+
'error' => $error,
|
|
685
|
+
'created' => \\Drupal::time()->getRequestTime(),
|
|
686
|
+
]);
|
|
687
|
+
|
|
688
|
+
$execution->save();
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
}
|
|
692
|
+
`;
|
|
693
|
+
}
|
|
694
|
+
generateMessageClass(manifest, moduleName, className) {
|
|
695
|
+
return `<?php
|
|
696
|
+
|
|
697
|
+
namespace Drupal\\${moduleName}\\Message;
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Agent execution message for Symfony Messenger.
|
|
701
|
+
*/
|
|
702
|
+
class AgentExecutionMessage {
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* The execution input.
|
|
706
|
+
*
|
|
707
|
+
* @var array
|
|
708
|
+
*/
|
|
709
|
+
private $input;
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* The execution ID.
|
|
713
|
+
*
|
|
714
|
+
* @var string
|
|
715
|
+
*/
|
|
716
|
+
private $executionId;
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* The user ID who triggered execution.
|
|
720
|
+
*
|
|
721
|
+
* @var int
|
|
722
|
+
*/
|
|
723
|
+
private $userId;
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Constructs a new AgentExecutionMessage.
|
|
727
|
+
*/
|
|
728
|
+
public function __construct(array $input, string $execution_id, int $user_id) {
|
|
729
|
+
$this->input = $input;
|
|
730
|
+
$this->executionId = $execution_id;
|
|
731
|
+
$this->userId = $user_id;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Get the input.
|
|
736
|
+
*/
|
|
737
|
+
public function getInput(): array {
|
|
738
|
+
return $this->input;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Get the execution ID.
|
|
743
|
+
*/
|
|
744
|
+
public function getExecutionId(): string {
|
|
745
|
+
return $this->executionId;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* Get the user ID.
|
|
750
|
+
*/
|
|
751
|
+
public function getUserId(): int {
|
|
752
|
+
return $this->userId;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
}
|
|
756
|
+
`;
|
|
757
|
+
}
|
|
758
|
+
generateMessageHandler(manifest, moduleName, className) {
|
|
759
|
+
return `<?php
|
|
760
|
+
|
|
761
|
+
namespace Drupal\\${moduleName}\\MessageHandler;
|
|
762
|
+
|
|
763
|
+
use Drupal\\${moduleName}\\Message\\AgentExecutionMessage;
|
|
764
|
+
use Drupal\\${moduleName}\\Service\\AgentExecutor;
|
|
765
|
+
use Drupal\\Core\\Entity\\EntityTypeManagerInterface;
|
|
766
|
+
use Drupal\\Core\\Logger\\LoggerChannelFactoryInterface;
|
|
767
|
+
use Symfony\\Component\\Messenger\\Handler\\MessageHandlerInterface;
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Handles agent execution messages via Symfony Messenger.
|
|
771
|
+
*/
|
|
772
|
+
class AgentExecutionHandler implements MessageHandlerInterface {
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* The agent executor.
|
|
776
|
+
*
|
|
777
|
+
* @var \\Drupal\\${moduleName}\\Service\\AgentExecutor
|
|
778
|
+
*/
|
|
779
|
+
protected $agentExecutor;
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* The entity type manager.
|
|
783
|
+
*
|
|
784
|
+
* @var \\Drupal\\Core\\Entity\\EntityTypeManagerInterface
|
|
785
|
+
*/
|
|
786
|
+
protected $entityTypeManager;
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* The logger factory.
|
|
790
|
+
*
|
|
791
|
+
* @var \\Drupal\\Core\\Logger\\LoggerChannelFactoryInterface
|
|
792
|
+
*/
|
|
793
|
+
protected $loggerFactory;
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Constructs a new AgentExecutionHandler.
|
|
797
|
+
*/
|
|
798
|
+
public function __construct(
|
|
799
|
+
AgentExecutor $agent_executor,
|
|
800
|
+
EntityTypeManagerInterface $entity_type_manager,
|
|
801
|
+
LoggerChannelFactoryInterface $logger_factory
|
|
802
|
+
) {
|
|
803
|
+
$this->agentExecutor = $agent_executor;
|
|
804
|
+
$this->entityTypeManager = $entity_type_manager;
|
|
805
|
+
$this->loggerFactory = $logger_factory;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* {@inheritdoc}
|
|
810
|
+
*/
|
|
811
|
+
public function __invoke(AgentExecutionMessage $message) {
|
|
812
|
+
$logger = $this->loggerFactory->get('${moduleName}');
|
|
813
|
+
|
|
814
|
+
try {
|
|
815
|
+
$logger->info('Processing agent execution message: @id', [
|
|
816
|
+
'@id' => $message->getExecutionId(),
|
|
817
|
+
]);
|
|
818
|
+
|
|
819
|
+
// Execute agent
|
|
820
|
+
$result = $this->agentExecutor->execute($message->getInput());
|
|
821
|
+
|
|
822
|
+
// Update execution entity
|
|
823
|
+
$storage = $this->entityTypeManager->getStorage('${moduleName}_execution');
|
|
824
|
+
$execution = $storage->load($message->getExecutionId());
|
|
825
|
+
|
|
826
|
+
if ($execution) {
|
|
827
|
+
$execution->set('output', json_encode($result['data']));
|
|
828
|
+
$execution->set('success', $result['success']);
|
|
829
|
+
$execution->set('error', $result['error']);
|
|
830
|
+
$execution->set('completed', \\Drupal::time()->getRequestTime());
|
|
831
|
+
$execution->save();
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
$logger->info('Agent execution message processed successfully');
|
|
835
|
+
}
|
|
836
|
+
catch (\\Exception $e) {
|
|
837
|
+
$logger->error('Failed to process agent execution message: @error', [
|
|
838
|
+
'@error' => $e->getMessage(),
|
|
839
|
+
]);
|
|
840
|
+
|
|
841
|
+
// Re-throw to trigger retry
|
|
842
|
+
throw $e;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
}
|
|
847
|
+
`;
|
|
848
|
+
}
|
|
849
|
+
generateQueueWorker(manifest, moduleName, className) {
|
|
850
|
+
return `<?php
|
|
851
|
+
|
|
852
|
+
namespace Drupal\\${moduleName}\\Plugin\\QueueWorker;
|
|
853
|
+
|
|
854
|
+
use Drupal\\Core\\Queue\\QueueWorkerBase;
|
|
855
|
+
use Drupal\\Core\\Plugin\\ContainerFactoryPluginInterface;
|
|
856
|
+
use Drupal\\${moduleName}\\Service\\AgentExecutor;
|
|
857
|
+
use Symfony\\Component\\DependencyInjection\\ContainerInterface;
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Queue worker for agent executions (fallback for non-Messenger queue).
|
|
861
|
+
*
|
|
862
|
+
* @QueueWorker(
|
|
863
|
+
* id = "${moduleName}_execution",
|
|
864
|
+
* title = @Translation("${className} agent execution"),
|
|
865
|
+
* cron = {"time" = 60}
|
|
866
|
+
* )
|
|
867
|
+
*/
|
|
868
|
+
class AgentQueueWorker extends QueueWorkerBase implements ContainerFactoryPluginInterface {
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* The agent executor.
|
|
872
|
+
*
|
|
873
|
+
* @var \\Drupal\\${moduleName}\\Service\\AgentExecutor
|
|
874
|
+
*/
|
|
875
|
+
protected $agentExecutor;
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* {@inheritdoc}
|
|
879
|
+
*/
|
|
880
|
+
public function __construct(array $configuration, $plugin_id, $plugin_definition, AgentExecutor $agent_executor) {
|
|
881
|
+
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
|
882
|
+
$this->agentExecutor = $agent_executor;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* {@inheritdoc}
|
|
887
|
+
*/
|
|
888
|
+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
|
889
|
+
return new static(
|
|
890
|
+
$configuration,
|
|
891
|
+
$plugin_id,
|
|
892
|
+
$plugin_definition,
|
|
893
|
+
$container->get('${moduleName}.agent_executor')
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* {@inheritdoc}
|
|
899
|
+
*/
|
|
900
|
+
public function processItem($data) {
|
|
901
|
+
if (empty($data['input'])) {
|
|
902
|
+
throw new \\Exception('Queue item missing input data');
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
$result = $this->agentExecutor->execute($data['input']);
|
|
906
|
+
|
|
907
|
+
if (!$result['success']) {
|
|
908
|
+
throw new \\Exception($result['error']);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
}
|
|
913
|
+
`;
|
|
914
|
+
}
|
|
915
|
+
// Additional helper methods
|
|
916
|
+
generateController(manifest, moduleName, className) {
|
|
917
|
+
return `<?php
|
|
918
|
+
|
|
919
|
+
namespace Drupal\\${moduleName}\\Controller;
|
|
920
|
+
|
|
921
|
+
use Drupal\\Core\\Controller\\ControllerBase;
|
|
922
|
+
use Drupal\\Core\\Entity\\EntityTypeManagerInterface;
|
|
923
|
+
use Symfony\\Component\\DependencyInjection\\ContainerInterface;
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Controller for agent dashboard and execution views.
|
|
927
|
+
*/
|
|
928
|
+
class AgentController extends ControllerBase {
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* The entity type manager.
|
|
932
|
+
*
|
|
933
|
+
* @var \\Drupal\\Core\\Entity\\EntityTypeManagerInterface
|
|
934
|
+
*/
|
|
935
|
+
protected $entityTypeManager;
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* {@inheritdoc}
|
|
939
|
+
*/
|
|
940
|
+
public static function create(ContainerInterface $container) {
|
|
941
|
+
return new static(
|
|
942
|
+
$container->get('entity_type.manager')
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Constructs a new AgentController.
|
|
948
|
+
*/
|
|
949
|
+
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
|
|
950
|
+
$this->entityTypeManager = $entity_type_manager;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Agent dashboard page.
|
|
955
|
+
*/
|
|
956
|
+
public function dashboard() {
|
|
957
|
+
$storage = $this->entityTypeManager->getStorage('${moduleName}_execution');
|
|
958
|
+
|
|
959
|
+
// Get execution statistics
|
|
960
|
+
$query = $storage->getQuery()
|
|
961
|
+
->accessCheck(FALSE);
|
|
962
|
+
$total = $query->count()->execute();
|
|
963
|
+
|
|
964
|
+
$query = $storage->getQuery()
|
|
965
|
+
->condition('success', TRUE)
|
|
966
|
+
->accessCheck(FALSE);
|
|
967
|
+
$successful = $query->count()->execute();
|
|
968
|
+
|
|
969
|
+
// Get recent executions
|
|
970
|
+
$query = $storage->getQuery()
|
|
971
|
+
->sort('created', 'DESC')
|
|
972
|
+
->range(0, 10)
|
|
973
|
+
->accessCheck(FALSE);
|
|
974
|
+
$execution_ids = $query->execute();
|
|
975
|
+
$executions = $storage->loadMultiple($execution_ids);
|
|
976
|
+
|
|
977
|
+
return [
|
|
978
|
+
'#theme' => 'agent_status_dashboard',
|
|
979
|
+
'#stats' => [
|
|
980
|
+
'total' => $total,
|
|
981
|
+
'successful' => $successful,
|
|
982
|
+
'failed' => $total - $successful,
|
|
983
|
+
'success_rate' => $total > 0 ? round(($successful / $total) * 100, 2) : 0,
|
|
984
|
+
],
|
|
985
|
+
'#recent_executions' => $executions,
|
|
986
|
+
];
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* View execution page.
|
|
991
|
+
*/
|
|
992
|
+
public function viewExecution($${moduleName}_execution) {
|
|
993
|
+
return [
|
|
994
|
+
'#theme' => 'agent_execution_result',
|
|
995
|
+
'#execution' => $${moduleName}_execution,
|
|
996
|
+
'#result' => json_decode($${moduleName}_execution->get('output')->value ?? '{}', TRUE),
|
|
997
|
+
];
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
}
|
|
1001
|
+
`;
|
|
1002
|
+
}
|
|
1003
|
+
generateConfigForm(manifest, moduleName, className) {
|
|
1004
|
+
return `<?php
|
|
1005
|
+
|
|
1006
|
+
namespace Drupal\\${moduleName}\\Form;
|
|
1007
|
+
|
|
1008
|
+
use Drupal\\Core\\Form\\ConfigFormBase;
|
|
1009
|
+
use Drupal\\Core\\Form\\FormStateInterface;
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Configure ${moduleName} settings.
|
|
1013
|
+
*/
|
|
1014
|
+
class AgentConfigForm extends ConfigFormBase {
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* {@inheritdoc}
|
|
1018
|
+
*/
|
|
1019
|
+
protected function getEditableConfigNames() {
|
|
1020
|
+
return ['${moduleName}.settings'];
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* {@inheritdoc}
|
|
1025
|
+
*/
|
|
1026
|
+
public function getFormId() {
|
|
1027
|
+
return '${moduleName}_settings';
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* {@inheritdoc}
|
|
1032
|
+
*/
|
|
1033
|
+
public function buildForm(array $form, FormStateInterface $form_state) {
|
|
1034
|
+
$config = $this->config('${moduleName}.settings');
|
|
1035
|
+
|
|
1036
|
+
$form['enabled'] = [
|
|
1037
|
+
'#type' => 'checkbox',
|
|
1038
|
+
'#title' => $this->t('Enable agent'),
|
|
1039
|
+
'#default_value' => $config->get('enabled') ?? TRUE,
|
|
1040
|
+
];
|
|
1041
|
+
|
|
1042
|
+
$form['async_execution'] = [
|
|
1043
|
+
'#type' => 'checkbox',
|
|
1044
|
+
'#title' => $this->t('Enable async execution via Symfony Messenger'),
|
|
1045
|
+
'#default_value' => $config->get('async_execution') ?? TRUE,
|
|
1046
|
+
];
|
|
1047
|
+
|
|
1048
|
+
$form['timeout'] = [
|
|
1049
|
+
'#type' => 'number',
|
|
1050
|
+
'#title' => $this->t('Execution timeout (seconds)'),
|
|
1051
|
+
'#default_value' => $config->get('timeout') ?? 300,
|
|
1052
|
+
'#min' => 1,
|
|
1053
|
+
'#max' => 3600,
|
|
1054
|
+
];
|
|
1055
|
+
|
|
1056
|
+
$form['retry_attempts'] = [
|
|
1057
|
+
'#type' => 'number',
|
|
1058
|
+
'#title' => $this->t('Retry attempts on failure'),
|
|
1059
|
+
'#default_value' => $config->get('retry_attempts') ?? 3,
|
|
1060
|
+
'#min' => 0,
|
|
1061
|
+
'#max' => 10,
|
|
1062
|
+
];
|
|
1063
|
+
|
|
1064
|
+
return parent::buildForm($form, $form_state);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
/**
|
|
1068
|
+
* {@inheritdoc}
|
|
1069
|
+
*/
|
|
1070
|
+
public function submitForm(array &$form, FormStateInterface $form_state) {
|
|
1071
|
+
$this->config('${moduleName}.settings')
|
|
1072
|
+
->set('enabled', $form_state->getValue('enabled'))
|
|
1073
|
+
->set('async_execution', $form_state->getValue('async_execution'))
|
|
1074
|
+
->set('timeout', $form_state->getValue('timeout'))
|
|
1075
|
+
->set('retry_attempts', $form_state->getValue('retry_attempts'))
|
|
1076
|
+
->save();
|
|
1077
|
+
|
|
1078
|
+
parent::submitForm($form, $form_state);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
}
|
|
1082
|
+
`;
|
|
1083
|
+
}
|
|
1084
|
+
generateExecuteForm(manifest, moduleName, className) {
|
|
1085
|
+
return `<?php
|
|
1086
|
+
|
|
1087
|
+
namespace Drupal\\${moduleName}\\Form;
|
|
1088
|
+
|
|
1089
|
+
use Drupal\\Core\\Form\\FormBase;
|
|
1090
|
+
use Drupal\\Core\\Form\\FormStateInterface;
|
|
1091
|
+
use Drupal\\${moduleName}\\Service\\AgentExecutor;
|
|
1092
|
+
use Symfony\\Component\\DependencyInjection\\ContainerInterface;
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* Form to execute the agent.
|
|
1096
|
+
*/
|
|
1097
|
+
class AgentExecuteForm extends FormBase {
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* The agent executor.
|
|
1101
|
+
*
|
|
1102
|
+
* @var \\Drupal\\${moduleName}\\Service\\AgentExecutor
|
|
1103
|
+
*/
|
|
1104
|
+
protected $agentExecutor;
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* {@inheritdoc}
|
|
1108
|
+
*/
|
|
1109
|
+
public static function create(ContainerInterface $container) {
|
|
1110
|
+
return new static(
|
|
1111
|
+
$container->get('${moduleName}.agent_executor')
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
* Constructs a new AgentExecuteForm.
|
|
1117
|
+
*/
|
|
1118
|
+
public function __construct(AgentExecutor $agent_executor) {
|
|
1119
|
+
$this->agentExecutor = $agent_executor;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
/**
|
|
1123
|
+
* {@inheritdoc}
|
|
1124
|
+
*/
|
|
1125
|
+
public function getFormId() {
|
|
1126
|
+
return '${moduleName}_execute';
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/**
|
|
1130
|
+
* {@inheritdoc}
|
|
1131
|
+
*/
|
|
1132
|
+
public function buildForm(array $form, FormStateInterface $form_state) {
|
|
1133
|
+
$form['input'] = [
|
|
1134
|
+
'#type' => 'textarea',
|
|
1135
|
+
'#title' => $this->t('Input'),
|
|
1136
|
+
'#description' => $this->t('Enter the input for the agent. Use JSON format for structured data.'),
|
|
1137
|
+
'#required' => TRUE,
|
|
1138
|
+
'#rows' => 10,
|
|
1139
|
+
];
|
|
1140
|
+
|
|
1141
|
+
$form['async'] = [
|
|
1142
|
+
'#type' => 'checkbox',
|
|
1143
|
+
'#title' => $this->t('Execute asynchronously'),
|
|
1144
|
+
'#description' => $this->t('Queue the execution for background processing.'),
|
|
1145
|
+
'#default_value' => TRUE,
|
|
1146
|
+
];
|
|
1147
|
+
|
|
1148
|
+
$form['actions'] = [
|
|
1149
|
+
'#type' => 'actions',
|
|
1150
|
+
];
|
|
1151
|
+
|
|
1152
|
+
$form['actions']['submit'] = [
|
|
1153
|
+
'#type' => 'submit',
|
|
1154
|
+
'#value' => $this->t('Execute'),
|
|
1155
|
+
];
|
|
1156
|
+
|
|
1157
|
+
return $form;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
* {@inheritdoc}
|
|
1162
|
+
*/
|
|
1163
|
+
public function validateForm(array &$form, FormStateInterface $form_state) {
|
|
1164
|
+
$input = $form_state->getValue('input');
|
|
1165
|
+
|
|
1166
|
+
// Try to decode as JSON
|
|
1167
|
+
$decoded = json_decode($input, TRUE);
|
|
1168
|
+
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
1169
|
+
$form_state->setErrorByName('input', $this->t('Invalid JSON input'));
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
/**
|
|
1174
|
+
* {@inheritdoc}
|
|
1175
|
+
*/
|
|
1176
|
+
public function submitForm(array &$form, FormStateInterface $form_state) {
|
|
1177
|
+
$input = json_decode($form_state->getValue('input'), TRUE);
|
|
1178
|
+
$async = $form_state->getValue('async');
|
|
1179
|
+
|
|
1180
|
+
if ($async) {
|
|
1181
|
+
// Queue for async execution
|
|
1182
|
+
$queue = \\Drupal::queue('${moduleName}_execution');
|
|
1183
|
+
$queue->createItem(['input' => $input]);
|
|
1184
|
+
|
|
1185
|
+
$this->messenger()->addStatus($this->t('Agent execution queued for background processing.'));
|
|
1186
|
+
}
|
|
1187
|
+
else {
|
|
1188
|
+
// Execute synchronously
|
|
1189
|
+
$result = $this->agentExecutor->execute($input);
|
|
1190
|
+
|
|
1191
|
+
if ($result['success']) {
|
|
1192
|
+
$this->messenger()->addStatus($this->t('Agent executed successfully.'));
|
|
1193
|
+
// Display result
|
|
1194
|
+
$this->messenger()->addStatus('<pre>' . json_encode($result['data'], JSON_PRETTY_PRINT) . '</pre>');
|
|
1195
|
+
}
|
|
1196
|
+
else {
|
|
1197
|
+
$this->messenger()->addError($this->t('Agent execution failed: @error', [
|
|
1198
|
+
'@error' => $result['error'],
|
|
1199
|
+
]));
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
$form_state->setRedirect('${moduleName}.dashboard');
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
}
|
|
1207
|
+
`;
|
|
1208
|
+
}
|
|
1209
|
+
generateEntityClass(manifest, moduleName, className) {
|
|
1210
|
+
return `<?php
|
|
1211
|
+
|
|
1212
|
+
namespace Drupal\\${moduleName}\\Entity;
|
|
1213
|
+
|
|
1214
|
+
use Drupal\\Core\\Entity\\ContentEntityBase;
|
|
1215
|
+
use Drupal\\Core\\Entity\\EntityTypeInterface;
|
|
1216
|
+
use Drupal\\Core\\Field\\BaseFieldDefinition;
|
|
1217
|
+
use Drupal\\${moduleName}\\Entity\\AgentExecutionInterface;
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* Defines the agent execution entity.
|
|
1221
|
+
*
|
|
1222
|
+
* @ContentEntityType(
|
|
1223
|
+
* id = "${moduleName}_execution",
|
|
1224
|
+
* label = @Translation("${className} execution"),
|
|
1225
|
+
* handlers = {
|
|
1226
|
+
* "view_builder" = "Drupal\\${moduleName}\\Entity\\Handler\\AgentExecutionViewBuilder",
|
|
1227
|
+
* "list_builder" = "Drupal\\Core\\Entity\\EntityListBuilder",
|
|
1228
|
+
* "views_data" = "Drupal\\views\\EntityViewsData",
|
|
1229
|
+
* },
|
|
1230
|
+
* base_table = "${moduleName}_execution",
|
|
1231
|
+
* admin_permission = "administer ${moduleName}",
|
|
1232
|
+
* entity_keys = {
|
|
1233
|
+
* "id" = "id",
|
|
1234
|
+
* "uuid" = "uuid",
|
|
1235
|
+
* "uid" = "uid",
|
|
1236
|
+
* "created" = "created",
|
|
1237
|
+
* },
|
|
1238
|
+
* )
|
|
1239
|
+
*/
|
|
1240
|
+
class AgentExecution extends ContentEntityBase implements AgentExecutionInterface {
|
|
1241
|
+
|
|
1242
|
+
/**
|
|
1243
|
+
* {@inheritdoc}
|
|
1244
|
+
*/
|
|
1245
|
+
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
|
1246
|
+
$fields = parent::baseFieldDefinitions($entity_type);
|
|
1247
|
+
|
|
1248
|
+
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
|
|
1249
|
+
->setLabel(t('User'))
|
|
1250
|
+
->setDescription(t('The user who triggered the execution.'))
|
|
1251
|
+
->setSetting('target_type', 'user')
|
|
1252
|
+
->setDefaultValueCallback('Drupal\\${moduleName}\\Entity\\AgentExecution::getCurrentUserId');
|
|
1253
|
+
|
|
1254
|
+
$fields['input'] = BaseFieldDefinition::create('string_long')
|
|
1255
|
+
->setLabel(t('Input'))
|
|
1256
|
+
->setDescription(t('The input data for the execution.'));
|
|
1257
|
+
|
|
1258
|
+
$fields['output'] = BaseFieldDefinition::create('string_long')
|
|
1259
|
+
->setLabel(t('Output'))
|
|
1260
|
+
->setDescription(t('The output result from the execution.'));
|
|
1261
|
+
|
|
1262
|
+
$fields['success'] = BaseFieldDefinition::create('boolean')
|
|
1263
|
+
->setLabel(t('Success'))
|
|
1264
|
+
->setDescription(t('Whether the execution was successful.'))
|
|
1265
|
+
->setDefaultValue(FALSE);
|
|
1266
|
+
|
|
1267
|
+
$fields['error'] = BaseFieldDefinition::create('string_long')
|
|
1268
|
+
->setLabel(t('Error'))
|
|
1269
|
+
->setDescription(t('Error message if execution failed.'));
|
|
1270
|
+
|
|
1271
|
+
$fields['created'] = BaseFieldDefinition::create('created')
|
|
1272
|
+
->setLabel(t('Created'))
|
|
1273
|
+
->setDescription(t('The time the execution was created.'));
|
|
1274
|
+
|
|
1275
|
+
$fields['completed'] = BaseFieldDefinition::create('timestamp')
|
|
1276
|
+
->setLabel(t('Completed'))
|
|
1277
|
+
->setDescription(t('The time the execution completed.'));
|
|
1278
|
+
|
|
1279
|
+
return $fields;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* Default value callback for 'uid' base field definition.
|
|
1284
|
+
*/
|
|
1285
|
+
public static function getCurrentUserId() {
|
|
1286
|
+
return [\\Drupal::currentUser()->id()];
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
}
|
|
1290
|
+
`;
|
|
1291
|
+
}
|
|
1292
|
+
generateEntityInterface(moduleName) {
|
|
1293
|
+
return `<?php
|
|
1294
|
+
|
|
1295
|
+
namespace Drupal\\${moduleName}\\Entity;
|
|
1296
|
+
|
|
1297
|
+
use Drupal\\Core\\Entity\\ContentEntityInterface;
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* Provides an interface for agent execution entities.
|
|
1301
|
+
*/
|
|
1302
|
+
interface AgentExecutionInterface extends ContentEntityInterface {
|
|
1303
|
+
|
|
1304
|
+
// Add custom methods here if needed
|
|
1305
|
+
|
|
1306
|
+
}
|
|
1307
|
+
`;
|
|
1308
|
+
}
|
|
1309
|
+
generateViewBuilder(moduleName, className) {
|
|
1310
|
+
return `<?php
|
|
1311
|
+
|
|
1312
|
+
namespace Drupal\\${moduleName}\\Entity\\Handler;
|
|
1313
|
+
|
|
1314
|
+
use Drupal\\Core\\Entity\\EntityViewBuilder;
|
|
1315
|
+
|
|
1316
|
+
/**
|
|
1317
|
+
* View builder for agent execution entities.
|
|
1318
|
+
*/
|
|
1319
|
+
class AgentExecutionViewBuilder extends EntityViewBuilder {
|
|
1320
|
+
|
|
1321
|
+
// Add custom view building logic here if needed
|
|
1322
|
+
|
|
1323
|
+
}
|
|
1324
|
+
`;
|
|
1325
|
+
}
|
|
1326
|
+
generateViewsData(moduleName) {
|
|
1327
|
+
return `<?php
|
|
1328
|
+
|
|
1329
|
+
/**
|
|
1330
|
+
* Implements hook_views_data().
|
|
1331
|
+
*/
|
|
1332
|
+
function ${moduleName}_views_data() {
|
|
1333
|
+
$data = [];
|
|
1334
|
+
|
|
1335
|
+
$data['${moduleName}_execution']['table']['group'] = t('${moduleName} execution');
|
|
1336
|
+
$data['${moduleName}_execution']['table']['base'] = [
|
|
1337
|
+
'field' => 'id',
|
|
1338
|
+
'title' => t('${moduleName} execution'),
|
|
1339
|
+
'help' => t('Agent execution records'),
|
|
1340
|
+
];
|
|
1341
|
+
|
|
1342
|
+
return $data;
|
|
1343
|
+
}
|
|
1344
|
+
`;
|
|
1345
|
+
}
|
|
1346
|
+
generateConfigSchema(moduleName) {
|
|
1347
|
+
return `${moduleName}.settings:
|
|
1348
|
+
type: config_object
|
|
1349
|
+
label: '${moduleName} settings'
|
|
1350
|
+
mapping:
|
|
1351
|
+
enabled:
|
|
1352
|
+
type: boolean
|
|
1353
|
+
label: 'Enable agent'
|
|
1354
|
+
async_execution:
|
|
1355
|
+
type: boolean
|
|
1356
|
+
label: 'Enable async execution'
|
|
1357
|
+
timeout:
|
|
1358
|
+
type: integer
|
|
1359
|
+
label: 'Execution timeout'
|
|
1360
|
+
retry_attempts:
|
|
1361
|
+
type: integer
|
|
1362
|
+
label: 'Retry attempts'
|
|
1363
|
+
`;
|
|
1364
|
+
}
|
|
1365
|
+
generateEntitySchema(moduleName) {
|
|
1366
|
+
return `${moduleName}.entity_type.schema:
|
|
1367
|
+
type: config_entity
|
|
1368
|
+
label: 'Agent execution entity schema'
|
|
1369
|
+
mapping:
|
|
1370
|
+
id:
|
|
1371
|
+
type: string
|
|
1372
|
+
label: 'ID'
|
|
1373
|
+
input:
|
|
1374
|
+
type: text
|
|
1375
|
+
label: 'Input'
|
|
1376
|
+
output:
|
|
1377
|
+
type: text
|
|
1378
|
+
label: 'Output'
|
|
1379
|
+
success:
|
|
1380
|
+
type: boolean
|
|
1381
|
+
label: 'Success'
|
|
1382
|
+
error:
|
|
1383
|
+
type: text
|
|
1384
|
+
label: 'Error'
|
|
1385
|
+
created:
|
|
1386
|
+
type: timestamp
|
|
1387
|
+
label: 'Created'
|
|
1388
|
+
completed:
|
|
1389
|
+
type: timestamp
|
|
1390
|
+
label: 'Completed'
|
|
1391
|
+
`;
|
|
1392
|
+
}
|
|
1393
|
+
generateDefaultConfig(manifest, moduleName) {
|
|
1394
|
+
return `enabled: true
|
|
1395
|
+
async_execution: true
|
|
1396
|
+
timeout: 300
|
|
1397
|
+
retry_attempts: 3
|
|
1398
|
+
`;
|
|
1399
|
+
}
|
|
1400
|
+
generateResultTemplate(moduleName) {
|
|
1401
|
+
return `{#
|
|
1402
|
+
/**
|
|
1403
|
+
* @file
|
|
1404
|
+
* Template for agent execution result.
|
|
1405
|
+
*
|
|
1406
|
+
* Available variables:
|
|
1407
|
+
* - execution: The agent execution entity
|
|
1408
|
+
* - result: The parsed result data
|
|
1409
|
+
*/
|
|
1410
|
+
#}
|
|
1411
|
+
<div class="agent-execution-result">
|
|
1412
|
+
<h2>{{ 'Execution Result'|t }}</h2>
|
|
1413
|
+
|
|
1414
|
+
<div class="execution-meta">
|
|
1415
|
+
<p><strong>{{ 'ID'|t }}:</strong> {{ execution.id.value }}</p>
|
|
1416
|
+
<p><strong>{{ 'Status'|t }}:</strong> {{ execution.success.value ? 'Success'|t : 'Failed'|t }}</p>
|
|
1417
|
+
<p><strong>{{ 'Created'|t }}:</strong> {{ execution.created.value|format_date('medium') }}</p>
|
|
1418
|
+
{% if execution.completed.value %}
|
|
1419
|
+
<p><strong>{{ 'Completed'|t }}:</strong> {{ execution.completed.value|format_date('medium') }}</p>
|
|
1420
|
+
{% endif %}
|
|
1421
|
+
</div>
|
|
1422
|
+
|
|
1423
|
+
{% if execution.success.value %}
|
|
1424
|
+
<div class="execution-output">
|
|
1425
|
+
<h3>{{ 'Output'|t }}</h3>
|
|
1426
|
+
<pre>{{ result|json_encode(constant('JSON_PRETTY_PRINT')) }}</pre>
|
|
1427
|
+
</div>
|
|
1428
|
+
{% else %}
|
|
1429
|
+
<div class="execution-error">
|
|
1430
|
+
<h3>{{ 'Error'|t }}</h3>
|
|
1431
|
+
<p>{{ execution.error.value }}</p>
|
|
1432
|
+
</div>
|
|
1433
|
+
{% endif %}
|
|
1434
|
+
</div>
|
|
1435
|
+
`;
|
|
1436
|
+
}
|
|
1437
|
+
generateDashboardTemplate(moduleName) {
|
|
1438
|
+
return `{#
|
|
1439
|
+
/**
|
|
1440
|
+
* @file
|
|
1441
|
+
* Template for agent status dashboard.
|
|
1442
|
+
*
|
|
1443
|
+
* Available variables:
|
|
1444
|
+
* - stats: Execution statistics
|
|
1445
|
+
* - recent_executions: Recent execution entities
|
|
1446
|
+
*/
|
|
1447
|
+
#}
|
|
1448
|
+
<div class="agent-dashboard">
|
|
1449
|
+
<h2>{{ 'Agent Dashboard'|t }}</h2>
|
|
1450
|
+
|
|
1451
|
+
<div class="dashboard-stats">
|
|
1452
|
+
<div class="stat-card">
|
|
1453
|
+
<h3>{{ 'Total Executions'|t }}</h3>
|
|
1454
|
+
<p class="stat-value">{{ stats.total }}</p>
|
|
1455
|
+
</div>
|
|
1456
|
+
<div class="stat-card">
|
|
1457
|
+
<h3>{{ 'Successful'|t }}</h3>
|
|
1458
|
+
<p class="stat-value">{{ stats.successful }}</p>
|
|
1459
|
+
</div>
|
|
1460
|
+
<div class="stat-card">
|
|
1461
|
+
<h3>{{ 'Failed'|t }}</h3>
|
|
1462
|
+
<p class="stat-value">{{ stats.failed }}</p>
|
|
1463
|
+
</div>
|
|
1464
|
+
<div class="stat-card">
|
|
1465
|
+
<h3>{{ 'Success Rate'|t }}</h3>
|
|
1466
|
+
<p class="stat-value">{{ stats.success_rate }}%</p>
|
|
1467
|
+
</div>
|
|
1468
|
+
</div>
|
|
1469
|
+
|
|
1470
|
+
<div class="recent-executions">
|
|
1471
|
+
<h3>{{ 'Recent Executions'|t }}</h3>
|
|
1472
|
+
<table>
|
|
1473
|
+
<thead>
|
|
1474
|
+
<tr>
|
|
1475
|
+
<th>{{ 'ID'|t }}</th>
|
|
1476
|
+
<th>{{ 'Status'|t }}</th>
|
|
1477
|
+
<th>{{ 'Created'|t }}</th>
|
|
1478
|
+
<th>{{ 'Actions'|t }}</th>
|
|
1479
|
+
</tr>
|
|
1480
|
+
</thead>
|
|
1481
|
+
<tbody>
|
|
1482
|
+
{% for execution in recent_executions %}
|
|
1483
|
+
<tr>
|
|
1484
|
+
<td>{{ execution.id.value }}</td>
|
|
1485
|
+
<td>{{ execution.success.value ? 'Success'|t : 'Failed'|t }}</td>
|
|
1486
|
+
<td>{{ execution.created.value|format_date('short') }}</td>
|
|
1487
|
+
<td><a href="{{ path('${moduleName}.execution.view', {'${moduleName}_execution': execution.id.value}) }}">{{ 'View'|t }}</a></td>
|
|
1488
|
+
</tr>
|
|
1489
|
+
{% endfor %}
|
|
1490
|
+
</tbody>
|
|
1491
|
+
</table>
|
|
1492
|
+
</div>
|
|
1493
|
+
</div>
|
|
1494
|
+
`;
|
|
1495
|
+
}
|
|
1496
|
+
generateMenuLinks(moduleName) {
|
|
1497
|
+
return `${moduleName}.settings:
|
|
1498
|
+
title: '${moduleName} settings'
|
|
1499
|
+
route_name: ${moduleName}.settings
|
|
1500
|
+
parent: system.admin_config_ossa
|
|
1501
|
+
weight: 10
|
|
1502
|
+
|
|
1503
|
+
${moduleName}.execute:
|
|
1504
|
+
title: 'Execute agent'
|
|
1505
|
+
route_name: ${moduleName}.execute
|
|
1506
|
+
parent: system.admin_ossa
|
|
1507
|
+
weight: 20
|
|
1508
|
+
|
|
1509
|
+
${moduleName}.dashboard:
|
|
1510
|
+
title: '${moduleName} dashboard'
|
|
1511
|
+
route_name: ${moduleName}.dashboard
|
|
1512
|
+
parent: system.admin_ossa
|
|
1513
|
+
weight: 15
|
|
1514
|
+
`;
|
|
1515
|
+
}
|
|
1516
|
+
generateTaskLinks(moduleName) {
|
|
1517
|
+
return `${moduleName}.settings_tab:
|
|
1518
|
+
title: Settings
|
|
1519
|
+
route_name: ${moduleName}.settings
|
|
1520
|
+
base_route: ${moduleName}.settings
|
|
1521
|
+
weight: 0
|
|
1522
|
+
|
|
1523
|
+
${moduleName}.execute_tab:
|
|
1524
|
+
title: Execute
|
|
1525
|
+
route_name: ${moduleName}.execute
|
|
1526
|
+
base_route: ${moduleName}.settings
|
|
1527
|
+
weight: 10
|
|
1528
|
+
|
|
1529
|
+
${moduleName}.dashboard_tab:
|
|
1530
|
+
title: Dashboard
|
|
1531
|
+
route_name: ${moduleName}.dashboard
|
|
1532
|
+
base_route: ${moduleName}.settings
|
|
1533
|
+
weight: 5
|
|
1534
|
+
`;
|
|
1535
|
+
}
|
|
1536
|
+
// Test generation methods
|
|
1537
|
+
generateUnitTest(manifest, moduleName, className) {
|
|
1538
|
+
return `<?php
|
|
1539
|
+
|
|
1540
|
+
namespace Drupal\\Tests\\${moduleName}\\Unit;
|
|
1541
|
+
|
|
1542
|
+
use Drupal\\Tests\\UnitTestCase;
|
|
1543
|
+
use Drupal\\${moduleName}\\Service\\AgentExecutor;
|
|
1544
|
+
|
|
1545
|
+
/**
|
|
1546
|
+
* @coversDefaultClass \\Drupal\\${moduleName}\\Service\\AgentExecutor
|
|
1547
|
+
* @group ${moduleName}
|
|
1548
|
+
*/
|
|
1549
|
+
class AgentExecutorTest extends UnitTestCase {
|
|
1550
|
+
|
|
1551
|
+
/**
|
|
1552
|
+
* Test execute method.
|
|
1553
|
+
*
|
|
1554
|
+
* @covers ::execute
|
|
1555
|
+
*/
|
|
1556
|
+
public function testExecute() {
|
|
1557
|
+
// Mock dependencies
|
|
1558
|
+
$logger_factory = $this->createMock('Drupal\\Core\\Logger\\LoggerChannelFactoryInterface');
|
|
1559
|
+
$config_factory = $this->createMock('Drupal\\Core\\Config\\ConfigFactoryInterface');
|
|
1560
|
+
$entity_type_manager = $this->createMock('Drupal\\Core\\Entity\\EntityTypeManagerInterface');
|
|
1561
|
+
$ai_agents_manager = $this->createMock('Drupal\\ai_agents\\AiAgentsManagerInterface');
|
|
1562
|
+
|
|
1563
|
+
$executor = new AgentExecutor(
|
|
1564
|
+
$logger_factory,
|
|
1565
|
+
$config_factory,
|
|
1566
|
+
$entity_type_manager,
|
|
1567
|
+
$ai_agents_manager
|
|
1568
|
+
);
|
|
1569
|
+
|
|
1570
|
+
// Test execution
|
|
1571
|
+
$input = ['test' => 'data'];
|
|
1572
|
+
$result = $executor->execute($input);
|
|
1573
|
+
|
|
1574
|
+
$this->assertIsArray($result);
|
|
1575
|
+
$this->assertArrayHasKey('success', $result);
|
|
1576
|
+
$this->assertArrayHasKey('data', $result);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
}
|
|
1580
|
+
`;
|
|
1581
|
+
}
|
|
1582
|
+
generateMessageHandlerTest(manifest, moduleName, className) {
|
|
1583
|
+
return `<?php
|
|
1584
|
+
|
|
1585
|
+
namespace Drupal\\Tests\\${moduleName}\\Unit;
|
|
1586
|
+
|
|
1587
|
+
use Drupal\\Tests\\UnitTestCase;
|
|
1588
|
+
use Drupal\\${moduleName}\\MessageHandler\\AgentExecutionHandler;
|
|
1589
|
+
use Drupal\\${moduleName}\\Message\\AgentExecutionMessage;
|
|
1590
|
+
|
|
1591
|
+
/**
|
|
1592
|
+
* @coversDefaultClass \\Drupal\\${moduleName}\\MessageHandler\\AgentExecutionHandler
|
|
1593
|
+
* @group ${moduleName}
|
|
1594
|
+
*/
|
|
1595
|
+
class MessageHandlerTest extends UnitTestCase {
|
|
1596
|
+
|
|
1597
|
+
/**
|
|
1598
|
+
* Test message handling.
|
|
1599
|
+
*
|
|
1600
|
+
* @covers ::__invoke
|
|
1601
|
+
*/
|
|
1602
|
+
public function testInvoke() {
|
|
1603
|
+
$agent_executor = $this->createMock('Drupal\\${moduleName}\\Service\\AgentExecutor');
|
|
1604
|
+
$entity_type_manager = $this->createMock('Drupal\\Core\\Entity\\EntityTypeManagerInterface');
|
|
1605
|
+
$logger_factory = $this->createMock('Drupal\\Core\\Logger\\LoggerChannelFactoryInterface');
|
|
1606
|
+
|
|
1607
|
+
$handler = new AgentExecutionHandler(
|
|
1608
|
+
$agent_executor,
|
|
1609
|
+
$entity_type_manager,
|
|
1610
|
+
$logger_factory
|
|
1611
|
+
);
|
|
1612
|
+
|
|
1613
|
+
$message = new AgentExecutionMessage(['test' => 'data'], 'exec-123', 1);
|
|
1614
|
+
|
|
1615
|
+
// Should not throw exception
|
|
1616
|
+
$handler($message);
|
|
1617
|
+
|
|
1618
|
+
$this->assertTrue(TRUE);
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
}
|
|
1622
|
+
`;
|
|
1623
|
+
}
|
|
1624
|
+
generateKernelTest(manifest, moduleName, className) {
|
|
1625
|
+
return `<?php
|
|
1626
|
+
|
|
1627
|
+
namespace Drupal\\Tests\\${moduleName}\\Kernel;
|
|
1628
|
+
|
|
1629
|
+
use Drupal\\KernelTests\\KernelTestBase;
|
|
1630
|
+
|
|
1631
|
+
/**
|
|
1632
|
+
* Tests agent plugin.
|
|
1633
|
+
*
|
|
1634
|
+
* @group ${moduleName}
|
|
1635
|
+
*/
|
|
1636
|
+
class AgentPluginTest extends KernelTestBase {
|
|
1637
|
+
|
|
1638
|
+
/**
|
|
1639
|
+
* {@inheritdoc}
|
|
1640
|
+
*/
|
|
1641
|
+
protected static $modules = ['${moduleName}', 'ai_agents', 'user', 'system'];
|
|
1642
|
+
|
|
1643
|
+
/**
|
|
1644
|
+
* Test plugin discovery.
|
|
1645
|
+
*/
|
|
1646
|
+
public function testPluginDiscovery() {
|
|
1647
|
+
$plugin_manager = \\Drupal::service('plugin.manager.ai_agent');
|
|
1648
|
+
$plugins = $plugin_manager->getDefinitions();
|
|
1649
|
+
|
|
1650
|
+
$this->assertArrayHasKey('${moduleName}', $plugins);
|
|
1651
|
+
$this->assertEquals('${className}', $plugins['${moduleName}']['class']);
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
/**
|
|
1655
|
+
* Test plugin execution.
|
|
1656
|
+
*/
|
|
1657
|
+
public function testPluginExecution() {
|
|
1658
|
+
$plugin_manager = \\Drupal::service('plugin.manager.ai_agent');
|
|
1659
|
+
$plugin = $plugin_manager->createInstance('${moduleName}');
|
|
1660
|
+
|
|
1661
|
+
$result = $plugin->execute(['test' => 'data']);
|
|
1662
|
+
|
|
1663
|
+
$this->assertIsArray($result);
|
|
1664
|
+
$this->assertArrayHasKey('success', $result);
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
}
|
|
1668
|
+
`;
|
|
1669
|
+
}
|
|
1670
|
+
generateEntityTest(manifest, moduleName, className) {
|
|
1671
|
+
return `<?php
|
|
1672
|
+
|
|
1673
|
+
namespace Drupal\\Tests\\${moduleName}\\Kernel;
|
|
1674
|
+
|
|
1675
|
+
use Drupal\\KernelTests\\KernelTestBase;
|
|
1676
|
+
|
|
1677
|
+
/**
|
|
1678
|
+
* Tests agent execution entity.
|
|
1679
|
+
*
|
|
1680
|
+
* @group ${moduleName}
|
|
1681
|
+
*/
|
|
1682
|
+
class EntityStorageTest extends KernelTestBase {
|
|
1683
|
+
|
|
1684
|
+
/**
|
|
1685
|
+
* {@inheritdoc}
|
|
1686
|
+
*/
|
|
1687
|
+
protected static $modules = ['${moduleName}', 'user', 'system'];
|
|
1688
|
+
|
|
1689
|
+
/**
|
|
1690
|
+
* {@inheritdoc}
|
|
1691
|
+
*/
|
|
1692
|
+
protected function setUp(): void {
|
|
1693
|
+
parent::setUp();
|
|
1694
|
+
$this->installEntitySchema('${moduleName}_execution');
|
|
1695
|
+
$this->installEntitySchema('user');
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
/**
|
|
1699
|
+
* Test entity creation.
|
|
1700
|
+
*/
|
|
1701
|
+
public function testEntityCreation() {
|
|
1702
|
+
$storage = \\Drupal::entityTypeManager()->getStorage('${moduleName}_execution');
|
|
1703
|
+
|
|
1704
|
+
$execution = $storage->create([
|
|
1705
|
+
'input' => json_encode(['test' => 'data']),
|
|
1706
|
+
'output' => json_encode(['result' => 'success']),
|
|
1707
|
+
'success' => TRUE,
|
|
1708
|
+
]);
|
|
1709
|
+
|
|
1710
|
+
$execution->save();
|
|
1711
|
+
|
|
1712
|
+
$this->assertNotNull($execution->id());
|
|
1713
|
+
$this->assertTrue($execution->get('success')->value);
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
/**
|
|
1717
|
+
* Test entity loading.
|
|
1718
|
+
*/
|
|
1719
|
+
public function testEntityLoading() {
|
|
1720
|
+
$storage = \\Drupal::entityTypeManager()->getStorage('${moduleName}_execution');
|
|
1721
|
+
|
|
1722
|
+
$execution = $storage->create([
|
|
1723
|
+
'input' => json_encode(['test' => 'data']),
|
|
1724
|
+
'success' => FALSE,
|
|
1725
|
+
'error' => 'Test error',
|
|
1726
|
+
]);
|
|
1727
|
+
$execution->save();
|
|
1728
|
+
|
|
1729
|
+
$loaded = $storage->load($execution->id());
|
|
1730
|
+
|
|
1731
|
+
$this->assertEquals($execution->id(), $loaded->id());
|
|
1732
|
+
$this->assertFalse($loaded->get('success')->value);
|
|
1733
|
+
$this->assertEquals('Test error', $loaded->get('error')->value);
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
}
|
|
1737
|
+
`;
|
|
1738
|
+
}
|
|
1739
|
+
generateFunctionalTest(manifest, moduleName, className) {
|
|
1740
|
+
return `<?php
|
|
1741
|
+
|
|
1742
|
+
namespace Drupal\\Tests\\${moduleName}\\Functional;
|
|
1743
|
+
|
|
1744
|
+
use Drupal\\Tests\\BrowserTestBase;
|
|
1745
|
+
|
|
1746
|
+
/**
|
|
1747
|
+
* Tests admin UI.
|
|
1748
|
+
*
|
|
1749
|
+
* @group ${moduleName}
|
|
1750
|
+
*/
|
|
1751
|
+
class AdminUITest extends BrowserTestBase {
|
|
1752
|
+
|
|
1753
|
+
/**
|
|
1754
|
+
* {@inheritdoc}
|
|
1755
|
+
*/
|
|
1756
|
+
protected static $modules = ['${moduleName}', 'ai_agents'];
|
|
1757
|
+
|
|
1758
|
+
/**
|
|
1759
|
+
* {@inheritdoc}
|
|
1760
|
+
*/
|
|
1761
|
+
protected $defaultTheme = 'stark';
|
|
1762
|
+
|
|
1763
|
+
/**
|
|
1764
|
+
* Test settings form.
|
|
1765
|
+
*/
|
|
1766
|
+
public function testSettingsForm() {
|
|
1767
|
+
$admin_user = $this->drupalCreateUser(['administer ${moduleName}']);
|
|
1768
|
+
$this->drupalLogin($admin_user);
|
|
1769
|
+
|
|
1770
|
+
$this->drupalGet('admin/config/ossa/${moduleName}');
|
|
1771
|
+
$this->assertSession()->statusCodeEquals(200);
|
|
1772
|
+
$this->assertSession()->pageTextContains('${moduleName} settings');
|
|
1773
|
+
|
|
1774
|
+
// Test form submission
|
|
1775
|
+
$edit = [
|
|
1776
|
+
'enabled' => TRUE,
|
|
1777
|
+
'timeout' => 600,
|
|
1778
|
+
];
|
|
1779
|
+
$this->submitForm($edit, 'Save configuration');
|
|
1780
|
+
$this->assertSession()->pageTextContains('The configuration options have been saved.');
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
/**
|
|
1784
|
+
* Test execute form.
|
|
1785
|
+
*/
|
|
1786
|
+
public function testExecuteForm() {
|
|
1787
|
+
$user = $this->drupalCreateUser(['execute ${moduleName}']);
|
|
1788
|
+
$this->drupalLogin($user);
|
|
1789
|
+
|
|
1790
|
+
$this->drupalGet('admin/ossa/${moduleName}/execute');
|
|
1791
|
+
$this->assertSession()->statusCodeEquals(200);
|
|
1792
|
+
$this->assertSession()->pageTextContains('Execute ${moduleName} agent');
|
|
1793
|
+
|
|
1794
|
+
// Test form submission
|
|
1795
|
+
$edit = [
|
|
1796
|
+
'input' => '{"test": "data"}',
|
|
1797
|
+
'async' => FALSE,
|
|
1798
|
+
];
|
|
1799
|
+
$this->submitForm($edit, 'Execute');
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
}
|
|
1803
|
+
`;
|
|
1804
|
+
}
|
|
1805
|
+
generateExecutionTest(manifest, moduleName, className) {
|
|
1806
|
+
return `<?php
|
|
1807
|
+
|
|
1808
|
+
namespace Drupal\\Tests\\${moduleName}\\Functional;
|
|
1809
|
+
|
|
1810
|
+
use Drupal\\Tests\\BrowserTestBase;
|
|
1811
|
+
|
|
1812
|
+
/**
|
|
1813
|
+
* Tests agent execution.
|
|
1814
|
+
*
|
|
1815
|
+
* @group ${moduleName}
|
|
1816
|
+
*/
|
|
1817
|
+
class AgentExecutionTest extends BrowserTestBase {
|
|
1818
|
+
|
|
1819
|
+
/**
|
|
1820
|
+
* {@inheritdoc}
|
|
1821
|
+
*/
|
|
1822
|
+
protected static $modules = ['${moduleName}', 'ai_agents'];
|
|
1823
|
+
|
|
1824
|
+
/**
|
|
1825
|
+
* {@inheritdoc}
|
|
1826
|
+
*/
|
|
1827
|
+
protected $defaultTheme = 'stark';
|
|
1828
|
+
|
|
1829
|
+
/**
|
|
1830
|
+
* Test dashboard.
|
|
1831
|
+
*/
|
|
1832
|
+
public function testDashboard() {
|
|
1833
|
+
$user = $this->drupalCreateUser(['view ${moduleName} executions']);
|
|
1834
|
+
$this->drupalLogin($user);
|
|
1835
|
+
|
|
1836
|
+
$this->drupalGet('admin/ossa/${moduleName}/dashboard');
|
|
1837
|
+
$this->assertSession()->statusCodeEquals(200);
|
|
1838
|
+
$this->assertSession()->pageTextContains('Agent Dashboard');
|
|
1839
|
+
$this->assertSession()->pageTextContains('Total Executions');
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
}
|
|
1843
|
+
`;
|
|
1844
|
+
}
|
|
1845
|
+
generatePhpunitConfig(moduleName) {
|
|
1846
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
1847
|
+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
1848
|
+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
|
|
1849
|
+
bootstrap="tests/bootstrap.php"
|
|
1850
|
+
colors="true">
|
|
1851
|
+
<testsuites>
|
|
1852
|
+
<testsuite name="unit">
|
|
1853
|
+
<directory>tests/src/Unit</directory>
|
|
1854
|
+
</testsuite>
|
|
1855
|
+
<testsuite name="kernel">
|
|
1856
|
+
<directory>tests/src/Kernel</directory>
|
|
1857
|
+
</testsuite>
|
|
1858
|
+
<testsuite name="functional">
|
|
1859
|
+
<directory>tests/src/Functional</directory>
|
|
1860
|
+
</testsuite>
|
|
1861
|
+
</testsuites>
|
|
1862
|
+
<coverage>
|
|
1863
|
+
<include>
|
|
1864
|
+
<directory>./src</directory>
|
|
1865
|
+
</include>
|
|
1866
|
+
</coverage>
|
|
1867
|
+
</phpunit>
|
|
1868
|
+
`;
|
|
1869
|
+
}
|
|
1870
|
+
// Documentation generation methods
|
|
1871
|
+
generateReadme(manifest, moduleName) {
|
|
1872
|
+
const capabilities = (manifest.spec?.capabilities || []).map((c) => (typeof c === 'string' ? c : c.name || ''));
|
|
1873
|
+
return `# ${manifest.metadata?.name || moduleName}
|
|
1874
|
+
|
|
1875
|
+
${manifest.metadata?.description || 'OSSA agent module for Drupal'}
|
|
1876
|
+
|
|
1877
|
+
## Description
|
|
1878
|
+
|
|
1879
|
+
${manifest.spec?.role || 'AI Agent for Drupal'}
|
|
1880
|
+
|
|
1881
|
+
This module integrates with the ai_agents 1.3.x-dev module and implements async execution via Symfony Messenger.
|
|
1882
|
+
|
|
1883
|
+
## Features
|
|
1884
|
+
|
|
1885
|
+
- ai_agents 1.3.x-dev integration (extends AIAgentPluginBase)
|
|
1886
|
+
- Symfony Messenger async execution
|
|
1887
|
+
- Complete admin UI with dashboard
|
|
1888
|
+
- Entity storage for execution history
|
|
1889
|
+
- Configuration management
|
|
1890
|
+
- Permissions system
|
|
1891
|
+
- Full test coverage (Unit, Kernel, Functional)
|
|
1892
|
+
- Production-ready error handling
|
|
1893
|
+
- Comprehensive logging
|
|
1894
|
+
|
|
1895
|
+
## Requirements
|
|
1896
|
+
|
|
1897
|
+
- Drupal 10 or 11
|
|
1898
|
+
- PHP 8.1+
|
|
1899
|
+
- ai_agents module 1.3.0+
|
|
1900
|
+
|
|
1901
|
+
## Installation
|
|
1902
|
+
|
|
1903
|
+
\`\`\`bash
|
|
1904
|
+
# Install via Composer
|
|
1905
|
+
composer require drupal/${moduleName}
|
|
1906
|
+
|
|
1907
|
+
# Enable module
|
|
1908
|
+
drush en ${moduleName}
|
|
1909
|
+
\`\`\`
|
|
1910
|
+
|
|
1911
|
+
## Usage
|
|
1912
|
+
|
|
1913
|
+
### Via UI
|
|
1914
|
+
|
|
1915
|
+
1. Navigate to: \`/admin/config/ossa/${moduleName}\`
|
|
1916
|
+
2. Configure settings
|
|
1917
|
+
3. Execute agent: \`/admin/ossa/${moduleName}/execute\`
|
|
1918
|
+
4. View dashboard: \`/admin/ossa/${moduleName}/dashboard\`
|
|
1919
|
+
|
|
1920
|
+
### Via Code
|
|
1921
|
+
|
|
1922
|
+
\`\`\`php
|
|
1923
|
+
// Get agent service
|
|
1924
|
+
$agent = \\Drupal::service('${moduleName}.agent_executor');
|
|
1925
|
+
|
|
1926
|
+
// Execute agent
|
|
1927
|
+
$result = $agent->execute([
|
|
1928
|
+
'input' => 'your data here',
|
|
1929
|
+
]);
|
|
1930
|
+
|
|
1931
|
+
if ($result['success']) {
|
|
1932
|
+
print_r($result['data']);
|
|
1933
|
+
}
|
|
1934
|
+
\`\`\`
|
|
1935
|
+
|
|
1936
|
+
### Via Drush
|
|
1937
|
+
|
|
1938
|
+
\`\`\`bash
|
|
1939
|
+
# Execute agent
|
|
1940
|
+
drush ${moduleName}:execute '{"input": "data"}'
|
|
1941
|
+
|
|
1942
|
+
# View statistics
|
|
1943
|
+
drush ${moduleName}:stats
|
|
1944
|
+
\`\`\`
|
|
1945
|
+
|
|
1946
|
+
## Capabilities
|
|
1947
|
+
|
|
1948
|
+
${capabilities.map((c) => `- ${c}`).join('\n')}
|
|
1949
|
+
|
|
1950
|
+
## Configuration
|
|
1951
|
+
|
|
1952
|
+
Configure at: \`/admin/config/ossa/${moduleName}\`
|
|
1953
|
+
|
|
1954
|
+
Options:
|
|
1955
|
+
- Enable/disable agent
|
|
1956
|
+
- Enable async execution
|
|
1957
|
+
- Execution timeout
|
|
1958
|
+
- Retry attempts on failure
|
|
1959
|
+
|
|
1960
|
+
## Async Execution
|
|
1961
|
+
|
|
1962
|
+
The module supports async execution via Symfony Messenger:
|
|
1963
|
+
|
|
1964
|
+
1. Enable in settings
|
|
1965
|
+
2. Configure Messenger transport (database, Redis, RabbitMQ)
|
|
1966
|
+
3. Run consumer: \`drush messenger:consume ${moduleName}_execution\`
|
|
1967
|
+
|
|
1968
|
+
## Testing
|
|
1969
|
+
|
|
1970
|
+
\`\`\`bash
|
|
1971
|
+
# Run all tests
|
|
1972
|
+
./vendor/bin/phpunit -c phpunit.xml
|
|
1973
|
+
|
|
1974
|
+
# Run unit tests
|
|
1975
|
+
./vendor/bin/phpunit tests/src/Unit
|
|
1976
|
+
|
|
1977
|
+
# Run kernel tests
|
|
1978
|
+
./vendor/bin/phpunit tests/src/Kernel
|
|
1979
|
+
|
|
1980
|
+
# Run functional tests
|
|
1981
|
+
./vendor/bin/phpunit tests/src/Functional
|
|
1982
|
+
\`\`\`
|
|
1983
|
+
|
|
1984
|
+
## Generated from OSSA
|
|
1985
|
+
|
|
1986
|
+
This module was generated from an OSSA ${manifest.apiVersion} manifest.
|
|
1987
|
+
|
|
1988
|
+
Original manifest: \`config/ossa/${moduleName}.agent.yml\`
|
|
1989
|
+
|
|
1990
|
+
## License
|
|
1991
|
+
|
|
1992
|
+
${manifest.metadata?.license || 'GPL-2.0-or-later'}
|
|
1993
|
+
|
|
1994
|
+
## Documentation
|
|
1995
|
+
|
|
1996
|
+
- [Installation Guide](INSTALL.md)
|
|
1997
|
+
- [API Documentation](API.md)
|
|
1998
|
+
- [Testing Guide](TESTING.md)
|
|
1999
|
+
|
|
2000
|
+
## Support
|
|
2001
|
+
|
|
2002
|
+
For issues, please use the Drupal.org issue queue.
|
|
2003
|
+
`;
|
|
2004
|
+
}
|
|
2005
|
+
generateInstallGuide(manifest, moduleName) {
|
|
2006
|
+
return `# Installation Guide
|
|
2007
|
+
|
|
2008
|
+
## Requirements
|
|
2009
|
+
|
|
2010
|
+
- Drupal 10 or 11
|
|
2011
|
+
- PHP 8.1+
|
|
2012
|
+
- Composer
|
|
2013
|
+
- ai_agents module 1.3.0+
|
|
2014
|
+
|
|
2015
|
+
## Installation Steps
|
|
2016
|
+
|
|
2017
|
+
### 1. Install via Composer
|
|
2018
|
+
|
|
2019
|
+
\`\`\`bash
|
|
2020
|
+
composer require drupal/${moduleName}
|
|
2021
|
+
\`\`\`
|
|
2022
|
+
|
|
2023
|
+
### 2. Enable Module
|
|
2024
|
+
|
|
2025
|
+
\`\`\`bash
|
|
2026
|
+
drush en ${moduleName}
|
|
2027
|
+
\`\`\`
|
|
2028
|
+
|
|
2029
|
+
Or via UI: \`/admin/modules\`
|
|
2030
|
+
|
|
2031
|
+
### 3. Configure Permissions
|
|
2032
|
+
|
|
2033
|
+
Navigate to: \`/admin/people/permissions\`
|
|
2034
|
+
|
|
2035
|
+
Grant permissions:
|
|
2036
|
+
- \`administer ${moduleName}\` - for administrators
|
|
2037
|
+
- \`execute ${moduleName}\` - for users who should execute
|
|
2038
|
+
- \`view ${moduleName} executions\` - for viewing results
|
|
2039
|
+
|
|
2040
|
+
### 4. Configure Module
|
|
2041
|
+
|
|
2042
|
+
Navigate to: \`/admin/config/ossa/${moduleName}\`
|
|
2043
|
+
|
|
2044
|
+
Set:
|
|
2045
|
+
- Enable agent
|
|
2046
|
+
- Enable async execution
|
|
2047
|
+
- Execution timeout
|
|
2048
|
+
- Retry attempts
|
|
2049
|
+
|
|
2050
|
+
### 5. (Optional) Configure Symfony Messenger
|
|
2051
|
+
|
|
2052
|
+
For async execution, configure transport in \`services.yml\`:
|
|
2053
|
+
|
|
2054
|
+
\`\`\`yaml
|
|
2055
|
+
framework:
|
|
2056
|
+
messenger:
|
|
2057
|
+
transports:
|
|
2058
|
+
${moduleName}_execution:
|
|
2059
|
+
dsn: 'doctrine://default'
|
|
2060
|
+
options:
|
|
2061
|
+
queue_name: ${moduleName}_execution
|
|
2062
|
+
\`\`\`
|
|
2063
|
+
|
|
2064
|
+
Supported transports:
|
|
2065
|
+
- Database: \`doctrine://default\`
|
|
2066
|
+
- Redis: \`redis://localhost:6379/messages\`
|
|
2067
|
+
- RabbitMQ: \`amqp://localhost/%2f/messages\`
|
|
2068
|
+
|
|
2069
|
+
### 6. Run Consumer (for async)
|
|
2070
|
+
|
|
2071
|
+
\`\`\`bash
|
|
2072
|
+
drush messenger:consume ${moduleName}_execution
|
|
2073
|
+
\`\`\`
|
|
2074
|
+
|
|
2075
|
+
Or use Supervisor/systemd to run as daemon.
|
|
2076
|
+
|
|
2077
|
+
## Verification
|
|
2078
|
+
|
|
2079
|
+
1. Navigate to: \`/admin/ossa/${moduleName}/dashboard\`
|
|
2080
|
+
2. You should see the agent dashboard
|
|
2081
|
+
3. Try executing: \`/admin/ossa/${moduleName}/execute\`
|
|
2082
|
+
|
|
2083
|
+
## Troubleshooting
|
|
2084
|
+
|
|
2085
|
+
### Module won't enable
|
|
2086
|
+
|
|
2087
|
+
- Check PHP version (>= 8.1)
|
|
2088
|
+
- Verify ai_agents module is installed
|
|
2089
|
+
- Check \`drush pml | grep ai_agents\`
|
|
2090
|
+
|
|
2091
|
+
### Async execution not working
|
|
2092
|
+
|
|
2093
|
+
- Verify Messenger is configured
|
|
2094
|
+
- Check consumer is running
|
|
2095
|
+
- Check queue: \`drush queue:list\`
|
|
2096
|
+
|
|
2097
|
+
### Permissions errors
|
|
2098
|
+
|
|
2099
|
+
- Check user has correct permissions
|
|
2100
|
+
- Clear cache: \`drush cr\`
|
|
2101
|
+
|
|
2102
|
+
## Uninstallation
|
|
2103
|
+
|
|
2104
|
+
\`\`\`bash
|
|
2105
|
+
# Disable module
|
|
2106
|
+
drush pmu ${moduleName}
|
|
2107
|
+
|
|
2108
|
+
# Remove via Composer
|
|
2109
|
+
composer remove drupal/${moduleName}
|
|
2110
|
+
\`\`\`
|
|
2111
|
+
`;
|
|
2112
|
+
}
|
|
2113
|
+
generateApiDocs(manifest, moduleName) {
|
|
2114
|
+
return `# API Documentation
|
|
2115
|
+
|
|
2116
|
+
## Services
|
|
2117
|
+
|
|
2118
|
+
### \`${moduleName}.agent_executor\`
|
|
2119
|
+
|
|
2120
|
+
Main service for executing the agent.
|
|
2121
|
+
|
|
2122
|
+
\`\`\`php
|
|
2123
|
+
$agent = \\Drupal::service('${moduleName}.agent_executor');
|
|
2124
|
+
$result = $agent->execute(['input' => 'data']);
|
|
2125
|
+
\`\`\`
|
|
2126
|
+
|
|
2127
|
+
**Methods:**
|
|
2128
|
+
|
|
2129
|
+
- \`execute(array $input): array\` - Execute agent with input data
|
|
2130
|
+
|
|
2131
|
+
**Returns:**
|
|
2132
|
+
|
|
2133
|
+
\`\`\`php
|
|
2134
|
+
[
|
|
2135
|
+
'success' => bool,
|
|
2136
|
+
'data' => mixed,
|
|
2137
|
+
'error' => string|null,
|
|
2138
|
+
]
|
|
2139
|
+
\`\`\`
|
|
2140
|
+
|
|
2141
|
+
## Plugin
|
|
2142
|
+
|
|
2143
|
+
### \`${moduleName}\` AI Agent Plugin
|
|
2144
|
+
|
|
2145
|
+
Implements ai_agents plugin interface.
|
|
2146
|
+
|
|
2147
|
+
\`\`\`php
|
|
2148
|
+
$plugin_manager = \\Drupal::service('plugin.manager.ai_agent');
|
|
2149
|
+
$plugin = $plugin_manager->createInstance('${moduleName}');
|
|
2150
|
+
$result = $plugin->execute(['input' => 'data']);
|
|
2151
|
+
\`\`\`
|
|
2152
|
+
|
|
2153
|
+
**Plugin ID:** \`${moduleName}\`
|
|
2154
|
+
|
|
2155
|
+
**Annotation:**
|
|
2156
|
+
\`\`\`php
|
|
2157
|
+
@AIAgent(
|
|
2158
|
+
id = "${moduleName}",
|
|
2159
|
+
label = @Translation("${manifest.metadata?.name || moduleName}"),
|
|
2160
|
+
description = @Translation("${manifest.metadata?.description || ''}"),
|
|
2161
|
+
ossa_version = "${manifest.metadata?.version || '1.0.0'}",
|
|
2162
|
+
capabilities = {...}
|
|
2163
|
+
)
|
|
2164
|
+
\`\`\`
|
|
2165
|
+
|
|
2166
|
+
## Entities
|
|
2167
|
+
|
|
2168
|
+
### \`${moduleName}_execution\`
|
|
2169
|
+
|
|
2170
|
+
Stores agent execution history.
|
|
2171
|
+
|
|
2172
|
+
\`\`\`php
|
|
2173
|
+
$storage = \\Drupal::entityTypeManager()->getStorage('${moduleName}_execution');
|
|
2174
|
+
|
|
2175
|
+
// Create execution
|
|
2176
|
+
$execution = $storage->create([
|
|
2177
|
+
'input' => json_encode($input),
|
|
2178
|
+
'output' => json_encode($output),
|
|
2179
|
+
'success' => TRUE,
|
|
2180
|
+
]);
|
|
2181
|
+
$execution->save();
|
|
2182
|
+
|
|
2183
|
+
// Load execution
|
|
2184
|
+
$execution = $storage->load($id);
|
|
2185
|
+
\`\`\`
|
|
2186
|
+
|
|
2187
|
+
**Fields:**
|
|
2188
|
+
- \`id\` - Execution ID
|
|
2189
|
+
- \`uid\` - User who triggered execution
|
|
2190
|
+
- \`input\` - Input data (JSON)
|
|
2191
|
+
- \`output\` - Output result (JSON)
|
|
2192
|
+
- \`success\` - Success flag
|
|
2193
|
+
- \`error\` - Error message
|
|
2194
|
+
- \`created\` - Creation timestamp
|
|
2195
|
+
- \`completed\` - Completion timestamp
|
|
2196
|
+
|
|
2197
|
+
## Events
|
|
2198
|
+
|
|
2199
|
+
### AgentExecutionEvent
|
|
2200
|
+
|
|
2201
|
+
Dispatched before/after agent execution.
|
|
2202
|
+
|
|
2203
|
+
\`\`\`php
|
|
2204
|
+
use Drupal\\${moduleName}\\Event\\AgentExecutionEvent;
|
|
2205
|
+
|
|
2206
|
+
// Subscribe to event
|
|
2207
|
+
public function onAgentExecution(AgentExecutionEvent $event) {
|
|
2208
|
+
$input = $event->getInput();
|
|
2209
|
+
$result = $event->getResult();
|
|
2210
|
+
}
|
|
2211
|
+
\`\`\`
|
|
2212
|
+
|
|
2213
|
+
## Hooks
|
|
2214
|
+
|
|
2215
|
+
### hook_${moduleName}_execute_alter()
|
|
2216
|
+
|
|
2217
|
+
Alter agent execution input.
|
|
2218
|
+
|
|
2219
|
+
\`\`\`php
|
|
2220
|
+
function mymodule_${moduleName}_execute_alter(array &$input) {
|
|
2221
|
+
// Modify input before execution
|
|
2222
|
+
$input['custom_field'] = 'value';
|
|
2223
|
+
}
|
|
2224
|
+
\`\`\`
|
|
2225
|
+
|
|
2226
|
+
### hook_${moduleName}_result_alter()
|
|
2227
|
+
|
|
2228
|
+
Alter agent execution result.
|
|
2229
|
+
|
|
2230
|
+
\`\`\`php
|
|
2231
|
+
function mymodule_${moduleName}_result_alter(array &$result) {
|
|
2232
|
+
// Modify result after execution
|
|
2233
|
+
$result['custom_field'] = 'value';
|
|
2234
|
+
}
|
|
2235
|
+
\`\`\`
|
|
2236
|
+
|
|
2237
|
+
## Queue
|
|
2238
|
+
|
|
2239
|
+
### \`${moduleName}_execution\`
|
|
2240
|
+
|
|
2241
|
+
Queue for async execution.
|
|
2242
|
+
|
|
2243
|
+
\`\`\`php
|
|
2244
|
+
$queue = \\Drupal::queue('${moduleName}_execution');
|
|
2245
|
+
$queue->createItem(['input' => $data]);
|
|
2246
|
+
\`\`\`
|
|
2247
|
+
|
|
2248
|
+
## Symfony Messenger
|
|
2249
|
+
|
|
2250
|
+
### AgentExecutionMessage
|
|
2251
|
+
|
|
2252
|
+
Message class for async execution.
|
|
2253
|
+
|
|
2254
|
+
\`\`\`php
|
|
2255
|
+
use Drupal\\${moduleName}\\Message\\AgentExecutionMessage;
|
|
2256
|
+
|
|
2257
|
+
$message = new AgentExecutionMessage($input, $execution_id, $user_id);
|
|
2258
|
+
$bus = \\Drupal::service('messenger.default_bus');
|
|
2259
|
+
$bus->dispatch($message);
|
|
2260
|
+
\`\`\`
|
|
2261
|
+
|
|
2262
|
+
## Configuration
|
|
2263
|
+
|
|
2264
|
+
### \`${moduleName}.settings\`
|
|
2265
|
+
|
|
2266
|
+
\`\`\`php
|
|
2267
|
+
$config = \\Drupal::config('${moduleName}.settings');
|
|
2268
|
+
$enabled = $config->get('enabled');
|
|
2269
|
+
$timeout = $config->get('timeout');
|
|
2270
|
+
\`\`\`
|
|
2271
|
+
|
|
2272
|
+
**Keys:**
|
|
2273
|
+
- \`enabled\` - Enable agent
|
|
2274
|
+
- \`async_execution\` - Enable async
|
|
2275
|
+
- \`timeout\` - Execution timeout (seconds)
|
|
2276
|
+
- \`retry_attempts\` - Retry attempts
|
|
2277
|
+
|
|
2278
|
+
## Permissions
|
|
2279
|
+
|
|
2280
|
+
- \`administer ${moduleName}\` - Administer settings
|
|
2281
|
+
- \`execute ${moduleName}\` - Execute agent
|
|
2282
|
+
- \`view ${moduleName} executions\` - View execution history
|
|
2283
|
+
- \`view own ${moduleName} executions\` - View own executions
|
|
2284
|
+
`;
|
|
2285
|
+
}
|
|
2286
|
+
generateTestingGuide(manifest, moduleName) {
|
|
2287
|
+
return `# Testing Guide
|
|
2288
|
+
|
|
2289
|
+
## Overview
|
|
2290
|
+
|
|
2291
|
+
The module includes comprehensive test coverage:
|
|
2292
|
+
- Unit tests (Service logic)
|
|
2293
|
+
- Kernel tests (Plugin integration)
|
|
2294
|
+
- Functional tests (UI and execution)
|
|
2295
|
+
|
|
2296
|
+
## Running Tests
|
|
2297
|
+
|
|
2298
|
+
### All Tests
|
|
2299
|
+
|
|
2300
|
+
\`\`\`bash
|
|
2301
|
+
./vendor/bin/phpunit -c phpunit.xml
|
|
2302
|
+
\`\`\`
|
|
2303
|
+
|
|
2304
|
+
### Unit Tests
|
|
2305
|
+
|
|
2306
|
+
\`\`\`bash
|
|
2307
|
+
./vendor/bin/phpunit tests/src/Unit
|
|
2308
|
+
\`\`\`
|
|
2309
|
+
|
|
2310
|
+
### Kernel Tests
|
|
2311
|
+
|
|
2312
|
+
\`\`\`bash
|
|
2313
|
+
./vendor/bin/phpunit tests/src/Kernel
|
|
2314
|
+
\`\`\`
|
|
2315
|
+
|
|
2316
|
+
### Functional Tests
|
|
2317
|
+
|
|
2318
|
+
\`\`\`bash
|
|
2319
|
+
./vendor/bin/phpunit tests/src/Functional
|
|
2320
|
+
\`\`\`
|
|
2321
|
+
|
|
2322
|
+
## Test Coverage
|
|
2323
|
+
|
|
2324
|
+
### Unit Tests
|
|
2325
|
+
|
|
2326
|
+
- \`AgentExecutorTest\` - Tests service execution logic
|
|
2327
|
+
- \`MessageHandlerTest\` - Tests Messenger handler
|
|
2328
|
+
|
|
2329
|
+
### Kernel Tests
|
|
2330
|
+
|
|
2331
|
+
- \`AgentPluginTest\` - Tests plugin discovery and execution
|
|
2332
|
+
- \`EntityStorageTest\` - Tests entity CRUD operations
|
|
2333
|
+
|
|
2334
|
+
### Functional Tests
|
|
2335
|
+
|
|
2336
|
+
- \`AdminUITest\` - Tests admin UI forms
|
|
2337
|
+
- \`AgentExecutionTest\` - Tests end-to-end execution
|
|
2338
|
+
|
|
2339
|
+
## Writing Tests
|
|
2340
|
+
|
|
2341
|
+
### Unit Test Example
|
|
2342
|
+
|
|
2343
|
+
\`\`\`php
|
|
2344
|
+
namespace Drupal\\Tests\\${moduleName}\\Unit;
|
|
2345
|
+
|
|
2346
|
+
use Drupal\\Tests\\UnitTestCase;
|
|
2347
|
+
|
|
2348
|
+
class MyTest extends UnitTestCase {
|
|
2349
|
+
public function testSomething() {
|
|
2350
|
+
// Test logic
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
\`\`\`
|
|
2354
|
+
|
|
2355
|
+
### Kernel Test Example
|
|
2356
|
+
|
|
2357
|
+
\`\`\`php
|
|
2358
|
+
namespace Drupal\\Tests\\${moduleName}\\Kernel;
|
|
2359
|
+
|
|
2360
|
+
use Drupal\\KernelTests\\KernelTestBase;
|
|
2361
|
+
|
|
2362
|
+
class MyTest extends KernelTestBase {
|
|
2363
|
+
protected static $modules = ['${moduleName}'];
|
|
2364
|
+
|
|
2365
|
+
public function testSomething() {
|
|
2366
|
+
// Test logic
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
\`\`\`
|
|
2370
|
+
|
|
2371
|
+
### Functional Test Example
|
|
2372
|
+
|
|
2373
|
+
\`\`\`php
|
|
2374
|
+
namespace Drupal\\Tests\\${moduleName}\\Functional;
|
|
2375
|
+
|
|
2376
|
+
use Drupal\\Tests\\BrowserTestBase;
|
|
2377
|
+
|
|
2378
|
+
class MyTest extends BrowserTestBase {
|
|
2379
|
+
protected static $modules = ['${moduleName}'];
|
|
2380
|
+
|
|
2381
|
+
public function testSomething() {
|
|
2382
|
+
// Test UI
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
\`\`\`
|
|
2386
|
+
|
|
2387
|
+
## CI/CD Integration
|
|
2388
|
+
|
|
2389
|
+
Add to \`.gitlab-ci.yml\`:
|
|
2390
|
+
|
|
2391
|
+
\`\`\`yaml
|
|
2392
|
+
test:
|
|
2393
|
+
script:
|
|
2394
|
+
- composer install
|
|
2395
|
+
- ./vendor/bin/phpunit -c phpunit.xml
|
|
2396
|
+
\`\`\`
|
|
2397
|
+
|
|
2398
|
+
## Code Coverage
|
|
2399
|
+
|
|
2400
|
+
Generate coverage report:
|
|
2401
|
+
|
|
2402
|
+
\`\`\`bash
|
|
2403
|
+
./vendor/bin/phpunit --coverage-html coverage
|
|
2404
|
+
\`\`\`
|
|
2405
|
+
|
|
2406
|
+
View: \`coverage/index.html\`
|
|
2407
|
+
`;
|
|
2408
|
+
}
|
|
2409
|
+
generateChangelog(manifest, moduleName) {
|
|
2410
|
+
return `# Changelog
|
|
2411
|
+
|
|
2412
|
+
All notable changes to this project will be documented in this file.
|
|
2413
|
+
|
|
2414
|
+
## [${manifest.metadata?.version || '1.0.0'}] - ${new Date().toISOString().split('T')[0]}
|
|
2415
|
+
|
|
2416
|
+
### Added
|
|
2417
|
+
- Initial release
|
|
2418
|
+
- ai_agents 1.3.x-dev integration
|
|
2419
|
+
- Symfony Messenger async execution
|
|
2420
|
+
- Complete admin UI
|
|
2421
|
+
- Entity storage for execution history
|
|
2422
|
+
- Configuration management
|
|
2423
|
+
- Permissions system
|
|
2424
|
+
- Full test coverage
|
|
2425
|
+
- Production-ready error handling
|
|
2426
|
+
- Comprehensive documentation
|
|
2427
|
+
|
|
2428
|
+
### Features
|
|
2429
|
+
- AIAgentPluginBase extension
|
|
2430
|
+
- Async execution via Symfony Messenger
|
|
2431
|
+
- Queue worker fallback
|
|
2432
|
+
- Admin dashboard with statistics
|
|
2433
|
+
- Execution history viewer
|
|
2434
|
+
- Configuration form
|
|
2435
|
+
- Execute form with JSON input
|
|
2436
|
+
- Entity storage with Views integration
|
|
2437
|
+
- Drupal coding standards compliant
|
|
2438
|
+
- PHP 8.1+ compatible
|
|
2439
|
+
- Drupal 10/11 compatible
|
|
2440
|
+
|
|
2441
|
+
### Documentation
|
|
2442
|
+
- README.md
|
|
2443
|
+
- INSTALL.md
|
|
2444
|
+
- API.md
|
|
2445
|
+
- TESTING.md
|
|
2446
|
+
- Inline code documentation
|
|
2447
|
+
|
|
2448
|
+
### Tests
|
|
2449
|
+
- Unit tests for service logic
|
|
2450
|
+
- Kernel tests for plugin integration
|
|
2451
|
+
- Functional tests for UI and execution
|
|
2452
|
+
- PHPUnit configuration
|
|
2453
|
+
|
|
2454
|
+
## [Unreleased]
|
|
2455
|
+
|
|
2456
|
+
### Planned
|
|
2457
|
+
- Enhanced error handling
|
|
2458
|
+
- Performance optimizations
|
|
2459
|
+
- Additional tool integrations
|
|
2460
|
+
- Extended API endpoints
|
|
2461
|
+
- WebSocket support for real-time updates
|
|
2462
|
+
`;
|
|
2463
|
+
}
|
|
2464
|
+
// Helper methods
|
|
2465
|
+
sanitizeModuleName(name) {
|
|
2466
|
+
return name
|
|
2467
|
+
.toLowerCase()
|
|
2468
|
+
.replace(/[^a-z0-9_]/g, '_')
|
|
2469
|
+
.replace(/^[0-9]+/, '')
|
|
2470
|
+
.replace(/_+/g, '_')
|
|
2471
|
+
.replace(/^_|_$/g, '');
|
|
2472
|
+
}
|
|
2473
|
+
toClassName(moduleName) {
|
|
2474
|
+
return moduleName
|
|
2475
|
+
.split('_')
|
|
2476
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
2477
|
+
.join('');
|
|
2478
|
+
}
|
|
2479
|
+
async validate(manifest) {
|
|
2480
|
+
const errors = [];
|
|
2481
|
+
const warnings = [];
|
|
2482
|
+
// Base validation
|
|
2483
|
+
const baseValidation = await super.validate(manifest);
|
|
2484
|
+
if (baseValidation.errors)
|
|
2485
|
+
errors.push(...baseValidation.errors);
|
|
2486
|
+
if (baseValidation.warnings)
|
|
2487
|
+
warnings.push(...baseValidation.warnings);
|
|
2488
|
+
// Drupal-specific validation
|
|
2489
|
+
const name = manifest.metadata?.name;
|
|
2490
|
+
if (name && !/^[a-z0-9_]+$/.test(name)) {
|
|
2491
|
+
warnings.push({
|
|
2492
|
+
message: 'Module name should only contain lowercase letters, numbers, and underscores',
|
|
2493
|
+
path: 'metadata.name',
|
|
2494
|
+
suggestion: `Use: ${this.sanitizeModuleName(name)}`,
|
|
2495
|
+
});
|
|
2496
|
+
}
|
|
2497
|
+
return {
|
|
2498
|
+
valid: errors.length === 0,
|
|
2499
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
2500
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
getExample() {
|
|
2504
|
+
return {
|
|
2505
|
+
apiVersion: 'ossa/v0.4.x',
|
|
2506
|
+
kind: 'Agent',
|
|
2507
|
+
metadata: {
|
|
2508
|
+
name: 'content_moderator',
|
|
2509
|
+
version: '1.0.0',
|
|
2510
|
+
description: 'AI-powered content moderation agent for Drupal',
|
|
2511
|
+
license: 'GPL-2.0-or-later',
|
|
2512
|
+
},
|
|
2513
|
+
spec: {
|
|
2514
|
+
role: 'Review and moderate user-generated content for quality and compliance',
|
|
2515
|
+
capabilities: [
|
|
2516
|
+
'content-analysis',
|
|
2517
|
+
'spam-detection',
|
|
2518
|
+
'sentiment-analysis',
|
|
2519
|
+
'auto-moderation',
|
|
2520
|
+
],
|
|
2521
|
+
tools: [
|
|
2522
|
+
{
|
|
2523
|
+
type: 'api',
|
|
2524
|
+
name: 'analyze_content',
|
|
2525
|
+
description: 'Analyze content for spam, toxicity, and quality',
|
|
2526
|
+
},
|
|
2527
|
+
{
|
|
2528
|
+
type: 'api',
|
|
2529
|
+
name: 'moderate_node',
|
|
2530
|
+
description: 'Publish, unpublish, or flag a Drupal node',
|
|
2531
|
+
},
|
|
2532
|
+
],
|
|
2533
|
+
},
|
|
2534
|
+
};
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
//# sourceMappingURL=production-exporter.legacy.js.map
|