mcoda 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +9 -0
- package/.eslintrc.cjs +12 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- package/.github/workflows/ci.yml +37 -0
- package/.github/workflows/nightly.yml +38 -0
- package/.github/workflows/release-dry-run.yml +40 -0
- package/.github/workflows/release-please.yml +22 -0
- package/.github/workflows/release.yml +149 -0
- package/.prettierrc +5 -0
- package/.release-please-manifest.json +8 -0
- package/CHANGELOG.md +7 -0
- package/CLA.md +42 -0
- package/CONTRIBUTING.md +38 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/docs/oss_publishing_plan.md +41 -0
- package/docs/pdr/.gitkeep +0 -0
- package/docs/quality_gates.md +32 -0
- package/docs/rfp/.gitkeep +0 -0
- package/docs/sds/sds.md +11963 -0
- package/docs/usage.md +72 -0
- package/openapi/gen-openapi.ts +1 -0
- package/openapi/generated/clients/.gitkeep +0 -0
- package/openapi/generated/types/.gitkeep +0 -0
- package/openapi/generated/types/index.ts +118 -0
- package/openapi/mcoda.yaml +2063 -0
- package/pack-mcoda.sh +88 -0
- package/package.json +46 -0
- package/packages/agents/CHANGELOG.md +7 -0
- package/packages/agents/LICENSE +21 -0
- package/packages/agents/README.md +9 -0
- package/packages/agents/package.json +41 -0
- package/packages/agents/src/AgentService/.gitkeep +0 -0
- package/packages/agents/src/AgentService/AgentService.d.ts +21 -0
- package/packages/agents/src/AgentService/AgentService.d.ts.map +1 -0
- package/packages/agents/src/AgentService/AgentService.js +141 -0
- package/packages/agents/src/AgentService/AgentService.ts +308 -0
- package/packages/agents/src/__tests__/AgentService.test.ts +284 -0
- package/packages/agents/src/adapters/AdapterTypes.d.ts +29 -0
- package/packages/agents/src/adapters/AdapterTypes.d.ts.map +1 -0
- package/packages/agents/src/adapters/AdapterTypes.js +1 -0
- package/packages/agents/src/adapters/AdapterTypes.ts +32 -0
- package/packages/agents/src/adapters/codex/.gitkeep +0 -0
- package/packages/agents/src/adapters/codex/CodexAdapter.d.ts +11 -0
- package/packages/agents/src/adapters/codex/CodexAdapter.d.ts.map +1 -0
- package/packages/agents/src/adapters/codex/CodexAdapter.js +43 -0
- package/packages/agents/src/adapters/codex/CodexAdapter.ts +63 -0
- package/packages/agents/src/adapters/codex/CodexCliRunner.ts +154 -0
- package/packages/agents/src/adapters/gemini/.gitkeep +0 -0
- package/packages/agents/src/adapters/gemini/GeminiAdapter.d.ts +11 -0
- package/packages/agents/src/adapters/gemini/GeminiAdapter.d.ts.map +1 -0
- package/packages/agents/src/adapters/gemini/GeminiAdapter.js +42 -0
- package/packages/agents/src/adapters/gemini/GeminiAdapter.ts +58 -0
- package/packages/agents/src/adapters/gemini/GeminiCliRunner.ts +75 -0
- package/packages/agents/src/adapters/local/.gitkeep +0 -0
- package/packages/agents/src/adapters/local/LocalAdapter.d.ts +11 -0
- package/packages/agents/src/adapters/local/LocalAdapter.d.ts.map +1 -0
- package/packages/agents/src/adapters/local/LocalAdapter.js +38 -0
- package/packages/agents/src/adapters/local/LocalAdapter.ts +43 -0
- package/packages/agents/src/adapters/ollama/OllamaCliAdapter.ts +58 -0
- package/packages/agents/src/adapters/ollama/OllamaCliRunner.ts +70 -0
- package/packages/agents/src/adapters/ollama/OllamaRemoteAdapter.ts +205 -0
- package/packages/agents/src/adapters/openai/.gitkeep +0 -0
- package/packages/agents/src/adapters/openai/OpenAiAdapter.d.ts +11 -0
- package/packages/agents/src/adapters/openai/OpenAiAdapter.d.ts.map +1 -0
- package/packages/agents/src/adapters/openai/OpenAiAdapter.js +51 -0
- package/packages/agents/src/adapters/openai/OpenAiAdapter.ts +56 -0
- package/packages/agents/src/adapters/openai/OpenAiCliAdapter.ts +62 -0
- package/packages/agents/src/adapters/qa/.gitkeep +0 -0
- package/packages/agents/src/adapters/qa/QaAdapter.d.ts +11 -0
- package/packages/agents/src/adapters/qa/QaAdapter.d.ts.map +1 -0
- package/packages/agents/src/adapters/qa/QaAdapter.js +37 -0
- package/packages/agents/src/adapters/qa/QaAdapter.ts +42 -0
- package/packages/agents/src/adapters/zhipu/ZhipuApiAdapter.ts +273 -0
- package/packages/agents/src/index.d.ts +8 -0
- package/packages/agents/src/index.d.ts.map +1 -0
- package/packages/agents/src/index.js +7 -0
- package/packages/agents/src/index.ts +11 -0
- package/packages/agents/tsconfig.json +14 -0
- package/packages/cli/CHANGELOG.md +7 -0
- package/packages/cli/LICENSE +21 -0
- package/packages/cli/README.md +23 -0
- package/packages/cli/package.json +61 -0
- package/packages/cli/src/__tests__/AgentsCommands.test.ts +137 -0
- package/packages/cli/src/__tests__/BacklogCommands.test.ts +40 -0
- package/packages/cli/src/__tests__/CodeReviewCommand.test.ts +594 -0
- package/packages/cli/src/__tests__/CreateTasksCommand.test.ts +40 -0
- package/packages/cli/src/__tests__/DocsCommands.test.ts +41 -0
- package/packages/cli/src/__tests__/EstimateCommands.test.ts +54 -0
- package/packages/cli/src/__tests__/JobsCommands.behavior.test.ts +311 -0
- package/packages/cli/src/__tests__/JobsCommands.test.ts +49 -0
- package/packages/cli/src/__tests__/MigrateTasksCommand.test.ts +36 -0
- package/packages/cli/src/__tests__/OpenapiCommands.test.ts +34 -0
- package/packages/cli/src/__tests__/OrderTasksCommand.test.ts +150 -0
- package/packages/cli/src/__tests__/PlanningCommands.test.ts +9 -0
- package/packages/cli/src/__tests__/QaTasksCommand.test.ts +58 -0
- package/packages/cli/src/__tests__/RefineTasksCommand.test.ts +63 -0
- package/packages/cli/src/__tests__/RoutingCommands.test.ts +302 -0
- package/packages/cli/src/__tests__/SetWorkspaceCommand.test.ts +18 -0
- package/packages/cli/src/__tests__/TaskShowCommands.test.ts +130 -0
- package/packages/cli/src/__tests__/TelemetryCommands.test.ts +35 -0
- package/packages/cli/src/__tests__/TestAgentCommand.test.ts +41 -0
- package/packages/cli/src/__tests__/UpdateCommands.test.ts +292 -0
- package/packages/cli/src/__tests__/WorkOnTasksCommand.test.ts +42 -0
- package/packages/cli/src/bin/.gitkeep +0 -0
- package/packages/cli/src/bin/McodaEntrypoint.ts +180 -0
- package/packages/cli/src/commands/agents/.gitkeep +0 -0
- package/packages/cli/src/commands/agents/AgentsCommands.ts +374 -0
- package/packages/cli/src/commands/agents/GatewayAgentCommand.ts +621 -0
- package/packages/cli/src/commands/agents/TestAgentCommand.ts +63 -0
- package/packages/cli/src/commands/backlog/.gitkeep +0 -0
- package/packages/cli/src/commands/backlog/BacklogCommands.ts +286 -0
- package/packages/cli/src/commands/backlog/OrderTasksCommand.ts +237 -0
- package/packages/cli/src/commands/backlog/TaskShowCommands.ts +289 -0
- package/packages/cli/src/commands/docs/.gitkeep +0 -0
- package/packages/cli/src/commands/docs/DocsCommands.ts +413 -0
- package/packages/cli/src/commands/estimate/EstimateCommands.ts +290 -0
- package/packages/cli/src/commands/jobs/.gitkeep +0 -0
- package/packages/cli/src/commands/jobs/JobsCommands.ts +595 -0
- package/packages/cli/src/commands/openapi/OpenapiCommands.ts +167 -0
- package/packages/cli/src/commands/planning/.gitkeep +0 -0
- package/packages/cli/src/commands/planning/CreateTasksCommand.ts +149 -0
- package/packages/cli/src/commands/planning/MigrateTasksCommand.ts +105 -0
- package/packages/cli/src/commands/planning/PlanningCommands.ts +1 -0
- package/packages/cli/src/commands/planning/QaTasksCommand.ts +320 -0
- package/packages/cli/src/commands/planning/RefineTasksCommand.ts +408 -0
- package/packages/cli/src/commands/review/CodeReviewCommand.ts +262 -0
- package/packages/cli/src/commands/routing/.gitkeep +0 -0
- package/packages/cli/src/commands/routing/RoutingCommands.ts +554 -0
- package/packages/cli/src/commands/telemetry/.gitkeep +0 -0
- package/packages/cli/src/commands/telemetry/TelemetryCommands.ts +348 -0
- package/packages/cli/src/commands/update/.gitkeep +0 -0
- package/packages/cli/src/commands/update/UpdateCommands.ts +301 -0
- package/packages/cli/src/commands/work/WorkOnTasksCommand.ts +264 -0
- package/packages/cli/src/commands/workspace/SetWorkspaceCommand.ts +132 -0
- package/packages/cli/src/index.ts +18 -0
- package/packages/cli/test/packaging_guardrails.test.js +75 -0
- package/packages/cli/tsconfig.json +20 -0
- package/packages/core/CHANGELOG.md +7 -0
- package/packages/core/LICENSE +21 -0
- package/packages/core/README.md +9 -0
- package/packages/core/package.json +45 -0
- package/packages/core/src/__tests__/SmokeClasses.test.ts +32 -0
- package/packages/core/src/api/AgentsApi.ts +219 -0
- package/packages/core/src/api/QaTasksApi.ts +38 -0
- package/packages/core/src/api/TasksApi.ts +35 -0
- package/packages/core/src/api/__tests__/AgentsApi.test.ts +203 -0
- package/packages/core/src/api/__tests__/QaTasksApi.test.ts +51 -0
- package/packages/core/src/api/__tests__/TasksApi.test.ts +56 -0
- package/packages/core/src/config/.gitkeep +0 -0
- package/packages/core/src/config/ConfigService.ts +1 -0
- package/packages/core/src/domain/dependencies/.gitkeep +0 -0
- package/packages/core/src/domain/dependencies/Dependency.ts +1 -0
- package/packages/core/src/domain/epics/.gitkeep +0 -0
- package/packages/core/src/domain/epics/Epic.ts +1 -0
- package/packages/core/src/domain/projects/.gitkeep +0 -0
- package/packages/core/src/domain/projects/Project.ts +1 -0
- package/packages/core/src/domain/tasks/.gitkeep +0 -0
- package/packages/core/src/domain/tasks/Task.ts +1 -0
- package/packages/core/src/domain/userStories/.gitkeep +0 -0
- package/packages/core/src/domain/userStories/UserStory.ts +1 -0
- package/packages/core/src/index.ts +27 -0
- package/packages/core/src/prompts/.gitkeep +0 -0
- package/packages/core/src/prompts/PdrPrompts.ts +23 -0
- package/packages/core/src/prompts/PromptLoader.ts +1 -0
- package/packages/core/src/prompts/SdsPrompts.ts +47 -0
- package/packages/core/src/services/agents/.gitkeep +0 -0
- package/packages/core/src/services/agents/AgentManagementService.ts +1 -0
- package/packages/core/src/services/agents/GatewayAgentService.ts +956 -0
- package/packages/core/src/services/agents/RoutingService.ts +461 -0
- package/packages/core/src/services/agents/__tests__/GatewayAgentService.test.ts +72 -0
- package/packages/core/src/services/agents/__tests__/RoutingService.test.ts +267 -0
- package/packages/core/src/services/agents/generated/RoutingApiClient.ts +89 -0
- package/packages/core/src/services/backlog/.gitkeep +0 -0
- package/packages/core/src/services/backlog/BacklogService.ts +580 -0
- package/packages/core/src/services/backlog/TaskOrderingService.ts +868 -0
- package/packages/core/src/services/backlog/__tests__/BacklogService.test.ts +219 -0
- package/packages/core/src/services/backlog/__tests__/TaskOrderingService.test.ts +268 -0
- package/packages/core/src/services/docs/.gitkeep +0 -0
- package/packages/core/src/services/docs/DocsService.ts +1913 -0
- package/packages/core/src/services/docs/__tests__/DocsService.test.ts +350 -0
- package/packages/core/src/services/estimate/EstimateService.ts +111 -0
- package/packages/core/src/services/estimate/VelocityService.ts +272 -0
- package/packages/core/src/services/estimate/__tests__/VelocityAndEstimate.test.ts +209 -0
- package/packages/core/src/services/estimate/types.ts +41 -0
- package/packages/core/src/services/execution/.gitkeep +0 -0
- package/packages/core/src/services/execution/ExecutionService.ts +1 -0
- package/packages/core/src/services/execution/QaFollowupService.ts +289 -0
- package/packages/core/src/services/execution/QaProfileService.ts +160 -0
- package/packages/core/src/services/execution/QaTasksService.ts +1303 -0
- package/packages/core/src/services/execution/TaskSelectionService.ts +362 -0
- package/packages/core/src/services/execution/TaskStateService.ts +64 -0
- package/packages/core/src/services/execution/WorkOnTasksService.ts +2023 -0
- package/packages/core/src/services/execution/__tests__/QaFollowupService.test.ts +58 -0
- package/packages/core/src/services/execution/__tests__/QaProfileService.test.ts +49 -0
- package/packages/core/src/services/execution/__tests__/QaTasksService.test.ts +157 -0
- package/packages/core/src/services/execution/__tests__/TaskSelectionService.test.ts +179 -0
- package/packages/core/src/services/execution/__tests__/TaskStateService.test.ts +51 -0
- package/packages/core/src/services/execution/__tests__/WorkOnTasksService.test.ts +285 -0
- package/packages/core/src/services/jobs/.gitkeep +0 -0
- package/packages/core/src/services/jobs/JobInsightsService.ts +355 -0
- package/packages/core/src/services/jobs/JobResumeService.ts +119 -0
- package/packages/core/src/services/jobs/JobService.ts +648 -0
- package/packages/core/src/services/jobs/JobsApiClient.ts +113 -0
- package/packages/core/src/services/jobs/__tests__/JobInsightsService.test.ts +17 -0
- package/packages/core/src/services/jobs/__tests__/JobResumeService.test.ts +45 -0
- package/packages/core/src/services/jobs/__tests__/JobService.test.ts +44 -0
- package/packages/core/src/services/openapi/OpenApiService.ts +558 -0
- package/packages/core/src/services/openapi/__tests__/OpenApiService.test.ts +57 -0
- package/packages/core/src/services/planning/.gitkeep +0 -0
- package/packages/core/src/services/planning/CreateTasksService.ts +1280 -0
- package/packages/core/src/services/planning/KeyHelpers.ts +80 -0
- package/packages/core/src/services/planning/PlanningService.ts +1 -0
- package/packages/core/src/services/planning/RefineTasksService.ts +1552 -0
- package/packages/core/src/services/planning/__tests__/CreateTasksService.test.ts +288 -0
- package/packages/core/src/services/planning/__tests__/KeyHelpers.test.ts +16 -0
- package/packages/core/src/services/planning/__tests__/RefineTasksService.test.ts +172 -0
- package/packages/core/src/services/review/CodeReviewService.ts +1386 -0
- package/packages/core/src/services/review/__tests__/CodeReviewService.test.ts +89 -0
- package/packages/core/src/services/system/SystemUpdateService.ts +177 -0
- package/packages/core/src/services/system/__tests__/SystemUpdateService.test.ts +40 -0
- package/packages/core/src/services/tasks/TaskApiResolver.ts +37 -0
- package/packages/core/src/services/tasks/TaskDetailService.ts +494 -0
- package/packages/core/src/services/tasks/__tests__/TaskApiResolver.test.ts +41 -0
- package/packages/core/src/services/tasks/__tests__/TaskDetailService.test.ts +178 -0
- package/packages/core/src/services/telemetry/.gitkeep +0 -0
- package/packages/core/src/services/telemetry/TelemetryService.ts +515 -0
- package/packages/core/src/services/telemetry/__tests__/TelemetryService.test.ts +160 -0
- package/packages/core/src/workspace/.gitkeep +0 -0
- package/packages/core/src/workspace/WorkspaceManager.ts +234 -0
- package/packages/core/tsconfig.json +20 -0
- package/packages/db/CHANGELOG.md +7 -0
- package/packages/db/LICENSE +21 -0
- package/packages/db/README.md +9 -0
- package/packages/db/package.json +42 -0
- package/packages/db/src/__tests__/GlobalRepository.test.ts +109 -0
- package/packages/db/src/__tests__/SchemaAlignment.test.ts +80 -0
- package/packages/db/src/__tests__/WorkspaceRepository.test.ts +19 -0
- package/packages/db/src/index.d.ts +6 -0
- package/packages/db/src/index.d.ts.map +1 -0
- package/packages/db/src/index.js +5 -0
- package/packages/db/src/index.ts +6 -0
- package/packages/db/src/migrations/global/.gitkeep +0 -0
- package/packages/db/src/migrations/global/GlobalMigrations.d.ts +9 -0
- package/packages/db/src/migrations/global/GlobalMigrations.d.ts.map +1 -0
- package/packages/db/src/migrations/global/GlobalMigrations.js +68 -0
- package/packages/db/src/migrations/global/GlobalMigrations.ts +336 -0
- package/packages/db/src/migrations/workspace/.gitkeep +0 -0
- package/packages/db/src/migrations/workspace/WorkspaceMigrations.d.ts +9 -0
- package/packages/db/src/migrations/workspace/WorkspaceMigrations.d.ts.map +1 -0
- package/packages/db/src/migrations/workspace/WorkspaceMigrations.js +251 -0
- package/packages/db/src/migrations/workspace/WorkspaceMigrations.ts +248 -0
- package/packages/db/src/repositories/global/.gitkeep +0 -0
- package/packages/db/src/repositories/global/GlobalRepository.d.ts +30 -0
- package/packages/db/src/repositories/global/GlobalRepository.d.ts.map +1 -0
- package/packages/db/src/repositories/global/GlobalRepository.js +209 -0
- package/packages/db/src/repositories/global/GlobalRepository.ts +492 -0
- package/packages/db/src/repositories/workspace/.gitkeep +0 -0
- package/packages/db/src/repositories/workspace/WorkspaceRepository.d.ts +282 -0
- package/packages/db/src/repositories/workspace/WorkspaceRepository.d.ts.map +1 -0
- package/packages/db/src/repositories/workspace/WorkspaceRepository.js +773 -0
- package/packages/db/src/repositories/workspace/WorkspaceRepository.ts +1511 -0
- package/packages/db/src/sqlite/connection.d.ts +11 -0
- package/packages/db/src/sqlite/connection.d.ts.map +1 -0
- package/packages/db/src/sqlite/connection.js +31 -0
- package/packages/db/src/sqlite/connection.ts +35 -0
- package/packages/db/src/sqlite/pragmas.d.ts +5 -0
- package/packages/db/src/sqlite/pragmas.d.ts.map +1 -0
- package/packages/db/src/sqlite/pragmas.js +6 -0
- package/packages/db/src/sqlite/pragmas.ts +10 -0
- package/packages/db/tsconfig.json +13 -0
- package/packages/generators/package.json +21 -0
- package/packages/generators/src/__tests__/Generators.test.ts +19 -0
- package/packages/generators/src/index.ts +1 -0
- package/packages/generators/src/openapi/generateTypes.ts +1 -0
- package/packages/generators/src/openapi/validateSchema.ts +1 -0
- package/packages/generators/src/scaffolding/docs/.gitkeep +0 -0
- package/packages/generators/src/scaffolding/docs/DocsScaffolder.ts +1 -0
- package/packages/generators/src/scaffolding/global/.gitkeep +0 -0
- package/packages/generators/src/scaffolding/global/GlobalScaffolder.ts +1 -0
- package/packages/generators/src/scaffolding/workspace/.gitkeep +0 -0
- package/packages/generators/src/scaffolding/workspace/WorkspaceScaffolder.ts +1 -0
- package/packages/generators/tsconfig.json +10 -0
- package/packages/integrations/CHANGELOG.md +7 -0
- package/packages/integrations/LICENSE +21 -0
- package/packages/integrations/README.md +9 -0
- package/packages/integrations/package.json +47 -0
- package/packages/integrations/src/docdex/.gitkeep +0 -0
- package/packages/integrations/src/docdex/DocdexClient.d.ts +50 -0
- package/packages/integrations/src/docdex/DocdexClient.d.ts.map +1 -0
- package/packages/integrations/src/docdex/DocdexClient.js +216 -0
- package/packages/integrations/src/docdex/DocdexClient.ts +261 -0
- package/packages/integrations/src/docdex/__tests__/DocdexClient.test.ts +29 -0
- package/packages/integrations/src/index.d.ts +2 -0
- package/packages/integrations/src/index.d.ts.map +1 -0
- package/packages/integrations/src/index.js +4 -0
- package/packages/integrations/src/index.ts +5 -0
- package/packages/integrations/src/issues/.gitkeep +0 -0
- package/packages/integrations/src/issues/IssuesClient.ts +1 -0
- package/packages/integrations/src/issues/__tests__/IssuesClient.test.ts +10 -0
- package/packages/integrations/src/qa/.gitkeep +0 -0
- package/packages/integrations/src/qa/ChromiumQaAdapter.ts +89 -0
- package/packages/integrations/src/qa/CliQaAdapter.ts +95 -0
- package/packages/integrations/src/qa/MaestroQaAdapter.ts +91 -0
- package/packages/integrations/src/qa/QaAdapter.ts +7 -0
- package/packages/integrations/src/qa/QaClient.ts +1 -0
- package/packages/integrations/src/qa/QaTypes.ts +26 -0
- package/packages/integrations/src/qa/__tests__/ChromiumQaAdapter.test.ts +30 -0
- package/packages/integrations/src/qa/__tests__/CliQaAdapter.test.ts +33 -0
- package/packages/integrations/src/qa/__tests__/MaestroQaAdapter.test.ts +30 -0
- package/packages/integrations/src/qa/index.ts +5 -0
- package/packages/integrations/src/system/SystemClient.ts +50 -0
- package/packages/integrations/src/system/__tests__/SystemClient.test.ts +40 -0
- package/packages/integrations/src/telemetry/TelemetryClient.ts +139 -0
- package/packages/integrations/src/telemetry/__tests__/TelemetryClient.test.ts +41 -0
- package/packages/integrations/src/vcs/.gitkeep +0 -0
- package/packages/integrations/src/vcs/VcsClient.ts +211 -0
- package/packages/integrations/src/vcs/__tests__/VcsClient.test.ts +26 -0
- package/packages/integrations/tsconfig.json +14 -0
- package/packages/shared/CHANGELOG.md +7 -0
- package/packages/shared/LICENSE +21 -0
- package/packages/shared/README.md +9 -0
- package/packages/shared/package.json +40 -0
- package/packages/shared/src/__tests__/CommandMetadata.test.ts +15 -0
- package/packages/shared/src/__tests__/ServiceShells.test.ts +16 -0
- package/packages/shared/src/crypto/.gitkeep +0 -0
- package/packages/shared/src/crypto/CryptoHelper.d.ts +15 -0
- package/packages/shared/src/crypto/CryptoHelper.d.ts.map +1 -0
- package/packages/shared/src/crypto/CryptoHelper.js +54 -0
- package/packages/shared/src/crypto/CryptoHelper.ts +57 -0
- package/packages/shared/src/errors/.gitkeep +0 -0
- package/packages/shared/src/errors/ErrorFactory.ts +1 -0
- package/packages/shared/src/index.d.ts +6 -0
- package/packages/shared/src/index.d.ts.map +1 -0
- package/packages/shared/src/index.js +4 -0
- package/packages/shared/src/index.ts +35 -0
- package/packages/shared/src/logging/.gitkeep +0 -0
- package/packages/shared/src/logging/Logger.ts +1 -0
- package/packages/shared/src/metadata/CommandMetadata.ts +165 -0
- package/packages/shared/src/openapi/.gitkeep +0 -0
- package/packages/shared/src/openapi/OpenApiTypes.d.ts +216 -0
- package/packages/shared/src/openapi/OpenApiTypes.d.ts.map +1 -0
- package/packages/shared/src/openapi/OpenApiTypes.js +1 -0
- package/packages/shared/src/openapi/OpenApiTypes.ts +312 -0
- package/packages/shared/src/paths/.gitkeep +0 -0
- package/packages/shared/src/paths/PathHelper.d.ts +12 -0
- package/packages/shared/src/paths/PathHelper.d.ts.map +1 -0
- package/packages/shared/src/paths/PathHelper.js +24 -0
- package/packages/shared/src/paths/PathHelper.ts +29 -0
- package/packages/shared/src/qa/QaProfile.ts +14 -0
- package/packages/shared/src/utils/.gitkeep +0 -0
- package/packages/shared/src/utils/UtilityService.ts +1 -0
- package/packages/shared/tsconfig.json +10 -0
- package/packages/testing/package.json +26 -0
- package/packages/testing/src/__tests__/TestingFakes.test.ts +15 -0
- package/packages/testing/src/cli/e2e/.gitkeep +0 -0
- package/packages/testing/src/cli/e2e/E2eSuite.ts +1 -0
- package/packages/testing/src/fakes/agents/.gitkeep +0 -0
- package/packages/testing/src/fakes/agents/FakeAgents.ts +1 -0
- package/packages/testing/src/fakes/docdex/.gitkeep +0 -0
- package/packages/testing/src/fakes/docdex/FakeDocdexClient.ts +1 -0
- package/packages/testing/src/fakes/qa/.gitkeep +0 -0
- package/packages/testing/src/fakes/qa/FakeQaClient.ts +1 -0
- package/packages/testing/src/fakes/vcs/.gitkeep +0 -0
- package/packages/testing/src/fakes/vcs/FakeVcsClient.ts +1 -0
- package/packages/testing/src/fixtures/db/.gitkeep +0 -0
- package/packages/testing/src/fixtures/db/DbFixtures.ts +1 -0
- package/packages/testing/src/fixtures/workspaces/.gitkeep +0 -0
- package/packages/testing/src/fixtures/workspaces/WorkspaceFixtures.ts +1 -0
- package/packages/testing/src/index.ts +1 -0
- package/packages/testing/tsconfig.json +10 -0
- package/pnpm-workspace.yaml +2 -0
- package/prompts/README.md +5 -0
- package/prompts/code-reviewer.md +23 -0
- package/prompts/code-writer.md +35 -0
- package/prompts/gateway-agent.md +27 -0
- package/prompts/qa-agent.md +21 -0
- package/release-please-config.json +39 -0
- package/scripts/build-all.ts +1 -0
- package/scripts/dev.ts +1 -0
- package/scripts/install-local-cli.sh +28 -0
- package/scripts/pack-npm-tarballs.js +63 -0
- package/scripts/release.ts +1 -0
- package/scripts/run-node-tests.js +37 -0
- package/tests/all.js +127 -0
- package/tests/api/openapi_spec.test.js +21 -0
- package/tests/artifacts.md +31 -0
- package/tests/component/cli_version.test.js +38 -0
- package/tests/integration/workspace_resolver.test.js +44 -0
- package/tests/unit/crypto_helper.test.js +36 -0
- package/tests/unit/path_helper.test.js +20 -0
- package/tsconfig.base.json +32 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Agent,
|
|
3
|
+
AgentAuthMetadata,
|
|
4
|
+
AgentHealth,
|
|
5
|
+
AgentPromptManifest,
|
|
6
|
+
CreateAgentInput,
|
|
7
|
+
UpdateAgentInput,
|
|
8
|
+
CryptoHelper,
|
|
9
|
+
} from "@mcoda/shared";
|
|
10
|
+
import { GlobalCommandRun, GlobalRepository } from "@mcoda/db";
|
|
11
|
+
import { AgentService, InvocationResult } from "@mcoda/agents";
|
|
12
|
+
import { RoutingService } from "../services/agents/RoutingService.js";
|
|
13
|
+
|
|
14
|
+
export interface AgentResponse extends Agent {
|
|
15
|
+
capabilities: string[];
|
|
16
|
+
prompts?: AgentPromptManifest;
|
|
17
|
+
health?: AgentHealth;
|
|
18
|
+
auth?: AgentAuthMetadata;
|
|
19
|
+
models?: Agent["models"];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class AgentsApi {
|
|
23
|
+
constructor(private repo: GlobalRepository, private agentService: AgentService, private routingService: RoutingService) {}
|
|
24
|
+
|
|
25
|
+
static async create(): Promise<AgentsApi> {
|
|
26
|
+
const repo = await GlobalRepository.create();
|
|
27
|
+
const agentService = new AgentService(repo);
|
|
28
|
+
const routingService = await RoutingService.create();
|
|
29
|
+
return new AgentsApi(repo, agentService, routingService);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async close(): Promise<void> {
|
|
33
|
+
await this.repo.close();
|
|
34
|
+
if ((this.routingService as any)?.close) {
|
|
35
|
+
await (this.routingService as any).close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private async resolveAgent(idOrSlug: string): Promise<Agent> {
|
|
40
|
+
return this.agentService.resolveAgent(idOrSlug);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private async withCommandRun<T>(
|
|
44
|
+
commandName: string,
|
|
45
|
+
payload: Record<string, unknown> | undefined,
|
|
46
|
+
fn: (run: GlobalCommandRun) => Promise<T>,
|
|
47
|
+
): Promise<T> {
|
|
48
|
+
const run = await this.repo.createCommandRun({
|
|
49
|
+
commandName,
|
|
50
|
+
startedAt: new Date().toISOString(),
|
|
51
|
+
status: "running",
|
|
52
|
+
payload,
|
|
53
|
+
});
|
|
54
|
+
try {
|
|
55
|
+
const result = await fn(run);
|
|
56
|
+
await this.repo.completeCommandRun(run.id, {
|
|
57
|
+
status: "succeeded",
|
|
58
|
+
completedAt: new Date().toISOString(),
|
|
59
|
+
exitCode: 0,
|
|
60
|
+
result: payload ? { payload, output: result } : { output: result },
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
await this.repo.completeCommandRun(run.id, {
|
|
65
|
+
status: "failed",
|
|
66
|
+
completedAt: new Date().toISOString(),
|
|
67
|
+
exitCode: 1,
|
|
68
|
+
errorSummary: (error as Error).message,
|
|
69
|
+
});
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async listAgents(): Promise<AgentResponse[]> {
|
|
75
|
+
const agents = await this.repo.listAgents();
|
|
76
|
+
const health = await this.repo.listAgentHealthSummary();
|
|
77
|
+
const healthById = new Map(health.map((h) => [h.agentId, h]));
|
|
78
|
+
const results: AgentResponse[] = [];
|
|
79
|
+
for (const agent of agents) {
|
|
80
|
+
const [capabilities, models] = await Promise.all([
|
|
81
|
+
this.repo.getAgentCapabilities(agent.id),
|
|
82
|
+
this.repo.getAgentModels(agent.id),
|
|
83
|
+
]);
|
|
84
|
+
results.push({
|
|
85
|
+
...agent,
|
|
86
|
+
capabilities,
|
|
87
|
+
models,
|
|
88
|
+
health: healthById.get(agent.id),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async createAgent(input: CreateAgentInput): Promise<AgentResponse> {
|
|
95
|
+
return this.withCommandRun("agent.add", { slug: input.slug, adapter: input.adapter }, async () => {
|
|
96
|
+
const agent = await this.repo.createAgent(input);
|
|
97
|
+
const [capabilities, models] = await Promise.all([
|
|
98
|
+
this.repo.getAgentCapabilities(agent.id),
|
|
99
|
+
this.repo.getAgentModels(agent.id),
|
|
100
|
+
]);
|
|
101
|
+
return { ...agent, capabilities, models };
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async getAgent(idOrSlug: string): Promise<AgentResponse> {
|
|
106
|
+
const agent = await this.resolveAgent(idOrSlug);
|
|
107
|
+
const [capabilities, prompts, health, auth, models] = await Promise.all([
|
|
108
|
+
this.repo.getAgentCapabilities(agent.id),
|
|
109
|
+
this.repo.getAgentPrompts(agent.id),
|
|
110
|
+
this.repo.getAgentHealth(agent.id),
|
|
111
|
+
this.repo.getAgentAuthMetadata(agent.id),
|
|
112
|
+
this.repo.getAgentModels(agent.id),
|
|
113
|
+
]);
|
|
114
|
+
return { ...agent, capabilities, prompts, health, auth, models };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async updateAgent(idOrSlug: string, patch: UpdateAgentInput): Promise<AgentResponse> {
|
|
118
|
+
const agent = await this.resolveAgent(idOrSlug);
|
|
119
|
+
return this.withCommandRun("agent.update", { id: agent.id, patch }, async () => {
|
|
120
|
+
const updated = await this.repo.updateAgent(agent.id, patch);
|
|
121
|
+
const [capabilities, models] = await Promise.all([
|
|
122
|
+
this.repo.getAgentCapabilities(agent.id),
|
|
123
|
+
this.repo.getAgentModels(agent.id),
|
|
124
|
+
]);
|
|
125
|
+
return { ...(updated as Agent), capabilities, models };
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async deleteAgent(idOrSlug: string, force = false): Promise<void> {
|
|
130
|
+
const agent = await this.resolveAgent(idOrSlug);
|
|
131
|
+
if (!force) {
|
|
132
|
+
const refs = await this.repo.findWorkspaceReferences(agent.id);
|
|
133
|
+
if (refs.length > 0) {
|
|
134
|
+
const details = refs
|
|
135
|
+
.map((r) => `${r.workspaceId === "__GLOBAL__" ? "global" : r.workspaceId}:${r.commandName}`)
|
|
136
|
+
.join(", ");
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Agent is referenced by routing defaults (${details}); re-run with --force to delete`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
await this.withCommandRun("agent.delete", { id: agent.id, slug: agent.slug }, async () => {
|
|
143
|
+
await this.repo.deleteAgent(agent.id);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async setAgentAuth(idOrSlug: string, secret: string): Promise<AgentAuthMetadata> {
|
|
148
|
+
const agent = await this.resolveAgent(idOrSlug);
|
|
149
|
+
return this.withCommandRun("agent.auth.set", { id: agent.id }, async () => {
|
|
150
|
+
const encrypted = await CryptoHelper.encryptSecret(secret);
|
|
151
|
+
await this.repo.setAgentAuth(agent.id, encrypted);
|
|
152
|
+
return this.repo.getAgentAuthMetadata(agent.id);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async getAgentPrompts(idOrSlug: string): Promise<AgentPromptManifest | undefined> {
|
|
157
|
+
const agent = await this.resolveAgent(idOrSlug);
|
|
158
|
+
return this.repo.getAgentPrompts(agent.id);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async testAgent(idOrSlug: string): Promise<AgentHealth> {
|
|
162
|
+
const agent = await this.resolveAgent(idOrSlug);
|
|
163
|
+
return this.withCommandRun("agent.test", { id: agent.id, slug: agent.slug }, async (run) => {
|
|
164
|
+
const health = await this.agentService.healthCheck(agent.id);
|
|
165
|
+
await this.repo.recordTokenUsage({
|
|
166
|
+
agentId: agent.id,
|
|
167
|
+
commandRunId: run.id,
|
|
168
|
+
modelName: agent.defaultModel,
|
|
169
|
+
tokensPrompt: 0,
|
|
170
|
+
tokensCompletion: 0,
|
|
171
|
+
tokensTotal: 0,
|
|
172
|
+
timestamp: new Date().toISOString(),
|
|
173
|
+
metadata: { reason: "agent.test", healthStatus: health.status },
|
|
174
|
+
});
|
|
175
|
+
return health;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async probeAgent(
|
|
180
|
+
idOrSlug: string,
|
|
181
|
+
prompt = "Hello from mcoda test-agent. Please reply with a short acknowledgement.",
|
|
182
|
+
): Promise<{ health: AgentHealth; response: InvocationResult; prompt: string }> {
|
|
183
|
+
const agent = await this.resolveAgent(idOrSlug);
|
|
184
|
+
const trimmedPrompt = prompt.trim() || "Hello from mcoda test-agent. Please reply with a short acknowledgement.";
|
|
185
|
+
return this.withCommandRun(
|
|
186
|
+
"agent.test",
|
|
187
|
+
{ id: agent.id, slug: agent.slug, prompt: trimmedPrompt },
|
|
188
|
+
async (run) => {
|
|
189
|
+
const health = await this.agentService.healthCheck(agent.id);
|
|
190
|
+
const response = await this.agentService.invoke(agent.id, {
|
|
191
|
+
input: trimmedPrompt,
|
|
192
|
+
metadata: { command: "test-agent" },
|
|
193
|
+
});
|
|
194
|
+
await this.repo.recordTokenUsage({
|
|
195
|
+
agentId: agent.id,
|
|
196
|
+
commandRunId: run.id,
|
|
197
|
+
modelName: agent.defaultModel,
|
|
198
|
+
tokensPrompt: 0,
|
|
199
|
+
tokensCompletion: 0,
|
|
200
|
+
tokensTotal: 0,
|
|
201
|
+
timestamp: new Date().toISOString(),
|
|
202
|
+
metadata: { reason: "agent.test", healthStatus: health.status, adapter: response.adapter },
|
|
203
|
+
});
|
|
204
|
+
return { health, response, prompt: trimmedPrompt };
|
|
205
|
+
},
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async setDefaultAgent(
|
|
210
|
+
idOrSlug: string,
|
|
211
|
+
workspaceId = "__GLOBAL__",
|
|
212
|
+
commandName = "default",
|
|
213
|
+
): Promise<void> {
|
|
214
|
+
const agent = await this.resolveAgent(idOrSlug);
|
|
215
|
+
await this.withCommandRun("agent.set-default", { workspaceId, commandName, agent: agent.slug }, async () => {
|
|
216
|
+
await this.routingService.updateWorkspaceDefaults(workspaceId, { set: { [commandName]: agent.slug } });
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { WorkspaceResolver } from "../workspace/WorkspaceManager.js";
|
|
2
|
+
import { QaTasksService, QaTasksRequest, QaTasksResponse } from "../services/execution/QaTasksService.js";
|
|
3
|
+
|
|
4
|
+
export class QaTasksApi {
|
|
5
|
+
static async runQa(
|
|
6
|
+
request: Partial<QaTasksRequest> & { workspaceRoot?: string; noTelemetry?: boolean },
|
|
7
|
+
): Promise<QaTasksResponse> {
|
|
8
|
+
const workspace = await WorkspaceResolver.resolveWorkspace({
|
|
9
|
+
cwd: process.cwd(),
|
|
10
|
+
explicitWorkspace: request.workspaceRoot,
|
|
11
|
+
});
|
|
12
|
+
const service = await QaTasksService.create(workspace, { noTelemetry: request.noTelemetry ?? false });
|
|
13
|
+
try {
|
|
14
|
+
return await service.run({
|
|
15
|
+
workspace,
|
|
16
|
+
projectKey: request.projectKey,
|
|
17
|
+
epicKey: request.epicKey,
|
|
18
|
+
storyKey: request.storyKey,
|
|
19
|
+
taskKeys: request.taskKeys,
|
|
20
|
+
statusFilter: request.statusFilter,
|
|
21
|
+
mode: request.mode,
|
|
22
|
+
resumeJobId: request.resumeJobId,
|
|
23
|
+
profileName: request.profileName,
|
|
24
|
+
level: request.level,
|
|
25
|
+
testCommand: request.testCommand,
|
|
26
|
+
agentName: request.agentName,
|
|
27
|
+
agentStream: request.agentStream,
|
|
28
|
+
createFollowupTasks: request.createFollowupTasks,
|
|
29
|
+
dryRun: request.dryRun,
|
|
30
|
+
result: request.result,
|
|
31
|
+
notes: request.notes,
|
|
32
|
+
evidenceUrl: request.evidenceUrl,
|
|
33
|
+
});
|
|
34
|
+
} finally {
|
|
35
|
+
await service.close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { RefineTasksRequest, RefineTasksResult } from "@mcoda/shared";
|
|
2
|
+
import { WorkspaceResolver } from "../workspace/WorkspaceManager.js";
|
|
3
|
+
import { RefineTasksService } from "../services/planning/RefineTasksService.js";
|
|
4
|
+
|
|
5
|
+
export class TasksApi {
|
|
6
|
+
static async refineTasks(request: RefineTasksRequest & { workspaceRoot?: string }): Promise<RefineTasksResult> {
|
|
7
|
+
const workspace = await WorkspaceResolver.resolveWorkspace({
|
|
8
|
+
cwd: process.cwd(),
|
|
9
|
+
explicitWorkspace: request.workspaceRoot,
|
|
10
|
+
});
|
|
11
|
+
const service = await RefineTasksService.create(workspace);
|
|
12
|
+
try {
|
|
13
|
+
return await service.refineTasks({
|
|
14
|
+
workspace,
|
|
15
|
+
projectKey: request.projectKey,
|
|
16
|
+
epicKey: request.epicKey,
|
|
17
|
+
storyKey: request.userStoryKey,
|
|
18
|
+
taskKeys: request.taskKeys,
|
|
19
|
+
statusFilter: request.statusFilter,
|
|
20
|
+
maxTasks: request.maxTasks,
|
|
21
|
+
strategy: request.strategy,
|
|
22
|
+
agentName: request.agentIdOverride,
|
|
23
|
+
agentStream: true,
|
|
24
|
+
fromDb: true,
|
|
25
|
+
dryRun: request.dryRun,
|
|
26
|
+
planInPath: request.planInPath,
|
|
27
|
+
planOutPath: request.planOutPath,
|
|
28
|
+
jobId: undefined,
|
|
29
|
+
outputJson: false,
|
|
30
|
+
});
|
|
31
|
+
} finally {
|
|
32
|
+
await service.close();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { after, test } from "node:test";
|
|
6
|
+
import { AgentsApi } from "../AgentsApi.js";
|
|
7
|
+
import { Connection, GlobalMigrations, GlobalRepository } from "@mcoda/db";
|
|
8
|
+
import { AgentService } from "@mcoda/agents";
|
|
9
|
+
import { PathHelper } from "@mcoda/shared";
|
|
10
|
+
|
|
11
|
+
const withTempHome = async (fn: (home: string) => Promise<void>): Promise<void> => {
|
|
12
|
+
const originalHome = process.env.HOME;
|
|
13
|
+
const home = await fs.mkdtemp(path.join(os.tmpdir(), "mcoda-agents-api-"));
|
|
14
|
+
process.env.HOME = home;
|
|
15
|
+
try {
|
|
16
|
+
await fn(home);
|
|
17
|
+
} finally {
|
|
18
|
+
process.env.HOME = originalHome;
|
|
19
|
+
await fs.rm(home, { recursive: true, force: true });
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const originalSkipCliChecks = process.env.MCODA_SKIP_CLI_CHECKS;
|
|
24
|
+
const originalCliStub = process.env.MCODA_CLI_STUB;
|
|
25
|
+
process.env.MCODA_SKIP_CLI_CHECKS = "1";
|
|
26
|
+
process.env.MCODA_CLI_STUB = "1";
|
|
27
|
+
|
|
28
|
+
const makeApi = async () => {
|
|
29
|
+
const conn = await Connection.open(PathHelper.getGlobalDbPath());
|
|
30
|
+
await GlobalMigrations.run(conn.db);
|
|
31
|
+
const repo = new GlobalRepository(conn.db, conn);
|
|
32
|
+
const agentService = new AgentService(repo);
|
|
33
|
+
const routingService = {
|
|
34
|
+
updateWorkspaceDefaults: async () => {},
|
|
35
|
+
close: async () => {},
|
|
36
|
+
};
|
|
37
|
+
const api = new AgentsApi(repo, agentService as any, routingService as any);
|
|
38
|
+
return { api, repo, conn };
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
test("setAgentAuth stores encrypted secret and returns redacted metadata", async () => {
|
|
42
|
+
await withTempHome(async () => {
|
|
43
|
+
const { api, repo } = await makeApi();
|
|
44
|
+
await repo.createAgent({ slug: "openai", adapter: "openai-api" });
|
|
45
|
+
|
|
46
|
+
const auth = await api.setAgentAuth("openai", "super-secret");
|
|
47
|
+
assert.equal(auth.configured, true);
|
|
48
|
+
assert.ok(auth.lastUpdatedAt);
|
|
49
|
+
// ensure secrets are not returned
|
|
50
|
+
assert.equal((auth as any).encryptedSecret, undefined);
|
|
51
|
+
|
|
52
|
+
const agent = await api.getAgent("openai");
|
|
53
|
+
assert.equal(agent.auth?.configured, true);
|
|
54
|
+
assert.equal((agent.auth as any)?.encryptedSecret, undefined);
|
|
55
|
+
const stored = await repo.getAgentAuthSecret(agent.id);
|
|
56
|
+
assert.ok(stored?.encryptedSecret);
|
|
57
|
+
assert.notEqual(stored?.encryptedSecret, "super-secret");
|
|
58
|
+
|
|
59
|
+
await api.close();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
after(() => {
|
|
64
|
+
process.env.MCODA_SKIP_CLI_CHECKS = originalSkipCliChecks;
|
|
65
|
+
if (originalCliStub === undefined) {
|
|
66
|
+
delete process.env.MCODA_CLI_STUB;
|
|
67
|
+
} else {
|
|
68
|
+
process.env.MCODA_CLI_STUB = originalCliStub;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("getAgentPrompts returns stored prompt manifest", async () => {
|
|
73
|
+
await withTempHome(async () => {
|
|
74
|
+
const { api, repo } = await makeApi();
|
|
75
|
+
await repo.createAgent({
|
|
76
|
+
slug: "prompted",
|
|
77
|
+
adapter: "local-model",
|
|
78
|
+
prompts: { jobPrompt: "job", characterPrompt: "character", commandPrompts: { test: "cmd" } },
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const manifest = await api.getAgentPrompts("prompted");
|
|
82
|
+
assert.ok(manifest);
|
|
83
|
+
assert.equal(manifest?.jobPrompt, "job");
|
|
84
|
+
assert.equal(manifest?.commandPrompts?.test, "cmd");
|
|
85
|
+
|
|
86
|
+
await api.close();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("testAgent stores health and command_runs entry", async () => {
|
|
91
|
+
await withTempHome(async () => {
|
|
92
|
+
const { api, repo, conn } = await makeApi();
|
|
93
|
+
await repo.createAgent({ slug: "codex", adapter: "codex-cli", capabilities: ["chat"] });
|
|
94
|
+
|
|
95
|
+
const health = await api.testAgent("codex");
|
|
96
|
+
assert.equal(health.status, "healthy");
|
|
97
|
+
const stored = await repo.getAgentHealth((await repo.getAgentBySlug("codex"))!.id);
|
|
98
|
+
assert.equal(stored?.status, "healthy");
|
|
99
|
+
const runs = await conn.db.all<{ command_name: string }[]>(
|
|
100
|
+
"SELECT command_name FROM command_runs WHERE command_name = 'agent.test'",
|
|
101
|
+
);
|
|
102
|
+
assert.ok(runs.length >= 1);
|
|
103
|
+
const tokenUsage = await conn.db.all<{ command_run_id: string }[]>("SELECT command_run_id FROM token_usage");
|
|
104
|
+
assert.ok(tokenUsage.length >= 1);
|
|
105
|
+
|
|
106
|
+
await api.close();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("deleteAgent blocks referenced agents unless forced and logs deletion", async () => {
|
|
111
|
+
await withTempHome(async () => {
|
|
112
|
+
const { api, repo, conn } = await makeApi();
|
|
113
|
+
const agent = await repo.createAgent({ slug: "used", adapter: "local-model" });
|
|
114
|
+
await repo.setWorkspaceDefault("ws-1", "work-on-tasks", agent.id);
|
|
115
|
+
|
|
116
|
+
await assert.rejects(() => api.deleteAgent("used"), /routing defaults/i);
|
|
117
|
+
const stillExists = await repo.getAgentBySlug("used");
|
|
118
|
+
assert.ok(stillExists);
|
|
119
|
+
|
|
120
|
+
await api.deleteAgent("used", true);
|
|
121
|
+
const missing = await repo.getAgentBySlug("used");
|
|
122
|
+
assert.equal(missing, undefined);
|
|
123
|
+
const runs = await conn.db.all<{ command_name: string }[]>(
|
|
124
|
+
"SELECT command_name FROM command_runs WHERE command_name = 'agent.delete'",
|
|
125
|
+
);
|
|
126
|
+
assert.ok(runs.length >= 1);
|
|
127
|
+
|
|
128
|
+
await api.close();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("listAgents returns capabilities, models, and stored health", async () => {
|
|
133
|
+
await withTempHome(async () => {
|
|
134
|
+
const { api, repo } = await makeApi();
|
|
135
|
+
const agent = await repo.createAgent({
|
|
136
|
+
slug: "cap-agent",
|
|
137
|
+
adapter: "openai-api",
|
|
138
|
+
defaultModel: "gpt-4o",
|
|
139
|
+
capabilities: ["chat", "code_write"],
|
|
140
|
+
models: [
|
|
141
|
+
{ agentId: "ignore", modelName: "gpt-4o", isDefault: true },
|
|
142
|
+
{ agentId: "ignore", modelName: "gpt-4.1-mini", isDefault: false },
|
|
143
|
+
],
|
|
144
|
+
});
|
|
145
|
+
await repo.setAgentHealth({
|
|
146
|
+
agentId: agent.id,
|
|
147
|
+
status: "healthy",
|
|
148
|
+
lastCheckedAt: new Date().toISOString(),
|
|
149
|
+
latencyMs: 1,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const agents = await api.listAgents();
|
|
153
|
+
const found = agents.find((a) => a.slug === "cap-agent");
|
|
154
|
+
assert.ok(found);
|
|
155
|
+
assert.equal(found.health?.status, "healthy");
|
|
156
|
+
assert.deepEqual(found.capabilities?.sort(), ["chat", "code_write"].sort());
|
|
157
|
+
assert.ok(found.models?.find((m) => m.modelName === "gpt-4o"));
|
|
158
|
+
|
|
159
|
+
await api.close();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("createAgent/updateAgent round trip with auth redaction", async () => {
|
|
164
|
+
await withTempHome(async () => {
|
|
165
|
+
const { api, repo } = await makeApi();
|
|
166
|
+
await api.createAgent({ slug: "crud", adapter: "openai-api", defaultModel: "gpt-4o", capabilities: ["chat"] });
|
|
167
|
+
await api.setAgentAuth("crud", "super-secret");
|
|
168
|
+
const updated = await api.updateAgent("crud", { defaultModel: "gpt-4.1-mini", capabilities: ["chat", "plan"] });
|
|
169
|
+
assert.equal(updated.defaultModel, "gpt-4.1-mini");
|
|
170
|
+
assert.deepEqual(updated.capabilities?.sort(), ["chat", "plan"].sort());
|
|
171
|
+
|
|
172
|
+
const agent = await api.getAgent("crud");
|
|
173
|
+
assert.equal(agent.auth?.configured, true);
|
|
174
|
+
assert.equal((agent.auth as any)?.encryptedSecret, undefined);
|
|
175
|
+
const stored = await repo.getAgentAuthSecret(agent.id);
|
|
176
|
+
assert.ok(stored?.encryptedSecret);
|
|
177
|
+
|
|
178
|
+
await api.close();
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("setDefaultAgent delegates to routing service", async () => {
|
|
183
|
+
await withTempHome(async () => {
|
|
184
|
+
const conn = await Connection.open(PathHelper.getGlobalDbPath());
|
|
185
|
+
await GlobalMigrations.run(conn.db);
|
|
186
|
+
const repo = new GlobalRepository(conn.db, conn);
|
|
187
|
+
const agentService = new AgentService(repo);
|
|
188
|
+
const agent = await repo.createAgent({ slug: "router", adapter: "local-model" });
|
|
189
|
+
let called = 0;
|
|
190
|
+
const routingService = {
|
|
191
|
+
updateWorkspaceDefaults: async (workspaceId: string, update: any) => {
|
|
192
|
+
called += 1;
|
|
193
|
+
assert.equal(workspaceId, "ws-routing");
|
|
194
|
+
assert.equal(update.set?.default, agent.slug);
|
|
195
|
+
},
|
|
196
|
+
close: async () => {},
|
|
197
|
+
};
|
|
198
|
+
const api = new AgentsApi(repo, agentService as any, routingService as any);
|
|
199
|
+
await api.setDefaultAgent(agent.slug, "ws-routing");
|
|
200
|
+
assert.equal(called, 1);
|
|
201
|
+
await api.close();
|
|
202
|
+
});
|
|
203
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { WorkspaceRepository } from "@mcoda/db";
|
|
7
|
+
import { WorkspaceResolver } from "../../workspace/WorkspaceManager.js";
|
|
8
|
+
import { QaTasksApi } from "../QaTasksApi.js";
|
|
9
|
+
|
|
10
|
+
test("QaTasksApi.runQa supports manual dry-run", async () => {
|
|
11
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "mcoda-qa-api-"));
|
|
12
|
+
const workspace = await WorkspaceResolver.resolveWorkspace({ cwd: dir, explicitWorkspace: dir });
|
|
13
|
+
const repo = await WorkspaceRepository.create(workspace.workspaceRoot);
|
|
14
|
+
try {
|
|
15
|
+
const project = await repo.createProjectIfMissing({ key: "proj", name: "Project" });
|
|
16
|
+
const [epic] = await repo.insertEpics([
|
|
17
|
+
{ projectId: project.id, key: "proj-epic", title: "Epic", description: "", priority: 1 },
|
|
18
|
+
]);
|
|
19
|
+
const [story] = await repo.insertStories([
|
|
20
|
+
{ projectId: project.id, epicId: epic.id, key: "proj-epic-us-01", title: "Story", description: "" },
|
|
21
|
+
]);
|
|
22
|
+
await repo.insertTasks([
|
|
23
|
+
{
|
|
24
|
+
projectId: project.id,
|
|
25
|
+
epicId: epic.id,
|
|
26
|
+
userStoryId: story.id,
|
|
27
|
+
key: "proj-epic-us-01-t01",
|
|
28
|
+
title: "Task QA",
|
|
29
|
+
description: "",
|
|
30
|
+
status: "ready_to_qa",
|
|
31
|
+
storyPoints: 1,
|
|
32
|
+
},
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
const result = await QaTasksApi.runQa({
|
|
36
|
+
workspaceRoot: dir,
|
|
37
|
+
projectKey: "proj",
|
|
38
|
+
mode: "manual",
|
|
39
|
+
result: "pass",
|
|
40
|
+
createFollowupTasks: "none",
|
|
41
|
+
dryRun: false,
|
|
42
|
+
agentStream: false,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
assert.equal(result.results.length, 1);
|
|
46
|
+
assert.equal(result.results[0]?.outcome, "pass");
|
|
47
|
+
} finally {
|
|
48
|
+
await repo.close();
|
|
49
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { WorkspaceRepository } from "@mcoda/db";
|
|
7
|
+
import { WorkspaceResolver } from "../../workspace/WorkspaceManager.js";
|
|
8
|
+
import { TasksApi } from "../TasksApi.js";
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
test("TasksApi.refineTasks wires plan-in requests", async () => {
|
|
12
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "mcoda-tasks-api-"));
|
|
13
|
+
const workspace = await WorkspaceResolver.resolveWorkspace({ cwd: dir, explicitWorkspace: dir });
|
|
14
|
+
const repo = await WorkspaceRepository.create(workspace.workspaceRoot);
|
|
15
|
+
try {
|
|
16
|
+
const project = await repo.createProjectIfMissing({ key: "demo", name: "demo" });
|
|
17
|
+
const [epic] = await repo.insertEpics([
|
|
18
|
+
{ projectId: project.id, key: "demo-01", title: "Epic", description: "", priority: 1 },
|
|
19
|
+
]);
|
|
20
|
+
const [story] = await repo.insertStories([
|
|
21
|
+
{ projectId: project.id, epicId: epic.id, key: "demo-01-us-01", title: "Story", description: "" },
|
|
22
|
+
]);
|
|
23
|
+
const [task] = await repo.insertTasks([
|
|
24
|
+
{
|
|
25
|
+
projectId: project.id,
|
|
26
|
+
epicId: epic.id,
|
|
27
|
+
userStoryId: story.id,
|
|
28
|
+
key: "demo-01-us-01-t01",
|
|
29
|
+
title: "Task",
|
|
30
|
+
description: "",
|
|
31
|
+
status: "not_started",
|
|
32
|
+
},
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
const plan = {
|
|
36
|
+
strategy: "estimate",
|
|
37
|
+
operations: [{ op: "update_estimate", taskKey: task.key, storyPoints: 5 }],
|
|
38
|
+
};
|
|
39
|
+
const planPath = path.join(dir, "plan.json");
|
|
40
|
+
await fs.writeFile(planPath, JSON.stringify(plan, null, 2), "utf8");
|
|
41
|
+
|
|
42
|
+
const result = await TasksApi.refineTasks({
|
|
43
|
+
workspaceRoot: dir,
|
|
44
|
+
projectKey: "demo",
|
|
45
|
+
planInPath: planPath,
|
|
46
|
+
strategy: "estimate",
|
|
47
|
+
dryRun: true,
|
|
48
|
+
} as any);
|
|
49
|
+
|
|
50
|
+
assert.equal(result.plan.operations.length, 1);
|
|
51
|
+
assert.equal(result.plan.operations[0]?.op, "update_estimate");
|
|
52
|
+
} finally {
|
|
53
|
+
await repo.close();
|
|
54
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
55
|
+
}
|
|
56
|
+
});
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class ConfigService {}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class Dependency {}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class Epic {}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class Project {}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class Task {}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class UserStory {}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export * from "./api/AgentsApi.js";
|
|
2
|
+
export * from "./services/docs/DocsService.js";
|
|
3
|
+
export * from "./services/openapi/OpenApiService.js";
|
|
4
|
+
export * from "./services/jobs/JobService.js";
|
|
5
|
+
export * from "./services/jobs/JobInsightsService.js";
|
|
6
|
+
export * from "./services/jobs/JobResumeService.js";
|
|
7
|
+
export * from "./services/planning/CreateTasksService.js";
|
|
8
|
+
export * from "./services/planning/RefineTasksService.js";
|
|
9
|
+
export * from "./services/planning/KeyHelpers.js";
|
|
10
|
+
export * from "./services/execution/TaskSelectionService.js";
|
|
11
|
+
export * from "./services/execution/TaskStateService.js";
|
|
12
|
+
export * from "./services/execution/WorkOnTasksService.js";
|
|
13
|
+
export * from "./services/execution/QaTasksService.js";
|
|
14
|
+
export * from "./services/review/CodeReviewService.js";
|
|
15
|
+
export * from "./api/TasksApi.js";
|
|
16
|
+
export * from "./api/QaTasksApi.js";
|
|
17
|
+
export * from "./services/backlog/BacklogService.js";
|
|
18
|
+
export * from "./services/estimate/EstimateService.js";
|
|
19
|
+
export * from "./services/estimate/VelocityService.js";
|
|
20
|
+
export * from "./services/estimate/types.js";
|
|
21
|
+
export * from "./services/telemetry/TelemetryService.js";
|
|
22
|
+
export * from "./services/tasks/TaskDetailService.js";
|
|
23
|
+
export * from "./services/backlog/TaskOrderingService.js";
|
|
24
|
+
export * from "./services/agents/RoutingService.js";
|
|
25
|
+
export * from "./services/agents/GatewayAgentService.js";
|
|
26
|
+
export * from "./workspace/WorkspaceManager.js";
|
|
27
|
+
export * from "./services/system/SystemUpdateService.js";
|
|
File without changes
|