crewly 1.6.1 → 1.6.3
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/roles/orchestrator/prompt.md +16 -0
- package/config/skills/agent/core/get-my-active-work/SKILL.md +101 -0
- package/config/skills/agent/core/get-my-active-work/execute.sh +122 -0
- package/config/skills/agent/core/record-learning/SKILL.md +29 -0
- package/config/skills/agent/core/reply-channel/SKILL.md +41 -0
- package/config/skills/agent/core/reply-channel/execute.sh +165 -0
- package/config/skills/agent/core/reply-channel/execute.test.sh +148 -0
- package/config/skills/agent/remote-browser/execute.sh +296 -14
- package/config/skills/agent/remote-browser/execute.test.sh +482 -0
- package/config/skills/orchestrator/send-message/SKILL.md +30 -7
- package/config/skills/orchestrator/team-health-scan/SKILL.md +98 -0
- package/config/skills/orchestrator/team-health-scan/execute.sh +44 -0
- package/config/skills/registry.json +62 -1
- package/config/slack-app-manifest.json +2 -1
- package/config/sops/developer/git-workflow.md +38 -3
- package/dist/backend/backend/src/constants.d.ts +69 -1
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +69 -2
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/active-work/active-work.controller.d.ts +53 -0
- package/dist/backend/backend/src/controllers/active-work/active-work.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/active-work/active-work.controller.js +92 -0
- package/dist/backend/backend/src/controllers/active-work/active-work.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.js +18 -1
- package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts +68 -0
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.js +233 -5
- package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.js +10 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js +8 -3
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts +132 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +401 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.d.ts +29 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.js +39 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/index.d.ts +8 -0
- package/dist/backend/backend/src/controllers/chat-v2/index.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/index.js +8 -0
- package/dist/backend/backend/src/controllers/chat-v2/index.js.map +1 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.d.ts +13 -13
- package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.js +74 -234
- package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.js +76 -15
- package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.controller.js +4 -6
- package/dist/backend/backend/src/controllers/request/request.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/tasks.controller.d.ts +43 -0
- package/dist/backend/backend/src/controllers/task-management/tasks.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/tasks.controller.js +200 -72
- package/dist/backend/backend/src/controllers/task-management/tasks.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +49 -0
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team-health/team-health.controller.d.ts +59 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.controller.js +127 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.routes.d.ts +13 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.routes.js +20 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.routes.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts +9 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +233 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +40 -6
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/active-work-briefing.service.d.ts +498 -0
- package/dist/backend/backend/src/services/agent/active-work-briefing.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/active-work-briefing.service.js +759 -0
- package/dist/backend/backend/src/services/agent/active-work-briefing.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +25 -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 +221 -58
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +9 -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 +35 -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/types.d.ts +8 -2
- 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 +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/types.js.map +1 -1
- package/dist/backend/backend/src/services/agent/tmux-command.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/tmux-command.service.js +2 -1
- package/dist/backend/backend/src/services/agent/tmux-command.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/tmux.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/tmux.service.js +2 -1
- package/dist/backend/backend/src/services/agent/tmux.service.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +148 -3
- 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 +241 -2
- package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.js +13 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js +26 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts +79 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts.map +1 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js +118 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js.map +1 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +161 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js +382 -2
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +105 -0
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js +232 -13
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +178 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +254 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts +134 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.js +232 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.d.ts +25 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.js +23 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +254 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +467 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.d.ts +27 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.js +57 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.d.ts +43 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.js +54 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/config.d.ts +100 -0
- package/dist/backend/backend/src/services/chat-v2/config.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/config.js +174 -0
- package/dist/backend/backend/src/services/chat-v2/config.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/index.d.ts +11 -0
- package/dist/backend/backend/src/services/chat-v2/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/index.js +12 -0
- package/dist/backend/backend/src/services/chat-v2/index.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.d.ts +114 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.js +194 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.d.ts +100 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.js +351 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +132 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +281 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/types.d.ts +295 -0
- package/dist/backend/backend/src/services/chat-v2/types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/types.js +61 -0
- package/dist/backend/backend/src/services/chat-v2/types.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.d.ts +113 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.js +179 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.d.ts +131 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.js +227 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.js.map +1 -0
- package/dist/backend/backend/src/services/core/config.service.js +3 -3
- package/dist/backend/backend/src/services/core/config.service.js.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.d.ts +22 -0
- package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.js +57 -0
- package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts +69 -1
- 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 +118 -0
- package/dist/backend/backend/src/services/event-bus/event-bus.service.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts +275 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +736 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -0
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.js +18 -2
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts +49 -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 +123 -29
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/learnings-index.service.d.ts +159 -0
- package/dist/backend/backend/src/services/knowledge/learnings-index.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/knowledge/learnings-index.service.js +304 -0
- package/dist/backend/backend/src/services/knowledge/learnings-index.service.js.map +1 -0
- 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 +24 -4
- package/dist/backend/backend/src/services/knowledge/vector-store.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.d.ts +174 -0
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.d.ts.map +1 -0
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.js +375 -0
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.js.map +1 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.d.ts +97 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.d.ts.map +1 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.js +209 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.js.map +1 -0
- package/dist/backend/backend/src/services/memory/vector-store.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/vector-store.service.js +19 -4
- package/dist/backend/backend/src/services/memory/vector-store.service.js.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.d.ts +16 -5
- package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.js +32 -5
- package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.js.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding.service.d.ts +157 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.service.js +229 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.service.js.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.types.d.ts +141 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.types.js +18 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.types.js.map +1 -0
- package/dist/backend/backend/src/services/pr-review/pr-review.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/pr-review/pr-review.service.js +1 -1
- package/dist/backend/backend/src/services/pr-review/pr-review.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/cross-machine-message.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/cross-machine-message.service.js +17 -1
- package/dist/backend/backend/src/services/slack/cross-machine-message.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +39 -1
- 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 +158 -26
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +248 -6
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js +531 -51
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/team-health/index.d.ts +16 -0
- package/dist/backend/backend/src/services/team-health/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/index.js +16 -0
- package/dist/backend/backend/src/services/team-health/index.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.d.ts +52 -0
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.js +161 -0
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.d.ts +53 -0
- package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.js +88 -0
- package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/stale-trigger-detector.d.ts +44 -0
- package/dist/backend/backend/src/services/team-health/stale-trigger-detector.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/stale-trigger-detector.js +83 -0
- package/dist/backend/backend/src/services/team-health/stale-trigger-detector.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-alert-router.d.ts +92 -0
- package/dist/backend/backend/src/services/team-health/team-health-alert-router.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-alert-router.js +328 -0
- package/dist/backend/backend/src/services/team-health/team-health-alert-router.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-config.d.ts +41 -0
- package/dist/backend/backend/src/services/team-health/team-health-config.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-config.js +213 -0
- package/dist/backend/backend/src/services/team-health/team-health-config.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-detector.d.ts +46 -0
- package/dist/backend/backend/src/services/team-health/team-health-detector.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-detector.js +347 -0
- package/dist/backend/backend/src/services/team-health/team-health-detector.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-types.d.ts +154 -0
- package/dist/backend/backend/src/services/team-health/team-health-types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-types.js +94 -0
- package/dist/backend/backend/src/services/team-health/team-health-types.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.d.ts +111 -0
- package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.js +226 -0
- package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.js.map +1 -0
- package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts +148 -0
- package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/mission-reminder.service.js +545 -0
- package/dist/backend/backend/src/services/v3/mission-reminder.service.js.map +1 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts +499 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.js +1105 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.js.map +1 -0
- package/dist/backend/backend/src/services/v3/request.service.d.ts +22 -0
- package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/request.service.js +71 -0
- package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/v3-data.service.d.ts +1 -0
- package/dist/backend/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/v3-data.service.js +22 -6
- package/dist/backend/backend/src/services/v3/v3-data.service.js.map +1 -1
- package/dist/backend/backend/src/types/event-bus.types.d.ts +19 -1
- package/dist/backend/backend/src/types/event-bus.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/event-bus.types.js +43 -0
- package/dist/backend/backend/src/types/event-bus.types.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +22 -1
- 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/review-reason.types.d.ts +63 -0
- package/dist/backend/backend/src/types/review-reason.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/review-reason.types.js +50 -0
- package/dist/backend/backend/src/types/review-reason.types.js.map +1 -0
- package/dist/backend/backend/src/types/slack.types.d.ts +4 -1
- package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/slack.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/mission.types.d.ts +18 -0
- package/dist/backend/backend/src/types/v2/mission.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/mission.types.js +1 -0
- package/dist/backend/backend/src/types/v2/mission.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.js +25 -1
- package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/backend/backend/src/utils/team.utils.d.ts +38 -0
- package/dist/backend/backend/src/utils/team.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/utils/team.utils.js +45 -0
- package/dist/backend/backend/src/utils/team.utils.js.map +1 -0
- package/dist/backend/backend/src/websocket/chat-v2.gateway.d.ts +195 -0
- package/dist/backend/backend/src/websocket/chat-v2.gateway.d.ts.map +1 -0
- package/dist/backend/backend/src/websocket/chat-v2.gateway.js +401 -0
- package/dist/backend/backend/src/websocket/chat-v2.gateway.js.map +1 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +37 -2
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js +106 -5
- package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +69 -1
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +69 -2
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/core/config.service.js +3 -3
- package/dist/cli/backend/src/services/core/config.service.js.map +1 -1
- package/dist/cli/backend/src/services/core/storage.service.d.ts +22 -0
- package/dist/cli/backend/src/services/core/storage.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/core/storage.service.js +57 -0
- package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.js +18 -2
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts +49 -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 +123 -29
- 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.map +1 -1
- package/dist/cli/backend/src/services/knowledge/vector-store.service.js +24 -4
- package/dist/cli/backend/src/services/knowledge/vector-store.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +22 -1
- 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/v2/work-item.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.js +25 -1
- package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
- package/frontend/dist/assets/{index-70356616.js → index-7a4e7df5.js} +328 -326
- package/frontend/dist/assets/index-b7e59b2b.css +33 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +2 -1
- package/config/skills/orchestrator/recall/SKILL.md +0 -47
- package/config/skills/orchestrator/recall/execute.sh +0 -13
- package/config/skills/orchestrator/record-learning/SKILL.md +0 -47
- package/config/skills/orchestrator/record-learning/execute.sh +0 -13
- package/config/skills/orchestrator/remember/SKILL.md +0 -55
- package/config/skills/orchestrator/remember/execute.sh +0 -15
- package/frontend/dist/assets/index-6aaa0630.css +0 -33
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Co-located test for remote-browser skill — covers the per-tab dispatch
|
|
3
|
+
# wiring added for the Crewly-in-Chrome concurrent-agent fix.
|
|
4
|
+
#
|
|
5
|
+
# Strategy: spin up a tiny Python HTTP stub on a free port, point the
|
|
6
|
+
# skill at it via CREWLY_API_URL, then drive scenarios. The stub records
|
|
7
|
+
# every request (method + path + body + headers) into a JSON log so we
|
|
8
|
+
# can assert exact wire shape — same pattern used by chat-v2 skill tests.
|
|
9
|
+
#
|
|
10
|
+
# Each scenario gets its own runtime dir under a per-run TMPDIR so cache
|
|
11
|
+
# state from one case never leaks into the next.
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
SKILL="${SCRIPT_DIR}/execute.sh"
|
|
17
|
+
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
# Stub HTTP server (Python). Logs every request to $LOG_FILE as JSONL,
|
|
20
|
+
# returns canned responses controlled by $RESPONSE_FILE (each line = one
|
|
21
|
+
# JSON response, consumed in order; empty line = use default).
|
|
22
|
+
# ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
start_stub_server() {
|
|
25
|
+
local port="$1" log_file="$2" responses_file="$3"
|
|
26
|
+
# CRITICAL: redirect python's stdio to /dev/null. Without this the surrounding
|
|
27
|
+
# `STUB_PID=$(start_stub_server ...)` $() subshell waits for python's stdout
|
|
28
|
+
# to close — and python never closes it — causing the test to hang on
|
|
29
|
+
# scenario startup. We don't need the python's chatter, only its pid.
|
|
30
|
+
PORT=$port LOG_FILE=$log_file RESPONSES=$responses_file \
|
|
31
|
+
python3 -c '
|
|
32
|
+
import http.server, json, os, threading, time, sys
|
|
33
|
+
|
|
34
|
+
LOG = os.environ["LOG_FILE"]
|
|
35
|
+
RESP = os.environ["RESPONSES"]
|
|
36
|
+
PORT = int(os.environ["PORT"])
|
|
37
|
+
|
|
38
|
+
# Load all canned responses up front.
|
|
39
|
+
with open(RESP) as f:
|
|
40
|
+
canned = [line.rstrip("\n") for line in f]
|
|
41
|
+
counter = {"i": 0}
|
|
42
|
+
|
|
43
|
+
class Handler(http.server.BaseHTTPRequestHandler):
|
|
44
|
+
def _read_body(self):
|
|
45
|
+
n = int(self.headers.get("Content-Length") or 0)
|
|
46
|
+
return self.rfile.read(n).decode("utf-8") if n else ""
|
|
47
|
+
|
|
48
|
+
def _log(self, body):
|
|
49
|
+
entry = {
|
|
50
|
+
"method": self.command,
|
|
51
|
+
"path": self.path,
|
|
52
|
+
"body": body,
|
|
53
|
+
"headers": {k: v for k, v in self.headers.items()},
|
|
54
|
+
}
|
|
55
|
+
with open(LOG, "a") as f:
|
|
56
|
+
f.write(json.dumps(entry) + "\n")
|
|
57
|
+
|
|
58
|
+
def _next_response(self):
|
|
59
|
+
# Skip ambient infra paths from the queued-response slot — `_common/lib.sh`
|
|
60
|
+
# auto-fires `/api/heartbeat` on every skill startup, which would burn the
|
|
61
|
+
# first canned response otherwise.
|
|
62
|
+
if self.path.startswith("/api/heartbeat"):
|
|
63
|
+
return json.dumps({"success": True})
|
|
64
|
+
i = counter["i"]
|
|
65
|
+
counter["i"] += 1
|
|
66
|
+
if i < len(canned) and canned[i]:
|
|
67
|
+
return canned[i]
|
|
68
|
+
return json.dumps({"success": True, "data": {}})
|
|
69
|
+
|
|
70
|
+
def _is_assertable(self):
|
|
71
|
+
"""True if this request should be visible in the request_field log
|
|
72
|
+
(i.e. not an ambient heartbeat)."""
|
|
73
|
+
return not self.path.startswith("/api/heartbeat")
|
|
74
|
+
|
|
75
|
+
def _serve(self, body):
|
|
76
|
+
if self._is_assertable():
|
|
77
|
+
self._log(body)
|
|
78
|
+
raw = self._next_response()
|
|
79
|
+
# raw format: "<status>|<json-body>" (status is optional, default 200)
|
|
80
|
+
if "|" in raw:
|
|
81
|
+
status_str, payload = raw.split("|", 1)
|
|
82
|
+
status = int(status_str)
|
|
83
|
+
else:
|
|
84
|
+
status = 200
|
|
85
|
+
payload = raw
|
|
86
|
+
self.send_response(status)
|
|
87
|
+
self.send_header("Content-Type", "application/json")
|
|
88
|
+
self.send_header("Content-Length", str(len(payload)))
|
|
89
|
+
self.end_headers()
|
|
90
|
+
self.wfile.write(payload.encode("utf-8"))
|
|
91
|
+
|
|
92
|
+
def log_message(self, fmt, *args): # silence default access log
|
|
93
|
+
return
|
|
94
|
+
|
|
95
|
+
def do_GET(self):
|
|
96
|
+
self._serve("")
|
|
97
|
+
|
|
98
|
+
def do_POST(self):
|
|
99
|
+
self._serve(self._read_body())
|
|
100
|
+
|
|
101
|
+
server = http.server.ThreadingHTTPServer(("127.0.0.1", PORT), Handler)
|
|
102
|
+
# Daemonize so SIGTERM cleanly kills it.
|
|
103
|
+
threading.Thread(target=server.serve_forever, daemon=True).start()
|
|
104
|
+
print(f"stub listening on :{PORT}", flush=True)
|
|
105
|
+
# Block forever — parent will SIGKILL.
|
|
106
|
+
while True:
|
|
107
|
+
time.sleep(60)
|
|
108
|
+
' >/dev/null 2>&1 &
|
|
109
|
+
echo $!
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Pick a free TCP port on 127.0.0.1
|
|
113
|
+
free_port() {
|
|
114
|
+
python3 -c 'import socket; s=socket.socket(); s.bind(("127.0.0.1",0)); print(s.getsockname()[1]); s.close()'
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# ---------------------------------------------------------------------------
|
|
118
|
+
# Test harness — minimal pass/fail printer
|
|
119
|
+
# ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
PASS_COUNT=0
|
|
122
|
+
FAIL_COUNT=0
|
|
123
|
+
|
|
124
|
+
pass() {
|
|
125
|
+
PASS_COUNT=$((PASS_COUNT + 1))
|
|
126
|
+
printf ' \033[32m✓\033[0m %s\n' "$1"
|
|
127
|
+
}
|
|
128
|
+
fail() {
|
|
129
|
+
FAIL_COUNT=$((FAIL_COUNT + 1))
|
|
130
|
+
printf ' \033[31m✗\033[0m %s\n' "$1"
|
|
131
|
+
[ -n "${2:-}" ] && printf ' %s\n' "$2"
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
assert_eq() {
|
|
135
|
+
local label="$1" expected="$2" actual="$3"
|
|
136
|
+
if [ "$expected" = "$actual" ]; then
|
|
137
|
+
pass "$label"
|
|
138
|
+
else
|
|
139
|
+
fail "$label" "expected=$expected actual=$actual"
|
|
140
|
+
fi
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
assert_contains() {
|
|
144
|
+
local label="$1" haystack="$2" needle="$3"
|
|
145
|
+
if printf '%s' "$haystack" | grep -qF "$needle"; then
|
|
146
|
+
pass "$label"
|
|
147
|
+
else
|
|
148
|
+
fail "$label" "needle=$needle haystack=$haystack"
|
|
149
|
+
fi
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# ---------------------------------------------------------------------------
|
|
153
|
+
# Per-scenario fixture: fresh stub + fresh runtime dir
|
|
154
|
+
# ---------------------------------------------------------------------------
|
|
155
|
+
|
|
156
|
+
scenario_init() {
|
|
157
|
+
local name="$1"
|
|
158
|
+
echo
|
|
159
|
+
echo "=== $name ==="
|
|
160
|
+
PORT=$(free_port)
|
|
161
|
+
WORK_DIR=$(mktemp -d -t remote-browser-test.XXXXXX)
|
|
162
|
+
LOG_FILE="${WORK_DIR}/requests.jsonl"
|
|
163
|
+
RESP_FILE="${WORK_DIR}/responses.txt"
|
|
164
|
+
RUNTIME_DIR="${WORK_DIR}/runtime"
|
|
165
|
+
: > "$LOG_FILE"
|
|
166
|
+
: > "$RESP_FILE"
|
|
167
|
+
mkdir -p "$RUNTIME_DIR"
|
|
168
|
+
export CREWLY_API_URL="http://127.0.0.1:${PORT}"
|
|
169
|
+
export CREWLY_RUNTIME_DIR="$RUNTIME_DIR"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
# Push a canned response onto the stub queue.
|
|
173
|
+
queue_response() {
|
|
174
|
+
printf '%s\n' "$1" >> "$RESP_FILE"
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
start_stub() {
|
|
178
|
+
STUB_PID=$(start_stub_server "$PORT" "$LOG_FILE" "$RESP_FILE")
|
|
179
|
+
# Wait for the server to be ready (poll the port).
|
|
180
|
+
local tries=0
|
|
181
|
+
until python3 -c "import socket; s=socket.socket(); s.settimeout(0.2); s.connect(('127.0.0.1', $PORT))" 2>/dev/null; do
|
|
182
|
+
tries=$((tries + 1))
|
|
183
|
+
if [ $tries -gt 50 ]; then
|
|
184
|
+
fail "stub server failed to start within 5s"
|
|
185
|
+
return 1
|
|
186
|
+
fi
|
|
187
|
+
sleep 0.1
|
|
188
|
+
done
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
scenario_teardown() {
|
|
192
|
+
if [ -n "${STUB_PID:-}" ]; then
|
|
193
|
+
kill "$STUB_PID" 2>/dev/null || true
|
|
194
|
+
wait "$STUB_PID" 2>/dev/null || true
|
|
195
|
+
fi
|
|
196
|
+
if [ -n "${WORK_DIR:-}" ] && [ -d "$WORK_DIR" ]; then
|
|
197
|
+
rm -rf "$WORK_DIR"
|
|
198
|
+
fi
|
|
199
|
+
unset CREWLY_API_URL CREWLY_RUNTIME_DIR CREWLY_SESSION_NAME STUB_PID WORK_DIR PORT
|
|
200
|
+
unset LOG_FILE RESP_FILE RUNTIME_DIR
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
# Read a logged request — `nth` is 0-indexed.
|
|
204
|
+
request_field() {
|
|
205
|
+
local nth="$1" field="$2"
|
|
206
|
+
python3 -c "
|
|
207
|
+
import json, sys
|
|
208
|
+
with open('${LOG_FILE}') as f:
|
|
209
|
+
lines = [json.loads(l) for l in f if l.strip()]
|
|
210
|
+
idx = int('${nth}')
|
|
211
|
+
if idx >= len(lines):
|
|
212
|
+
sys.exit(0)
|
|
213
|
+
entry = lines[idx]
|
|
214
|
+
keys = '${field}'.split('.')
|
|
215
|
+
v = entry
|
|
216
|
+
for k in keys:
|
|
217
|
+
if isinstance(v, dict):
|
|
218
|
+
v = v.get(k)
|
|
219
|
+
else:
|
|
220
|
+
v = None
|
|
221
|
+
break
|
|
222
|
+
if v is None:
|
|
223
|
+
print('', end='')
|
|
224
|
+
else:
|
|
225
|
+
print(v if isinstance(v, str) else json.dumps(v), end='')
|
|
226
|
+
"
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
# ---------------------------------------------------------------------------
|
|
230
|
+
# Scenarios
|
|
231
|
+
# ---------------------------------------------------------------------------
|
|
232
|
+
|
|
233
|
+
# Scenario 1: bind-tab caches tabId locally
|
|
234
|
+
scenario_init "scenario 1: bind-tab caches tabId"
|
|
235
|
+
queue_response '{"success":true,"data":{"tabId":42,"windowId":9}}'
|
|
236
|
+
start_stub
|
|
237
|
+
export CREWLY_SESSION_NAME="agent-1"
|
|
238
|
+
out=$("$SKILL" --action bind-tab 2>&1) || true
|
|
239
|
+
assert_contains "bind-tab response carries tabId" "$out" '"tabId":42'
|
|
240
|
+
assert_eq "stub got POST /api/browser/bind" "POST /api/browser/bind" "$(request_field 0 method) $(request_field 0 path)"
|
|
241
|
+
assert_eq "X-Agent-Session forwarded" "agent-1" "$(request_field 0 headers.X-Agent-Session)"
|
|
242
|
+
[ -f "${RUNTIME_DIR}/agent-1/browser-tab-id" ] \
|
|
243
|
+
&& pass "cache file written" \
|
|
244
|
+
|| fail "cache file written" "missing ${RUNTIME_DIR}/agent-1/browser-tab-id"
|
|
245
|
+
assert_eq "cache content = tabId" "42" "$(cat ${RUNTIME_DIR}/agent-1/browser-tab-id 2>/dev/null)"
|
|
246
|
+
scenario_teardown
|
|
247
|
+
|
|
248
|
+
# Scenario 2: subsequent action injects cached tabId into body
|
|
249
|
+
scenario_init "scenario 2: cached tabId injected into body"
|
|
250
|
+
mkdir -p "${RUNTIME_DIR}/agent-2"
|
|
251
|
+
echo "77" > "${RUNTIME_DIR}/agent-2/browser-tab-id"
|
|
252
|
+
queue_response '{"success":true,"data":{"text":"hello"}}'
|
|
253
|
+
start_stub
|
|
254
|
+
export CREWLY_SESSION_NAME="agent-2"
|
|
255
|
+
"$SKILL" --action read-text > /dev/null 2>&1 || true
|
|
256
|
+
body=$(request_field 0 body)
|
|
257
|
+
assert_contains "read-text body contains tabId:77" "$body" '"tabId":77'
|
|
258
|
+
scenario_teardown
|
|
259
|
+
|
|
260
|
+
# Scenario 3: --tab-id flag overrides cache
|
|
261
|
+
scenario_init "scenario 3: --tab-id flag overrides cache"
|
|
262
|
+
mkdir -p "${RUNTIME_DIR}/agent-3"
|
|
263
|
+
echo "55" > "${RUNTIME_DIR}/agent-3/browser-tab-id"
|
|
264
|
+
queue_response '{"success":true,"data":{}}'
|
|
265
|
+
start_stub
|
|
266
|
+
export CREWLY_SESSION_NAME="agent-3"
|
|
267
|
+
"$SKILL" --action read-text --tab-id 999 > /dev/null 2>&1 || true
|
|
268
|
+
body=$(request_field 0 body)
|
|
269
|
+
assert_contains "body uses --tab-id override" "$body" '"tabId":999'
|
|
270
|
+
scenario_teardown
|
|
271
|
+
|
|
272
|
+
# Scenario 4: --no-bind drops X-Agent-Session header
|
|
273
|
+
scenario_init "scenario 4: --no-bind drops session header"
|
|
274
|
+
queue_response '{"success":true,"data":{}}'
|
|
275
|
+
start_stub
|
|
276
|
+
export CREWLY_SESSION_NAME="agent-4"
|
|
277
|
+
"$SKILL" --action read-text --no-bind > /dev/null 2>&1 || true
|
|
278
|
+
hdr=$(request_field 0 headers.X-Agent-Session)
|
|
279
|
+
assert_eq "no X-Agent-Session header on --no-bind" "" "$hdr"
|
|
280
|
+
scenario_teardown
|
|
281
|
+
|
|
282
|
+
# Scenario 5: unbind-tab purges cache
|
|
283
|
+
scenario_init "scenario 5: unbind-tab purges cache"
|
|
284
|
+
mkdir -p "${RUNTIME_DIR}/agent-5"
|
|
285
|
+
echo "33" > "${RUNTIME_DIR}/agent-5/browser-tab-id"
|
|
286
|
+
queue_response '{"success":true,"data":{"released":true,"tabClosed":true}}'
|
|
287
|
+
start_stub
|
|
288
|
+
export CREWLY_SESSION_NAME="agent-5"
|
|
289
|
+
"$SKILL" --action unbind-tab > /dev/null 2>&1 || true
|
|
290
|
+
[ -f "${RUNTIME_DIR}/agent-5/browser-tab-id" ] \
|
|
291
|
+
&& fail "cache should be purged" "still present at ${RUNTIME_DIR}/agent-5/browser-tab-id" \
|
|
292
|
+
|| pass "cache file purged"
|
|
293
|
+
scenario_teardown
|
|
294
|
+
|
|
295
|
+
# Scenario 6: 404 tab_not_found triggers cache purge + auto-retry
|
|
296
|
+
scenario_init "scenario 6: 404 tab_not_found triggers retry"
|
|
297
|
+
mkdir -p "${RUNTIME_DIR}/agent-6"
|
|
298
|
+
echo "100" > "${RUNTIME_DIR}/agent-6/browser-tab-id"
|
|
299
|
+
# First call: 404 with tab_not_found body
|
|
300
|
+
queue_response '404|{"success":false,"error":"tab_not_found","details":"Tab 100 closed"}'
|
|
301
|
+
# Second call (retry without tabId): success
|
|
302
|
+
queue_response '{"success":true,"data":{"text":"recovered"}}'
|
|
303
|
+
start_stub
|
|
304
|
+
export CREWLY_SESSION_NAME="agent-6"
|
|
305
|
+
out=$("$SKILL" --action read-text 2>&1) || true
|
|
306
|
+
# Two requests should have been made.
|
|
307
|
+
total_reqs=$(wc -l < "$LOG_FILE")
|
|
308
|
+
assert_eq "stub received 2 requests" "2" "$(printf '%s' "$total_reqs" | tr -d ' ')"
|
|
309
|
+
# First request had tabId:100, second omits tabId (auto-bind path)
|
|
310
|
+
first_body=$(request_field 0 body)
|
|
311
|
+
second_body=$(request_field 1 body)
|
|
312
|
+
assert_contains "first request had stale tabId:100" "$first_body" '"tabId":100'
|
|
313
|
+
[ -z "$(printf '%s' "$second_body" | grep -o '"tabId"' || true)" ] \
|
|
314
|
+
&& pass "retry request omitted tabId (auto-bind path)" \
|
|
315
|
+
|| fail "retry request omitted tabId" "second_body=$second_body"
|
|
316
|
+
[ -f "${RUNTIME_DIR}/agent-6/browser-tab-id" ] \
|
|
317
|
+
&& fail "cache purged on 404" "still present" \
|
|
318
|
+
|| pass "cache purged on 404"
|
|
319
|
+
scenario_teardown
|
|
320
|
+
|
|
321
|
+
# Scenario 7: bind-tab with --active sends active:true
|
|
322
|
+
scenario_init "scenario 7: bind-tab --active forwards foreground flag"
|
|
323
|
+
queue_response '{"success":true,"data":{"tabId":7}}'
|
|
324
|
+
start_stub
|
|
325
|
+
export CREWLY_SESSION_NAME="agent-7"
|
|
326
|
+
"$SKILL" --action bind-tab --active > /dev/null 2>&1 || true
|
|
327
|
+
body=$(request_field 0 body)
|
|
328
|
+
assert_contains "body contains active:true" "$body" '"active":true'
|
|
329
|
+
scenario_teardown
|
|
330
|
+
|
|
331
|
+
# Scenario 8: no CREWLY_SESSION_NAME — no cache, no tabId, legacy fallback
|
|
332
|
+
scenario_init "scenario 8: missing CREWLY_SESSION_NAME → legacy active-tab path"
|
|
333
|
+
queue_response '{"success":true,"data":{}}'
|
|
334
|
+
start_stub
|
|
335
|
+
unset CREWLY_SESSION_NAME
|
|
336
|
+
"$SKILL" --action read-text > /dev/null 2>&1 || true
|
|
337
|
+
hdr=$(request_field 0 headers.X-Agent-Session)
|
|
338
|
+
body=$(request_field 0 body)
|
|
339
|
+
assert_eq "no X-Agent-Session header" "" "$hdr"
|
|
340
|
+
[ -z "$(printf '%s' "$body" | grep -o '"tabId"' || true)" ] \
|
|
341
|
+
&& pass "body has no tabId field" \
|
|
342
|
+
|| fail "body has no tabId field" "body=$body"
|
|
343
|
+
scenario_teardown
|
|
344
|
+
|
|
345
|
+
# ---------------------------------------------------------------------------
|
|
346
|
+
# Scenarios 9–13: brace-injection bug regression coverage
|
|
347
|
+
#
|
|
348
|
+
# Repro: `BODY="${EXTRA_PARAMS:-{}}"` was mis-parsed by bash — the closing
|
|
349
|
+
# `}` of the parameter expansion was the FIRST `}`, so `${EXTRA_PARAMS:-{}}`
|
|
350
|
+
# was read as `${EXTRA_PARAMS:-{}` (default = literal `{`) followed by a
|
|
351
|
+
# stray literal `}`. With EXTRA_PARAMS set, body became `<value>}` —
|
|
352
|
+
# malformed JSON. With EXTRA_PARAMS empty, the bug coincidentally produced
|
|
353
|
+
# `{}` and masked itself. Fix replaces the pattern with `_body_or_empty`.
|
|
354
|
+
#
|
|
355
|
+
# These scenarios drive --params with a non-empty value through every
|
|
356
|
+
# affected action and assert the wire body is parseable JSON without a
|
|
357
|
+
# trailing stray `}`. Each action is a separate scenario so a regression
|
|
358
|
+
# in one branch does not mask another.
|
|
359
|
+
# ---------------------------------------------------------------------------
|
|
360
|
+
|
|
361
|
+
# Helper for the brace-bug regression scenarios — drives one action with
|
|
362
|
+
# a known payload and asserts the body is exactly that payload (no stray
|
|
363
|
+
# trailing `}`).
|
|
364
|
+
_assert_brace_clean() {
|
|
365
|
+
local action="$1" payload="$2"
|
|
366
|
+
scenario_init "scenario brace-clean: $action --params"
|
|
367
|
+
queue_response '{"success":true,"data":{}}'
|
|
368
|
+
start_stub
|
|
369
|
+
unset CREWLY_SESSION_NAME
|
|
370
|
+
"$SKILL" --action "$action" --params "$payload" > /dev/null 2>&1 || true
|
|
371
|
+
local body
|
|
372
|
+
body=$(request_field 0 body)
|
|
373
|
+
# Body must parse cleanly as JSON (the bug appended a literal `}`).
|
|
374
|
+
if printf '%s' "$body" | jq -e . >/dev/null 2>&1; then
|
|
375
|
+
pass "[$action] body parses as JSON"
|
|
376
|
+
else
|
|
377
|
+
fail "[$action] body parses as JSON" "body=$body"
|
|
378
|
+
fi
|
|
379
|
+
# Body must equal the payload byte-for-byte (no trailing extra char).
|
|
380
|
+
assert_eq "[$action] body == payload" "$payload" "$body"
|
|
381
|
+
scenario_teardown
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
# Scenario 9: scroll
|
|
385
|
+
_assert_brace_clean "scroll" '{"direction":"down","amount":500}'
|
|
386
|
+
# Scenario 10: scroll-in-element
|
|
387
|
+
_assert_brace_clean "scroll-in-element" '{"selector":".sb","amount":200}'
|
|
388
|
+
# Scenario 11: press-key
|
|
389
|
+
_assert_brace_clean "press-key" '{"key":"Enter","modifiers":["Shift"]}'
|
|
390
|
+
# Scenario 12: local-storage
|
|
391
|
+
_assert_brace_clean "local-storage" '{"keys":["uid","theme"]}'
|
|
392
|
+
# Scenario 13: get-interactive-elements
|
|
393
|
+
_assert_brace_clean "get-interactive-elements" '{"textContains":"Submit"}'
|
|
394
|
+
# Scenario 14: set-file-input (was missing from Olivias original list)
|
|
395
|
+
_assert_brace_clean "set-file-input" '{"selector":"input","filePaths":["/tmp/a"]}'
|
|
396
|
+
|
|
397
|
+
# Scenario 15: empty --params still produces a valid `{}` body
|
|
398
|
+
scenario_init "scenario 15: empty --params produces {} (back-compat)"
|
|
399
|
+
queue_response '{"success":true,"data":{}}'
|
|
400
|
+
start_stub
|
|
401
|
+
unset CREWLY_SESSION_NAME
|
|
402
|
+
"$SKILL" --action scroll > /dev/null 2>&1 || true
|
|
403
|
+
body=$(request_field 0 body)
|
|
404
|
+
assert_eq "empty params → body is canonical {}" "{}" "$body"
|
|
405
|
+
scenario_teardown
|
|
406
|
+
|
|
407
|
+
# ---------------------------------------------------------------------------
|
|
408
|
+
# Scenarios 16–18: select-option route + body shapes
|
|
409
|
+
# ---------------------------------------------------------------------------
|
|
410
|
+
|
|
411
|
+
# Scenario 16: select-option with --value projects {selector, value}
|
|
412
|
+
scenario_init "scenario 16: select-option --selector --value"
|
|
413
|
+
queue_response '{"success":true,"data":{"selectedValue":"opt2","selectedText":"Option 2"}}'
|
|
414
|
+
start_stub
|
|
415
|
+
unset CREWLY_SESSION_NAME
|
|
416
|
+
"$SKILL" --action select-option --selector "#level" --value "opt2" > /dev/null 2>&1 || true
|
|
417
|
+
assert_eq "POST /api/browser/select-option" \
|
|
418
|
+
"POST /api/browser/select-option" \
|
|
419
|
+
"$(request_field 0 method) $(request_field 0 path)"
|
|
420
|
+
body=$(request_field 0 body)
|
|
421
|
+
assert_eq "body has selector" "#level" "$(printf '%s' "$body" | jq -r '.selector')"
|
|
422
|
+
assert_eq "body has value" "opt2" "$(printf '%s' "$body" | jq -r '.value')"
|
|
423
|
+
scenario_teardown
|
|
424
|
+
|
|
425
|
+
# Scenario 17: select-option with --params (label-based)
|
|
426
|
+
scenario_init "scenario 17: select-option --params with label"
|
|
427
|
+
queue_response '{"success":true,"data":{}}'
|
|
428
|
+
start_stub
|
|
429
|
+
unset CREWLY_SESSION_NAME
|
|
430
|
+
"$SKILL" --action select-option --selector "#level" \
|
|
431
|
+
--params '{"label":"Beginner"}' > /dev/null 2>&1 || true
|
|
432
|
+
body=$(request_field 0 body)
|
|
433
|
+
assert_eq "body has selector merged from --selector" "#level" \
|
|
434
|
+
"$(printf '%s' "$body" | jq -r '.selector')"
|
|
435
|
+
assert_eq "body has label from --params" "Beginner" \
|
|
436
|
+
"$(printf '%s' "$body" | jq -r '.label')"
|
|
437
|
+
# Must be parseable JSON (regression guard against the brace bug since
|
|
438
|
+
# this path also uses EXTRA_PARAMS in a jq pipeline).
|
|
439
|
+
if printf '%s' "$body" | jq -e . >/dev/null 2>&1; then
|
|
440
|
+
pass "select-option --params body parses as JSON"
|
|
441
|
+
else
|
|
442
|
+
fail "select-option --params body parses as JSON" "body=$body"
|
|
443
|
+
fi
|
|
444
|
+
scenario_teardown
|
|
445
|
+
|
|
446
|
+
# Scenario 18: select-option with --params (index-based)
|
|
447
|
+
scenario_init "scenario 18: select-option --params with index"
|
|
448
|
+
queue_response '{"success":true,"data":{}}'
|
|
449
|
+
start_stub
|
|
450
|
+
unset CREWLY_SESSION_NAME
|
|
451
|
+
"$SKILL" --action select-option --selector "#level" \
|
|
452
|
+
--params '{"index":2}' > /dev/null 2>&1 || true
|
|
453
|
+
body=$(request_field 0 body)
|
|
454
|
+
assert_eq "body has index from --params" "2" \
|
|
455
|
+
"$(printf '%s' "$body" | jq -r '.index')"
|
|
456
|
+
scenario_teardown
|
|
457
|
+
|
|
458
|
+
# Scenario 19: select-option missing --value AND --params errors out
|
|
459
|
+
scenario_init "scenario 19: select-option without value or params errors"
|
|
460
|
+
queue_response '{"success":true,"data":{}}'
|
|
461
|
+
start_stub
|
|
462
|
+
unset CREWLY_SESSION_NAME
|
|
463
|
+
out=$("$SKILL" --action select-option --selector "#level" 2>&1) || true
|
|
464
|
+
assert_contains "error message mentions value/params requirement" "$out" \
|
|
465
|
+
"select-option requires"
|
|
466
|
+
# Stub should NOT have received any request (hard-fail before HTTP).
|
|
467
|
+
total_reqs=$(wc -l < "$LOG_FILE" | tr -d ' ')
|
|
468
|
+
assert_eq "stub received 0 requests" "0" "$total_reqs"
|
|
469
|
+
scenario_teardown
|
|
470
|
+
|
|
471
|
+
# ---------------------------------------------------------------------------
|
|
472
|
+
# Summary
|
|
473
|
+
# ---------------------------------------------------------------------------
|
|
474
|
+
echo
|
|
475
|
+
TOTAL=$((PASS_COUNT + FAIL_COUNT))
|
|
476
|
+
if [ "$FAIL_COUNT" -gt 0 ]; then
|
|
477
|
+
printf '\033[31mFAIL\033[0m %d/%d passed (%d failed)\n' "$PASS_COUNT" "$TOTAL" "$FAIL_COUNT"
|
|
478
|
+
exit 1
|
|
479
|
+
else
|
|
480
|
+
printf '\033[32mOK\033[0m %d/%d passed\n' "$PASS_COUNT" "$TOTAL"
|
|
481
|
+
exit 0
|
|
482
|
+
fi
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Send Message
|
|
3
|
-
description: "
|
|
4
|
-
version: 1.
|
|
3
|
+
description: "Readiness-aware message delivery to an agent's terminal session via /terminal/{session}/deliver. Distinct from agent/core/send-message which uses /terminal/{session}/write."
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
category: communication
|
|
6
6
|
skillType: claude-skill
|
|
7
7
|
assignableRoles:
|
|
@@ -10,10 +10,12 @@ triggers:
|
|
|
10
10
|
- send message
|
|
11
11
|
- tell agent
|
|
12
12
|
- message agent
|
|
13
|
+
- deliver message
|
|
13
14
|
tags:
|
|
14
15
|
- communication
|
|
15
16
|
- agent
|
|
16
17
|
- message
|
|
18
|
+
- readiness-aware
|
|
17
19
|
execution:
|
|
18
20
|
type: script
|
|
19
21
|
script:
|
|
@@ -22,14 +24,34 @@ execution:
|
|
|
22
24
|
timeoutMs: 30000
|
|
23
25
|
---
|
|
24
26
|
|
|
25
|
-
# Send Message
|
|
27
|
+
# Send Message (orchestrator — readiness-aware delivery)
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
Delivers a text message to an agent's terminal session via the
|
|
30
|
+
**`POST /terminal/{session}/deliver`** endpoint.
|
|
31
|
+
|
|
32
|
+
## When to use this vs `agent/core/send-message`
|
|
33
|
+
|
|
34
|
+
| | `orchestrator/send-message` | `agent/core/send-message` |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| Endpoint | `POST /terminal/{id}/deliver` | `POST /terminal/{id}/write` |
|
|
37
|
+
| Readiness gate | Yes — waits up to `waitTimeout` ms (default 120 s) for the agent prompt | No — direct PTY write, fires immediately |
|
|
38
|
+
| Force override | Yes — `force: true` skips the readiness wait | n/a |
|
|
39
|
+
| Typical caller | Orchestrator dispatching new work to an agent that may currently be busy | Any agent that just wants to drop a line into another session's PTY |
|
|
40
|
+
|
|
41
|
+
Prefer this skill when the orchestrator needs the message to land **at**
|
|
42
|
+
the agent's prompt rather than mid-token. Use `agent/core/send-message`
|
|
43
|
+
for fire-and-forget cross-agent comms.
|
|
28
44
|
|
|
29
45
|
## Usage
|
|
30
46
|
|
|
31
47
|
```bash
|
|
32
|
-
|
|
48
|
+
# Default: wait up to 120 s for the agent to be ready, then deliver
|
|
49
|
+
bash config/skills/orchestrator/send-message/execute.sh \
|
|
50
|
+
'{"sessionName":"agent-joe","message":"Please review the PR"}'
|
|
51
|
+
|
|
52
|
+
# Force: write immediately even if the agent is busy mid-token
|
|
53
|
+
bash config/skills/orchestrator/send-message/execute.sh \
|
|
54
|
+
'{"sessionName":"agent-joe","message":"URGENT: stop","force":true}'
|
|
33
55
|
```
|
|
34
56
|
|
|
35
57
|
## Parameters
|
|
@@ -37,8 +59,9 @@ bash config/skills/orchestrator/send-message/execute.sh '{"sessionName":"agent-j
|
|
|
37
59
|
| Parameter | Required | Description |
|
|
38
60
|
|-----------|----------|-------------|
|
|
39
61
|
| `sessionName` | Yes | The target agent's PTY session name |
|
|
40
|
-
| `message` | Yes | The message text to
|
|
62
|
+
| `message` | Yes | The message text to deliver |
|
|
63
|
+
| `force` | No | When `true`, write directly to PTY without waiting for the agent prompt. Defaults to `false` (wait for ready). |
|
|
41
64
|
|
|
42
65
|
## Output
|
|
43
66
|
|
|
44
|
-
JSON confirmation of delivery.
|
|
67
|
+
JSON confirmation of delivery from the deliver endpoint.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Team Health Scan
|
|
3
|
+
description: On-demand snapshot of the Team-Health-Watchdog (THW) verdicts. Returns per-team health (🟢/🟡/🔴/🚨/🟪) plus the gates that fired, so an operator can investigate before the next 60s sweep.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
category: monitoring
|
|
6
|
+
skillType: claude-skill
|
|
7
|
+
assignableRoles:
|
|
8
|
+
- orchestrator
|
|
9
|
+
triggers:
|
|
10
|
+
- team health
|
|
11
|
+
- health scan
|
|
12
|
+
- is anything stuck
|
|
13
|
+
- team-health-scan
|
|
14
|
+
tags:
|
|
15
|
+
- team-health
|
|
16
|
+
- watchdog
|
|
17
|
+
- monitoring
|
|
18
|
+
- liveness
|
|
19
|
+
execution:
|
|
20
|
+
type: script
|
|
21
|
+
script:
|
|
22
|
+
file: execute.sh
|
|
23
|
+
interpreter: bash
|
|
24
|
+
timeoutMs: 30000
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# Team Health Scan
|
|
28
|
+
|
|
29
|
+
Returns the current per-team health verdicts from the Team-Health-Watchdog (THW), the system-level liveness aggregator (Layer 4 of the four-layer liveness stack).
|
|
30
|
+
|
|
31
|
+
## When to use
|
|
32
|
+
|
|
33
|
+
- Before EOD: "is anything stuck I should know about?"
|
|
34
|
+
- After a Slack alert: "you flagged Marketing 🔴; show me the gates."
|
|
35
|
+
- During shadow-mode review: inspect candidate detections without waiting for the next sweep.
|
|
36
|
+
|
|
37
|
+
## Verdict tiers
|
|
38
|
+
|
|
39
|
+
| Code | Display | Meaning |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `healthy` | 🟢 | No concerning signals |
|
|
42
|
+
| `stalling` | 🟡 | Soft concern; observation-only |
|
|
43
|
+
| `stuck` | 🔴 | Sharp concern; action expected |
|
|
44
|
+
| `cascade` | 🚨 | Multi-team correlated failure |
|
|
45
|
+
| `stale` | 🟪 | Stale-trigger refire — assignee should confirm/cancel |
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# All teams:
|
|
51
|
+
bash execute.sh '{}'
|
|
52
|
+
|
|
53
|
+
# One team:
|
|
54
|
+
bash execute.sh '{"teamId":"marketing"}'
|
|
55
|
+
|
|
56
|
+
# Force a fresh sweep (bypass the 60s cache):
|
|
57
|
+
bash execute.sh '{"force":true}'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Response shape
|
|
61
|
+
|
|
62
|
+
```jsonc
|
|
63
|
+
{
|
|
64
|
+
"success": true,
|
|
65
|
+
"data": {
|
|
66
|
+
"verdicts": [
|
|
67
|
+
{
|
|
68
|
+
"teamId": "marketing",
|
|
69
|
+
"verdict": "stuck",
|
|
70
|
+
"gates": {
|
|
71
|
+
"team_idle": true,
|
|
72
|
+
"team_pending": true,
|
|
73
|
+
"team_silent": true,
|
|
74
|
+
"cascade_with_siblings": false
|
|
75
|
+
},
|
|
76
|
+
"pendingWorkItemIds": ["wi-1", "wi-2"],
|
|
77
|
+
"idleAgentSessions": ["ella", "grace"],
|
|
78
|
+
"lostDispatchWorkItemIds": [],
|
|
79
|
+
"rationale": "Team has 2 pending WorkItem(s); 2 member(s) idle and no trigger has fired recently.",
|
|
80
|
+
"detectedAt": "2026-04-25T19:30:00.000Z"
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"lastSweep": {
|
|
84
|
+
"sweptAt": "2026-04-25T19:30:00.000Z",
|
|
85
|
+
"durationMs": 7,
|
|
86
|
+
"shadowMode": true
|
|
87
|
+
},
|
|
88
|
+
"lastSweepAgeMs": 1234,
|
|
89
|
+
"degraded": false
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`degraded: true` indicates the watchdog itself has stopped sweeping (last sweep > 3× sweep interval). Investigate the backend `/api/health` endpoint.
|
|
95
|
+
|
|
96
|
+
## Layer-4 invariant
|
|
97
|
+
|
|
98
|
+
This skill is **read-only**. THW does NOT change agent status, claims, or work items — it only emits alerts. To act on a verdict, use the relevant skill (`start-agent` to restart a member, `assign-task` to reassign, etc.).
|