crewly 1.3.31 → 1.4.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/config/constants.ts +18 -3
- package/config/hooks/install-hooks.sh +88 -0
- package/config/hooks/pre-commit +104 -0
- package/config/orchestrator_tasks/prompts/orchestrator-prompt.md +17 -24
- package/config/roles/auditor/role.json +13 -0
- package/config/roles/orchestrator/prompt.md +25 -0
- package/config/roles/product-manager/prompt.md +18 -1
- package/config/roles/researcher/prompt.md +110 -0
- package/config/roles/team-leader/prompt.md +31 -8
- package/config/roles/team-leader/tl-addon.md +40 -9
- package/config/roles/ux-designer/prompt.md +111 -0
- package/config/skills/_common/lib.sh +33 -0
- package/config/skills/agent/browse-stealth/{instructions.md → SKILL.md} +40 -0
- package/config/skills/agent/chrome-attach/SKILL.md +84 -0
- package/config/skills/agent/chrome-attach/execute.sh +279 -0
- package/config/skills/agent/competitor-content-tracker/{instructions.md → SKILL.md} +34 -0
- package/config/skills/agent/computer-use/{instructions.md → SKILL.md} +43 -0
- package/config/skills/agent/content-calendar/{instructions.md → SKILL.md} +32 -0
- package/config/skills/agent/content-repurposer/{instructions.md → SKILL.md} +38 -0
- package/config/skills/agent/content-writer/{instructions.md → SKILL.md} +38 -0
- package/config/skills/agent/core/accept-task/{instructions.md → SKILL.md} +37 -0
- package/config/skills/agent/core/block-task/{instructions.md → SKILL.md} +37 -0
- package/config/skills/agent/core/check-quality-gates/{instructions.md → SKILL.md} +40 -0
- package/config/skills/agent/core/complete-task/{instructions.md → SKILL.md} +37 -0
- package/config/skills/agent/core/complete-task/execute.sh +15 -0
- package/config/skills/agent/core/generate-pdf/{instructions.md → SKILL.md} +42 -0
- package/config/skills/agent/core/get-my-context/{instructions.md → SKILL.md} +38 -0
- package/config/skills/agent/core/get-sops/{instructions.md → SKILL.md} +38 -0
- package/config/skills/agent/core/get-team-norms/execute.sh +106 -0
- package/config/skills/agent/core/get-team-status/SKILL.md +55 -0
- package/config/skills/agent/core/handoff-task/execute.sh +150 -0
- package/config/skills/agent/core/heartbeat/{instructions.md → SKILL.md} +27 -0
- package/config/skills/agent/core/marketplace-search/{instructions.md → SKILL.md} +41 -0
- package/config/skills/agent/core/query-knowledge/{instructions.md → SKILL.md} +40 -0
- package/config/skills/agent/core/read-task/SKILL.md +56 -0
- package/config/skills/agent/core/recall/{instructions.md → SKILL.md} +38 -0
- package/config/skills/agent/core/record-learning/{instructions.md → SKILL.md} +38 -0
- package/config/skills/agent/core/register-self/SKILL.md +54 -0
- package/config/skills/agent/core/remember/{instructions.md → SKILL.md} +37 -0
- package/config/skills/agent/core/remember/execute.sh +6 -0
- package/config/skills/agent/core/reply-chat/{instructions.md → SKILL.md} +37 -0
- package/config/skills/agent/core/report-progress/{instructions.md → SKILL.md} +38 -0
- package/config/skills/agent/core/report-status/{instructions.md → SKILL.md} +39 -0
- package/config/skills/agent/core/send-chat-response/{instructions.md → SKILL.md} +37 -0
- package/config/skills/agent/core/send-message/SKILL.md +58 -0
- package/config/skills/agent/core/update-team-norm/execute.sh +115 -0
- package/config/skills/agent/desktop-app-control/{instructions.md → SKILL.md} +42 -0
- package/config/skills/agent/trend-monitor/{instructions.md → SKILL.md} +34 -0
- package/config/skills/agent/vnc-browser/{instructions.md → SKILL.md} +38 -0
- package/config/skills/auditor/score-task/SKILL.md +28 -0
- package/config/skills/auditor/score-task/execute.sh +21 -0
- package/config/skills/examples/enterprise-skill-example.json +22 -0
- package/config/skills/examples/premium-skill-example.json +22 -0
- package/config/skills/orchestrator/assign-task/SKILL.md +41 -0
- package/config/skills/orchestrator/assign-team-to-project/{instructions.md → SKILL.md} +25 -0
- package/config/skills/orchestrator/broadcast/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/broadcast-to-org/{instructions.md → SKILL.md} +25 -0
- package/config/skills/orchestrator/cancel-all-schedules/{instructions.md → SKILL.md} +5 -0
- package/config/skills/orchestrator/cancel-schedule/SKILL.md +43 -0
- package/config/skills/orchestrator/complete-task/SKILL.md +41 -0
- package/config/skills/orchestrator/create-project/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/create-team/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/delegate-task/{instructions.md → SKILL.md} +27 -0
- package/config/skills/orchestrator/delegate-task/execute.sh +31 -2
- package/config/skills/orchestrator/get-agent-logs/{instructions.md → SKILL.md} +25 -0
- package/config/skills/orchestrator/get-agent-status/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/get-project-overview/SKILL.md +41 -0
- package/config/skills/orchestrator/get-tasks/SKILL.md +41 -0
- package/config/skills/orchestrator/get-team-status/SKILL.md +43 -0
- package/config/skills/orchestrator/handle-agent-failure/{instructions.md → SKILL.md} +27 -0
- package/config/skills/orchestrator/heartbeat/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/list-schedules/{instructions.md → SKILL.md} +5 -0
- package/config/skills/orchestrator/list-subscriptions/SKILL.md +41 -0
- package/config/skills/orchestrator/query-knowledge/{instructions.md → SKILL.md} +28 -0
- package/config/skills/orchestrator/read-session-logs/{instructions.md → SKILL.md} +26 -0
- package/config/skills/orchestrator/read-system-logs/{instructions.md → SKILL.md} +25 -0
- package/config/skills/orchestrator/recall/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/record-failure/{instructions.md → SKILL.md} +27 -0
- package/config/skills/orchestrator/record-learning/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/record-success/{instructions.md → SKILL.md} +26 -0
- package/config/skills/orchestrator/register-self/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/remember/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/reply-chat/{instructions.md → SKILL.md} +25 -0
- package/config/skills/orchestrator/reply-chat/execute.sh +0 -13
- package/config/skills/orchestrator/reply-gchat/{instructions.md → SKILL.md} +25 -0
- package/config/skills/orchestrator/reply-gchat/execute.sh +0 -18
- package/config/skills/orchestrator/reply-slack/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/reply-slack/execute.sh +18 -31
- package/config/skills/orchestrator/report-bug/{instructions.md → SKILL.md} +26 -0
- package/config/skills/orchestrator/restart-crewly/{instructions.md → SKILL.md} +26 -0
- package/config/skills/orchestrator/resume-session/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/schedule-check/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/send-key/{instructions.md → SKILL.md} +26 -0
- package/config/skills/orchestrator/send-message/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/send-pdf-to-slack/{instructions.md → SKILL.md} +27 -0
- package/config/skills/orchestrator/set-goal/{instructions.md → SKILL.md} +26 -0
- package/config/skills/orchestrator/start-agent/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/start-team/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/stop-agent/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/stop-team/SKILL.md +43 -0
- package/config/skills/orchestrator/subscribe-event/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/terminate-agent/{instructions.md → SKILL.md} +24 -0
- package/config/skills/orchestrator/unsubscribe-event/SKILL.md +42 -0
- package/config/skills/orchestrator/update-focus/{instructions.md → SKILL.md} +26 -0
- package/config/skills/orchestrator/update-team/{instructions.md → SKILL.md} +24 -0
- package/config/skills/team-leader/aggregate-results/{instructions.md → SKILL.md} +26 -0
- package/config/skills/team-leader/decompose-goal/{instructions.md → SKILL.md} +26 -0
- package/config/skills/team-leader/delegate-task/{instructions.md → SKILL.md} +26 -0
- package/config/skills/team-leader/delegate-task/execute.sh +14 -6
- package/config/skills/team-leader/delegate-task/execute.test.sh +401 -0
- package/config/skills/team-leader/handle-failure/{instructions.md → SKILL.md} +27 -0
- package/config/skills/team-leader/schedule-check/{instructions.md → SKILL.md} +26 -0
- package/config/skills/team-leader/start-agent/{instructions.md → SKILL.md} +26 -0
- package/config/skills/team-leader/stop-agent/{instructions.md → SKILL.md} +26 -0
- package/config/skills/team-leader/verify-output/{instructions.md → SKILL.md} +27 -0
- package/config/templates/agent-agents-md.md +35 -0
- package/config/templates/agent-gemini-md.md +35 -0
- package/config/templates/code-review-team/team-config.json +7 -0
- package/config/templates/content-generation-team/norms/brand-guidelines.md +64 -0
- package/config/templates/content-generation-team/norms/content-review.md +66 -0
- package/config/templates/content-generation-team/norms/publish-checklist.md +58 -0
- package/config/templates/content-generation-team/team-config.json +8 -0
- package/config/templates/dev-fullstack/norms/code-commit-sop.md +40 -0
- package/config/templates/dev-fullstack/norms/quality-gates.md +35 -0
- package/config/templates/dev-fullstack/template.json +17 -1
- package/config/templates/education-smb/template.json +10 -1
- package/config/templates/insurance-smb/template.json +10 -1
- package/config/templates/research-analysis/norms/research-methodology.md +36 -0
- package/config/templates/research-analysis/norms/source-citation.md +33 -0
- package/config/templates/research-analysis/template.json +17 -1
- package/config/templates/security-audit-team.json +67 -0
- package/config/templates/social-media-ops/norms/engagement-rules.md +35 -0
- package/config/templates/social-media-ops/norms/posting-schedule.md +43 -0
- package/config/templates/social-media-ops/template.json +17 -1
- package/config/templates/video-production/template.json +10 -1
- package/dist/backend/backend/src/constants.d.ts +80 -11
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +85 -11
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/approvals/approvals.controller.d.ts +99 -0
- package/dist/backend/backend/src/controllers/approvals/approvals.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/approvals/approvals.controller.js +183 -0
- package/dist/backend/backend/src/controllers/approvals/approvals.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/approvals/approvals.routes.d.ts +15 -0
- package/dist/backend/backend/src/controllers/approvals/approvals.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/approvals/approvals.routes.js +27 -0
- package/dist/backend/backend/src/controllers/approvals/approvals.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/cloud/cloud-google-auth.controller.d.ts +70 -0
- package/dist/backend/backend/src/controllers/cloud/cloud-google-auth.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/cloud/cloud-google-auth.controller.js +368 -0
- package/dist/backend/backend/src/controllers/cloud/cloud-google-auth.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts +24 -0
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +195 -3
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.routes.d.ts +9 -4
- package/dist/backend/backend/src/controllers/cloud/cloud.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.routes.js +19 -5
- package/dist/backend/backend/src/controllers/cloud/cloud.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/index.d.ts +1 -0
- package/dist/backend/backend/src/controllers/cloud/index.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/index.js +1 -0
- package/dist/backend/backend/src/controllers/cloud/index.js.map +1 -1
- package/dist/backend/backend/src/controllers/index.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/index.js +2 -0
- package/dist/backend/backend/src/controllers/index.js.map +1 -1
- package/dist/backend/backend/src/controllers/marketplace/marketplace.controller.js +1 -1
- package/dist/backend/backend/src/controllers/marketplace/marketplace.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/marketplace/template-marketplace.routes.d.ts +3 -3
- package/dist/backend/backend/src/controllers/marketplace/template-marketplace.routes.js +9 -9
- package/dist/backend/backend/src/controllers/marketplace/template-marketplace.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/memory/memory.controller.js +6 -6
- package/dist/backend/backend/src/controllers/memory/memory.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts +0 -7
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +2 -135
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts +14 -0
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +96 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.js +8 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/payment/payment.controller.js +2 -2
- package/dist/backend/backend/src/controllers/payment/payment.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/payment/payment.routes.d.ts +3 -3
- package/dist/backend/backend/src/controllers/payment/payment.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/payment/payment.routes.js +4 -14
- package/dist/backend/backend/src/controllers/payment/payment.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/payment/payment.types.d.ts +15 -94
- package/dist/backend/backend/src/controllers/payment/payment.types.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/payment/payment.types.js +11 -35
- package/dist/backend/backend/src/controllers/payment/payment.types.js.map +1 -1
- package/dist/backend/backend/src/controllers/pr-review/pr-review.controller.d.ts +49 -0
- package/dist/backend/backend/src/controllers/pr-review/pr-review.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/pr-review/pr-review.controller.js +138 -0
- package/dist/backend/backend/src/controllers/pr-review/pr-review.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/pr-review/pr-review.routes.d.ts +20 -0
- package/dist/backend/backend/src/controllers/pr-review/pr-review.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/pr-review/pr-review.routes.js +30 -0
- package/dist/backend/backend/src/controllers/pr-review/pr-review.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/quality-gate/quality-gate.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/quality-gate/quality-gate.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/quality-gate/quality-gate.controller.js +107 -0
- package/dist/backend/backend/src/controllers/quality-gate/quality-gate.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/request-types.d.ts +20 -1
- package/dist/backend/backend/src/controllers/request-types.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +11 -5
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +46 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +598 -326
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +105 -36
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.routes.js +2 -1
- package/dist/backend/backend/src/controllers/team/team.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/template/template.controller.d.ts +11 -0
- package/dist/backend/backend/src/controllers/template/template.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/template/template.controller.js +59 -0
- package/dist/backend/backend/src/controllers/template/template.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/template/template.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/template/template.routes.js +2 -1
- package/dist/backend/backend/src/controllers/template/template.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/workspace/workspace.controller.d.ts +39 -0
- package/dist/backend/backend/src/controllers/workspace/workspace.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/workspace/workspace.controller.js +120 -0
- package/dist/backend/backend/src/controllers/workspace/workspace.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/workspace/workspace.routes.d.ts +18 -0
- package/dist/backend/backend/src/controllers/workspace/workspace.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/workspace/workspace.routes.js +27 -0
- package/dist/backend/backend/src/controllers/workspace/workspace.routes.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +108 -15
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/middleware/require-auth.middleware.d.ts +20 -0
- package/dist/backend/backend/src/middleware/require-auth.middleware.d.ts.map +1 -0
- package/dist/backend/backend/src/middleware/require-auth.middleware.js +21 -0
- package/dist/backend/backend/src/middleware/require-auth.middleware.js.map +1 -0
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +18 -5
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/quality-gate.routes.d.ts +2 -1
- package/dist/backend/backend/src/routes/modules/quality-gate.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/quality-gate.routes.js +4 -2
- package/dist/backend/backend/src/routes/modules/quality-gate.routes.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.js +8 -0
- package/dist/backend/backend/src/routes/modules/task-management.routes.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/terminal.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/terminal.routes.js +4 -0
- package/dist/backend/backend/src/routes/modules/terminal.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/adaptive-heartbeat.service.d.ts +149 -0
- package/dist/backend/backend/src/services/agent/adaptive-heartbeat.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/adaptive-heartbeat.service.js +200 -0
- package/dist/backend/backend/src/services/agent/adaptive-heartbeat.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.d.ts +13 -0
- package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.js +65 -6
- package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +36 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +174 -52
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/auditor-scheduler.service.d.ts +66 -20
- package/dist/backend/backend/src/services/agent/auditor-scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/auditor-scheduler.service.js +261 -60
- package/dist/backend/backend/src/services/agent/auditor-scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts +19 -0
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js +80 -0
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts +11 -0
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js +49 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts +74 -3
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js +248 -18
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/approval-queue.service.d.ts +161 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/approval-queue.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/approval-queue.service.js +237 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/approval-queue.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts +74 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js +140 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js +50 -2
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts +16 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js +45 -5
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts +3 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js +3 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts +135 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js +185 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +10 -2
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +22 -2
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts +143 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js +264 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js +2 -2
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts +55 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js +660 -45
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts +75 -3
- package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/types.js +49 -2
- package/dist/backend/backend/src/services/agent/crewly-agent/types.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js +17 -2
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +37 -0
- package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-builder.service.js +170 -3
- package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/chrome-discovery.service.d.ts +108 -0
- package/dist/backend/backend/src/services/browser/chrome-discovery.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/browser/chrome-discovery.service.js +251 -0
- package/dist/backend/backend/src/services/browser/chrome-discovery.service.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts +12 -0
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js +19 -0
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.d.ts +191 -0
- package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.js +415 -0
- package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/device-identity.service.d.ts +89 -0
- package/dist/backend/backend/src/services/cloud/device-identity.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/cloud/device-identity.service.js +148 -0
- package/dist/backend/backend/src/services/cloud/device-identity.service.js.map +1 -0
- package/dist/backend/backend/src/services/core/tracing.service.d.ts +127 -0
- package/dist/backend/backend/src/services/core/tracing.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/core/tracing.service.js +238 -0
- package/dist/backend/backend/src/services/core/tracing.service.js.map +1 -0
- package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-bus.service.js +11 -3
- package/dist/backend/backend/src/services/event-bus/event-bus.service.js.map +1 -1
- package/dist/backend/backend/src/services/index.d.ts +1 -0
- package/dist/backend/backend/src/services/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/index.js +1 -0
- package/dist/backend/backend/src/services/index.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/embedding-provider.d.ts +78 -0
- package/dist/backend/backend/src/services/knowledge/embedding-provider.d.ts.map +1 -0
- package/dist/backend/backend/src/services/knowledge/embedding-provider.js +164 -0
- package/dist/backend/backend/src/services/knowledge/embedding-provider.js.map +1 -0
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts +39 -13
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +114 -17
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/vector-store.service.d.ts +170 -23
- package/dist/backend/backend/src/services/knowledge/vector-store.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/vector-store.service.js +565 -73
- package/dist/backend/backend/src/services/knowledge/vector-store.service.js.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js +8 -11
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace.service.js +1 -0
- package/dist/backend/backend/src/services/marketplace/marketplace.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/context-flush.service.d.ts +73 -0
- package/dist/backend/backend/src/services/memory/context-flush.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/memory/context-flush.service.js +131 -0
- package/dist/backend/backend/src/services/memory/context-flush.service.js.map +1 -0
- package/dist/backend/backend/src/services/memory/learning-accumulation.service.d.ts +23 -2
- package/dist/backend/backend/src/services/memory/learning-accumulation.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/learning-accumulation.service.js +78 -16
- package/dist/backend/backend/src/services/memory/learning-accumulation.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.d.ts +38 -0
- package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.js +121 -2
- package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/google-chat-messenger.adapter.d.ts +29 -207
- package/dist/backend/backend/src/services/messaging/adapters/google-chat-messenger.adapter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/google-chat-messenger.adapter.js +97 -683
- package/dist/backend/backend/src/services/messaging/adapters/google-chat-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/google-chat-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/google-chat-initializer.js +13 -12
- package/dist/backend/backend/src/services/messaging/google-chat-initializer.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts +2 -0
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts +6 -23
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js +48 -184
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +51 -5
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/index.d.ts +1 -1
- package/dist/backend/backend/src/services/orchestrator/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/index.js +1 -1
- package/dist/backend/backend/src/services/orchestrator/index.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.d.ts +65 -0
- package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.js +165 -2
- package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts +8 -0
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js +23 -0
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js.map +1 -1
- package/dist/backend/backend/src/services/payment/stripe.service.d.ts +95 -43
- package/dist/backend/backend/src/services/payment/stripe.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/payment/stripe.service.js +229 -190
- package/dist/backend/backend/src/services/payment/stripe.service.js.map +1 -1
- package/dist/backend/backend/src/services/pr-review/pr-review.service.d.ts +181 -0
- package/dist/backend/backend/src/services/pr-review/pr-review.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/pr-review/pr-review.service.js +336 -0
- package/dist/backend/backend/src/services/pr-review/pr-review.service.js.map +1 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +23 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.js +88 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.js.map +1 -1
- package/dist/backend/backend/src/services/session/index.d.ts +2 -0
- package/dist/backend/backend/src/services/session/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/session/index.js +2 -0
- package/dist/backend/backend/src/services/session/index.js.map +1 -1
- package/dist/backend/backend/src/services/session/session-handoff.service.d.ts +260 -0
- package/dist/backend/backend/src/services/session/session-handoff.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/session/session-handoff.service.js +565 -0
- package/dist/backend/backend/src/services/session/session-handoff.service.js.map +1 -0
- package/dist/backend/backend/src/services/skill/index.d.ts +1 -0
- package/dist/backend/backend/src/services/skill/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/skill/index.js +1 -0
- package/dist/backend/backend/src/services/skill/index.js.map +1 -1
- package/dist/backend/backend/src/services/skill/skill-catalog.service.d.ts +25 -6
- package/dist/backend/backend/src/services/skill/skill-catalog.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/skill/skill-catalog.service.js +78 -20
- package/dist/backend/backend/src/services/skill/skill-catalog.service.js.map +1 -1
- package/dist/backend/backend/src/services/skill/skill-tier.service.d.ts +116 -0
- package/dist/backend/backend/src/services/skill/skill-tier.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/skill/skill-tier.service.js +155 -0
- package/dist/backend/backend/src/services/skill/skill-tier.service.js.map +1 -0
- package/dist/backend/backend/src/services/skill/skill.service.d.ts +35 -7
- package/dist/backend/backend/src/services/skill/skill.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/skill/skill.service.js +128 -35
- package/dist/backend/backend/src/services/skill/skill.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +50 -47
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +267 -202
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts +28 -2
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +69 -3
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/backend/src/services/template/template.service.d.ts +19 -1
- package/dist/backend/backend/src/services/template/template.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/template/template.service.js +110 -3
- package/dist/backend/backend/src/services/template/template.service.js.map +1 -1
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts +11 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js +57 -3
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.js +6 -0
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts +52 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.js +319 -6
- package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/types/chat.types.d.ts +2 -2
- package/dist/backend/backend/src/types/chat.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/chat.types.js +18 -22
- package/dist/backend/backend/src/types/chat.types.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +37 -0
- package/dist/backend/backend/src/types/index.d.ts.map +1 -1
- package/dist/backend/backend/src/types/index.js.map +1 -1
- package/dist/backend/backend/src/types/marketplace.types.d.ts +1 -1
- package/dist/backend/backend/src/types/marketplace.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/scheduler.types.d.ts +4 -0
- package/dist/backend/backend/src/types/scheduler.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/scheduler.types.js.map +1 -1
- package/dist/backend/backend/src/types/skill.types.d.ts +4 -0
- package/dist/backend/backend/src/types/skill.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/skill.types.js.map +1 -1
- package/dist/backend/backend/src/types/task-tracking.types.d.ts +6 -0
- package/dist/backend/backend/src/types/task-tracking.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/task-tracking.types.js.map +1 -1
- package/dist/backend/backend/src/types/team-template.types.d.ts +2 -0
- package/dist/backend/backend/src/types/team-template.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/team-template.types.js.map +1 -1
- package/dist/backend/backend/src/utils/skill-md-parser.d.ts +38 -0
- package/dist/backend/backend/src/utils/skill-md-parser.d.ts.map +1 -0
- package/dist/backend/backend/src/utils/skill-md-parser.js +47 -0
- package/dist/backend/backend/src/utils/skill-md-parser.js.map +1 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +0 -154
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js +0 -515
- package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/dist/backend/config/constants.d.ts +18 -3
- package/dist/backend/config/constants.d.ts.map +1 -1
- package/dist/backend/config/constants.js +18 -3
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +80 -11
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +85 -11
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/embedding-provider.d.ts +78 -0
- package/dist/cli/backend/src/services/knowledge/embedding-provider.d.ts.map +1 -0
- package/dist/cli/backend/src/services/knowledge/embedding-provider.js +164 -0
- package/dist/cli/backend/src/services/knowledge/embedding-provider.js.map +1 -0
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts +39 -13
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +114 -17
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/vector-store.service.d.ts +170 -23
- package/dist/cli/backend/src/services/knowledge/vector-store.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/vector-store.service.js +565 -73
- package/dist/cli/backend/src/services/knowledge/vector-store.service.js.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.d.ts +38 -0
- package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.js +121 -2
- package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/cli/backend/src/types/chat.types.d.ts +2 -2
- package/dist/cli/backend/src/types/chat.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/chat.types.js +18 -22
- package/dist/cli/backend/src/types/chat.types.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +37 -0
- package/dist/cli/backend/src/types/index.d.ts.map +1 -1
- package/dist/cli/backend/src/types/index.js.map +1 -1
- package/dist/cli/backend/src/types/scheduler.types.d.ts +4 -0
- package/dist/cli/backend/src/types/scheduler.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/scheduler.types.js.map +1 -1
- package/dist/cli/backend/src/types/skill.types.d.ts +4 -0
- package/dist/cli/backend/src/types/skill.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/skill.types.js.map +1 -1
- package/dist/cli/cli/src/commands/onboard.d.ts +19 -2
- package/dist/cli/cli/src/commands/onboard.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/onboard.js +58 -15
- package/dist/cli/cli/src/commands/onboard.js.map +1 -1
- package/dist/cli/cli/src/commands/pair.d.ts +46 -0
- package/dist/cli/cli/src/commands/pair.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/pair.js +258 -0
- package/dist/cli/cli/src/commands/pair.js.map +1 -0
- package/dist/cli/cli/src/commands/service.d.ts +86 -0
- package/dist/cli/cli/src/commands/service.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/service.js +687 -0
- package/dist/cli/cli/src/commands/service.js.map +1 -0
- package/dist/cli/cli/src/index.js +17 -0
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/config/constants.d.ts +18 -3
- package/dist/cli/config/constants.d.ts.map +1 -1
- package/dist/cli/config/constants.js +18 -3
- package/dist/cli/config/constants.js.map +1 -1
- package/frontend/dist/assets/index-1d23cce8.js +4919 -0
- package/frontend/dist/assets/index-60a9e4ea.css +33 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +22 -10
- package/config/skills/agent/browse-stealth/skill.json +0 -20
- package/config/skills/agent/competitor-content-tracker/skill.json +0 -22
- package/config/skills/agent/computer-use/skill.json +0 -29
- package/config/skills/agent/content-calendar/skill.json +0 -22
- package/config/skills/agent/content-repurposer/skill.json +0 -22
- package/config/skills/agent/content-writer/skill.json +0 -22
- package/config/skills/agent/core/accept-task/skill.json +0 -20
- package/config/skills/agent/core/block-task/skill.json +0 -20
- package/config/skills/agent/core/check-quality-gates/skill.json +0 -20
- package/config/skills/agent/core/complete-task/skill.json +0 -20
- package/config/skills/agent/core/generate-pdf/skill.json +0 -20
- package/config/skills/agent/core/get-my-context/skill.json +0 -20
- package/config/skills/agent/core/get-sops/skill.json +0 -20
- package/config/skills/agent/core/get-team-status/instructions.md +0 -17
- package/config/skills/agent/core/get-team-status/skill.json +0 -20
- package/config/skills/agent/core/heartbeat/skill.json +0 -20
- package/config/skills/agent/core/marketplace-search/skill.json +0 -20
- package/config/skills/agent/core/query-knowledge/skill.json +0 -20
- package/config/skills/agent/core/read-task/instructions.md +0 -19
- package/config/skills/agent/core/read-task/skill.json +0 -20
- package/config/skills/agent/core/recall/skill.json +0 -20
- package/config/skills/agent/core/record-learning/skill.json +0 -20
- package/config/skills/agent/core/register-self/instructions.md +0 -18
- package/config/skills/agent/core/register-self/skill.json +0 -20
- package/config/skills/agent/core/remember/skill.json +0 -20
- package/config/skills/agent/core/reply-chat/skill.json +0 -20
- package/config/skills/agent/core/report-progress/skill.json +0 -20
- package/config/skills/agent/core/report-status/skill.json +0 -20
- package/config/skills/agent/core/send-chat-response/skill.json +0 -20
- package/config/skills/agent/core/send-message/instructions.md +0 -20
- package/config/skills/agent/core/send-message/skill.json +0 -20
- package/config/skills/agent/desktop-app-control/skill.json +0 -33
- package/config/skills/agent/trend-monitor/skill.json +0 -22
- package/config/skills/agent/vnc-browser/skill.json +0 -20
- package/config/skills/orchestrator/assign-task/instructions.md +0 -17
- package/config/skills/orchestrator/assign-task/skill.json +0 -20
- package/config/skills/orchestrator/assign-team-to-project/skill.json +0 -20
- package/config/skills/orchestrator/broadcast/skill.json +0 -20
- package/config/skills/orchestrator/broadcast-to-org/skill.json +0 -20
- package/config/skills/orchestrator/cancel-all-schedules/skill.json +0 -17
- package/config/skills/orchestrator/cancel-schedule/instructions.md +0 -19
- package/config/skills/orchestrator/cancel-schedule/skill.json +0 -20
- package/config/skills/orchestrator/complete-task/instructions.md +0 -17
- package/config/skills/orchestrator/complete-task/skill.json +0 -20
- package/config/skills/orchestrator/create-project/skill.json +0 -20
- package/config/skills/orchestrator/create-team/skill.json +0 -20
- package/config/skills/orchestrator/delegate-task/skill.json +0 -20
- package/config/skills/orchestrator/get-agent-logs/skill.json +0 -20
- package/config/skills/orchestrator/get-agent-status/skill.json +0 -20
- package/config/skills/orchestrator/get-project-overview/instructions.md +0 -17
- package/config/skills/orchestrator/get-project-overview/skill.json +0 -20
- package/config/skills/orchestrator/get-tasks/instructions.md +0 -17
- package/config/skills/orchestrator/get-tasks/skill.json +0 -20
- package/config/skills/orchestrator/get-team-status/instructions.md +0 -17
- package/config/skills/orchestrator/get-team-status/skill.json +0 -20
- package/config/skills/orchestrator/handle-agent-failure/skill.json +0 -20
- package/config/skills/orchestrator/heartbeat/skill.json +0 -20
- package/config/skills/orchestrator/list-schedules/skill.json +0 -12
- package/config/skills/orchestrator/list-subscriptions/instructions.md +0 -17
- package/config/skills/orchestrator/list-subscriptions/skill.json +0 -20
- package/config/skills/orchestrator/query-knowledge/skill.json +0 -20
- package/config/skills/orchestrator/read-session-logs/skill.json +0 -20
- package/config/skills/orchestrator/read-system-logs/skill.json +0 -20
- package/config/skills/orchestrator/recall/skill.json +0 -20
- package/config/skills/orchestrator/record-failure/skill.json +0 -20
- package/config/skills/orchestrator/record-learning/skill.json +0 -20
- package/config/skills/orchestrator/record-success/skill.json +0 -20
- package/config/skills/orchestrator/register-self/skill.json +0 -20
- package/config/skills/orchestrator/remember/skill.json +0 -20
- package/config/skills/orchestrator/reply-chat/skill.json +0 -20
- package/config/skills/orchestrator/reply-gchat/skill.json +0 -20
- package/config/skills/orchestrator/reply-slack/skill.json +0 -20
- package/config/skills/orchestrator/report-bug/skill.json +0 -20
- package/config/skills/orchestrator/restart-crewly/skill.json +0 -20
- package/config/skills/orchestrator/resume-session/skill.json +0 -20
- package/config/skills/orchestrator/schedule-check/skill.json +0 -20
- package/config/skills/orchestrator/send-key/skill.json +0 -20
- package/config/skills/orchestrator/send-message/skill.json +0 -20
- package/config/skills/orchestrator/send-pdf-to-slack/skill.json +0 -20
- package/config/skills/orchestrator/set-goal/skill.json +0 -20
- package/config/skills/orchestrator/start-agent/skill.json +0 -20
- package/config/skills/orchestrator/start-team/skill.json +0 -20
- package/config/skills/orchestrator/stop-agent/skill.json +0 -20
- package/config/skills/orchestrator/stop-team/instructions.md +0 -19
- package/config/skills/orchestrator/stop-team/skill.json +0 -20
- package/config/skills/orchestrator/subscribe-event/skill.json +0 -20
- package/config/skills/orchestrator/terminate-agent/skill.json +0 -20
- package/config/skills/orchestrator/unsubscribe-event/instructions.md +0 -19
- package/config/skills/orchestrator/unsubscribe-event/skill.json +0 -20
- package/config/skills/orchestrator/update-focus/skill.json +0 -20
- package/config/skills/orchestrator/update-team/skill.json +0 -20
- package/config/skills/team-leader/aggregate-results/skill.json +0 -20
- package/config/skills/team-leader/decompose-goal/skill.json +0 -20
- package/config/skills/team-leader/delegate-task/skill.json +0 -20
- package/config/skills/team-leader/handle-failure/skill.json +0 -20
- package/config/skills/team-leader/schedule-check/skill.json +0 -20
- package/config/skills/team-leader/start-agent/skill.json +0 -20
- package/config/skills/team-leader/stop-agent/skill.json +0 -20
- package/config/skills/team-leader/verify-output/skill.json +0 -20
- package/frontend/dist/assets/index-0e5673b0.css +0 -33
- package/frontend/dist/assets/index-e6d7db4a.js +0 -5213
|
@@ -6,6 +6,8 @@ import { updateAgentHeartbeat } from '../../services/agent/agent-heartbeat.servi
|
|
|
6
6
|
import { CREWLY_CONSTANTS } from '../../constants.js';
|
|
7
7
|
import { LoggerService } from '../../services/core/logger.service.js';
|
|
8
8
|
import { TaskOutputValidatorService } from '../../services/quality/task-output-validator.service.js';
|
|
9
|
+
import { TracingService } from '../../services/core/tracing.service.js';
|
|
10
|
+
import { TRACING_CONSTANTS } from '../../constants.js';
|
|
9
11
|
import { TASK_OUTPUT_CONSTANTS } from '../../types/task-output.types.js';
|
|
10
12
|
const logger = LoggerService.getInstance().createComponentLogger('TaskManagementController');
|
|
11
13
|
/** Module-level reference to EventBusService for auto-cleanup on task completion */
|
|
@@ -67,85 +69,92 @@ export function getEventBusServiceForTaskCleanup() {
|
|
|
67
69
|
* @param res - Response with success status, created task path, and status
|
|
68
70
|
*/
|
|
69
71
|
export async function createTask(req, res) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return;
|
|
72
|
+
return TracingService.getInstance().withSpan(TRACING_CONSTANTS.SPANS.TASK_CREATE, {
|
|
73
|
+
attributes: {
|
|
74
|
+
'task.priority': req.body.priority || 'medium',
|
|
75
|
+
'task.milestone': req.body.milestone || 'delegated',
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
77
|
+
}, async (span) => {
|
|
78
|
+
try {
|
|
79
|
+
const { projectPath, task, priority = 'medium', sessionName, milestone = 'delegated', outputSchema, } = req.body;
|
|
80
|
+
if (!projectPath) {
|
|
81
|
+
res.status(400).json({ success: false, error: 'projectPath is required' });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (!task) {
|
|
85
|
+
res.status(400).json({ success: false, error: 'task is required' });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Determine initial status folder based on whether an assignee is provided
|
|
89
|
+
const statusFolder = sessionName ? 'in_progress' : 'open';
|
|
90
|
+
const tasksDir = join(projectPath, '.crewly', 'tasks', milestone, statusFolder);
|
|
91
|
+
// Ensure directory exists
|
|
92
|
+
await ensureDirectoryExists(tasksDir);
|
|
93
|
+
// Generate sanitized filename from task description
|
|
94
|
+
const sanitizedName = task
|
|
95
|
+
.toLowerCase()
|
|
96
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
97
|
+
.replace(/^_|_$/g, '')
|
|
98
|
+
.substring(0, 80);
|
|
99
|
+
const timestamp = Date.now();
|
|
100
|
+
const fileName = `${sanitizedName}_${timestamp}.md`;
|
|
101
|
+
const taskPath = join(tasksDir, fileName);
|
|
102
|
+
// Build task markdown content
|
|
103
|
+
let taskContent = `# ${task}\n\n## Task Information\n- **Priority**: ${priority}\n- **Milestone**: ${milestone}\n- **Created at**: ${new Date().toISOString()}\n- **Status**: ${statusFolder === 'in_progress' ? 'In Progress' : 'Open'}\n`;
|
|
104
|
+
if (sessionName) {
|
|
105
|
+
taskContent += `\n## Assignment Information\n- **Assigned to**: ${sessionName}\n- **Assigned at**: ${new Date().toISOString()}\n- **Status**: In Progress\n`;
|
|
106
|
+
}
|
|
107
|
+
taskContent += `\n## Task Description\n\n${task}\n`;
|
|
108
|
+
// Embed output schema if provided
|
|
109
|
+
if (outputSchema && typeof outputSchema === 'object') {
|
|
110
|
+
const validator = TaskOutputValidatorService.getInstance();
|
|
111
|
+
taskContent += validator.generateSchemaMarkdown(outputSchema);
|
|
112
|
+
}
|
|
113
|
+
await writeFile(taskPath, taskContent, 'utf-8');
|
|
114
|
+
// If assigned, track via TaskTrackingService
|
|
115
|
+
let trackedTaskId;
|
|
116
|
+
if (sessionName) {
|
|
117
|
+
try {
|
|
118
|
+
const projects = await this.storageService.getProjects();
|
|
119
|
+
const project = projects.find(p => projectPath.startsWith(p.path));
|
|
120
|
+
if (project) {
|
|
121
|
+
const teams = await this.storageService.getTeams();
|
|
122
|
+
let teamId = '';
|
|
123
|
+
let memberId = '';
|
|
124
|
+
for (const team of teams) {
|
|
125
|
+
const member = team.members.find(m => m.sessionName === sessionName);
|
|
126
|
+
if (member) {
|
|
127
|
+
teamId = team.id;
|
|
128
|
+
memberId = member.id;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (teamId) {
|
|
133
|
+
const trackedTask = await this.taskTrackingService.assignTask(project.id, teamId, taskPath, task, 'delegated', memberId, sessionName);
|
|
134
|
+
trackedTaskId = trackedTask?.id;
|
|
122
135
|
}
|
|
123
|
-
}
|
|
124
|
-
if (teamId) {
|
|
125
|
-
const trackedTask = await this.taskTrackingService.assignTask(project.id, teamId, taskPath, task, 'delegated', memberId, sessionName);
|
|
126
|
-
trackedTaskId = trackedTask?.id;
|
|
127
136
|
}
|
|
128
137
|
}
|
|
138
|
+
catch (trackingError) {
|
|
139
|
+
logger.warn('Failed to track task assignment', { error: trackingError instanceof Error ? trackingError.message : String(trackingError) });
|
|
140
|
+
// Non-fatal - the file was still created
|
|
141
|
+
}
|
|
129
142
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
143
|
+
res.json({
|
|
144
|
+
success: true,
|
|
145
|
+
message: `Task file created: ${fileName}`,
|
|
146
|
+
taskPath,
|
|
147
|
+
fileName,
|
|
148
|
+
status: statusFolder,
|
|
149
|
+
milestone,
|
|
150
|
+
taskId: trackedTaskId,
|
|
151
|
+
});
|
|
134
152
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
status: statusFolder,
|
|
141
|
-
milestone,
|
|
142
|
-
taskId: trackedTaskId,
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
catch (error) {
|
|
146
|
-
logger.error('Error creating task', { error: error instanceof Error ? error.message : String(error) });
|
|
147
|
-
res.status(500).json({ success: false, error: 'Failed to create task' });
|
|
148
|
-
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
logger.error('Error creating task', { error: error instanceof Error ? error.message : String(error) });
|
|
155
|
+
res.status(500).json({ success: false, error: 'Failed to create task' });
|
|
156
|
+
}
|
|
157
|
+
});
|
|
149
158
|
}
|
|
150
159
|
/**
|
|
151
160
|
* Assigns a task to a team member by moving it from open/ to in_progress/ folder
|
|
@@ -154,106 +163,113 @@ export async function createTask(req, res) {
|
|
|
154
163
|
* @param res - Response with success status and task information
|
|
155
164
|
*/
|
|
156
165
|
export async function assignTask(req, res) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
await updateAgentHeartbeat(sessionName, undefined, CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE);
|
|
162
|
-
}
|
|
163
|
-
catch (error) {
|
|
164
|
-
logger.warn('Failed to update agent heartbeat', { error: error instanceof Error ? error.message : String(error) });
|
|
165
|
-
// Continue execution - heartbeat failures shouldn't break task assignment
|
|
166
|
-
}
|
|
167
|
-
if (!taskPath) {
|
|
168
|
-
res.status(400).json({ success: false, error: 'taskPath is required' });
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
if (!sessionName) {
|
|
172
|
-
res.status(400).json({ success: false, error: 'sessionName is required' });
|
|
173
|
-
return;
|
|
166
|
+
return TracingService.getInstance().withSpan(TRACING_CONSTANTS.SPANS.TASK_ASSIGN, {
|
|
167
|
+
attributes: {
|
|
168
|
+
'task.path': req.body.taskPath || 'unknown',
|
|
169
|
+
'agent.session': req.body.sessionName || 'unknown',
|
|
174
170
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
taskPath,
|
|
182
|
-
suggestion: 'Verify the task file path is correct and the file exists'
|
|
183
|
-
});
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
// Ensure task is in open/ folder
|
|
187
|
-
if (!taskPath.includes('/open/')) {
|
|
188
|
-
res.status(200).json({
|
|
189
|
-
success: false,
|
|
190
|
-
error: 'Task is not in the correct folder for assignment',
|
|
191
|
-
details: `Task must be in open/ folder to be assigned. Current path: ${taskPath}`,
|
|
192
|
-
taskPath,
|
|
193
|
-
expectedFolder: 'open',
|
|
194
|
-
currentFolder: taskPath.includes('/in_progress/') ? 'in_progress' : taskPath.includes('/done/') ? 'done' : taskPath.includes('/blocked/') ? 'blocked' : 'unknown'
|
|
195
|
-
});
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
// Parse task information
|
|
199
|
-
const taskContent = await readFile(taskPath, 'utf-8');
|
|
200
|
-
const taskInfo = parseTaskInfo(taskContent, basename(taskPath));
|
|
201
|
-
// Extract project and team information from task path
|
|
202
|
-
const pathMatch = taskPath.match(/\/([^/]+)\/\.crewly/);
|
|
203
|
-
if (!pathMatch) {
|
|
204
|
-
res.status(400).json({ success: false, error: 'Cannot determine project from task path' });
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const projectPath = taskPath.substring(0, taskPath.indexOf('.crewly'));
|
|
208
|
-
// Find project by path
|
|
209
|
-
const projects = await this.storageService.getProjects();
|
|
210
|
-
const project = projects.find(p => resolve(p.path) === resolve(projectPath));
|
|
211
|
-
if (!project) {
|
|
212
|
-
res.status(404).json({ success: false, error: 'Project not found' });
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
// Find team and member by sessionName
|
|
216
|
-
const teams = await this.storageService.getTeams();
|
|
217
|
-
let teamId = '';
|
|
218
|
-
let memberId = '';
|
|
219
|
-
for (const team of teams) {
|
|
220
|
-
const member = team.members.find(m => m.sessionName === sessionName);
|
|
221
|
-
if (member) {
|
|
222
|
-
teamId = team.id;
|
|
223
|
-
memberId = member.id;
|
|
224
|
-
break;
|
|
171
|
+
}, async (span) => {
|
|
172
|
+
try {
|
|
173
|
+
const { taskPath, sessionName } = req.body;
|
|
174
|
+
// Update agent heartbeat (proof of life)
|
|
175
|
+
try {
|
|
176
|
+
await updateAgentHeartbeat(sessionName, undefined, CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE);
|
|
225
177
|
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
logger.warn('Failed to update agent heartbeat', { error: error instanceof Error ? error.message : String(error) });
|
|
180
|
+
// Continue execution - heartbeat failures shouldn't break task assignment
|
|
181
|
+
}
|
|
182
|
+
if (!taskPath) {
|
|
183
|
+
res.status(400).json({ success: false, error: 'taskPath is required' });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (!sessionName) {
|
|
187
|
+
res.status(400).json({ success: false, error: 'sessionName is required' });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// Verify source task file exists
|
|
191
|
+
if (!existsSync(taskPath)) {
|
|
192
|
+
res.status(200).json({
|
|
193
|
+
success: false,
|
|
194
|
+
error: 'Task file does not exist at the specified path',
|
|
195
|
+
details: `No task file found at: ${taskPath}. Make sure the task file exists in the open/ folder.`,
|
|
196
|
+
taskPath,
|
|
197
|
+
suggestion: 'Verify the task file path is correct and the file exists'
|
|
198
|
+
});
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Ensure task is in open/ folder
|
|
202
|
+
if (!taskPath.includes('/open/')) {
|
|
203
|
+
res.status(200).json({
|
|
204
|
+
success: false,
|
|
205
|
+
error: 'Task is not in the correct folder for assignment',
|
|
206
|
+
details: `Task must be in open/ folder to be assigned. Current path: ${taskPath}`,
|
|
207
|
+
taskPath,
|
|
208
|
+
expectedFolder: 'open',
|
|
209
|
+
currentFolder: taskPath.includes('/in_progress/') ? 'in_progress' : taskPath.includes('/done/') ? 'done' : taskPath.includes('/blocked/') ? 'blocked' : 'unknown'
|
|
210
|
+
});
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// Parse task information
|
|
214
|
+
const taskContent = await readFile(taskPath, 'utf-8');
|
|
215
|
+
const taskInfo = parseTaskInfo(taskContent, basename(taskPath));
|
|
216
|
+
// Extract project and team information from task path
|
|
217
|
+
const pathMatch = taskPath.match(/\/([^/]+)\/\.crewly/);
|
|
218
|
+
if (!pathMatch) {
|
|
219
|
+
res.status(400).json({ success: false, error: 'Cannot determine project from task path' });
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const projectPath = taskPath.substring(0, taskPath.indexOf('.crewly'));
|
|
223
|
+
// Find project by path
|
|
224
|
+
const projects = await this.storageService.getProjects();
|
|
225
|
+
const project = projects.find(p => resolve(p.path) === resolve(projectPath));
|
|
226
|
+
if (!project) {
|
|
227
|
+
res.status(404).json({ success: false, error: 'Project not found' });
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// Find team and member by sessionName
|
|
231
|
+
const teams = await this.storageService.getTeams();
|
|
232
|
+
let teamId = '';
|
|
233
|
+
let memberId = '';
|
|
234
|
+
for (const team of teams) {
|
|
235
|
+
const member = team.members.find(m => m.sessionName === sessionName);
|
|
236
|
+
if (member) {
|
|
237
|
+
teamId = team.id;
|
|
238
|
+
memberId = member.id;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (!teamId) {
|
|
243
|
+
res.status(404).json({ success: false, error: 'Team member not found for sessionName' });
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
// Create target path in in_progress/ folder
|
|
247
|
+
const fileName = basename(taskPath);
|
|
248
|
+
const targetPath = taskPath.replace('/open/', '/in_progress/');
|
|
249
|
+
const targetDir = dirname(targetPath);
|
|
250
|
+
// Ensure in_progress directory exists
|
|
251
|
+
await ensureDirectoryExists(targetDir);
|
|
252
|
+
// Read, update, and move task file
|
|
253
|
+
const updatedContent = addTaskAssignmentInfo(taskContent, memberId, sessionName);
|
|
254
|
+
await writeFile(targetPath, updatedContent, 'utf-8');
|
|
255
|
+
await unlinkFile(taskPath);
|
|
256
|
+
// Add to task tracking
|
|
257
|
+
await this.taskTrackingService.assignTask(project.id, teamId, targetPath, taskInfo.title || taskInfo.fileName, taskInfo.targetRole || 'unknown', memberId, sessionName);
|
|
258
|
+
res.json({
|
|
259
|
+
success: true,
|
|
260
|
+
message: `Task ${fileName} assigned to member ${sessionName}`,
|
|
261
|
+
originalPath: taskPath,
|
|
262
|
+
newPath: targetPath,
|
|
263
|
+
memberId,
|
|
264
|
+
sessionName,
|
|
265
|
+
status: 'in_progress',
|
|
266
|
+
});
|
|
226
267
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
268
|
+
catch (error) {
|
|
269
|
+
logger.error('Error assigning task', { error: error instanceof Error ? error.message : String(error) });
|
|
270
|
+
res.status(500).json({ success: false, error: 'Failed to assign task' });
|
|
230
271
|
}
|
|
231
|
-
|
|
232
|
-
const fileName = basename(taskPath);
|
|
233
|
-
const targetPath = taskPath.replace('/open/', '/in_progress/');
|
|
234
|
-
const targetDir = dirname(targetPath);
|
|
235
|
-
// Ensure in_progress directory exists
|
|
236
|
-
await ensureDirectoryExists(targetDir);
|
|
237
|
-
// Read, update, and move task file
|
|
238
|
-
const updatedContent = addTaskAssignmentInfo(taskContent, memberId, sessionName);
|
|
239
|
-
await writeFile(targetPath, updatedContent, 'utf-8');
|
|
240
|
-
await unlinkFile(taskPath);
|
|
241
|
-
// Add to task tracking
|
|
242
|
-
await this.taskTrackingService.assignTask(project.id, teamId, targetPath, taskInfo.title || taskInfo.fileName, taskInfo.targetRole || 'unknown', memberId, sessionName);
|
|
243
|
-
res.json({
|
|
244
|
-
success: true,
|
|
245
|
-
message: `Task ${fileName} assigned to member ${sessionName}`,
|
|
246
|
-
originalPath: taskPath,
|
|
247
|
-
newPath: targetPath,
|
|
248
|
-
memberId,
|
|
249
|
-
sessionName,
|
|
250
|
-
status: 'in_progress',
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
catch (error) {
|
|
254
|
-
logger.error('Error assigning task', { error: error instanceof Error ? error.message : String(error) });
|
|
255
|
-
res.status(500).json({ success: false, error: 'Failed to assign task' });
|
|
256
|
-
}
|
|
272
|
+
});
|
|
257
273
|
}
|
|
258
274
|
/**
|
|
259
275
|
* Completes a task by moving it from in_progress/ to done/ folder
|
|
@@ -262,203 +278,222 @@ export async function assignTask(req, res) {
|
|
|
262
278
|
* @param res - Response with success status and completion information
|
|
263
279
|
*/
|
|
264
280
|
export async function completeTask(req, res) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
await updateAgentHeartbeat(sessionName, undefined, CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE);
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
logger.warn('Failed to update agent heartbeat', { error: error instanceof Error ? error.message : String(error) });
|
|
273
|
-
// Continue execution - heartbeat failures shouldn't break task completion
|
|
281
|
+
return TracingService.getInstance().withSpan(TRACING_CONSTANTS.SPANS.TASK_COMPLETE, {
|
|
282
|
+
attributes: {
|
|
283
|
+
'task.path': req.body.taskPath || 'unknown',
|
|
284
|
+
'agent.session': req.body.sessionName || 'unknown',
|
|
274
285
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
error:
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
res.status(200).json({
|
|
293
|
-
success: false,
|
|
294
|
-
error: 'Task is not in the correct folder for completion',
|
|
295
|
-
details: `Task must be in in_progress/ folder to be completed. Current path: ${taskPath}. Use accept_task first to move the task from open/ to in_progress/.`,
|
|
296
|
-
taskPath,
|
|
297
|
-
expectedFolder: 'in_progress',
|
|
298
|
-
currentFolder: taskPath.includes('/open/') ? 'open' : taskPath.includes('/done/') ? 'done' : taskPath.includes('/blocked/') ? 'blocked' : 'unknown',
|
|
299
|
-
action: 'Use accept_task tool first to assign the task'
|
|
300
|
-
});
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
// Read task content to check for output schema
|
|
304
|
-
const taskContent = await readFile(taskPath, 'utf-8');
|
|
305
|
-
const validator = TaskOutputValidatorService.getInstance();
|
|
306
|
-
const schema = validator.extractSchemaFromMarkdown(taskContent);
|
|
307
|
-
// If task has an output schema, validate the output
|
|
308
|
-
if (schema) {
|
|
309
|
-
if (!output || typeof output !== 'object') {
|
|
286
|
+
}, async (span) => {
|
|
287
|
+
try {
|
|
288
|
+
const { taskPath, sessionName, output, qualityScore } = req.body;
|
|
289
|
+
// Update agent heartbeat (proof of life)
|
|
290
|
+
try {
|
|
291
|
+
await updateAgentHeartbeat(sessionName, undefined, CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
logger.warn('Failed to update agent heartbeat', { error: error instanceof Error ? error.message : String(error) });
|
|
295
|
+
// Continue execution - heartbeat failures shouldn't break task completion
|
|
296
|
+
}
|
|
297
|
+
if (!taskPath) {
|
|
298
|
+
res.status(400).json({ success: false, error: 'taskPath is required' });
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
// Verify source task file exists
|
|
302
|
+
if (!existsSync(taskPath)) {
|
|
310
303
|
res.status(200).json({
|
|
311
304
|
success: false,
|
|
312
|
-
error: 'Task
|
|
313
|
-
details:
|
|
305
|
+
error: 'Task file does not exist at the specified path',
|
|
306
|
+
details: `No task file found at: ${taskPath}. Make sure the task has been properly assigned and is in the in_progress folder.`,
|
|
314
307
|
taskPath,
|
|
308
|
+
suggestion: 'Check if the task file exists and use accept_task first to move it from open/ to in_progress/'
|
|
315
309
|
});
|
|
316
310
|
return;
|
|
317
311
|
}
|
|
318
|
-
//
|
|
319
|
-
|
|
320
|
-
if (!sizeCheck.valid) {
|
|
312
|
+
// Ensure task is in in_progress/ folder
|
|
313
|
+
if (!taskPath.includes('/in_progress/')) {
|
|
321
314
|
res.status(200).json({
|
|
322
315
|
success: false,
|
|
323
|
-
error: '
|
|
324
|
-
details:
|
|
316
|
+
error: 'Task is not in the correct folder for completion',
|
|
317
|
+
details: `Task must be in in_progress/ folder to be completed. Current path: ${taskPath}. Use accept_task first to move the task from open/ to in_progress/.`,
|
|
325
318
|
taskPath,
|
|
319
|
+
expectedFolder: 'in_progress',
|
|
320
|
+
currentFolder: taskPath.includes('/open/') ? 'open' : taskPath.includes('/done/') ? 'done' : taskPath.includes('/blocked/') ? 'blocked' : 'unknown',
|
|
321
|
+
action: 'Use accept_task tool first to assign the task'
|
|
326
322
|
});
|
|
327
323
|
return;
|
|
328
324
|
}
|
|
329
|
-
//
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
325
|
+
// Read task content to check for output schema
|
|
326
|
+
const taskContent = await readFile(taskPath, 'utf-8');
|
|
327
|
+
const validator = TaskOutputValidatorService.getInstance();
|
|
328
|
+
const schema = validator.extractSchemaFromMarkdown(taskContent);
|
|
329
|
+
// If task has an output schema, validate the output
|
|
330
|
+
if (schema) {
|
|
331
|
+
if (!output || typeof output !== 'object') {
|
|
332
|
+
res.status(200).json({
|
|
333
|
+
success: false,
|
|
334
|
+
error: 'Task requires structured output but none was provided',
|
|
335
|
+
details: 'This task has an output schema. Provide an "output" object matching the schema.',
|
|
336
|
+
taskPath,
|
|
337
|
+
});
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
// Check output size
|
|
341
|
+
const sizeCheck = validator.validateOutputSize(output);
|
|
342
|
+
if (!sizeCheck.valid) {
|
|
343
|
+
res.status(200).json({
|
|
344
|
+
success: false,
|
|
345
|
+
error: 'Output size exceeds maximum',
|
|
346
|
+
details: sizeCheck.error,
|
|
347
|
+
taskPath,
|
|
348
|
+
});
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
// Validate output against schema
|
|
352
|
+
const validationResult = validator.validate(output, schema);
|
|
353
|
+
if (!validationResult.valid) {
|
|
354
|
+
// Check retry info
|
|
355
|
+
const existingRetryInfo = validator.extractRetryInfoFromMarkdown(taskContent);
|
|
356
|
+
const retryCount = existingRetryInfo ? existingRetryInfo.retryCount + 1 : 1;
|
|
357
|
+
const maxRetries = TASK_OUTPUT_CONSTANTS.MAX_RETRIES;
|
|
358
|
+
if (retryCount > maxRetries) {
|
|
359
|
+
// Max retries exceeded - move to blocked
|
|
360
|
+
const blockedPath = taskPath.replace('/in_progress/', '/blocked/');
|
|
361
|
+
const blockedDir = dirname(blockedPath);
|
|
362
|
+
await ensureDirectoryExists(blockedDir);
|
|
363
|
+
const failureInfo = `\n\n${TASK_OUTPUT_CONSTANTS.SECTION_HEADERS.VALIDATION_FAILURE}\n- **Status**: Blocked (max validation retries exceeded)\n- **Retry count**: ${retryCount}/${maxRetries}\n- **Errors**: ${validationResult.errors.join('; ')}\n- **Blocked at**: ${new Date().toISOString()}\n`;
|
|
364
|
+
const blockedContent = taskContent + failureInfo;
|
|
365
|
+
await writeFile(blockedPath, blockedContent, 'utf-8');
|
|
366
|
+
await unlinkFile(taskPath);
|
|
367
|
+
res.status(200).json({
|
|
368
|
+
success: false,
|
|
369
|
+
validationFailed: true,
|
|
370
|
+
maxRetriesExceeded: true,
|
|
371
|
+
errors: validationResult.errors,
|
|
372
|
+
retryCount,
|
|
373
|
+
maxRetries,
|
|
374
|
+
message: `Task moved to blocked/ after ${maxRetries} failed validation attempts`,
|
|
375
|
+
taskPath: blockedPath,
|
|
376
|
+
});
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
// Retries remaining - update retry info in task file
|
|
380
|
+
const retryInfo = {
|
|
381
|
+
retryCount,
|
|
382
|
+
maxRetries,
|
|
383
|
+
lastErrors: validationResult.errors,
|
|
384
|
+
lastAttemptAt: new Date().toISOString(),
|
|
385
|
+
};
|
|
386
|
+
// Remove existing retry info section if present, then append new one
|
|
387
|
+
const retryHeader = TASK_OUTPUT_CONSTANTS.SECTION_HEADERS.RETRY_INFO;
|
|
388
|
+
let updatedTaskContent = taskContent;
|
|
389
|
+
const retryHeaderIdx = updatedTaskContent.indexOf(retryHeader);
|
|
390
|
+
if (retryHeaderIdx !== -1) {
|
|
391
|
+
// Find the end of the retry section (next ## header or end of file)
|
|
392
|
+
const afterRetry = updatedTaskContent.substring(retryHeaderIdx + retryHeader.length);
|
|
393
|
+
const nextSectionMatch = afterRetry.match(/\n## /);
|
|
394
|
+
if (nextSectionMatch && nextSectionMatch.index !== undefined) {
|
|
395
|
+
updatedTaskContent = updatedTaskContent.substring(0, retryHeaderIdx) +
|
|
396
|
+
updatedTaskContent.substring(retryHeaderIdx + retryHeader.length + nextSectionMatch.index);
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
updatedTaskContent = updatedTaskContent.substring(0, retryHeaderIdx);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
updatedTaskContent += validator.generateRetryMarkdown(retryInfo);
|
|
403
|
+
await writeFile(taskPath, updatedTaskContent, 'utf-8');
|
|
345
404
|
res.status(200).json({
|
|
346
405
|
success: false,
|
|
347
406
|
validationFailed: true,
|
|
348
|
-
maxRetriesExceeded: true,
|
|
349
407
|
errors: validationResult.errors,
|
|
350
408
|
retryCount,
|
|
351
409
|
maxRetries,
|
|
352
|
-
message: `
|
|
353
|
-
taskPath
|
|
410
|
+
message: `Output validation failed. ${maxRetries - retryCount} retries remaining.`,
|
|
411
|
+
taskPath,
|
|
354
412
|
});
|
|
355
413
|
return;
|
|
356
414
|
}
|
|
357
|
-
//
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
415
|
+
// Validation passed - store output file alongside the done task
|
|
416
|
+
const doneTargetPath = taskPath.replace('/in_progress/', '/done/');
|
|
417
|
+
const outputFilePath = doneTargetPath.replace(/\.md$/, TASK_OUTPUT_CONSTANTS.OUTPUT_FILE_EXTENSION);
|
|
418
|
+
const doneDir = dirname(doneTargetPath);
|
|
419
|
+
await ensureDirectoryExists(doneDir);
|
|
420
|
+
const outputData = {
|
|
421
|
+
output,
|
|
422
|
+
producedAt: new Date().toISOString(),
|
|
423
|
+
sessionName: sessionName || 'unknown',
|
|
363
424
|
};
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
425
|
+
await writeFile(outputFilePath, JSON.stringify(outputData, null, 2), 'utf-8');
|
|
426
|
+
// Move task to done
|
|
427
|
+
const updatedContent = addTaskCompletionInfo(taskContent);
|
|
428
|
+
await writeFile(doneTargetPath, updatedContent, 'utf-8');
|
|
429
|
+
await unlinkFile(taskPath);
|
|
430
|
+
// Remove from task tracking and clean up monitoring
|
|
431
|
+
const allTasksWithSchema = await this.taskTrackingService.getAllInProgressTasks();
|
|
432
|
+
const taskToRemoveWithSchema = allTasksWithSchema.find(t => t.taskFilePath === taskPath);
|
|
433
|
+
let cleanupResultSchema = { cancelledSchedules: 0, unsubscribedEvents: 0 };
|
|
434
|
+
if (taskToRemoveWithSchema) {
|
|
435
|
+
// #174: Store quality score on task before completing
|
|
436
|
+
if (typeof qualityScore === 'number' && qualityScore >= 0 && qualityScore <= 100) {
|
|
437
|
+
taskToRemoveWithSchema.qualityScore = qualityScore;
|
|
438
|
+
taskToRemoveWithSchema.scoredAt = new Date().toISOString();
|
|
439
|
+
taskToRemoveWithSchema.scoredBy = sessionName;
|
|
378
440
|
}
|
|
441
|
+
publishTaskCompletedEvent(taskToRemoveWithSchema, sessionName);
|
|
442
|
+
cleanupResultSchema = await cleanupTaskMonitoring(this, taskToRemoveWithSchema);
|
|
443
|
+
await this.taskTrackingService.removeTask(taskToRemoveWithSchema.id);
|
|
379
444
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
taskPath,
|
|
445
|
+
res.json({
|
|
446
|
+
success: true,
|
|
447
|
+
message: `Task ${basename(taskPath)} marked as completed with validated output`,
|
|
448
|
+
originalPath: taskPath,
|
|
449
|
+
newPath: doneTargetPath,
|
|
450
|
+
outputPath: outputFilePath,
|
|
451
|
+
status: 'done',
|
|
452
|
+
completedAt: new Date().toISOString(),
|
|
453
|
+
monitoringCleanup: cleanupResultSchema,
|
|
390
454
|
});
|
|
391
455
|
return;
|
|
392
456
|
}
|
|
393
|
-
//
|
|
394
|
-
const
|
|
395
|
-
const
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
producedAt: new Date().toISOString(),
|
|
401
|
-
sessionName: sessionName || 'unknown',
|
|
402
|
-
};
|
|
403
|
-
await writeFile(outputFilePath, JSON.stringify(outputData, null, 2), 'utf-8');
|
|
404
|
-
// Move task to done
|
|
457
|
+
// No schema - original behavior (backward compatible)
|
|
458
|
+
const fileName = basename(taskPath);
|
|
459
|
+
const targetPath = taskPath.replace('/in_progress/', '/done/');
|
|
460
|
+
const targetDir = dirname(targetPath);
|
|
461
|
+
// Ensure done directory exists
|
|
462
|
+
await ensureDirectoryExists(targetDir);
|
|
463
|
+
// Read, update, and move task file
|
|
405
464
|
const updatedContent = addTaskCompletionInfo(taskContent);
|
|
406
|
-
await writeFile(
|
|
465
|
+
await writeFile(targetPath, updatedContent, 'utf-8');
|
|
407
466
|
await unlinkFile(taskPath);
|
|
408
467
|
// Remove from task tracking and clean up monitoring
|
|
409
|
-
const
|
|
410
|
-
const
|
|
411
|
-
let
|
|
412
|
-
if (
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
468
|
+
const allTasks = await this.taskTrackingService.getAllInProgressTasks();
|
|
469
|
+
const taskToRemove = allTasks.find(t => t.taskFilePath === taskPath);
|
|
470
|
+
let cleanupResult = { cancelledSchedules: 0, unsubscribedEvents: 0 };
|
|
471
|
+
if (taskToRemove) {
|
|
472
|
+
// #174: Store quality score on task before completing
|
|
473
|
+
if (typeof qualityScore === 'number' && qualityScore >= 0 && qualityScore <= 100) {
|
|
474
|
+
taskToRemove.qualityScore = qualityScore;
|
|
475
|
+
taskToRemove.scoredAt = new Date().toISOString();
|
|
476
|
+
taskToRemove.scoredBy = sessionName;
|
|
477
|
+
}
|
|
478
|
+
publishTaskCompletedEvent(taskToRemove, sessionName);
|
|
479
|
+
cleanupResult = await cleanupTaskMonitoring(this, taskToRemove);
|
|
480
|
+
await this.taskTrackingService.removeTask(taskToRemove.id);
|
|
416
481
|
}
|
|
417
482
|
res.json({
|
|
418
483
|
success: true,
|
|
419
|
-
message: `Task ${
|
|
484
|
+
message: `Task ${fileName} marked as completed`,
|
|
420
485
|
originalPath: taskPath,
|
|
421
|
-
newPath:
|
|
422
|
-
outputPath: outputFilePath,
|
|
486
|
+
newPath: targetPath,
|
|
423
487
|
status: 'done',
|
|
424
488
|
completedAt: new Date().toISOString(),
|
|
425
|
-
monitoringCleanup:
|
|
489
|
+
monitoringCleanup: cleanupResult,
|
|
426
490
|
});
|
|
427
|
-
return;
|
|
428
491
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
const targetDir = dirname(targetPath);
|
|
433
|
-
// Ensure done directory exists
|
|
434
|
-
await ensureDirectoryExists(targetDir);
|
|
435
|
-
// Read, update, and move task file
|
|
436
|
-
const updatedContent = addTaskCompletionInfo(taskContent);
|
|
437
|
-
await writeFile(targetPath, updatedContent, 'utf-8');
|
|
438
|
-
await unlinkFile(taskPath);
|
|
439
|
-
// Remove from task tracking and clean up monitoring
|
|
440
|
-
const allTasks = await this.taskTrackingService.getAllInProgressTasks();
|
|
441
|
-
const taskToRemove = allTasks.find(t => t.taskFilePath === taskPath);
|
|
442
|
-
let cleanupResult = { cancelledSchedules: 0, unsubscribedEvents: 0 };
|
|
443
|
-
if (taskToRemove) {
|
|
444
|
-
publishTaskCompletedEvent(taskToRemove, sessionName);
|
|
445
|
-
cleanupResult = await cleanupTaskMonitoring(this, taskToRemove);
|
|
446
|
-
await this.taskTrackingService.removeTask(taskToRemove.id);
|
|
492
|
+
catch (error) {
|
|
493
|
+
logger.error('Error completing task', { error: error instanceof Error ? error.message : String(error) });
|
|
494
|
+
res.status(500).json({ success: false, error: 'Failed to complete task' });
|
|
447
495
|
}
|
|
448
|
-
|
|
449
|
-
success: true,
|
|
450
|
-
message: `Task ${fileName} marked as completed`,
|
|
451
|
-
originalPath: taskPath,
|
|
452
|
-
newPath: targetPath,
|
|
453
|
-
status: 'done',
|
|
454
|
-
completedAt: new Date().toISOString(),
|
|
455
|
-
monitoringCleanup: cleanupResult,
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
catch (error) {
|
|
459
|
-
logger.error('Error completing task', { error: error instanceof Error ? error.message : String(error) });
|
|
460
|
-
res.status(500).json({ success: false, error: 'Failed to complete task' });
|
|
461
|
-
}
|
|
496
|
+
});
|
|
462
497
|
}
|
|
463
498
|
/**
|
|
464
499
|
* Blocks a task by moving it from in_progress/ to blocked/ folder
|
|
@@ -1456,4 +1491,241 @@ export async function completeTasksBySession(req, res) {
|
|
|
1456
1491
|
res.status(500).json({ success: false, error: 'Failed to complete tasks by session' });
|
|
1457
1492
|
}
|
|
1458
1493
|
}
|
|
1494
|
+
/**
|
|
1495
|
+
* GET /task-management/tasks
|
|
1496
|
+
*
|
|
1497
|
+
* List task files for a project, optionally filtered by status.
|
|
1498
|
+
* Returns task filenames and paths grouped by milestone.
|
|
1499
|
+
*
|
|
1500
|
+
* @param req - Request with query: { projectPath, status? }
|
|
1501
|
+
* @param res - Response with { success, tasks }
|
|
1502
|
+
*/
|
|
1503
|
+
/**
|
|
1504
|
+
* Detect and optionally clean up orphan tasks — tasks stuck in progress
|
|
1505
|
+
* assigned to agents that no longer exist or have been inactive too long.
|
|
1506
|
+
*
|
|
1507
|
+
* POST /api/task-management/cleanup
|
|
1508
|
+
* Body:
|
|
1509
|
+
* - action: 'detect' (default, dry run) | 'cancel' | 'reopen'
|
|
1510
|
+
* - staleThresholdHours: number (default 24)
|
|
1511
|
+
* - taskIds: string[] (optional, specific tasks to clean; if omitted, cleans all detected orphans)
|
|
1512
|
+
*
|
|
1513
|
+
* @param req - Request with cleanup parameters
|
|
1514
|
+
* @param res - Response with orphan detection/cleanup report
|
|
1515
|
+
* @see https://github.com/stevehuang0115/crewly/issues/168
|
|
1516
|
+
*/
|
|
1517
|
+
export async function cleanupOrphanTasks(req, res) {
|
|
1518
|
+
try {
|
|
1519
|
+
const { action = 'detect', staleThresholdHours = 24, taskIds, } = req.body;
|
|
1520
|
+
const staleThresholdMs = staleThresholdHours * 60 * 60 * 1000;
|
|
1521
|
+
const getTeamStatus = async () => {
|
|
1522
|
+
return await this.storageService.getTeams();
|
|
1523
|
+
};
|
|
1524
|
+
// Step 1: Detect orphan tasks
|
|
1525
|
+
const orphans = await this.taskTrackingService.detectOrphanTasks(getTeamStatus, staleThresholdMs);
|
|
1526
|
+
if (action === 'detect') {
|
|
1527
|
+
res.json({
|
|
1528
|
+
success: true,
|
|
1529
|
+
message: `Found ${orphans.length} orphan task(s)`,
|
|
1530
|
+
data: {
|
|
1531
|
+
orphanCount: orphans.length,
|
|
1532
|
+
orphans: orphans.map(t => ({
|
|
1533
|
+
id: t.id,
|
|
1534
|
+
taskName: t.taskName,
|
|
1535
|
+
assignedSessionName: t.assignedSessionName,
|
|
1536
|
+
assignedTeamMemberId: t.assignedTeamMemberId,
|
|
1537
|
+
status: t.status,
|
|
1538
|
+
assignedAt: t.assignedAt,
|
|
1539
|
+
staleSinceHours: Math.round(t.staleSinceMs / (60 * 60 * 1000) * 10) / 10,
|
|
1540
|
+
taskFilePath: t.taskFilePath,
|
|
1541
|
+
})),
|
|
1542
|
+
},
|
|
1543
|
+
});
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
// Step 2: Clean up
|
|
1547
|
+
const idsToClean = taskIds || orphans.map(t => t.id);
|
|
1548
|
+
if (idsToClean.length === 0) {
|
|
1549
|
+
res.json({ success: true, message: 'No orphan tasks to clean up', data: { cleaned: 0 } });
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1552
|
+
const cleanupAction = action === 'reopen' ? 'reopen' : 'cancel';
|
|
1553
|
+
const report = await this.taskTrackingService.cleanupOrphanTasks(idsToClean, cleanupAction);
|
|
1554
|
+
logger.info('Orphan task cleanup completed', {
|
|
1555
|
+
action: cleanupAction,
|
|
1556
|
+
cleaned: report.cleaned,
|
|
1557
|
+
errors: report.errors.length,
|
|
1558
|
+
});
|
|
1559
|
+
res.json({
|
|
1560
|
+
success: true,
|
|
1561
|
+
message: `Cleaned ${report.cleaned} orphan task(s) (action: ${cleanupAction})`,
|
|
1562
|
+
data: {
|
|
1563
|
+
cleaned: report.cleaned,
|
|
1564
|
+
errors: report.errors,
|
|
1565
|
+
totalOrphansDetected: orphans.length,
|
|
1566
|
+
},
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
catch (error) {
|
|
1570
|
+
logger.error('Orphan task cleanup failed', { error: error instanceof Error ? error.message : String(error) });
|
|
1571
|
+
res.status(500).json({
|
|
1572
|
+
success: false,
|
|
1573
|
+
error: 'Failed to clean up orphan tasks',
|
|
1574
|
+
details: error instanceof Error ? error.message : String(error),
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
export async function listTasks(req, res) {
|
|
1579
|
+
try {
|
|
1580
|
+
const projectPath = req.query.projectPath;
|
|
1581
|
+
const statusFilter = req.query.status;
|
|
1582
|
+
if (!projectPath) {
|
|
1583
|
+
res.status(400).json({ success: false, error: 'projectPath query parameter is required' });
|
|
1584
|
+
return;
|
|
1585
|
+
}
|
|
1586
|
+
// Validate status filter against known values to prevent path traversal
|
|
1587
|
+
const VALID_STATUSES = ['open', 'in_progress', 'blocked', 'done'];
|
|
1588
|
+
if (statusFilter && !VALID_STATUSES.includes(statusFilter)) {
|
|
1589
|
+
res.status(400).json({ success: false, error: `status must be one of: ${VALID_STATUSES.join(', ')}` });
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
// Resolve and validate project path to prevent directory traversal
|
|
1593
|
+
const resolvedPath = resolve(projectPath);
|
|
1594
|
+
const tasksBasePath = join(resolvedPath, '.crewly', 'tasks');
|
|
1595
|
+
if (!existsSync(tasksBasePath)) {
|
|
1596
|
+
res.json({ success: true, tasks: [] });
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
const tasks = [];
|
|
1600
|
+
const milestones = await readdir(tasksBasePath);
|
|
1601
|
+
for (const milestone of milestones) {
|
|
1602
|
+
const milestonePath = join(tasksBasePath, milestone);
|
|
1603
|
+
const milestoneStat = await stat(milestonePath).catch(() => null);
|
|
1604
|
+
if (!milestoneStat?.isDirectory())
|
|
1605
|
+
continue;
|
|
1606
|
+
const statusDirs = statusFilter ? [statusFilter] : [...VALID_STATUSES];
|
|
1607
|
+
for (const status of statusDirs) {
|
|
1608
|
+
const statusPath = join(milestonePath, status);
|
|
1609
|
+
if (!existsSync(statusPath))
|
|
1610
|
+
continue;
|
|
1611
|
+
const files = await readdir(statusPath);
|
|
1612
|
+
for (const file of files) {
|
|
1613
|
+
if (file.endsWith('.md')) {
|
|
1614
|
+
tasks.push({
|
|
1615
|
+
name: file.replace('.md', ''),
|
|
1616
|
+
path: join(statusPath, file),
|
|
1617
|
+
milestone,
|
|
1618
|
+
status,
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
res.json({ success: true, tasks });
|
|
1625
|
+
}
|
|
1626
|
+
catch (error) {
|
|
1627
|
+
logger.error('Error listing tasks', { error: error instanceof Error ? error.message : String(error) });
|
|
1628
|
+
res.status(500).json({ success: false, error: 'Failed to list tasks' });
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Score a completed task's quality (#174).
|
|
1633
|
+
* Called by the auditor's score-task skill after task:completed events.
|
|
1634
|
+
* Updates the task's qualityScore in the tracking data.
|
|
1635
|
+
*
|
|
1636
|
+
* @param req - Request containing taskId, qualityScore, and optional scoredBy
|
|
1637
|
+
* @param res - Response with success status
|
|
1638
|
+
*/
|
|
1639
|
+
export async function scoreTask(req, res) {
|
|
1640
|
+
try {
|
|
1641
|
+
const { taskId, qualityScore, scoredBy } = req.body;
|
|
1642
|
+
if (!taskId) {
|
|
1643
|
+
res.status(400).json({ success: false, error: 'taskId is required' });
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
if (typeof qualityScore !== 'number' || qualityScore < 0 || qualityScore > 100) {
|
|
1647
|
+
res.status(400).json({ success: false, error: 'qualityScore must be a number between 0 and 100' });
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
// Load task data directly for in-place update
|
|
1651
|
+
const taskData = await this.taskTrackingService.loadTaskData();
|
|
1652
|
+
const task = taskData.tasks.find(t => t.id === taskId);
|
|
1653
|
+
if (task) {
|
|
1654
|
+
// Task still in tracking — update in place and persist
|
|
1655
|
+
task.qualityScore = qualityScore;
|
|
1656
|
+
task.scoredAt = new Date().toISOString();
|
|
1657
|
+
task.scoredBy = scoredBy || 'auditor';
|
|
1658
|
+
await this.taskTrackingService.saveTaskData(taskData);
|
|
1659
|
+
logger.info('Task scored', { taskId, qualityScore, scoredBy: scoredBy || 'auditor' });
|
|
1660
|
+
res.json({ success: true, message: 'Task scored successfully', taskId, qualityScore });
|
|
1661
|
+
}
|
|
1662
|
+
else {
|
|
1663
|
+
// Task already removed from tracking — score acknowledged
|
|
1664
|
+
logger.warn('Task not found in tracking (may already be completed)', { taskId });
|
|
1665
|
+
res.json({ success: true, message: 'Score acknowledged but task already completed', taskId, qualityScore });
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
catch (error) {
|
|
1669
|
+
logger.error('Error scoring task', { error: error instanceof Error ? error.message : String(error) });
|
|
1670
|
+
res.status(500).json({ success: false, error: 'Failed to score task' });
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Record a task handoff from one agent to another (F12).
|
|
1675
|
+
*
|
|
1676
|
+
* POST /api/task-management/handoff
|
|
1677
|
+
* Body: { from, to, taskPath?, reason, progress?, projectPath? }
|
|
1678
|
+
*
|
|
1679
|
+
* Updates the task tracking data to reflect the handoff and logs the event.
|
|
1680
|
+
*
|
|
1681
|
+
* @param req - Request with handoff parameters
|
|
1682
|
+
* @param res - Response with handoff record
|
|
1683
|
+
*/
|
|
1684
|
+
export async function recordHandoff(req, res) {
|
|
1685
|
+
try {
|
|
1686
|
+
const { from, to, taskPath, reason, progress, projectPath } = req.body;
|
|
1687
|
+
if (!from || !to || !reason) {
|
|
1688
|
+
res.status(400).json({ success: false, error: 'from, to, and reason are required' });
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
// Find the task being handed off (by assignedSessionName)
|
|
1692
|
+
const tasks = await this.taskTrackingService.getTasksBySessionName(from);
|
|
1693
|
+
const activeTask = tasks.find(t => t.status === 'assigned' || t.status === 'active' || t.status === 'working');
|
|
1694
|
+
if (activeTask) {
|
|
1695
|
+
// Update task assignment to new agent
|
|
1696
|
+
const data = await this.taskTrackingService.loadTaskData();
|
|
1697
|
+
const task = data.tasks.find(t => t.id === activeTask.id);
|
|
1698
|
+
if (task) {
|
|
1699
|
+
task.assignedSessionName = to;
|
|
1700
|
+
task.status = 'assigned';
|
|
1701
|
+
task.statusHistory = task.statusHistory || [];
|
|
1702
|
+
task.statusHistory.push({
|
|
1703
|
+
timestamp: new Date().toISOString(),
|
|
1704
|
+
fromStatus: activeTask.status,
|
|
1705
|
+
toStatus: 'assigned',
|
|
1706
|
+
message: `Handed off from ${from} to ${to}: ${reason}`,
|
|
1707
|
+
reportedBy: from,
|
|
1708
|
+
});
|
|
1709
|
+
await this.taskTrackingService.saveTaskData(data);
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
logger.info('Task handoff recorded', { from, to, reason, taskId: activeTask?.id });
|
|
1713
|
+
res.json({
|
|
1714
|
+
success: true,
|
|
1715
|
+
handoff: {
|
|
1716
|
+
from,
|
|
1717
|
+
to,
|
|
1718
|
+
reason,
|
|
1719
|
+
taskId: activeTask?.id || null,
|
|
1720
|
+
taskPath: taskPath || null,
|
|
1721
|
+
progress: progress || null,
|
|
1722
|
+
timestamp: new Date().toISOString(),
|
|
1723
|
+
},
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
catch (error) {
|
|
1727
|
+
logger.error('Error recording handoff', { error: error instanceof Error ? error.message : String(error) });
|
|
1728
|
+
res.status(500).json({ success: false, error: 'Failed to record handoff' });
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1459
1731
|
//# sourceMappingURL=task-management.controller.js.map
|