@bluefly/openstandardagents 0.2.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/.env.example +41 -0
- package/.eslintrc.cjs +43 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +39 -0
- package/.github/dependabot.yml +58 -0
- package/.github/workflows/ci.yml +154 -0
- package/.github/workflows/codeql.yml +41 -0
- package/.github/workflows/dependabot-auto-merge.yml +28 -0
- package/.github/workflows/release.yml +103 -0
- package/.prettierignore +7 -0
- package/.prettierrc.json +10 -0
- package/.redocly.yaml +9 -0
- package/.releaserc.json +84 -0
- package/.releaserc.json.disabled +81 -0
- package/CHANGELOG.md +152 -0
- package/CONTRIBUTING.md +249 -0
- package/LICENSE +190 -0
- package/README.md +280 -0
- package/bin/ossa +8 -0
- package/bin/validate-ossa-0.2.2.ts +244 -0
- package/dist/di-container.d.ts +18 -0
- package/dist/di-container.d.ts.map +1 -0
- package/dist/di-container.js +43 -0
- package/dist/di-container.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/repositories/manifest.repository.d.ts +26 -0
- package/dist/repositories/manifest.repository.d.ts.map +1 -0
- package/dist/repositories/manifest.repository.js +90 -0
- package/dist/repositories/manifest.repository.js.map +1 -0
- package/dist/repositories/schema.repository.d.ts +30 -0
- package/dist/repositories/schema.repository.d.ts.map +1 -0
- package/dist/repositories/schema.repository.js +143 -0
- package/dist/repositories/schema.repository.js.map +1 -0
- package/dist/services/generation.service.d.ts +54 -0
- package/dist/services/generation.service.d.ts.map +1 -0
- package/dist/services/generation.service.js +298 -0
- package/dist/services/generation.service.js.map +1 -0
- package/dist/services/migration.service.d.ts +30 -0
- package/dist/services/migration.service.d.ts.map +1 -0
- package/dist/services/migration.service.js +231 -0
- package/dist/services/migration.service.js.map +1 -0
- package/dist/services/runtime/openai.adapter.d.ts +94 -0
- package/dist/services/runtime/openai.adapter.d.ts.map +1 -0
- package/dist/services/runtime/openai.adapter.js +209 -0
- package/dist/services/runtime/openai.adapter.js.map +1 -0
- package/dist/services/validation.service.d.ts +45 -0
- package/dist/services/validation.service.d.ts.map +1 -0
- package/dist/services/validation.service.js +362 -0
- package/dist/services/validation.service.js.map +1 -0
- package/dist/services/validators/anthropic.validator.d.ts +9 -0
- package/dist/services/validators/anthropic.validator.d.ts.map +1 -0
- package/dist/services/validators/anthropic.validator.js +105 -0
- package/dist/services/validators/anthropic.validator.js.map +1 -0
- package/dist/services/validators/autogen.validator.d.ts +9 -0
- package/dist/services/validators/autogen.validator.d.ts.map +1 -0
- package/dist/services/validators/autogen.validator.js +111 -0
- package/dist/services/validators/autogen.validator.js.map +1 -0
- package/dist/services/validators/crewai.validator.d.ts +9 -0
- package/dist/services/validators/crewai.validator.d.ts.map +1 -0
- package/dist/services/validators/crewai.validator.js +117 -0
- package/dist/services/validators/crewai.validator.js.map +1 -0
- package/dist/services/validators/cursor.validator.d.ts +9 -0
- package/dist/services/validators/cursor.validator.d.ts.map +1 -0
- package/dist/services/validators/cursor.validator.js +88 -0
- package/dist/services/validators/cursor.validator.js.map +1 -0
- package/dist/services/validators/index.d.ts +15 -0
- package/dist/services/validators/index.d.ts.map +1 -0
- package/dist/services/validators/index.js +15 -0
- package/dist/services/validators/index.js.map +1 -0
- package/dist/services/validators/langchain.validator.d.ts +9 -0
- package/dist/services/validators/langchain.validator.d.ts.map +1 -0
- package/dist/services/validators/langchain.validator.js +103 -0
- package/dist/services/validators/langchain.validator.js.map +1 -0
- package/dist/services/validators/langflow.validator.d.ts +9 -0
- package/dist/services/validators/langflow.validator.d.ts.map +1 -0
- package/dist/services/validators/langflow.validator.js +92 -0
- package/dist/services/validators/langflow.validator.js.map +1 -0
- package/dist/services/validators/langgraph.validator.d.ts +9 -0
- package/dist/services/validators/langgraph.validator.d.ts.map +1 -0
- package/dist/services/validators/langgraph.validator.js +123 -0
- package/dist/services/validators/langgraph.validator.js.map +1 -0
- package/dist/services/validators/llamaindex.validator.d.ts +9 -0
- package/dist/services/validators/llamaindex.validator.d.ts.map +1 -0
- package/dist/services/validators/llamaindex.validator.js +121 -0
- package/dist/services/validators/llamaindex.validator.js.map +1 -0
- package/dist/services/validators/openai.validator.d.ts +9 -0
- package/dist/services/validators/openai.validator.d.ts.map +1 -0
- package/dist/services/validators/openai.validator.js +126 -0
- package/dist/services/validators/openai.validator.js.map +1 -0
- package/dist/services/validators/vercel-ai.validator.d.ts +9 -0
- package/dist/services/validators/vercel-ai.validator.d.ts.map +1 -0
- package/dist/services/validators/vercel-ai.validator.js +99 -0
- package/dist/services/validators/vercel-ai.validator.js.map +1 -0
- package/dist/spec/v0.1.9/agent-autonomous-extensions.json +234 -0
- package/dist/spec/v0.1.9/ecosystem-compliance.json +235 -0
- package/dist/spec/v0.1.9/ossa-v0.1.9.schema.json +695 -0
- package/dist/spec/v0.1.9/ossa-v0.1.9.schema.json.backup +695 -0
- package/dist/spec/v0.1.9/reasoning-compliance.json +654 -0
- package/dist/spec/v0.2.2/kagent-enhancements.json +395 -0
- package/dist/spec/v0.2.2/ossa-0.2.2.schema.json +906 -0
- package/dist/spec/v0.2.2/ossa-0.2.2.yaml +448 -0
- package/dist/spec/v0.2.2/ossa-reasoning-compliance-1.0.schema.json +424 -0
- package/dist/spec/v0.2.3/CHANGELOG.md +176 -0
- package/dist/spec/v0.2.3/README.md +154 -0
- package/dist/spec/v0.2.3/migrations/v0.2.2-to-v0.2.3.md +343 -0
- package/dist/spec/v0.2.3/ossa-0.2.3.schema.json +1397 -0
- package/dist/spec/v0.2.3/ossa-0.2.3.yaml +448 -0
- package/dist/spec/v0.2.4-dev/CHANGELOG.md +403 -0
- package/dist/spec/v0.2.4-dev/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/dist/spec/v0.2.4-dev/ossa-0.2.4-dev.schema.json +1696 -0
- package/dist/spec/v0.2.4-dev/ossa-0.2.4-dev.yaml +581 -0
- package/dist/spec/v0.2.5-dev/CHANGELOG.md +171 -0
- package/dist/spec/v0.2.5-dev/examples/customer-support-graph.ossa.yaml +362 -0
- package/dist/spec/v0.2.5-dev/examples/parallel-processors.ossa.yaml +464 -0
- package/dist/spec/v0.2.5-dev/examples/research-team.ossa.yaml +440 -0
- package/dist/spec/v0.2.5-dev/migrations/v0.2.4-to-v0.2.5.md +317 -0
- package/dist/spec/v0.2.5-dev/ossa-0.2.5-dev.schema.json +1732 -0
- package/dist/spec/v0.2.5-dev/ossa-0.2.5-dev.yaml +409 -0
- package/dist/types/index.d.ts +178 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/openapi-extensions.d.ts +164 -0
- package/dist/types/openapi-extensions.d.ts.map +1 -0
- package/dist/types/openapi-extensions.js +6 -0
- package/dist/types/openapi-extensions.js.map +1 -0
- package/docs/OSSA-COMPLIANT-BADGE.md +248 -0
- package/docs/README.md +31 -0
- package/docs/VERSIONING.md +284 -0
- package/docs/agent-openapi-spec.yml +942 -0
- package/docs/getting-started.md +87 -0
- package/docs/migration/general-agent-schema.yml +255 -0
- package/docs/migration/migration-manifest.json +64 -0
- package/docs/openapi-extensions.md +930 -0
- package/docs/schemas/openapi-extensions.schema.json +486 -0
- package/examples/adk-integration/code-review-workflow.yml +136 -0
- package/examples/adk-integration/customer-support.yml +263 -0
- package/examples/adk-integration/data-pipeline.yml +173 -0
- package/examples/advanced/patterns/compliance-context-production.json +53 -0
- package/examples/advanced/patterns/model-router.ts +274 -0
- package/examples/advanced/patterns/smart-model-routing.ts +248 -0
- package/examples/advanced/workflows/hybrid-model-strategy.yaml +232 -0
- package/examples/agent-manifests/critics/critic-agent.yaml +149 -0
- package/examples/agent-manifests/governors/governor-agent.yaml +128 -0
- package/examples/agent-manifests/integrators/integrator-agent.yaml +103 -0
- package/examples/agent-manifests/judges/judge-agent.yaml +153 -0
- package/examples/agent-manifests/monitors/monitor-agent.yaml +122 -0
- package/examples/agent-manifests/orchestrators/orchestrator-agent.yaml +247 -0
- package/examples/agent-manifests/sample-compliant-agent.yaml +147 -0
- package/examples/agent-manifests/workers/worker-agent.yaml +82 -0
- package/examples/anthropic/claude-assistant.ossa.json +45 -0
- package/examples/architecture/model-configuration/ollama-integration.ts +110 -0
- package/examples/autogen/multi-agent.ossa.json +37 -0
- package/examples/bridge-configurations.yaml +346 -0
- package/examples/bridges/Dockerfile.production +87 -0
- package/examples/bridges/__pycache__/aiflow-bridge-enhanced.cpython-313.pyc +0 -0
- package/examples/bridges/__pycache__/aiflow-phoenix-tracing.cpython-313.pyc +0 -0
- package/examples/bridges/__pycache__/test_aiflow_integration.cpython-313.pyc +0 -0
- package/examples/bridges/aiflow-bridge-enhanced.py +462 -0
- package/examples/bridges/aiflow-bridge-example.yml +310 -0
- package/examples/bridges/aiflow-phoenix-tracing.py +310 -0
- package/examples/bridges/aiflow-registration-api.openapi.yml +439 -0
- package/examples/bridges/k8s/configmap.yaml +121 -0
- package/examples/bridges/k8s/deployment-simple.yaml +34 -0
- package/examples/bridges/k8s/deployment.yaml +275 -0
- package/examples/bridges/k8s/hpa.yaml +126 -0
- package/examples/bridges/k8s/ingress.yaml +155 -0
- package/examples/bridges/kagent-bridge-example.yml +94 -0
- package/examples/bridges/load-tests/Dockerfile +28 -0
- package/examples/bridges/load-tests/k6-load-test.js +302 -0
- package/examples/bridges/load-tests/requirements.txt +20 -0
- package/examples/bridges/loadtest/k6-scenarios.js +270 -0
- package/examples/bridges/phase4/SLO-SLA.yaml +249 -0
- package/examples/bridges/phase4/chaos-tests.yaml +226 -0
- package/examples/bridges/requirements.txt +24 -0
- package/examples/bridges/test_aiflow_integration.py +341 -0
- package/examples/common_npm/agent-router.ossa.yaml +182 -0
- package/examples/common_npm/agent-router.v0.2.2.ossa.yaml +60 -0
- package/examples/compliance-agent.yml +155 -0
- package/examples/crewai/research-team.ossa.json +36 -0
- package/examples/cursor/code-review-agent.ossa.json +47 -0
- package/examples/drupal/gitlab-ml-recommender.ossa.yaml +609 -0
- package/examples/drupal/gitlab-ml-recommender.v0.2.2.ossa.yaml +68 -0
- package/examples/enterprise/agent.yml +452 -0
- package/examples/extensions/drupal-v1.yml +266 -0
- package/examples/extensions/kagent-v1.yml +167 -0
- package/examples/getting-started/hello-world-complete.ossa.yaml +266 -0
- package/examples/integration-patterns/agent-to-agent-orchestration.ossa.yaml +376 -0
- package/examples/kagent/README.md +31 -0
- package/examples/kagent/compliance-validator.ossa.yaml +111 -0
- package/examples/kagent/cost-optimizer.ossa.yaml +93 -0
- package/examples/kagent/documentation-agent.ossa.yaml +91 -0
- package/examples/kagent/k8s-troubleshooter-v1.ossa.yaml +269 -0
- package/examples/kagent/k8s-troubleshooter-v1.v0.2.2.ossa.yaml +106 -0
- package/examples/kagent/k8s-troubleshooter.ossa.yaml +257 -0
- package/examples/kagent/security-scanner.ossa.yaml +140 -0
- package/examples/langchain/chain-agent.ossa.json +42 -0
- package/examples/langflow/workflow-agent.ossa.json +39 -0
- package/examples/langgraph/state-machine-agent.ossa.json +59 -0
- package/examples/llamaindex/rag-agent.ossa.json +41 -0
- package/examples/migration-guides/from-langchain-to-ossa.yaml +309 -0
- package/examples/minimal/agent.yml +152 -0
- package/examples/minimal/openapi.yaml +95 -0
- package/examples/openai/swarm-agent.ossa.json +59 -0
- package/examples/openapi-extensions/README.md +87 -0
- package/examples/openapi-extensions/minimal-agent-api.openapi.yml +288 -0
- package/examples/openapi-extensions/orchestrator-agent-api.openapi.yml +633 -0
- package/examples/openapi-extensions/worker-agent-api.openapi.yml +533 -0
- package/examples/production/agent.yml +713 -0
- package/examples/production/document-analyzer-openai.yml +134 -0
- package/examples/quickstart/support-agent.ossa.yaml +59 -0
- package/examples/service-registry-usage.ts +423 -0
- package/examples/spec-examples/audit-agent.yml +147 -0
- package/examples/spec-examples/chat-agent.yml +189 -0
- package/examples/spec-examples/compliance-agent.yml +204 -0
- package/examples/spec-examples/data-processing-agent.yml +132 -0
- package/examples/spec-examples/development-agent.yml +138 -0
- package/examples/spec-examples/edge-agent.yml +101 -0
- package/examples/spec-examples/integration-agent.yml +129 -0
- package/examples/spec-examples/monitoring-agent.yml +130 -0
- package/examples/spec-examples/serverless-agent.yml +82 -0
- package/examples/spec-examples/workflow-agent.yml +223 -0
- package/examples/templates/ossa-compliance.yaml +56 -0
- package/examples/typescript/advanced/demo-registry.ts +168 -0
- package/examples/typescript/mcpb-agent-example.ts +358 -0
- package/examples/vercel/edge-agent.ossa.json +43 -0
- package/infrastructure/docker-compose.yml +33 -0
- package/junit.xml +1 -0
- package/openapi/drupal-agent-api.openapi.yaml +348 -0
- package/openapi/gitlab-orchestrator.openapi.yaml +330 -0
- package/openapi/helm-generator.openapi.yaml +389 -0
- package/openapi/ossa-core-api.openapi.yaml +1448 -0
- package/openapi/ossa-registry-api.openapi.yaml +980 -0
- package/openapi/ossa-registry.openapi.yaml +782 -0
- package/openapi/self-evolving-ecosystem.openapi.yaml +1530 -0
- package/openapi/unified-agent-gateway.openapi.yaml +833 -0
- package/ossa-website-swarm-tasks.json +105 -0
- package/package.json +132 -0
- package/release.config.js +64 -0
- package/spec/v0.1.9/agent-autonomous-extensions.json +234 -0
- package/spec/v0.1.9/ecosystem-compliance.json +235 -0
- package/spec/v0.1.9/ossa-v0.1.9.schema.json +695 -0
- package/spec/v0.1.9/ossa-v0.1.9.schema.json.backup +695 -0
- package/spec/v0.1.9/reasoning-compliance.json +654 -0
- package/spec/v0.2.2/kagent-enhancements.json +395 -0
- package/spec/v0.2.2/ossa-0.2.2.schema.json +906 -0
- package/spec/v0.2.2/ossa-0.2.2.yaml +448 -0
- package/spec/v0.2.2/ossa-reasoning-compliance-1.0.schema.json +424 -0
- package/spec/v0.2.3/CHANGELOG.md +176 -0
- package/spec/v0.2.3/README.md +154 -0
- package/spec/v0.2.3/migrations/v0.2.2-to-v0.2.3.md +343 -0
- package/spec/v0.2.3/ossa-0.2.3.schema.json +1397 -0
- package/spec/v0.2.3/ossa-0.2.3.yaml +448 -0
- package/spec/v0.2.4-dev/CHANGELOG.md +403 -0
- package/spec/v0.2.4-dev/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/spec/v0.2.4-dev/ossa-0.2.4-dev.schema.json +1696 -0
- package/spec/v0.2.4-dev/ossa-0.2.4-dev.yaml +581 -0
- package/spec/v0.2.5-dev/CHANGELOG.md +171 -0
- package/spec/v0.2.5-dev/examples/customer-support-graph.ossa.yaml +362 -0
- package/spec/v0.2.5-dev/examples/parallel-processors.ossa.yaml +464 -0
- package/spec/v0.2.5-dev/examples/research-team.ossa.yaml +440 -0
- package/spec/v0.2.5-dev/migrations/v0.2.4-to-v0.2.5.md +317 -0
- package/spec/v0.2.5-dev/ossa-0.2.5-dev.schema.json +1732 -0
- package/spec/v0.2.5-dev/ossa-0.2.5-dev.yaml +409 -0
- package/test-results.xml +1 -0
- package/website/.lighthouserc.js +20 -0
- package/website/.prettierrc +10 -0
- package/website/Dockerfile +17 -0
- package/website/app/about/page.tsx +295 -0
- package/website/app/api/validate/route.ts +88 -0
- package/website/app/blog/[slug]/page.tsx +167 -0
- package/website/app/blog/page.tsx +162 -0
- package/website/app/docs/[[...slug]]/page.tsx +349 -0
- package/website/app/docs/core-concepts/project-structure/page.tsx +349 -0
- package/website/app/ecosystem/page.tsx +375 -0
- package/website/app/examples/page.tsx +123 -0
- package/website/app/globals.css +108 -0
- package/website/app/layout.tsx +106 -0
- package/website/app/page.tsx +409 -0
- package/website/app/playground/page.tsx +507 -0
- package/website/app/robots.ts +19 -0
- package/website/app/rss.xml/route.ts +74 -0
- package/website/app/schema/page.tsx +970 -0
- package/website/app/sitemap.ts +56 -0
- package/website/app/specification/page.tsx +211 -0
- package/website/components/InstallCommand.tsx +96 -0
- package/website/components/Logo.tsx +24 -0
- package/website/components/StructuredData.tsx +65 -0
- package/website/components/docs/DocsSearch.tsx +104 -0
- package/website/components/docs/DocsSidebar.tsx +118 -0
- package/website/components/docs/MarkdownContent.tsx +183 -0
- package/website/components/docs/VersionSelector.tsx +49 -0
- package/website/components/examples/ExamplesViewer.tsx +293 -0
- package/website/components/layout/Footer.tsx +111 -0
- package/website/components/layout/Header.tsx +170 -0
- package/website/components/schema/SchemaExplorer.tsx +213 -0
- package/website/content/blog/OpenAPI-AI-Agents-Standard.md +285 -0
- package/website/content/blog/Why-Formal-Standards-Matter-Now.md +209 -0
- package/website/content/blog/introducing-ossa-framework.md +328 -0
- package/website/content/blog/ossa-production-results.md +279 -0
- package/website/content/blog/welcome-to-ossa.md +43 -0
- package/website/content/blog/why-ai-agents-need-open-standard.md +98 -0
- package/website/content/docs/00-HOME.md +160 -0
- package/website/content/docs/AIFlow-Framework-Integration-with-OSSA.md +107 -0
- package/website/content/docs/OpenAPI-Extensions.md +498 -0
- package/website/content/docs/architecture/execution-flow.md +335 -0
- package/website/content/docs/architecture/multi-agent-systems.md +737 -0
- package/website/content/docs/architecture/overview.md +121 -0
- package/website/content/docs/architecture/stack-integration.md +461 -0
- package/website/content/docs/changelog.md +246 -0
- package/website/content/docs/contributing.md +599 -0
- package/website/content/docs/core-concepts/project-structure.md +348 -0
- package/website/content/docs/ecosystem/framework-support.md +821 -0
- package/website/content/docs/ecosystem/overview.md +366 -0
- package/website/content/docs/examples/Migration-Guides.md +214 -0
- package/website/content/docs/examples.md +71 -0
- package/website/content/docs/for-audiences/Enterprises.md +256 -0
- package/website/content/docs/for-audiences/Students-Researchers.md +122 -0
- package/website/content/docs/for-audiences/architects.md +224 -0
- package/website/content/docs/for-audiences/developers.md +220 -0
- package/website/content/docs/getting-started/5-minute-overview.md +85 -0
- package/website/content/docs/getting-started/Hello-World.md +184 -0
- package/website/content/docs/getting-started/first-agent.md +196 -0
- package/website/content/docs/getting-started/installation.md +155 -0
- package/website/content/docs/getting-started/running-agents.md +107 -0
- package/website/content/docs/integrations/aiflow.md +104 -0
- package/website/content/docs/integrations/drupal.md +105 -0
- package/website/content/docs/migration-guides/00-index.md +76 -0
- package/website/content/docs/migration-guides/README.md +133 -0
- package/website/content/docs/migration-guides/anthropic-mcp-to-ossa.md +1750 -0
- package/website/content/docs/migration-guides/crewai-to-ossa.md +274 -0
- package/website/content/docs/migration-guides/drupal-eca-to-ossa.md +2017 -0
- package/website/content/docs/migration-guides/index.md +133 -0
- package/website/content/docs/migration-guides/langchain-to-ossa.md +1714 -0
- package/website/content/docs/migration-guides/langflow-to-ossa.md +2075 -0
- package/website/content/docs/migration-guides/openai-to-ossa.md +1202 -0
- package/website/content/docs/openapi-extensions/examples.md +550 -0
- package/website/content/docs/openapi-extensions/index.md +495 -0
- package/website/content/docs/openapi-extensions/operation-extensions.md +398 -0
- package/website/content/docs/openapi-extensions/root-extensions.md +364 -0
- package/website/content/docs/pre-release/index.md +175 -0
- package/website/content/docs/quick-reference.md +17 -0
- package/website/content/docs/schema-reference/agent-spec.md +406 -0
- package/website/content/docs/schema-reference/autonomy.md +568 -0
- package/website/content/docs/schema-reference/constraints.md +543 -0
- package/website/content/docs/schema-reference/index.md +176 -0
- package/website/content/docs/schema-reference/llm-config.md +445 -0
- package/website/content/docs/schema-reference/observability.md +654 -0
- package/website/content/docs/schema-reference/ossa-manifest.md +309 -0
- package/website/content/docs/schema-reference/taxonomy.md +509 -0
- package/website/content/docs/schema-reference/tools.md +628 -0
- package/website/content/docs/templates/blog-post.md +43 -0
- package/website/content/docs/use-cases/00-index.md +395 -0
- package/website/content/docs/use-cases/cicd-code-review.md +1236 -0
- package/website/content/docs/use-cases/customer-support.md +1234 -0
- package/website/content/docs/use-cases/enterprise-compliance.md +1208 -0
- package/website/content/docs/use-cases/research-multi-agent.md +1161 -0
- package/website/lib/version.ts +18 -0
- package/website/next.config.js +17 -0
- package/website/next.config.ts +16 -0
- package/website/nginx.conf +32 -0
- package/website/package-lock.json +9145 -0
- package/website/package.json +53 -0
- package/website/postcss.config.js +7 -0
- package/website/postcss.config.mjs +9 -0
- package/website/scripts/sync-version.js +44 -0
- package/website/scripts/sync-wiki.ts +261 -0
- package/website/tailwind.config.js +58 -0
- package/website/tailwind.config.ts +65 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* k6 Load Testing Script for AIFlow Social Agent
|
|
3
|
+
*
|
|
4
|
+
* Tests:
|
|
5
|
+
* 1. Baseline performance (moderate load)
|
|
6
|
+
* 2. Stress testing (high load)
|
|
7
|
+
* 3. Spike testing (sudden traffic increase)
|
|
8
|
+
* 4. Soak testing (sustained load)
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* k6 run k6-load-test.js
|
|
12
|
+
* k6 run --vus 100 --duration 60s k6-load-test.js
|
|
13
|
+
* k6 run --stage "1m:10,5m:50,1m:0" k6-load-test.js
|
|
14
|
+
*
|
|
15
|
+
* Metrics exported to Prometheus via k6-operator
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { check, group, sleep } from 'k6';
|
|
19
|
+
import http from 'k6/http';
|
|
20
|
+
import { Counter, Rate, Trend } from 'k6/metrics';
|
|
21
|
+
|
|
22
|
+
// Custom metrics
|
|
23
|
+
const errorRate = new Rate('errors');
|
|
24
|
+
const postGenerationDuration = new Trend('post_generation_duration');
|
|
25
|
+
const responseGenerationDuration = new Trend('response_generation_duration');
|
|
26
|
+
const healthCheckDuration = new Trend('health_check_duration');
|
|
27
|
+
const apiRequests = new Counter('api_requests_total');
|
|
28
|
+
|
|
29
|
+
// Configuration
|
|
30
|
+
const BASE_URL = __ENV.BASE_URL || 'http://aiflow-social-agent.agents.svc.cluster.local:8000';
|
|
31
|
+
const API_KEY = __ENV.API_KEY || 'test-api-key-for-development';
|
|
32
|
+
|
|
33
|
+
// Load test scenarios
|
|
34
|
+
export const options = {
|
|
35
|
+
scenarios: {
|
|
36
|
+
// Scenario 1: Baseline Performance Test
|
|
37
|
+
baseline: {
|
|
38
|
+
executor: 'ramping-vus',
|
|
39
|
+
startVUs: 0,
|
|
40
|
+
stages: [
|
|
41
|
+
{ duration: '1m', target: 10 }, // Ramp up to 10 VUs
|
|
42
|
+
{ duration: '3m', target: 10 }, // Stay at 10 VUs
|
|
43
|
+
{ duration: '1m', target: 0 }, // Ramp down to 0
|
|
44
|
+
],
|
|
45
|
+
gracefulRampDown: '30s',
|
|
46
|
+
exec: 'baselineTest',
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// Scenario 2: Stress Test
|
|
50
|
+
stress: {
|
|
51
|
+
executor: 'ramping-vus',
|
|
52
|
+
startVUs: 0,
|
|
53
|
+
stages: [
|
|
54
|
+
{ duration: '2m', target: 50 }, // Ramp up to 50 VUs
|
|
55
|
+
{ duration: '5m', target: 50 }, // Stay at 50 VUs
|
|
56
|
+
{ duration: '2m', target: 100 }, // Ramp up to 100 VUs
|
|
57
|
+
{ duration: '5m', target: 100 }, // Stay at 100 VUs
|
|
58
|
+
{ duration: '2m', target: 0 }, // Ramp down
|
|
59
|
+
],
|
|
60
|
+
gracefulRampDown: '30s',
|
|
61
|
+
exec: 'stressTest',
|
|
62
|
+
startTime: '6m', // Start after baseline
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
// Scenario 3: Spike Test
|
|
66
|
+
spike: {
|
|
67
|
+
executor: 'ramping-vus',
|
|
68
|
+
startVUs: 0,
|
|
69
|
+
stages: [
|
|
70
|
+
{ duration: '10s', target: 100 }, // Sudden spike
|
|
71
|
+
{ duration: '1m', target: 100 }, // Stay high
|
|
72
|
+
{ duration: '10s', target: 0 }, // Drop
|
|
73
|
+
],
|
|
74
|
+
gracefulRampDown: '10s',
|
|
75
|
+
exec: 'spikeTest',
|
|
76
|
+
startTime: '22m', // Start after stress
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
thresholds: {
|
|
81
|
+
// HTTP request duration
|
|
82
|
+
'http_req_duration': ['p(95)<500', 'p(99)<1000'], // 95% < 500ms, 99% < 1s
|
|
83
|
+
|
|
84
|
+
// HTTP request failure rate
|
|
85
|
+
'http_req_failed': ['rate<0.01'], // <1% failure rate
|
|
86
|
+
|
|
87
|
+
// Custom metrics
|
|
88
|
+
'errors': ['rate<0.05'], // <5% error rate
|
|
89
|
+
'post_generation_duration': ['p(95)<600'],
|
|
90
|
+
'response_generation_duration': ['p(95)<600'],
|
|
91
|
+
'health_check_duration': ['p(95)<100'],
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Helper function: Make authenticated request
|
|
96
|
+
function makeAuthenticatedRequest(method, url, body = null) {
|
|
97
|
+
const params = {
|
|
98
|
+
headers: {
|
|
99
|
+
'Content-Type': 'application/json',
|
|
100
|
+
'X-API-Key': API_KEY,
|
|
101
|
+
},
|
|
102
|
+
timeout: '30s',
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
if (body) {
|
|
106
|
+
return http[method](url, JSON.stringify(body), params);
|
|
107
|
+
}
|
|
108
|
+
return http[method](url, params);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Scenario 1: Baseline Test
|
|
112
|
+
export function baselineTest() {
|
|
113
|
+
group('Baseline Performance', function() {
|
|
114
|
+
// Test 1: Health check
|
|
115
|
+
group('Health Check', function() {
|
|
116
|
+
const start = new Date();
|
|
117
|
+
const res = http.get(`${BASE_URL}/health`);
|
|
118
|
+
const duration = new Date() - start;
|
|
119
|
+
|
|
120
|
+
healthCheckDuration.add(duration);
|
|
121
|
+
apiRequests.add(1);
|
|
122
|
+
|
|
123
|
+
const success = check(res, {
|
|
124
|
+
'health check status is 200': (r) => r.status === 200,
|
|
125
|
+
'health check returns healthy': (r) => JSON.parse(r.body).status === 'healthy',
|
|
126
|
+
'health check < 100ms': (r) => r.timings.duration < 100,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
errorRate.add(!success);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
sleep(1);
|
|
133
|
+
|
|
134
|
+
// Test 2: Generate post
|
|
135
|
+
group('Generate Post', function() {
|
|
136
|
+
const payload = {
|
|
137
|
+
platform: 'twitter',
|
|
138
|
+
time_of_day: ['morning', 'afternoon', 'evening', 'night'][Math.floor(Math.random() * 4)],
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const start = new Date();
|
|
142
|
+
const res = makeAuthenticatedRequest('post', `${BASE_URL}/generate_post`, payload);
|
|
143
|
+
const duration = new Date() - start;
|
|
144
|
+
|
|
145
|
+
postGenerationDuration.add(duration);
|
|
146
|
+
apiRequests.add(1);
|
|
147
|
+
|
|
148
|
+
const success = check(res, {
|
|
149
|
+
'generate_post status is 200': (r) => r.status === 200,
|
|
150
|
+
'generate_post returns content': (r) => JSON.parse(r.body).content !== undefined,
|
|
151
|
+
'generate_post < 500ms': (r) => r.timings.duration < 500,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
errorRate.add(!success);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
sleep(2);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Scenario 2: Stress Test
|
|
162
|
+
export function stressTest() {
|
|
163
|
+
group('Stress Test', function() {
|
|
164
|
+
// Mix of operations
|
|
165
|
+
const operation = Math.random();
|
|
166
|
+
|
|
167
|
+
if (operation < 0.4) {
|
|
168
|
+
// 40% - Generate post
|
|
169
|
+
const payload = {
|
|
170
|
+
platform: Math.random() < 0.5 ? 'twitter' : 'telegram',
|
|
171
|
+
time_of_day: ['morning', 'afternoon', 'evening', 'night'][Math.floor(Math.random() * 4)],
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const start = new Date();
|
|
175
|
+
const res = makeAuthenticatedRequest('post', `${BASE_URL}/generate_post`, payload);
|
|
176
|
+
const duration = new Date() - start;
|
|
177
|
+
|
|
178
|
+
postGenerationDuration.add(duration);
|
|
179
|
+
apiRequests.add(1);
|
|
180
|
+
errorRate.add(res.status !== 200);
|
|
181
|
+
|
|
182
|
+
} else if (operation < 0.8) {
|
|
183
|
+
// 40% - Generate response
|
|
184
|
+
const payload = {
|
|
185
|
+
message: {
|
|
186
|
+
id: `msg-${Date.now()}`,
|
|
187
|
+
author: `user${Math.floor(Math.random() * 1000)}`,
|
|
188
|
+
content: 'What do you think about OSSA and multi-agent systems?',
|
|
189
|
+
platform: Math.random() < 0.5 ? 'twitter' : 'telegram',
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const start = new Date();
|
|
194
|
+
const res = makeAuthenticatedRequest('post', `${BASE_URL}/generate_response`, payload);
|
|
195
|
+
const duration = new Date() - start;
|
|
196
|
+
|
|
197
|
+
responseGenerationDuration.add(duration);
|
|
198
|
+
apiRequests.add(1);
|
|
199
|
+
errorRate.add(res.status !== 200);
|
|
200
|
+
|
|
201
|
+
} else {
|
|
202
|
+
// 20% - Health check
|
|
203
|
+
const start = new Date();
|
|
204
|
+
const res = http.get(`${BASE_URL}/health`);
|
|
205
|
+
const duration = new Date() - start;
|
|
206
|
+
|
|
207
|
+
healthCheckDuration.add(duration);
|
|
208
|
+
apiRequests.add(1);
|
|
209
|
+
errorRate.add(res.status !== 200);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
sleep(0.5);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Scenario 3: Spike Test
|
|
217
|
+
export function spikeTest() {
|
|
218
|
+
group('Spike Test', function() {
|
|
219
|
+
// Rapid-fire requests
|
|
220
|
+
const payload = {
|
|
221
|
+
platform: 'twitter',
|
|
222
|
+
time_of_day: 'afternoon',
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const res = makeAuthenticatedRequest('post', `${BASE_URL}/generate_post`, payload);
|
|
226
|
+
apiRequests.add(1);
|
|
227
|
+
errorRate.add(res.status !== 200);
|
|
228
|
+
|
|
229
|
+
// No sleep - maximum load
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Setup function (runs once)
|
|
234
|
+
export function setup() {
|
|
235
|
+
console.log('🚀 Starting k6 load test for AIFlow Social Agent');
|
|
236
|
+
console.log(` Target: ${BASE_URL}`);
|
|
237
|
+
console.log(` API Key: ${API_KEY.substring(0, 8)}...`);
|
|
238
|
+
|
|
239
|
+
// Verify service is accessible
|
|
240
|
+
const res = http.get(`${BASE_URL}/health`);
|
|
241
|
+
if (res.status !== 200) {
|
|
242
|
+
throw new Error(`Service not healthy: ${res.status}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
console.log('✅ Service is healthy. Starting load test...');
|
|
246
|
+
return { startTime: Date.now() };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Teardown function (runs once)
|
|
250
|
+
export function teardown(data) {
|
|
251
|
+
const duration = (Date.now() - data.startTime) / 1000;
|
|
252
|
+
console.log(`\n✅ Load test complete. Duration: ${duration}s`);
|
|
253
|
+
console.log('📊 Check k6 summary and Grafana dashboards for detailed metrics.');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Handle summary (custom output)
|
|
257
|
+
export function handleSummary(data) {
|
|
258
|
+
return {
|
|
259
|
+
'stdout': textSummary(data, { indent: ' ', enableColors: true }),
|
|
260
|
+
'load-test-results.json': JSON.stringify(data),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Text summary helper
|
|
265
|
+
function textSummary(data, options) {
|
|
266
|
+
const indent = options.indent || '';
|
|
267
|
+
const colors = options.enableColors || false;
|
|
268
|
+
|
|
269
|
+
let output = '\n' + indent + '📊 Load Test Summary\n';
|
|
270
|
+
output += indent + '='.repeat(60) + '\n';
|
|
271
|
+
|
|
272
|
+
// HTTP metrics
|
|
273
|
+
if (data.metrics.http_reqs) {
|
|
274
|
+
output += indent + `Total Requests: ${data.metrics.http_reqs.values.count}\n`;
|
|
275
|
+
output += indent + `Request Rate: ${data.metrics.http_reqs.values.rate.toFixed(2)}/s\n`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (data.metrics.http_req_duration) {
|
|
279
|
+
output += indent + `Avg Duration: ${data.metrics.http_req_duration.values.avg.toFixed(2)}ms\n`;
|
|
280
|
+
output += indent + `P95 Duration: ${data.metrics.http_req_duration.values['p(95)'].toFixed(2)}ms\n`;
|
|
281
|
+
output += indent + `P99 Duration: ${data.metrics.http_req_duration.values['p(99)'].toFixed(2)}ms\n`;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (data.metrics.http_req_failed) {
|
|
285
|
+
const failRate = (data.metrics.http_req_failed.values.rate * 100).toFixed(2);
|
|
286
|
+
output += indent + `Failure Rate: ${failRate}%\n`;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Custom metrics
|
|
290
|
+
if (data.metrics.post_generation_duration) {
|
|
291
|
+
output += indent + `\nPost Generation P95: ${data.metrics.post_generation_duration.values['p(95)'].toFixed(2)}ms\n`;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (data.metrics.response_generation_duration) {
|
|
295
|
+
output += indent + `Response Generation P95: ${data.metrics.response_generation_duration.values['p(95)'].toFixed(2)}ms\n`;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
output += indent + '='.repeat(60) + '\n';
|
|
299
|
+
|
|
300
|
+
return output;
|
|
301
|
+
}
|
|
302
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# AIFlow FastAPI Bridge - Production Dependencies
|
|
2
|
+
|
|
3
|
+
# Web Framework
|
|
4
|
+
fastapi==0.109.0
|
|
5
|
+
uvicorn[standard]==0.27.0
|
|
6
|
+
pydantic==2.5.3
|
|
7
|
+
|
|
8
|
+
# HTTP Client
|
|
9
|
+
httpx==0.26.0
|
|
10
|
+
|
|
11
|
+
# Metrics
|
|
12
|
+
prometheus-client==0.19.0
|
|
13
|
+
|
|
14
|
+
# OpenTelemetry (Phoenix Tracing)
|
|
15
|
+
opentelemetry-api==1.22.0
|
|
16
|
+
opentelemetry-sdk==1.22.0
|
|
17
|
+
opentelemetry-instrumentation-fastapi==0.43b0
|
|
18
|
+
opentelemetry-instrumentation-requests==0.43b0
|
|
19
|
+
opentelemetry-exporter-otlp-proto-http==1.22.0
|
|
20
|
+
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* k6 Load Testing Scenarios for AIFlow Agent
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* k6 run loadtest/k6-scenarios.js
|
|
6
|
+
* k6 run --out json=results.json loadtest/k6-scenarios.js
|
|
7
|
+
* k6 run --vus 100 --duration 5m loadtest/k6-scenarios.js
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { check, sleep } from 'k6';
|
|
11
|
+
import http from 'k6/http';
|
|
12
|
+
import { Counter, Rate, Trend } from 'k6/metrics';
|
|
13
|
+
|
|
14
|
+
// Custom Metrics
|
|
15
|
+
const postsGenerated = new Counter('posts_generated');
|
|
16
|
+
const responsesGenerated = new Counter('responses_generated');
|
|
17
|
+
const apiLatency = new Trend('api_latency');
|
|
18
|
+
const successRate = new Rate('success_rate');
|
|
19
|
+
const phoenixTraces = new Counter('phoenix_traces');
|
|
20
|
+
|
|
21
|
+
// Configuration
|
|
22
|
+
const BASE_URL = __ENV.BASE_URL || 'http://aiflow-social-agent.agents.svc.cluster.local:8000';
|
|
23
|
+
const API_KEY = __ENV.API_KEY || 'test-api-key-for-development';
|
|
24
|
+
|
|
25
|
+
// Scenario: Smoke Test (Quick validation)
|
|
26
|
+
export const options = {
|
|
27
|
+
scenarios: {
|
|
28
|
+
// 1. Smoke Test: Verify basic functionality
|
|
29
|
+
smoke: {
|
|
30
|
+
executor: 'constant-vus',
|
|
31
|
+
vus: 1,
|
|
32
|
+
duration: '1m',
|
|
33
|
+
tags: { scenario: 'smoke' },
|
|
34
|
+
exec: 'smokeTest',
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// 2. Load Test: Normal production load
|
|
38
|
+
load: {
|
|
39
|
+
executor: 'ramping-vus',
|
|
40
|
+
startVUs: 0,
|
|
41
|
+
stages: [
|
|
42
|
+
{ duration: '2m', target: 10 }, // Ramp up to 10 users
|
|
43
|
+
{ duration: '5m', target: 10 }, // Stay at 10 users
|
|
44
|
+
{ duration: '2m', target: 0 }, // Ramp down to 0
|
|
45
|
+
],
|
|
46
|
+
tags: { scenario: 'load' },
|
|
47
|
+
exec: 'loadTest',
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
// 3. Stress Test: Find breaking point
|
|
51
|
+
stress: {
|
|
52
|
+
executor: 'ramping-vus',
|
|
53
|
+
startVUs: 0,
|
|
54
|
+
stages: [
|
|
55
|
+
{ duration: '2m', target: 20 }, // Below normal load
|
|
56
|
+
{ duration: '5m', target: 20 }, // Normal load
|
|
57
|
+
{ duration: '2m', target: 50 }, // Around breaking point
|
|
58
|
+
{ duration: '5m', target: 50 }, // Beyond breaking point
|
|
59
|
+
{ duration: '2m', target: 100 }, // Far beyond
|
|
60
|
+
{ duration: '5m', target: 100 },
|
|
61
|
+
{ duration: '5m', target: 0 }, // Recovery
|
|
62
|
+
],
|
|
63
|
+
tags: { scenario: 'stress' },
|
|
64
|
+
exec: 'stressTest',
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// 4. Spike Test: Sudden traffic spikes
|
|
68
|
+
spike: {
|
|
69
|
+
executor: 'ramping-vus',
|
|
70
|
+
startVUs: 0,
|
|
71
|
+
stages: [
|
|
72
|
+
{ duration: '10s', target: 100 }, // Spike to 100 users
|
|
73
|
+
{ duration: '1m', target: 100 }, // Stay at spike
|
|
74
|
+
{ duration: '10s', target: 0 }, // Drop to 0
|
|
75
|
+
{ duration: '1m', target: 0 }, // Recovery
|
|
76
|
+
],
|
|
77
|
+
tags: { scenario: 'spike' },
|
|
78
|
+
exec: 'spikeTest',
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
// 5. Soak Test: Extended duration for memory leaks
|
|
82
|
+
soak: {
|
|
83
|
+
executor: 'constant-vus',
|
|
84
|
+
vus: 20,
|
|
85
|
+
duration: '30m',
|
|
86
|
+
tags: { scenario: 'soak' },
|
|
87
|
+
exec: 'soakTest',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
thresholds: {
|
|
92
|
+
// HTTP Metrics
|
|
93
|
+
'http_req_duration': ['p(95)<500', 'p(99)<1000'], // 95% < 500ms, 99% < 1s
|
|
94
|
+
'http_req_failed': ['rate<0.05'], // Error rate < 5%
|
|
95
|
+
|
|
96
|
+
// Custom Metrics
|
|
97
|
+
'success_rate': ['rate>0.95'], // Success rate > 95%
|
|
98
|
+
'api_latency': ['p(95)<500'], // API latency p95 < 500ms
|
|
99
|
+
|
|
100
|
+
// Scenario-specific thresholds
|
|
101
|
+
'http_req_duration{scenario:smoke}': ['p(95)<300'],
|
|
102
|
+
'http_req_duration{scenario:load}': ['p(95)<500'],
|
|
103
|
+
'http_req_duration{scenario:stress}': ['p(95)<1000'],
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Test Functions
|
|
108
|
+
|
|
109
|
+
export function smokeTest() {
|
|
110
|
+
const responses = {
|
|
111
|
+
health: http.get(`${BASE_URL}/health`),
|
|
112
|
+
metrics: http.get(`${BASE_URL}/metrics`),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
check(responses.health, {
|
|
116
|
+
'health status is 200': (r) => r.status === 200,
|
|
117
|
+
'health returns healthy': (r) => r.json('status') === 'healthy',
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
check(responses.metrics, {
|
|
121
|
+
'metrics status is 200': (r) => r.status === 200,
|
|
122
|
+
'metrics contains prometheus data': (r) => r.body.includes('aiflow_'),
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
sleep(1);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function loadTest() {
|
|
129
|
+
const scenarios = [generatePost, generateResponse];
|
|
130
|
+
const scenario = scenarios[Math.floor(Math.random() * scenarios.length)];
|
|
131
|
+
scenario();
|
|
132
|
+
sleep(Math.random() * 2 + 1); // 1-3 seconds between requests
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function stressTest() {
|
|
136
|
+
const scenarios = [generatePost, generateResponse, checkHealth];
|
|
137
|
+
const scenario = scenarios[Math.floor(Math.random() * scenarios.length)];
|
|
138
|
+
scenario();
|
|
139
|
+
sleep(Math.random() * 0.5); // 0-0.5 seconds (high load)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function spikeTest() {
|
|
143
|
+
generatePost();
|
|
144
|
+
generateResponse();
|
|
145
|
+
sleep(0.1); // Minimal sleep during spike
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function soakTest() {
|
|
149
|
+
const scenarios = [generatePost, generateResponse];
|
|
150
|
+
const scenario = scenarios[Math.floor(Math.random() * scenarios.length)];
|
|
151
|
+
scenario();
|
|
152
|
+
sleep(Math.random() * 3 + 2); // 2-5 seconds (sustained load)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Helper Functions
|
|
156
|
+
|
|
157
|
+
function generatePost() {
|
|
158
|
+
const platforms = ['twitter', 'telegram'];
|
|
159
|
+
const timesOfDay = ['morning', 'afternoon', 'evening', 'night'];
|
|
160
|
+
|
|
161
|
+
const payload = {
|
|
162
|
+
platform: platforms[Math.floor(Math.random() * platforms.length)],
|
|
163
|
+
time_of_day: timesOfDay[Math.floor(Math.random() * timesOfDay.length)],
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const params = {
|
|
167
|
+
headers: {
|
|
168
|
+
'Content-Type': 'application/json',
|
|
169
|
+
'X-API-Key': API_KEY,
|
|
170
|
+
},
|
|
171
|
+
tags: { endpoint: 'generate_post' },
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const start = Date.now();
|
|
175
|
+
const response = http.post(
|
|
176
|
+
`${BASE_URL}/generate_post`,
|
|
177
|
+
JSON.stringify(payload),
|
|
178
|
+
params
|
|
179
|
+
);
|
|
180
|
+
const duration = Date.now() - start;
|
|
181
|
+
|
|
182
|
+
const success = check(response, {
|
|
183
|
+
'post status is 200': (r) => r.status === 200,
|
|
184
|
+
'post has content': (r) => r.json('content') !== undefined,
|
|
185
|
+
'post has platform': (r) => r.json('platform') !== undefined,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Record metrics
|
|
189
|
+
apiLatency.add(duration);
|
|
190
|
+
successRate.add(success);
|
|
191
|
+
if (success) {
|
|
192
|
+
postsGenerated.add(1);
|
|
193
|
+
phoenixTraces.add(1);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return response;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function generateResponse() {
|
|
200
|
+
const platforms = ['twitter', 'telegram'];
|
|
201
|
+
const authors = ['user1', 'user2', 'user3', 'user4'];
|
|
202
|
+
const contents = [
|
|
203
|
+
'What do you think about AI agents?',
|
|
204
|
+
'How does OSSA work?',
|
|
205
|
+
'Tell me about BuildKit',
|
|
206
|
+
'What is Phoenix tracing?',
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
const payload = {
|
|
210
|
+
message: {
|
|
211
|
+
id: `msg-${Date.now()}`,
|
|
212
|
+
author: authors[Math.floor(Math.random() * authors.length)],
|
|
213
|
+
content: contents[Math.floor(Math.random() * contents.length)],
|
|
214
|
+
platform: platforms[Math.floor(Math.random() * platforms.length)],
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const params = {
|
|
219
|
+
headers: {
|
|
220
|
+
'Content-Type': 'application/json',
|
|
221
|
+
'X-API-Key': API_KEY,
|
|
222
|
+
},
|
|
223
|
+
tags: { endpoint: 'generate_response' },
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const start = Date.now();
|
|
227
|
+
const response = http.post(
|
|
228
|
+
`${BASE_URL}/generate_response`,
|
|
229
|
+
JSON.stringify(payload),
|
|
230
|
+
params
|
|
231
|
+
);
|
|
232
|
+
const duration = Date.now() - start;
|
|
233
|
+
|
|
234
|
+
const success = check(response, {
|
|
235
|
+
'response status is 200': (r) => r.status === 200,
|
|
236
|
+
'response has content': (r) => r.json('content') !== undefined,
|
|
237
|
+
'response has should_respond': (r) => r.json('should_respond') !== undefined,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Record metrics
|
|
241
|
+
apiLatency.add(duration);
|
|
242
|
+
successRate.add(success);
|
|
243
|
+
if (success) {
|
|
244
|
+
responsesGenerated.add(1);
|
|
245
|
+
phoenixTraces.add(1);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return response;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function checkHealth() {
|
|
252
|
+
const response = http.get(`${BASE_URL}/health`, {
|
|
253
|
+
tags: { endpoint: 'health' },
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
check(response, {
|
|
257
|
+
'health is 200': (r) => r.status === 200,
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
return response;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Teardown function
|
|
264
|
+
export function teardown(data) {
|
|
265
|
+
console.log('Load test completed');
|
|
266
|
+
console.log(`Total posts generated: ${postsGenerated.count}`);
|
|
267
|
+
console.log(`Total responses generated: ${responsesGenerated.count}`);
|
|
268
|
+
console.log(`Total Phoenix traces: ${phoenixTraces.count}`);
|
|
269
|
+
}
|
|
270
|
+
|