crewly 1.20.192 → 1.20.193
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 +11 -0
- package/config/hooks/subagent-guard/subagent.sh +113 -0
- package/config/roles/architect/prompt.md +1 -1
- package/config/roles/auditor/prompt.md +1 -1
- package/config/roles/backend-developer/prompt.md +1 -1
- package/config/roles/content-strategist/prompt.md +2 -2
- package/config/roles/designer/prompt.md +1 -1
- package/config/roles/developer/prompt.md +2 -2
- package/config/roles/frontend-developer/prompt.md +1 -1
- package/config/roles/fullstack-dev/prompt.md +1 -1
- package/config/roles/generalist/prompt.md +1 -1
- package/config/roles/ops/prompt.md +1 -1
- package/config/roles/orchestrator/prompt.md +2 -2
- package/config/roles/product-manager/prompt.md +1 -1
- package/config/roles/qa/prompt.md +1 -1
- package/config/roles/qa-engineer/prompt.md +1 -1
- package/config/roles/researcher/prompt.md +1 -1
- package/config/roles/sales/prompt.md +1 -1
- package/config/roles/support/prompt.md +1 -1
- package/config/roles/team-leader/prompt.md +1 -1
- package/config/roles/tpm/prompt.md +1 -1
- package/config/roles/ux-designer/prompt.md +1 -1
- package/config/skills/_common/complete-body-shape.test.sh +17 -0
- package/config/skills/agent/core/complete-task/SKILL.md +27 -4
- package/config/skills/agent/core/complete-task/execute.sh +23 -3
- package/config/skills/agent/core/complete-task/execute.test.sh +34 -0
- package/config/skills/agent/core/handoff-task/execute.sh +1 -1
- package/config/skills/agent/core/report-status/SKILL.md +27 -4
- package/config/skills/agent/core/report-status/execute.sh +104 -4
- package/config/skills/agent/core/todo-add/SKILL.md +16 -2
- package/config/skills/agent/core/todo-add/execute.sh +21 -5
- package/config/skills/agent/core/todo-add/execute.test.sh +14 -0
- package/config/skills/agent/core/todo-tasks/SKILL.md +4 -3
- package/config/skills/agent/core/todo-update/SKILL.md +13 -2
- package/config/skills/agent/core/todo-update/execute.sh +41 -3
- package/config/skills/agent/core/todo-update/execute.test.sh +7 -0
- package/config/skills/marketplace-registry.ts +4 -4
- package/config/skills/orchestrator/complete-task/SKILL.md +13 -6
- package/config/skills/orchestrator/complete-task/execute.sh +22 -3
- package/config/skills/orchestrator/delegate-task/execute.sh +2 -2
- package/config/skills/orchestrator/harness-login/SKILL.md +9 -1
- package/config/skills/orchestrator/harness-login/execute.sh +12 -4
- package/config/skills/orchestrator/harness-login/execute.test.sh +7 -0
- package/config/skills/team-leader/delegate-task/execute.sh +1 -1
- package/config/skills/team-leader/verify-output/SKILL.md +18 -1
- package/config/skills/team-leader/verify-output/execute.sh +28 -0
- package/config/skills/team-leader/verify-output/execute.test.sh +27 -0
- package/dist/backend/backend/src/constants.d.ts +135 -2
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +136 -1
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts +6 -0
- package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.controller.js +13 -2
- package/dist/backend/backend/src/controllers/canva/canva.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.js +3 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +4 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/connector/connector.controller.d.ts +4 -0
- package/dist/backend/backend/src/controllers/connector/connector.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/connector/connector.controller.js +32 -3
- package/dist/backend/backend/src/controllers/connector/connector.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.d.ts +41 -0
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.js +75 -0
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.js.map +1 -0
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts +6 -0
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.js +19 -0
- package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.routes.js +3 -1
- package/dist/backend/backend/src/controllers/google/google.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.js +22 -3
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.controller.d.ts +19 -2
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.controller.js +37 -4
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.js +3 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts +9 -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 +26 -0
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/people/people.routes.d.ts +25 -0
- package/dist/backend/backend/src/controllers/people/people.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/people/people.routes.js +90 -0
- package/dist/backend/backend/src/controllers/people/people.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/request-types.d.ts +2 -0
- package/dist/backend/backend/src/controllers/request-types.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.d.ts +22 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.js +143 -3
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +25 -3
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +125 -19
- package/dist/backend/backend/src/controllers/task-pool/task-pool.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 +14 -0
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +44 -1
- 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 +3 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +13 -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 +28 -3
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts +3 -2
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.js +14 -3
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts +28 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js +48 -4
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +2 -1
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.js +17 -4
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts +14 -0
- 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 +38 -0
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts +34 -0
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.js +49 -5
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js +8 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js.map +1 -1
- package/dist/backend/backend/src/services/canva/canva-token.service.d.ts +17 -4
- package/dist/backend/backend/src/services/canva/canva-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/canva/canva-token.service.js +49 -17
- package/dist/backend/backend/src/services/canva/canva-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +24 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +52 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.d.ts +17 -2
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.js +30 -6
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.d.ts +38 -2
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.js +63 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts +74 -4
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +204 -56
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +19 -0
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +3 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts +25 -2
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js +48 -7
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/claude-accounts.d.ts +207 -0
- package/dist/backend/backend/src/services/harness/claude-accounts.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/claude-accounts.js +306 -0
- package/dist/backend/backend/src/services/harness/claude-accounts.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.d.ts +35 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/harness-credentials.store.js +48 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.js.map +1 -1
- package/dist/backend/backend/src/services/harness/harness-relogin.service.d.ts +70 -1
- package/dist/backend/backend/src/services/harness/harness-relogin.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/harness-relogin.service.js +156 -19
- package/dist/backend/backend/src/services/harness/harness-relogin.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/harness.types.d.ts +2 -0
- package/dist/backend/backend/src/services/harness/harness.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/harness.types.js.map +1 -1
- package/dist/backend/backend/src/services/harness/login-broker.service.d.ts +19 -4
- package/dist/backend/backend/src/services/harness/login-broker.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/login-broker.service.js +46 -7
- package/dist/backend/backend/src/services/harness/login-broker.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/owner-login-request.d.ts +18 -2
- package/dist/backend/backend/src/services/harness/owner-login-request.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/owner-login-request.js +31 -7
- package/dist/backend/backend/src/services/harness/owner-login-request.js.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts +21 -0
- 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 +39 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts +11 -0
- 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 +29 -0
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +5 -0
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js +13 -0
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-todo.service.d.ts +87 -5
- package/dist/backend/backend/src/services/microsoft/microsoft-todo.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-todo.service.js +151 -12
- package/dist/backend/backend/src/services/microsoft/microsoft-todo.service.js.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.d.ts +17 -4
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.js +45 -17
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-session-tokens.service.d.ts +53 -7
- package/dist/backend/backend/src/services/monitoring/claude-session-tokens.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-session-tokens.service.js +77 -14
- package/dist/backend/backend/src/services/monitoring/claude-session-tokens.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.d.ts +53 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.js +130 -29
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/people/acting-for.service.d.ts +151 -0
- package/dist/backend/backend/src/services/people/acting-for.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/people/acting-for.service.js +224 -0
- package/dist/backend/backend/src/services/people/acting-for.service.js.map +1 -0
- package/dist/backend/backend/src/services/people/dedicated-agent.d.ts +89 -0
- package/dist/backend/backend/src/services/people/dedicated-agent.d.ts.map +1 -0
- package/dist/backend/backend/src/services/people/dedicated-agent.js +113 -0
- package/dist/backend/backend/src/services/people/dedicated-agent.js.map +1 -0
- package/dist/backend/backend/src/services/people/grant-sharing.d.ts +79 -0
- package/dist/backend/backend/src/services/people/grant-sharing.d.ts.map +1 -0
- package/dist/backend/backend/src/services/people/grant-sharing.js +135 -0
- package/dist/backend/backend/src/services/people/grant-sharing.js.map +1 -0
- package/dist/backend/backend/src/services/people/people-directory.service.d.ts +181 -0
- package/dist/backend/backend/src/services/people/people-directory.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/people/people-directory.service.js +317 -0
- package/dist/backend/backend/src/services/people/people-directory.service.js.map +1 -0
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/effective-runtime.d.ts +29 -1
- package/dist/backend/backend/src/services/runtime-fallback/effective-runtime.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/effective-runtime.js +40 -0
- package/dist/backend/backend/src/services/runtime-fallback/effective-runtime.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.d.ts +8 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.js +16 -2
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts +60 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js +140 -8
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.store.js +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.store.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts +20 -7
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.js +24 -7
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.js +12 -2
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-usage-probe.d.ts +7 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-usage-probe.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-usage-probe.js +18 -3
- package/dist/backend/backend/src/services/runtime-fallback/runtime-usage-probe.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +3 -0
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +10 -0
- 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 +51 -0
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +9 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +46 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.d.ts +105 -0
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.js +238 -0
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.js.map +1 -0
- 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 +4 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/usage/usage-stats.service.d.ts +39 -12
- package/dist/backend/backend/src/services/usage/usage-stats.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/usage/usage-stats.service.js +61 -20
- package/dist/backend/backend/src/services/usage/usage-stats.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts +2 -0
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js +9 -0
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +10 -0
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +45 -2
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +12 -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/messaging.types.d.ts +5 -0
- package/dist/backend/backend/src/types/messaging.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/messaging.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/completion-evidence.types.d.ts +77 -0
- package/dist/backend/backend/src/types/v2/completion-evidence.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/v2/completion-evidence.types.js +119 -0
- package/dist/backend/backend/src/types/v2/completion-evidence.types.js.map +1 -0
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts +13 -0
- 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.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/backend/config/constants.d.ts +11 -0
- package/dist/backend/config/constants.d.ts.map +1 -1
- package/dist/backend/config/constants.js +11 -0
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +135 -2
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +136 -1
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +13 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +28 -3
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts +3 -2
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.js +14 -3
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts +28 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js +48 -4
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +2 -1
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.js +17 -4
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts +14 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js +38 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts +34 -0
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.js +49 -5
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.d.ts.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js +8 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +24 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +52 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts +74 -4
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js +204 -56
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts +19 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/cli/backend/src/services/harness/claude-accounts.d.ts +207 -0
- package/dist/cli/backend/src/services/harness/claude-accounts.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/claude-accounts.js +306 -0
- package/dist/cli/backend/src/services/harness/claude-accounts.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.d.ts +35 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/harness-credentials.store.js +48 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.js.map +1 -1
- package/dist/cli/backend/src/services/harness/harness-relogin.service.d.ts +70 -1
- package/dist/cli/backend/src/services/harness/harness-relogin.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/harness-relogin.service.js +156 -19
- package/dist/cli/backend/src/services/harness/harness-relogin.service.js.map +1 -1
- package/dist/cli/backend/src/services/harness/harness.types.d.ts +2 -0
- package/dist/cli/backend/src/services/harness/harness.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/harness.types.js.map +1 -1
- package/dist/cli/backend/src/services/harness/login-broker.service.d.ts +19 -4
- package/dist/cli/backend/src/services/harness/login-broker.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/login-broker.service.js +46 -7
- package/dist/cli/backend/src/services/harness/login-broker.service.js.map +1 -1
- package/dist/cli/backend/src/services/harness/owner-login-request.d.ts +18 -2
- package/dist/cli/backend/src/services/harness/owner-login-request.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/owner-login-request.js +31 -7
- package/dist/cli/backend/src/services/harness/owner-login-request.js.map +1 -1
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.d.ts +21 -0
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.js +39 -1
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts +11 -0
- package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js +29 -0
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +5 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +13 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/claude-session-tokens.service.d.ts +197 -0
- package/dist/cli/backend/src/services/monitoring/claude-session-tokens.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/monitoring/claude-session-tokens.service.js +455 -0
- package/dist/cli/backend/src/services/monitoring/claude-session-tokens.service.js.map +1 -0
- package/dist/cli/backend/src/services/people/acting-for.service.d.ts +151 -0
- package/dist/cli/backend/src/services/people/acting-for.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/people/acting-for.service.js +224 -0
- package/dist/cli/backend/src/services/people/acting-for.service.js.map +1 -0
- package/dist/cli/backend/src/services/people/dedicated-agent.d.ts +89 -0
- package/dist/cli/backend/src/services/people/dedicated-agent.d.ts.map +1 -0
- package/dist/cli/backend/src/services/people/dedicated-agent.js +113 -0
- package/dist/cli/backend/src/services/people/dedicated-agent.js.map +1 -0
- package/dist/cli/backend/src/services/people/people-directory.service.d.ts +181 -0
- package/dist/cli/backend/src/services/people/people-directory.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/people/people-directory.service.js +317 -0
- package/dist/cli/backend/src/services/people/people-directory.service.js.map +1 -0
- package/dist/cli/backend/src/services/runtime-fallback/effective-runtime.d.ts +29 -1
- package/dist/cli/backend/src/services/runtime-fallback/effective-runtime.d.ts.map +1 -1
- package/dist/cli/backend/src/services/runtime-fallback/effective-runtime.js +40 -0
- package/dist/cli/backend/src/services/runtime-fallback/effective-runtime.js.map +1 -1
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts +20 -7
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.js +24 -7
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +3 -0
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +10 -0
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +51 -0
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +9 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +46 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js +4 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +12 -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/messaging.types.d.ts +5 -0
- package/dist/cli/backend/src/types/messaging.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/messaging.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts +13 -0
- 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.map +1 -1
- package/dist/cli/cli/src/utils/marketplace.d.ts +21 -0
- package/dist/cli/cli/src/utils/marketplace.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/marketplace.js +35 -1
- package/dist/cli/cli/src/utils/marketplace.js.map +1 -1
- package/dist/cli/config/constants.d.ts +11 -0
- package/dist/cli/config/constants.d.ts.map +1 -1
- package/dist/cli/config/constants.js +11 -0
- package/dist/cli/config/constants.js.map +1 -1
- package/dist/cli/config/skills/marketplace-registry.d.ts +4 -4
- package/dist/cli/config/skills/marketplace-registry.js +4 -4
- package/frontend/dist/assets/{index-5b7af029.js → index-465d1f8f.js} +293 -293
- package/frontend/dist/assets/{index-fc715ec3.css → index-5e967795.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/packages/crewly-agent/src/runtime/tool-registry.test.ts +45 -0
- package/packages/crewly-agent/src/runtime/tool-registry.ts +40 -5
- package/packages/crewly-agent/src/test/isolated-home.test.ts +24 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Acting-for — the person each agent session is working for right now
|
|
3
|
+
* (issue #968).
|
|
4
|
+
*
|
|
5
|
+
* Every human message delivered to an agent records its sender as the person
|
|
6
|
+
* that agent acts for until the next human message: a Slack message records
|
|
7
|
+
* the sender's Slack user id, a dashboard message records the owner. A
|
|
8
|
+
* message one agent sends another passes the sender's person on, so work
|
|
9
|
+
* delegated for Info stays Info's. Scheduled and system turns change nothing.
|
|
10
|
+
*
|
|
11
|
+
* The record is set only by the backend from what it delivered — never from
|
|
12
|
+
* anything an agent sends — and connector credential requests carry it to
|
|
13
|
+
* Cloud, which decides whether that person may use the grant.
|
|
14
|
+
*
|
|
15
|
+
* Kept in `<CREWLY_HOME>/acting-for.json` so a restart does not turn a
|
|
16
|
+
* member's in-flight turn into the owner's.
|
|
17
|
+
*
|
|
18
|
+
* specs/per-person-access.md
|
|
19
|
+
*
|
|
20
|
+
* @module services/people/acting-for.service
|
|
21
|
+
*/
|
|
22
|
+
import { type PeopleDirectoryService, type PersonRole } from './people-directory.service.js';
|
|
23
|
+
/** Where an acting-for record came from. */
|
|
24
|
+
export type ActingForSource = 'slack' | 'dashboard' | 'agent';
|
|
25
|
+
/** One session's record. */
|
|
26
|
+
export interface ActingForEntry {
|
|
27
|
+
/** Person id (Slack user id, or `owner`) */
|
|
28
|
+
personId: string;
|
|
29
|
+
source: ActingForSource;
|
|
30
|
+
/** ISO time it was recorded */
|
|
31
|
+
at: string;
|
|
32
|
+
}
|
|
33
|
+
/** The person a request acts for, as Cloud is told. */
|
|
34
|
+
export interface Actor {
|
|
35
|
+
id: string;
|
|
36
|
+
role: PersonRole;
|
|
37
|
+
/** Display name, for messages */
|
|
38
|
+
name: string;
|
|
39
|
+
}
|
|
40
|
+
/** Injectable dependencies. */
|
|
41
|
+
export interface ActingForDeps {
|
|
42
|
+
filePath?: string;
|
|
43
|
+
people?: () => PeopleDirectoryService;
|
|
44
|
+
now?: () => number;
|
|
45
|
+
}
|
|
46
|
+
/** The acting-for record. */
|
|
47
|
+
export declare class ActingForService {
|
|
48
|
+
private readonly filePathOverride?;
|
|
49
|
+
private readonly people;
|
|
50
|
+
private readonly now;
|
|
51
|
+
private cache;
|
|
52
|
+
/**
|
|
53
|
+
* @param deps - Store path, people directory, clock
|
|
54
|
+
*/
|
|
55
|
+
constructor(deps?: ActingForDeps);
|
|
56
|
+
/**
|
|
57
|
+
* Record that a session now acts for a person.
|
|
58
|
+
*
|
|
59
|
+
* @param session - Agent session name
|
|
60
|
+
* @param personId - Slack user id, or `owner`
|
|
61
|
+
* @param source - What delivered the message
|
|
62
|
+
*/
|
|
63
|
+
record(session: string, personId: string, source: ActingForSource): void;
|
|
64
|
+
/**
|
|
65
|
+
* Record a human message delivered to a session: a Slack sender, or the
|
|
66
|
+
* owner when it carries no Slack sender (dashboard / terminal).
|
|
67
|
+
*
|
|
68
|
+
* @param session - Agent session name
|
|
69
|
+
* @param slackUserId - Sender's Slack user id, when the message came from Slack
|
|
70
|
+
*/
|
|
71
|
+
recordHumanMessage(session: string, slackUserId: string | null | undefined): void;
|
|
72
|
+
/**
|
|
73
|
+
* A message from one agent to another: the target acts for whoever the
|
|
74
|
+
* sender acts for (the owner when the sender has no record).
|
|
75
|
+
*
|
|
76
|
+
* @param target - Receiving session
|
|
77
|
+
* @param fromSession - Sending session
|
|
78
|
+
*/
|
|
79
|
+
inherit(target: string, fromSession: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* A session's record.
|
|
82
|
+
*
|
|
83
|
+
* @param session - Agent session name
|
|
84
|
+
* @returns Entry, or null when the session never got a human message
|
|
85
|
+
*/
|
|
86
|
+
get(session: string): ActingForEntry | null;
|
|
87
|
+
/**
|
|
88
|
+
* The person a request acts for: the owner for a request with no agent
|
|
89
|
+
* session (the owner's dashboard), else the session's record (the owner
|
|
90
|
+
* when it has none).
|
|
91
|
+
*
|
|
92
|
+
* @param session - Calling agent session, if any
|
|
93
|
+
* @returns Actor
|
|
94
|
+
*/
|
|
95
|
+
actorFor(session?: string | null): Actor;
|
|
96
|
+
/** Forget everything (tests). */
|
|
97
|
+
clear(): void;
|
|
98
|
+
/** @returns Store path */
|
|
99
|
+
private filePath;
|
|
100
|
+
/** @returns All records (read once, then cached) */
|
|
101
|
+
private load;
|
|
102
|
+
/**
|
|
103
|
+
* Save atomically (best effort: the in-memory record still applies).
|
|
104
|
+
*
|
|
105
|
+
* @param all - Records
|
|
106
|
+
*/
|
|
107
|
+
private save;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The backend's acting-for record.
|
|
111
|
+
*
|
|
112
|
+
* @returns Singleton
|
|
113
|
+
*/
|
|
114
|
+
export declare function getActingFor(): ActingForService;
|
|
115
|
+
/**
|
|
116
|
+
* Replace the singleton (tests).
|
|
117
|
+
*
|
|
118
|
+
* @param service - Instance, or null to reset
|
|
119
|
+
*/
|
|
120
|
+
export declare function setActingForForTesting(service: ActingForService | null): void;
|
|
121
|
+
/**
|
|
122
|
+
* Run work as a person: connector token requests made inside carry that
|
|
123
|
+
* person to Cloud.
|
|
124
|
+
*
|
|
125
|
+
* @param actor - Person
|
|
126
|
+
* @param fn - Work
|
|
127
|
+
* @returns What `fn` returns
|
|
128
|
+
*/
|
|
129
|
+
export declare function runAsActor<T>(actor: Actor, fn: () => T): T;
|
|
130
|
+
/**
|
|
131
|
+
* The person the current request acts for.
|
|
132
|
+
*
|
|
133
|
+
* @returns Actor, or null outside a connector request (backend-internal calls)
|
|
134
|
+
*/
|
|
135
|
+
export declare function currentActor(): Actor | null;
|
|
136
|
+
/**
|
|
137
|
+
* Headers that tell Cloud who a credential request is for.
|
|
138
|
+
*
|
|
139
|
+
* @param actor - Person (default: the current request's)
|
|
140
|
+
* @returns Headers (empty outside a connector request)
|
|
141
|
+
*/
|
|
142
|
+
export declare function actingForHeaders(actor?: Actor | null): Record<string, string>;
|
|
143
|
+
/**
|
|
144
|
+
* Cache-key suffix for a token fetched for the current person, so one
|
|
145
|
+
* person's cached token is never handed to another.
|
|
146
|
+
*
|
|
147
|
+
* @param actor - Person (default: the current request's)
|
|
148
|
+
* @returns `''` outside a connector request, else `\0<person id>`
|
|
149
|
+
*/
|
|
150
|
+
export declare function actorCacheSuffix(actor?: Actor | null): string;
|
|
151
|
+
//# sourceMappingURL=acting-for.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acting-for.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/people/acting-for.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,OAAO,EAAsB,KAAK,sBAAsB,EAAE,KAAK,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEjH,4CAA4C;AAC5C,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC;AAE9D,4BAA4B;AAC5B,MAAM,WAAW,cAAc;IAC9B,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,eAAe,CAAC;IACxB,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;CACX;AAED,uDAAuD;AACvD,MAAM,WAAW,KAAK;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;CACb;AAED,+BAA+B;AAC/B,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,sBAAsB,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAED,6BAA6B;AAC7B,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,KAAK,CAA+C;IAE5D;;OAEG;gBACS,IAAI,GAAE,aAAkB;IAMpC;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI;IASxE;;;;;;OAMG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAajF;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAMlD;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAK3C;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK;IAOxC,iCAAiC;IACjC,KAAK,IAAI,IAAI;IAIb,0BAA0B;IAC1B,OAAO,CAAC,QAAQ;IAIhB,oDAAoD;IACpD,OAAO,CAAC,IAAI;IAoBZ;;;;OAIG;IACH,OAAO,CAAC,IAAI;CAYZ;AAID;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,gBAAgB,CAG/C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAE7E;AAID;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,KAAK,GAAG,IAAI,CAE3C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,KAAK,GAAG,IAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAG7F;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,KAAK,GAAG,IAAqB,GAAG,MAAM,CAE7E"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Acting-for — the person each agent session is working for right now
|
|
3
|
+
* (issue #968).
|
|
4
|
+
*
|
|
5
|
+
* Every human message delivered to an agent records its sender as the person
|
|
6
|
+
* that agent acts for until the next human message: a Slack message records
|
|
7
|
+
* the sender's Slack user id, a dashboard message records the owner. A
|
|
8
|
+
* message one agent sends another passes the sender's person on, so work
|
|
9
|
+
* delegated for Info stays Info's. Scheduled and system turns change nothing.
|
|
10
|
+
*
|
|
11
|
+
* The record is set only by the backend from what it delivered — never from
|
|
12
|
+
* anything an agent sends — and connector credential requests carry it to
|
|
13
|
+
* Cloud, which decides whether that person may use the grant.
|
|
14
|
+
*
|
|
15
|
+
* Kept in `<CREWLY_HOME>/acting-for.json` so a restart does not turn a
|
|
16
|
+
* member's in-flight turn into the owner's.
|
|
17
|
+
*
|
|
18
|
+
* specs/per-person-access.md
|
|
19
|
+
*
|
|
20
|
+
* @module services/people/acting-for.service
|
|
21
|
+
*/
|
|
22
|
+
import * as fs from 'fs';
|
|
23
|
+
import * as path from 'path';
|
|
24
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
25
|
+
import { PEOPLE_CONSTANTS } from '../../constants.js';
|
|
26
|
+
import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
|
|
27
|
+
import { getPeopleDirectory } from './people-directory.service.js';
|
|
28
|
+
/** The acting-for record. */
|
|
29
|
+
export class ActingForService {
|
|
30
|
+
filePathOverride;
|
|
31
|
+
people;
|
|
32
|
+
now;
|
|
33
|
+
cache = null;
|
|
34
|
+
/**
|
|
35
|
+
* @param deps - Store path, people directory, clock
|
|
36
|
+
*/
|
|
37
|
+
constructor(deps = {}) {
|
|
38
|
+
this.filePathOverride = deps.filePath;
|
|
39
|
+
this.people = deps.people ?? getPeopleDirectory;
|
|
40
|
+
this.now = deps.now ?? (() => Date.now());
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Record that a session now acts for a person.
|
|
44
|
+
*
|
|
45
|
+
* @param session - Agent session name
|
|
46
|
+
* @param personId - Slack user id, or `owner`
|
|
47
|
+
* @param source - What delivered the message
|
|
48
|
+
*/
|
|
49
|
+
record(session, personId, source) {
|
|
50
|
+
if (!session || !personId)
|
|
51
|
+
return;
|
|
52
|
+
const all = this.load();
|
|
53
|
+
const current = all[session];
|
|
54
|
+
if (current && current.personId === personId && current.source === source)
|
|
55
|
+
return;
|
|
56
|
+
all[session] = { personId, source, at: new Date(this.now()).toISOString() };
|
|
57
|
+
this.save(all);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Record a human message delivered to a session: a Slack sender, or the
|
|
61
|
+
* owner when it carries no Slack sender (dashboard / terminal).
|
|
62
|
+
*
|
|
63
|
+
* @param session - Agent session name
|
|
64
|
+
* @param slackUserId - Sender's Slack user id, when the message came from Slack
|
|
65
|
+
*/
|
|
66
|
+
recordHumanMessage(session, slackUserId) {
|
|
67
|
+
if (slackUserId && PEOPLE_CONSTANTS.SLACK_USER_ID_PATTERN.test(slackUserId)) {
|
|
68
|
+
this.record(session, slackUserId, 'slack');
|
|
69
|
+
try {
|
|
70
|
+
this.people().noteSeen(slackUserId);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// the directory is best effort here
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.record(session, PEOPLE_CONSTANTS.OWNER_ID, 'dashboard');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A message from one agent to another: the target acts for whoever the
|
|
81
|
+
* sender acts for (the owner when the sender has no record).
|
|
82
|
+
*
|
|
83
|
+
* @param target - Receiving session
|
|
84
|
+
* @param fromSession - Sending session
|
|
85
|
+
*/
|
|
86
|
+
inherit(target, fromSession) {
|
|
87
|
+
if (!target || !fromSession || target === fromSession)
|
|
88
|
+
return;
|
|
89
|
+
const from = this.load()[fromSession];
|
|
90
|
+
this.record(target, from?.personId ?? PEOPLE_CONSTANTS.OWNER_ID, 'agent');
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A session's record.
|
|
94
|
+
*
|
|
95
|
+
* @param session - Agent session name
|
|
96
|
+
* @returns Entry, or null when the session never got a human message
|
|
97
|
+
*/
|
|
98
|
+
get(session) {
|
|
99
|
+
const entry = this.load()[session];
|
|
100
|
+
return entry ? { ...entry } : null;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The person a request acts for: the owner for a request with no agent
|
|
104
|
+
* session (the owner's dashboard), else the session's record (the owner
|
|
105
|
+
* when it has none).
|
|
106
|
+
*
|
|
107
|
+
* @param session - Calling agent session, if any
|
|
108
|
+
* @returns Actor
|
|
109
|
+
*/
|
|
110
|
+
actorFor(session) {
|
|
111
|
+
const people = this.people();
|
|
112
|
+
const raw = session ? this.load()[session]?.personId : undefined;
|
|
113
|
+
const id = !raw || people.isOwner(raw) ? people.ownerId() : raw;
|
|
114
|
+
return { id, role: people.roleOf(id), name: people.displayName(id) };
|
|
115
|
+
}
|
|
116
|
+
/** Forget everything (tests). */
|
|
117
|
+
clear() {
|
|
118
|
+
this.save({});
|
|
119
|
+
}
|
|
120
|
+
/** @returns Store path */
|
|
121
|
+
filePath() {
|
|
122
|
+
return this.filePathOverride ?? path.join(getCrewlyHomePath(), PEOPLE_CONSTANTS.ACTING_FOR_FILE);
|
|
123
|
+
}
|
|
124
|
+
/** @returns All records (read once, then cached) */
|
|
125
|
+
load() {
|
|
126
|
+
if (this.cache)
|
|
127
|
+
return this.cache;
|
|
128
|
+
try {
|
|
129
|
+
const raw = JSON.parse(fs.readFileSync(this.filePath(), 'utf-8'));
|
|
130
|
+
const sessions = raw && typeof raw === 'object' ? raw.sessions : undefined;
|
|
131
|
+
const out = {};
|
|
132
|
+
if (sessions && typeof sessions === 'object') {
|
|
133
|
+
for (const [name, e] of Object.entries(sessions)) {
|
|
134
|
+
if (e && typeof e.personId === 'string' && typeof e.at === 'string') {
|
|
135
|
+
out[name] = { personId: e.personId, at: e.at, source: e.source === 'slack' || e.source === 'agent' ? e.source : 'dashboard' };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
this.cache = out;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
this.cache = {};
|
|
143
|
+
}
|
|
144
|
+
return this.cache;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Save atomically (best effort: the in-memory record still applies).
|
|
148
|
+
*
|
|
149
|
+
* @param all - Records
|
|
150
|
+
*/
|
|
151
|
+
save(all) {
|
|
152
|
+
this.cache = all;
|
|
153
|
+
try {
|
|
154
|
+
const target = this.filePath();
|
|
155
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
156
|
+
const tmp = `${target}.${process.pid}.tmp`;
|
|
157
|
+
fs.writeFileSync(tmp, `${JSON.stringify({ version: 1, sessions: all }, null, 2)}\n`, 'utf-8');
|
|
158
|
+
fs.renameSync(tmp, target);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// kept in memory
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
let instance = null;
|
|
166
|
+
/**
|
|
167
|
+
* The backend's acting-for record.
|
|
168
|
+
*
|
|
169
|
+
* @returns Singleton
|
|
170
|
+
*/
|
|
171
|
+
export function getActingFor() {
|
|
172
|
+
instance ??= new ActingForService();
|
|
173
|
+
return instance;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Replace the singleton (tests).
|
|
177
|
+
*
|
|
178
|
+
* @param service - Instance, or null to reset
|
|
179
|
+
*/
|
|
180
|
+
export function setActingForForTesting(service) {
|
|
181
|
+
instance = service;
|
|
182
|
+
}
|
|
183
|
+
const actorStore = new AsyncLocalStorage();
|
|
184
|
+
/**
|
|
185
|
+
* Run work as a person: connector token requests made inside carry that
|
|
186
|
+
* person to Cloud.
|
|
187
|
+
*
|
|
188
|
+
* @param actor - Person
|
|
189
|
+
* @param fn - Work
|
|
190
|
+
* @returns What `fn` returns
|
|
191
|
+
*/
|
|
192
|
+
export function runAsActor(actor, fn) {
|
|
193
|
+
return actorStore.run(actor, fn);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The person the current request acts for.
|
|
197
|
+
*
|
|
198
|
+
* @returns Actor, or null outside a connector request (backend-internal calls)
|
|
199
|
+
*/
|
|
200
|
+
export function currentActor() {
|
|
201
|
+
return actorStore.getStore() ?? null;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Headers that tell Cloud who a credential request is for.
|
|
205
|
+
*
|
|
206
|
+
* @param actor - Person (default: the current request's)
|
|
207
|
+
* @returns Headers (empty outside a connector request)
|
|
208
|
+
*/
|
|
209
|
+
export function actingForHeaders(actor = currentActor()) {
|
|
210
|
+
if (!actor)
|
|
211
|
+
return {};
|
|
212
|
+
return { [PEOPLE_CONSTANTS.ACTING_FOR_HEADER]: actor.id, [PEOPLE_CONSTANTS.ACTING_FOR_ROLE_HEADER]: actor.role };
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Cache-key suffix for a token fetched for the current person, so one
|
|
216
|
+
* person's cached token is never handed to another.
|
|
217
|
+
*
|
|
218
|
+
* @param actor - Person (default: the current request's)
|
|
219
|
+
* @returns `''` outside a connector request, else `\0<person id>`
|
|
220
|
+
*/
|
|
221
|
+
export function actorCacheSuffix(actor = currentActor()) {
|
|
222
|
+
return actor ? `\0${actor.id}` : '';
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=acting-for.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acting-for.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/people/acting-for.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAgD,MAAM,+BAA+B,CAAC;AA6BjH,6BAA6B;AAC7B,MAAM,OAAO,gBAAgB;IACX,gBAAgB,CAAU;IAC1B,MAAM,CAA+B;IACrC,GAAG,CAAe;IAC3B,KAAK,GAA0C,IAAI,CAAC;IAE5D;;OAEG;IACH,YAAY,OAAsB,EAAE;QACnC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,kBAAkB,CAAC;QAChD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,OAAe,EAAE,QAAgB,EAAE,MAAuB;QAChE,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ;YAAE,OAAO;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO;QAClF,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5E,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IAED;;;;;;OAMG;IACH,kBAAkB,CAAC,OAAe,EAAE,WAAsC;QACzE,IAAI,WAAW,IAAI,gBAAgB,CAAC,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7E,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;YAC3C,IAAI,CAAC;gBACJ,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YACrC,CAAC;YAAC,MAAM,CAAC;gBACR,oCAAoC;YACrC,CAAC;YACD,OAAO;QACR,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC9D,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,MAAc,EAAE,WAAmB;QAC1C,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,IAAI,MAAM,KAAK,WAAW;YAAE,OAAO;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3E,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,OAAe;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC;IAED;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAuB;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QACjE,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAChE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC;IACtE,CAAC;IAED,iCAAiC;IACjC,KAAK;QACJ,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IAED,0BAA0B;IAClB,QAAQ;QACf,OAAO,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAClG,CAAC;IAED,oDAAoD;IAC5C,IAAI;QACX,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC;QAClC,IAAI,CAAC;YACJ,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3E,MAAM,QAAQ,GAAG,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAE,GAA8B,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YACvG,MAAM,GAAG,GAAmC,EAAE,CAAC;YAC/C,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC9C,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAmD,CAAC,EAAE,CAAC;oBAC7F,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;wBACrE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;oBAC/H,CAAC;gBACF,CAAC;YACF,CAAC;YACD,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACR,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACK,IAAI,CAAC,GAAmC;QAC/C,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC;QACjB,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;YAC3C,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC9F,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACR,iBAAiB;QAClB,CAAC;IACF,CAAC;CACD;AAED,IAAI,QAAQ,GAA4B,IAAI,CAAC;AAE7C;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC3B,QAAQ,KAAK,IAAI,gBAAgB,EAAE,CAAC;IACpC,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACtE,QAAQ,GAAG,OAAO,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,GAAG,IAAI,iBAAiB,EAAS,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAI,KAAY,EAAE,EAAW;IACtD,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC3B,OAAO,UAAU,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAsB,YAAY,EAAE;IACpE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;AAClH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAsB,YAAY,EAAE;IACpE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedicated agents (issue #968): an agent bound to one person works only for
|
|
3
|
+
* them. When anyone else DMs it or @'s it, it does no work and is not woken —
|
|
4
|
+
* it answers once with a polite decline that points to the team lead.
|
|
5
|
+
*
|
|
6
|
+
* The decision is made where a Slack message enters (the agent-DM and team
|
|
7
|
+
* channel routers), before anything is recorded, dispatched or woken.
|
|
8
|
+
* Messages from other agents are never declined: delegation still works.
|
|
9
|
+
*
|
|
10
|
+
* specs/per-person-access.md
|
|
11
|
+
*
|
|
12
|
+
* @module services/people/dedicated-agent
|
|
13
|
+
*/
|
|
14
|
+
import type { Team, TeamMember } from '../../types/index.js';
|
|
15
|
+
import { type PeopleDirectoryService } from './people-directory.service.js';
|
|
16
|
+
/** A message's sender, as far as the decision needs it. */
|
|
17
|
+
export interface DedicatedSender {
|
|
18
|
+
/** Slack user id of the human who wrote it */
|
|
19
|
+
slackUserId?: string | null;
|
|
20
|
+
/** Set when another agent wrote it */
|
|
21
|
+
authorAgentSession?: string | null;
|
|
22
|
+
}
|
|
23
|
+
/** The decision for one message to one agent. */
|
|
24
|
+
export type DedicatedDecision = {
|
|
25
|
+
decline: false;
|
|
26
|
+
} | {
|
|
27
|
+
decline: true;
|
|
28
|
+
text: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Whether a person id is the one an agent is dedicated to.
|
|
32
|
+
*
|
|
33
|
+
* @param dedicatedTo - The member's `dedicatedTo`
|
|
34
|
+
* @param sender - Sender's Slack user id
|
|
35
|
+
* @param people - Directory (owner matching)
|
|
36
|
+
* @returns True when they are the same person
|
|
37
|
+
*/
|
|
38
|
+
export declare function isDedicatedPerson(dedicatedTo: string, sender: string, people: Pick<PeopleDirectoryService, 'isOwner'>): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The polite decline: who the agent works for, and where to go instead.
|
|
41
|
+
*
|
|
42
|
+
* @param member - The dedicated agent
|
|
43
|
+
* @param team - Its team (for the lead), when known
|
|
44
|
+
* @param senderSlackUserId - The person to answer
|
|
45
|
+
* @param people - Directory (names)
|
|
46
|
+
* @returns Slack mrkdwn text
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* declineText(member, team, 'U0STEVE');
|
|
51
|
+
* // "Hi <@U0STEVE>, I'm Info's personal assistant, so I can't take this on. For this, please ask Ella (team lead)."
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function declineText(member: Pick<TeamMember, 'id' | 'name' | 'dedicatedTo'>, team: Pick<Team, 'members' | 'leaderId' | 'leaderIds'> | null, senderSlackUserId: string, people?: Pick<PeopleDirectoryService, 'displayName'>): string;
|
|
55
|
+
/**
|
|
56
|
+
* Decide whether an agent declines a message.
|
|
57
|
+
*
|
|
58
|
+
* @param member - The receiving agent (with its `dedicatedTo`)
|
|
59
|
+
* @param team - Its team, when known
|
|
60
|
+
* @param sender - Who wrote the message
|
|
61
|
+
* @param people - Directory (default: the backend's)
|
|
62
|
+
* @returns `{ decline: true, text }` for a human other than the agent's person
|
|
63
|
+
*/
|
|
64
|
+
export declare function dedicatedDecision(member: Pick<TeamMember, 'id' | 'name' | 'dedicatedTo'> | null | undefined, team: Pick<Team, 'members' | 'leaderId' | 'leaderIds'> | null, sender: DedicatedSender, people?: Pick<PeopleDirectoryService, 'isOwner' | 'displayName'>): DedicatedDecision;
|
|
65
|
+
/** Where an agent's member record and team come from. */
|
|
66
|
+
export interface DedicatedLookup {
|
|
67
|
+
getTeams(): Promise<Team[]>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The member record and team of an agent session.
|
|
71
|
+
*
|
|
72
|
+
* @param storage - Team storage
|
|
73
|
+
* @param sessionName - Agent session
|
|
74
|
+
* @returns Both, or null when the session is not a team member (the orchestrator, a smoke test)
|
|
75
|
+
*/
|
|
76
|
+
export declare function findMemberWithTeam(storage: DedicatedLookup, sessionName: string): Promise<{
|
|
77
|
+
member: TeamMember;
|
|
78
|
+
team: Team;
|
|
79
|
+
} | null>;
|
|
80
|
+
/**
|
|
81
|
+
* Decide for an agent session (looks the member up).
|
|
82
|
+
*
|
|
83
|
+
* @param storage - Team storage
|
|
84
|
+
* @param sessionName - Receiving agent session
|
|
85
|
+
* @param sender - Who wrote the message
|
|
86
|
+
* @returns The decision (no decline when the agent is unknown or shared)
|
|
87
|
+
*/
|
|
88
|
+
export declare function dedicatedDecisionFor(storage: DedicatedLookup, sessionName: string, sender: DedicatedSender): Promise<DedicatedDecision>;
|
|
89
|
+
//# sourceMappingURL=dedicated-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedicated-agent.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/people/dedicated-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAsB,KAAK,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAEhG,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC/B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,iDAAiD;AACjD,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErF;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,sBAAsB,EAAE,SAAS,CAAC,GAAG,OAAO,CAG/H;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAC1B,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,GAAG,aAAa,CAAC,EACvD,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC,GAAG,IAAI,EAC7D,iBAAiB,EAAE,MAAM,EACzB,MAAM,GAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAwB,GACxE,MAAM,CAMR;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,GAAG,aAAa,CAAC,GAAG,IAAI,GAAG,SAAS,EAC1E,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC,GAAG,IAAI,EAC7D,MAAM,EAAE,eAAe,EACvB,MAAM,GAAE,IAAI,CAAC,sBAAsB,EAAE,SAAS,GAAG,aAAa,CAAwB,GACpF,iBAAiB,CAOnB;AAED,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC/B,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CAAC,CAU1I;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAS7I"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedicated agents (issue #968): an agent bound to one person works only for
|
|
3
|
+
* them. When anyone else DMs it or @'s it, it does no work and is not woken —
|
|
4
|
+
* it answers once with a polite decline that points to the team lead.
|
|
5
|
+
*
|
|
6
|
+
* The decision is made where a Slack message enters (the agent-DM and team
|
|
7
|
+
* channel routers), before anything is recorded, dispatched or woken.
|
|
8
|
+
* Messages from other agents are never declined: delegation still works.
|
|
9
|
+
*
|
|
10
|
+
* specs/per-person-access.md
|
|
11
|
+
*
|
|
12
|
+
* @module services/people/dedicated-agent
|
|
13
|
+
*/
|
|
14
|
+
import { getTeamLeads } from '../../utils/team.utils.js';
|
|
15
|
+
import { getPeopleDirectory } from './people-directory.service.js';
|
|
16
|
+
/**
|
|
17
|
+
* Whether a person id is the one an agent is dedicated to.
|
|
18
|
+
*
|
|
19
|
+
* @param dedicatedTo - The member's `dedicatedTo`
|
|
20
|
+
* @param sender - Sender's Slack user id
|
|
21
|
+
* @param people - Directory (owner matching)
|
|
22
|
+
* @returns True when they are the same person
|
|
23
|
+
*/
|
|
24
|
+
export function isDedicatedPerson(dedicatedTo, sender, people) {
|
|
25
|
+
if (dedicatedTo === sender)
|
|
26
|
+
return true;
|
|
27
|
+
return people.isOwner(dedicatedTo) && people.isOwner(sender);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The polite decline: who the agent works for, and where to go instead.
|
|
31
|
+
*
|
|
32
|
+
* @param member - The dedicated agent
|
|
33
|
+
* @param team - Its team (for the lead), when known
|
|
34
|
+
* @param senderSlackUserId - The person to answer
|
|
35
|
+
* @param people - Directory (names)
|
|
36
|
+
* @returns Slack mrkdwn text
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* declineText(member, team, 'U0STEVE');
|
|
41
|
+
* // "Hi <@U0STEVE>, I'm Info's personal assistant, so I can't take this on. For this, please ask Ella (team lead)."
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function declineText(member, team, senderSlackUserId, people = getPeopleDirectory()) {
|
|
45
|
+
const owner = member.dedicatedTo ? people.displayName(member.dedicatedTo) : 'someone else';
|
|
46
|
+
const whose = owner === 'the owner' ? "the owner's" : `${owner}'s`;
|
|
47
|
+
const lead = team ? getTeamLeads(team).find((m) => m.id !== member.id) : undefined;
|
|
48
|
+
const pointer = lead ? `${lead.name} (team lead)` : 'the Orc (the orchestrator)';
|
|
49
|
+
return `Hi <@${senderSlackUserId}>, I'm ${whose} personal assistant, so I can't take this on. For this, please ask ${pointer}.`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Decide whether an agent declines a message.
|
|
53
|
+
*
|
|
54
|
+
* @param member - The receiving agent (with its `dedicatedTo`)
|
|
55
|
+
* @param team - Its team, when known
|
|
56
|
+
* @param sender - Who wrote the message
|
|
57
|
+
* @param people - Directory (default: the backend's)
|
|
58
|
+
* @returns `{ decline: true, text }` for a human other than the agent's person
|
|
59
|
+
*/
|
|
60
|
+
export function dedicatedDecision(member, team, sender, people = getPeopleDirectory()) {
|
|
61
|
+
if (!member?.dedicatedTo)
|
|
62
|
+
return { decline: false };
|
|
63
|
+
if (sender.authorAgentSession)
|
|
64
|
+
return { decline: false };
|
|
65
|
+
const slackUserId = sender.slackUserId;
|
|
66
|
+
if (!slackUserId)
|
|
67
|
+
return { decline: false };
|
|
68
|
+
if (isDedicatedPerson(member.dedicatedTo, slackUserId, people))
|
|
69
|
+
return { decline: false };
|
|
70
|
+
return { decline: true, text: declineText(member, team, slackUserId, people) };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The member record and team of an agent session.
|
|
74
|
+
*
|
|
75
|
+
* @param storage - Team storage
|
|
76
|
+
* @param sessionName - Agent session
|
|
77
|
+
* @returns Both, or null when the session is not a team member (the orchestrator, a smoke test)
|
|
78
|
+
*/
|
|
79
|
+
export async function findMemberWithTeam(storage, sessionName) {
|
|
80
|
+
try {
|
|
81
|
+
for (const team of await storage.getTeams()) {
|
|
82
|
+
const member = team.members?.find((m) => m.sessionName === sessionName);
|
|
83
|
+
if (member)
|
|
84
|
+
return { member, team };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// storage unavailable: no decision
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Decide for an agent session (looks the member up).
|
|
94
|
+
*
|
|
95
|
+
* @param storage - Team storage
|
|
96
|
+
* @param sessionName - Receiving agent session
|
|
97
|
+
* @param sender - Who wrote the message
|
|
98
|
+
* @returns The decision (no decline when the agent is unknown or shared)
|
|
99
|
+
*/
|
|
100
|
+
export async function dedicatedDecisionFor(storage, sessionName, sender) {
|
|
101
|
+
if (!sender.slackUserId || sender.authorAgentSession)
|
|
102
|
+
return { decline: false };
|
|
103
|
+
const found = await findMemberWithTeam(storage, sessionName);
|
|
104
|
+
if (!found?.member.dedicatedTo)
|
|
105
|
+
return { decline: false };
|
|
106
|
+
try {
|
|
107
|
+
return dedicatedDecision(found.member, found.team, sender);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return { decline: false };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=dedicated-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedicated-agent.js","sourceRoot":"","sources":["../../../../../../backend/src/services/people/dedicated-agent.ts"],"names":[],"mappings":"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"}
|