crewly 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/constants.ts +8 -0
- package/config/roles/orchestrator/prompt.md +23 -0
- package/config/skills/_common/complete-body-shape.test.sh +113 -0
- package/config/skills/_common/no-dangling-symlinks.test.sh +63 -0
- package/config/skills/_common/task-pool-body-shape.test.sh +471 -0
- package/config/skills/agent/core/accept-task/execute.sh +30 -5
- package/config/skills/agent/core/block-task/execute.sh +59 -6
- package/config/skills/agent/core/complete-task/SKILL.md +37 -5
- package/config/skills/agent/core/complete-task/execute.sh +40 -9
- package/config/skills/agent/core/complete-task/execute.test.sh +213 -0
- package/config/skills/agent/core/create-task/SKILL.md +33 -0
- package/config/skills/agent/core/create-task/execute.sh +82 -23
- package/config/skills/agent/core/delegate-task/execute.sh +46 -0
- package/config/skills/agent/core/get-team-norms/SKILL.md +1 -1
- package/config/skills/agent/core/get-team-norms/execute.sh +73 -2
- package/config/skills/agent/core/handoff-task/execute.sh +8 -1
- package/config/skills/agent/core/reply-channel/SKILL.md +6 -0
- package/config/skills/agent/core/reply-channel/execute.sh +14 -2
- package/config/skills/agent/core/report-status/SKILL.md +26 -0
- package/config/skills/agent/core/report-status/execute.sh +40 -5
- package/config/skills/agent/core/slack-post/SKILL.md +126 -0
- package/config/skills/agent/core/slack-post/execute.sh +127 -0
- package/config/skills/agent/remote-browser/SKILL.md +178 -0
- package/config/skills/agent/xiaoyuzhoufm-transcript/SKILL.md +46 -22
- package/config/skills/agent/xiaoyuzhoufm-transcript/execute.sh +82 -214
- package/config/skills/agent/xiaoyuzhoufm-transcript/skill.json +3 -3
- package/config/skills/orchestrator/delegate-task/SKILL.md +1 -1
- package/config/skills/orchestrator/delegate-task/execute.sh +45 -11
- package/config/skills/orchestrator/delegate-task/execute.test.sh +153 -1
- package/config/skills/orchestrator/get-team-status/SKILL.md +5 -1
- package/config/skills/orchestrator/get-team-status/execute.sh +28 -2
- package/config/skills/team-leader/aggregate-results/SKILL.md +1 -1
- package/config/skills/team-leader/decompose-goal/execute.sh +11 -16
- package/config/skills/team-leader/delegate-task/SKILL.md +14 -1
- package/config/skills/team-leader/delegate-task/execute.sh +132 -43
- package/config/skills/team-leader/delegate-task/execute.test.sh +180 -27
- package/config/slack-app-manifest.json +7 -1
- package/config/vitest-exclude.constants.ts +56 -0
- package/dist/backend/backend/src/config/oauth.config.d.ts +93 -19
- package/dist/backend/backend/src/config/oauth.config.d.ts.map +1 -1
- package/dist/backend/backend/src/config/oauth.config.js +121 -19
- package/dist/backend/backend/src/config/oauth.config.js.map +1 -1
- package/dist/backend/backend/src/constants.d.ts +60 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +74 -0
- package/dist/backend/backend/src/constants.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 +33 -4
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.js +27 -9
- package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +18 -3
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +360 -15
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +6 -1
- 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 +19 -10
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +43 -7
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/scripts/stamp-build.d.ts +25 -0
- package/dist/backend/backend/src/scripts/stamp-build.d.ts.map +1 -0
- package/dist/backend/backend/src/scripts/stamp-build.js +48 -0
- package/dist/backend/backend/src/scripts/stamp-build.js.map +1 -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 +25 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +9 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts +42 -3
- package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/types.js +22 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/types.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts +10 -0
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js +37 -0
- package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
- 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 +13 -11
- 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 +14 -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 +56 -0
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-services.registry.d.ts +63 -0
- package/dist/backend/backend/src/services/browser/browser-services.registry.d.ts.map +1 -0
- package/dist/backend/backend/src/services/browser/browser-services.registry.js +74 -0
- package/dist/backend/backend/src/services/browser/browser-services.registry.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +25 -1
- 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 +19 -7
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +57 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +110 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +21 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +43 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.d.ts +6 -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 +1 -1
- package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -1
- package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +6 -2
- package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts +15 -0
- 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 +54 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.d.ts +8 -0
- package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.js +31 -3
- package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts +28 -3
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js +65 -8
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts +214 -4
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +330 -48
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts +47 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +183 -15
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts +14 -0
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js +77 -3
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-identity.service.d.ts +209 -0
- package/dist/backend/backend/src/services/slack/slack-agent-identity.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-agent-identity.service.js +416 -0
- package/dist/backend/backend/src/services/slack/slack-agent-identity.service.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts +124 -0
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.js +243 -0
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts +11 -0
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js +56 -0
- package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-mention-resolver.d.ts +103 -0
- package/dist/backend/backend/src/services/slack/slack-mention-resolver.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-mention-resolver.js +197 -0
- package/dist/backend/backend/src/services/slack/slack-mention-resolver.js.map +1 -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 +18 -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 +329 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +821 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack.service.d.ts +116 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +297 -3
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +152 -7
- 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 +268 -36
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/escalation-router.service.js +2 -2
- package/dist/backend/backend/src/services/v3/escalation-router.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.js +39 -2
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +22 -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 +71 -0
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.d.ts +20 -2
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.js +27 -2
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.d.ts +15 -2
- package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.js +33 -7
- package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts +37 -0
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js +74 -8
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/types/slack.types.d.ts +87 -0
- 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/index.d.ts +1 -1
- package/dist/backend/backend/src/types/v2/index.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/index.js +1 -1
- package/dist/backend/backend/src/types/v2/index.js.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts +181 -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 +104 -17
- package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/backend/backend/src/utils/build-provenance.d.ts +150 -0
- package/dist/backend/backend/src/utils/build-provenance.d.ts.map +1 -0
- package/dist/backend/backend/src/utils/build-provenance.js +211 -0
- package/dist/backend/backend/src/utils/build-provenance.js.map +1 -0
- package/dist/backend/build-info.json +4 -0
- package/dist/backend/config/constants.d.ts +8 -0
- package/dist/backend/config/constants.d.ts.map +1 -1
- package/dist/backend/config/constants.js +8 -0
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/backend/config/vitest-exclude.constants.d.ts +53 -0
- package/dist/backend/config/vitest-exclude.constants.d.ts.map +1 -0
- package/dist/backend/config/vitest-exclude.constants.js +55 -0
- package/dist/backend/config/vitest-exclude.constants.js.map +1 -0
- package/dist/cli/backend/src/config/oauth.config.d.ts +93 -19
- package/dist/cli/backend/src/config/oauth.config.d.ts.map +1 -1
- package/dist/cli/backend/src/config/oauth.config.js +121 -19
- package/dist/cli/backend/src/config/oauth.config.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +60 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +74 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/active-work-briefing.service.d.ts +538 -0
- package/dist/cli/backend/src/services/agent/active-work-briefing.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/active-work-briefing.service.js +802 -0
- package/dist/cli/backend/src/services/agent/active-work-briefing.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/agent-heartbeat.service.d.ts +240 -0
- package/dist/cli/backend/src/services/agent/agent-heartbeat.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/agent-heartbeat.service.js +524 -0
- package/dist/cli/backend/src/services/agent/agent-heartbeat.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +629 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +4548 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/agent-suspend.service.d.ts +118 -0
- package/dist/cli/backend/src/services/agent/agent-suspend.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/agent-suspend.service.js +304 -0
- package/dist/cli/backend/src/services/agent/agent-suspend.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/auditor-scheduler.service.d.ts +196 -0
- package/dist/cli/backend/src/services/agent/auditor-scheduler.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/auditor-scheduler.service.js +504 -0
- package/dist/cli/backend/src/services/agent/auditor-scheduler.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/claude-runtime.service.d.ts +97 -0
- package/dist/cli/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/claude-runtime.service.js +334 -0
- package/dist/cli/backend/src/services/agent/claude-runtime.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/codex-runtime.service.d.ts +47 -0
- package/dist/cli/backend/src/services/agent/codex-runtime.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/codex-runtime.service.js +112 -0
- package/dist/cli/backend/src/services/agent/codex-runtime.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/context-window-monitor.service.d.ts +323 -0
- package/dist/cli/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/context-window-monitor.service.js +1056 -0
- package/dist/cli/backend/src/services/agent/context-window-monitor.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts +198 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +816 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/in-process-log-buffer.d.ts +155 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/in-process-log-buffer.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/in-process-log-buffer.js +272 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/in-process-log-buffer.js.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts +91 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js +120 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/types.d.ts +536 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/types.js +282 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/types.js.map +1 -0
- package/dist/cli/backend/src/services/agent/disk-cleanup.service.d.ts +100 -0
- package/dist/cli/backend/src/services/agent/disk-cleanup.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/disk-cleanup.service.js +149 -0
- package/dist/cli/backend/src/services/agent/disk-cleanup.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/gemini-runtime.service.d.ts +130 -0
- package/dist/cli/backend/src/services/agent/gemini-runtime.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/gemini-runtime.service.js +758 -0
- package/dist/cli/backend/src/services/agent/gemini-runtime.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +216 -0
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.js +508 -0
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/pty-activity-tracker.service.d.ts +113 -0
- package/dist/cli/backend/src/services/agent/pty-activity-tracker.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/pty-activity-tracker.service.js +161 -0
- package/dist/cli/backend/src/services/agent/pty-activity-tracker.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts +156 -0
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js +641 -0
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts +295 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js +1166 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/runtime-service.factory.d.ts +71 -0
- package/dist/cli/backend/src/services/agent/runtime-service.factory.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/runtime-service.factory.js +174 -0
- package/dist/cli/backend/src/services/agent/runtime-service.factory.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts +435 -0
- package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-builder.service.js +1331 -0
- package/dist/cli/backend/src/services/ai/prompt-builder.service.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/capability-overlay.module.d.ts +33 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/capability-overlay.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/capability-overlay.module.js +70 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/capability-overlay.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.d.ts +100 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js +296 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts +59 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.js +87 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/default-execution-loop.module.d.ts +67 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/default-execution-loop.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/default-execution-loop.module.js +84 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/default-execution-loop.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/domain-sop.module.d.ts +35 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/domain-sop.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/domain-sop.module.js +50 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/domain-sop.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/expert-profile.module.d.ts +41 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/expert-profile.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/expert-profile.module.js +95 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/expert-profile.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/identity.module.d.ts +28 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/identity.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/identity.module.js +47 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/identity.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.d.ts +65 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js +79 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/learning-reference.module.d.ts +28 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/learning-reference.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/learning-reference.module.js +55 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/learning-reference.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/lifecycle.module.d.ts +44 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/lifecycle.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/lifecycle.module.js +120 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/lifecycle.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/markdown-file-module.d.ts +46 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/markdown-file-module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/markdown-file-module.js +44 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/markdown-file-module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.d.ts +28 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.js +46 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/mission-context.module.d.ts +60 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/mission-context.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/mission-context.module.js +104 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/mission-context.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/project-reference.module.d.ts +29 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/project-reference.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/project-reference.module.js +50 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/project-reference.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.d.ts +103 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.js +383 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/recovery.module.d.ts +34 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/recovery.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/recovery.module.js +96 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/recovery.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/request-contract.module.d.ts +106 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/request-contract.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/request-contract.module.js +167 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/request-contract.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/risk-policy.module.d.ts +35 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/risk-policy.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/risk-policy.module.js +50 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/risk-policy.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts +91 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/role-boundary.module.js +411 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/role-boundary.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts +62 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +199 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts +79 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js +118 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/soul.module.d.ts +102 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/soul.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/soul.module.js +229 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/soul.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/team-norms.module.d.ts +61 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/team-norms.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/team-norms.module.js +197 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/team-norms.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/team-reference.module.d.ts +54 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/team-reference.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/team-reference.module.js +149 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/team-reference.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/user-profile-reference.module.d.ts +32 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/user-profile-reference.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/user-profile-reference.module.js +69 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/user-profile-reference.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/working-memory.module.d.ts +91 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/working-memory.module.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/working-memory.module.js +136 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/working-memory.module.js.map +1 -0
- package/dist/cli/backend/src/services/ai/self-improvement/growth-areas.service.d.ts +81 -0
- package/dist/cli/backend/src/services/ai/self-improvement/growth-areas.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/self-improvement/growth-areas.service.js +135 -0
- package/dist/cli/backend/src/services/ai/self-improvement/growth-areas.service.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +292 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +420 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts +134 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.mention-resolver.js +232 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.mention-resolver.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +794 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +1322 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.singleton.d.ts +27 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.singleton.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.singleton.js +57 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.singleton.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/config.d.ts +100 -0
- package/dist/cli/backend/src/services/chat-v2/config.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/config.js +174 -0
- package/dist/cli/backend/src/services/chat-v2/config.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/legacy-dto.utils.d.ts +118 -0
- package/dist/cli/backend/src/services/chat-v2/legacy-dto.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/legacy-dto.utils.js +171 -0
- package/dist/cli/backend/src/services/chat-v2/legacy-dto.utils.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.d.ts +188 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.js +317 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/chat-db.d.ts +119 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/chat-db.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/chat-db.js +551 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/chat-db.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +229 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +448 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/types.d.ts +341 -0
- package/dist/cli/backend/src/services/chat-v2/types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/types.js +61 -0
- package/dist/cli/backend/src/services/chat-v2/types.js.map +1 -0
- package/dist/cli/backend/src/services/continuation/patterns/idle-patterns.d.ts +37 -0
- package/dist/cli/backend/src/services/continuation/patterns/idle-patterns.d.ts.map +1 -0
- package/dist/cli/backend/src/services/continuation/patterns/idle-patterns.js +63 -0
- package/dist/cli/backend/src/services/continuation/patterns/idle-patterns.js.map +1 -0
- package/dist/cli/backend/src/services/core/storage.service.d.ts +6 -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 +1 -1
- package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -1
- package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +6 -2
- package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -1
- package/dist/cli/backend/src/services/intent-task/intent-classifier.rules.d.ts +335 -0
- package/dist/cli/backend/src/services/intent-task/intent-classifier.rules.d.ts.map +1 -0
- package/dist/cli/backend/src/services/intent-task/intent-classifier.rules.js +421 -0
- package/dist/cli/backend/src/services/intent-task/intent-classifier.rules.js.map +1 -0
- package/dist/cli/backend/src/services/mcp-client.d.ts +233 -0
- package/dist/cli/backend/src/services/mcp-client.d.ts.map +1 -0
- package/dist/cli/backend/src/services/mcp-client.js +302 -0
- package/dist/cli/backend/src/services/mcp-client.js.map +1 -0
- package/dist/cli/backend/src/services/memory/mission-context.service.d.ts +168 -0
- package/dist/cli/backend/src/services/memory/mission-context.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/mission-context.service.js +365 -0
- package/dist/cli/backend/src/services/memory/mission-context.service.js.map +1 -0
- package/dist/cli/backend/src/services/memory/session-memory.service.d.ts +197 -0
- package/dist/cli/backend/src/services/memory/session-memory.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/session-memory.service.js +369 -0
- package/dist/cli/backend/src/services/memory/session-memory.service.js.map +1 -0
- package/dist/cli/backend/src/services/memory/user-profile.service.d.ts +77 -0
- package/dist/cli/backend/src/services/memory/user-profile.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/user-profile.service.js +171 -0
- package/dist/cli/backend/src/services/memory/user-profile.service.js.map +1 -0
- package/dist/cli/backend/src/services/memory/working-memory.service.d.ts +232 -0
- package/dist/cli/backend/src/services/memory/working-memory.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/working-memory.service.js +417 -0
- package/dist/cli/backend/src/services/memory/working-memory.service.js.map +1 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +84 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +136 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -0
- package/dist/cli/backend/src/services/messaging/thread-status-queue.service.d.ts +358 -0
- package/dist/cli/backend/src/services/messaging/thread-status-queue.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/messaging/thread-status-queue.service.js +755 -0
- package/dist/cli/backend/src/services/messaging/thread-status-queue.service.js.map +1 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts +269 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js +391 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js.map +1 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.service.d.ts +132 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.service.js +284 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.service.js.map +1 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.singleton.d.ts +70 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.singleton.d.ts.map +1 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.singleton.js +121 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.singleton.js.map +1 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.types.d.ts +130 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.types.js +48 -0
- package/dist/cli/backend/src/services/observability/agent-behavior-log.types.js.map +1 -0
- package/dist/cli/backend/src/services/observability/observability-db.d.ts +84 -0
- package/dist/cli/backend/src/services/observability/observability-db.d.ts.map +1 -0
- package/dist/cli/backend/src/services/observability/observability-db.js +165 -0
- package/dist/cli/backend/src/services/observability/observability-db.js.map +1 -0
- package/dist/cli/backend/src/services/onboarding/content-approval.service.d.ts +124 -0
- package/dist/cli/backend/src/services/onboarding/content-approval.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/onboarding/content-approval.service.js +256 -0
- package/dist/cli/backend/src/services/onboarding/content-approval.service.js.map +1 -0
- package/dist/cli/backend/src/services/onboarding/content-approval.types.d.ts +80 -0
- package/dist/cli/backend/src/services/onboarding/content-approval.types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/onboarding/content-approval.types.js +16 -0
- package/dist/cli/backend/src/services/onboarding/content-approval.types.js.map +1 -0
- package/dist/cli/backend/src/services/orc/orc-delivery-enforcer.service.d.ts +150 -0
- package/dist/cli/backend/src/services/orc/orc-delivery-enforcer.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orc/orc-delivery-enforcer.service.js +293 -0
- package/dist/cli/backend/src/services/orc/orc-delivery-enforcer.service.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/improvement-marker.service.d.ts +231 -0
- package/dist/cli/backend/src/services/orchestrator/improvement-marker.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/improvement-marker.service.js +353 -0
- package/dist/cli/backend/src/services/orchestrator/improvement-marker.service.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/improvement-startup.service.d.ts +157 -0
- package/dist/cli/backend/src/services/orchestrator/improvement-startup.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/improvement-startup.service.js +483 -0
- package/dist/cli/backend/src/services/orchestrator/improvement-startup.service.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/index.d.ts +16 -0
- package/dist/cli/backend/src/services/orchestrator/index.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/index.js +16 -0
- package/dist/cli/backend/src/services/orchestrator/index.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-restart.service.d.ts +117 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-restart.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-restart.service.js +300 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-restart.service.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-setup.service.d.ts +114 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-setup.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-setup.service.js +195 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-setup.service.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-status.service.d.ts +94 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-status.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-status.service.js +279 -0
- package/dist/cli/backend/src/services/orchestrator/orchestrator-status.service.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/safe-restart.service.d.ts +192 -0
- package/dist/cli/backend/src/services/orchestrator/safe-restart.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/safe-restart.service.js +395 -0
- package/dist/cli/backend/src/services/orchestrator/safe-restart.service.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/self-improvement.service.d.ts +201 -0
- package/dist/cli/backend/src/services/orchestrator/self-improvement.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/self-improvement.service.js +396 -0
- package/dist/cli/backend/src/services/orchestrator/self-improvement.service.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/slack-bridge-lazy.d.ts +17 -0
- package/dist/cli/backend/src/services/orchestrator/slack-bridge-lazy.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/slack-bridge-lazy.js +30 -0
- package/dist/cli/backend/src/services/orchestrator/slack-bridge-lazy.js.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/state-persistence.service.d.ts +249 -0
- package/dist/cli/backend/src/services/orchestrator/state-persistence.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orchestrator/state-persistence.service.js +569 -0
- package/dist/cli/backend/src/services/orchestrator/state-persistence.service.js.map +1 -0
- package/dist/cli/backend/src/services/session/index.d.ts +47 -0
- package/dist/cli/backend/src/services/session/index.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/index.js +50 -0
- package/dist/cli/backend/src/services/session/index.js.map +1 -0
- package/dist/cli/backend/src/services/session/log-rotation.service.d.ts +163 -0
- package/dist/cli/backend/src/services/session/log-rotation.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/log-rotation.service.js +362 -0
- package/dist/cli/backend/src/services/session/log-rotation.service.js.map +1 -0
- package/dist/cli/backend/src/services/session/pty/index.d.ts +11 -0
- package/dist/cli/backend/src/services/session/pty/index.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/pty/index.js +11 -0
- package/dist/cli/backend/src/services/session/pty/index.js.map +1 -0
- package/dist/cli/backend/src/services/session/pty/pty-session-backend.d.ts +445 -0
- package/dist/cli/backend/src/services/session/pty/pty-session-backend.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/pty/pty-session-backend.js +804 -0
- package/dist/cli/backend/src/services/session/pty/pty-session-backend.js.map +1 -0
- package/dist/cli/backend/src/services/session/pty/pty-session.d.ts +252 -0
- package/dist/cli/backend/src/services/session/pty/pty-session.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/pty/pty-session.js +611 -0
- package/dist/cli/backend/src/services/session/pty/pty-session.js.map +1 -0
- package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.d.ts +275 -0
- package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.js +403 -0
- package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.js.map +1 -0
- package/dist/cli/backend/src/services/session/runtime-pid-registry.service.d.ts +86 -0
- package/dist/cli/backend/src/services/session/runtime-pid-registry.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/runtime-pid-registry.service.js +214 -0
- package/dist/cli/backend/src/services/session/runtime-pid-registry.service.js.map +1 -0
- package/dist/cli/backend/src/services/session/session-backend.factory.d.ts +127 -0
- package/dist/cli/backend/src/services/session/session-backend.factory.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/session-backend.factory.js +226 -0
- package/dist/cli/backend/src/services/session/session-backend.factory.js.map +1 -0
- package/dist/cli/backend/src/services/session/session-backend.interface.d.ts +390 -0
- package/dist/cli/backend/src/services/session/session-backend.interface.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/session-backend.interface.js +19 -0
- package/dist/cli/backend/src/services/session/session-backend.interface.js.map +1 -0
- package/dist/cli/backend/src/services/session/session-command-helper.d.ts +350 -0
- package/dist/cli/backend/src/services/session/session-command-helper.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/session-command-helper.js +810 -0
- package/dist/cli/backend/src/services/session/session-command-helper.js.map +1 -0
- package/dist/cli/backend/src/services/session/session-handoff.service.d.ts +307 -0
- package/dist/cli/backend/src/services/session/session-handoff.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/session-handoff.service.js +742 -0
- package/dist/cli/backend/src/services/session/session-handoff.service.js.map +1 -0
- package/dist/cli/backend/src/services/session/session-state-persistence.d.ts +231 -0
- package/dist/cli/backend/src/services/session/session-state-persistence.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/session-state-persistence.js +407 -0
- package/dist/cli/backend/src/services/session/session-state-persistence.js.map +1 -0
- package/dist/cli/backend/src/services/settings/role.service.d.ts +277 -0
- package/dist/cli/backend/src/services/settings/role.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/settings/role.service.js +728 -0
- package/dist/cli/backend/src/services/settings/role.service.js.map +1 -0
- package/dist/cli/backend/src/services/slack/cross-machine-message.service.d.ts +152 -0
- package/dist/cli/backend/src/services/slack/cross-machine-message.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/cross-machine-message.service.js +354 -0
- package/dist/cli/backend/src/services/slack/cross-machine-message.service.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-agent-identity.service.d.ts +209 -0
- package/dist/cli/backend/src/services/slack/slack-agent-identity.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-agent-identity.service.js +416 -0
- package/dist/cli/backend/src/services/slack/slack-agent-identity.service.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-image.service.d.ts +114 -0
- package/dist/cli/backend/src/services/slack/slack-image.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-image.service.js +331 -0
- package/dist/cli/backend/src/services/slack/slack-image.service.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-mention-resolver.d.ts +103 -0
- package/dist/cli/backend/src/services/slack/slack-mention-resolver.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-mention-resolver.js +197 -0
- package/dist/cli/backend/src/services/slack/slack-mention-resolver.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +499 -0
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +1946 -0
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +329 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +821 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack.service.d.ts +430 -0
- package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/slack.service.js +1388 -0
- package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -0
- package/dist/cli/backend/src/services/sop/sop.service.d.ts +364 -0
- package/dist/cli/backend/src/services/sop/sop.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/sop/sop.service.js +734 -0
- package/dist/cli/backend/src/services/sop/sop.service.js.map +1 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +152 -7
- 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 +268 -36
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/services/v3/escalation-router.service.d.ts +178 -0
- package/dist/cli/backend/src/services/v3/escalation-router.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/v3/escalation-router.service.js +692 -0
- package/dist/cli/backend/src/services/v3/escalation-router.service.js.map +1 -0
- package/dist/cli/backend/src/services/v3/kr-tracking.service.d.ts +200 -0
- package/dist/cli/backend/src/services/v3/kr-tracking.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/v3/kr-tracking.service.js +482 -0
- package/dist/cli/backend/src/services/v3/kr-tracking.service.js.map +1 -0
- package/dist/cli/backend/src/services/v3/mission-executor.service.d.ts +117 -0
- package/dist/cli/backend/src/services/v3/mission-executor.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/v3/mission-executor.service.js +321 -0
- package/dist/cli/backend/src/services/v3/mission-executor.service.js.map +1 -0
- package/dist/cli/backend/src/services/v3/request-sla.subscriber.d.ts +610 -0
- package/dist/cli/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -0
- package/dist/cli/backend/src/services/v3/request-sla.subscriber.js +1529 -0
- package/dist/cli/backend/src/services/v3/request-sla.subscriber.js.map +1 -0
- package/dist/cli/backend/src/services/v3/request-tracker.service.d.ts +78 -0
- package/dist/cli/backend/src/services/v3/request-tracker.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/v3/request-tracker.service.js +108 -0
- package/dist/cli/backend/src/services/v3/request-tracker.service.js.map +1 -0
- package/dist/cli/backend/src/services/v3/request.service.d.ts +295 -0
- package/dist/cli/backend/src/services/v3/request.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/v3/request.service.js +534 -0
- package/dist/cli/backend/src/services/v3/request.service.js.map +1 -0
- package/dist/cli/backend/src/services/v3/v3-data.service.d.ts +340 -0
- package/dist/cli/backend/src/services/v3/v3-data.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/v3/v3-data.service.js +1113 -0
- package/dist/cli/backend/src/services/v3/v3-data.service.js.map +1 -0
- package/dist/cli/backend/src/types/cross-machine.types.d.ts +103 -0
- package/dist/cli/backend/src/types/cross-machine.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/cross-machine.types.js +47 -0
- package/dist/cli/backend/src/types/cross-machine.types.js.map +1 -0
- package/dist/cli/backend/src/types/intent-task.types.d.ts +402 -0
- package/dist/cli/backend/src/types/intent-task.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/intent-task.types.js +403 -0
- package/dist/cli/backend/src/types/intent-task.types.js.map +1 -0
- package/dist/cli/backend/src/types/orchestrator-state.types.d.ts +531 -0
- package/dist/cli/backend/src/types/orchestrator-state.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/orchestrator-state.types.js +110 -0
- package/dist/cli/backend/src/types/orchestrator-state.types.js.map +1 -0
- package/dist/cli/backend/src/types/slack.types.d.ts +87 -0
- package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/slack.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/index.d.ts +30 -0
- package/dist/cli/backend/src/types/v2/index.d.ts.map +1 -0
- package/dist/cli/backend/src/types/v2/index.js +22 -0
- package/dist/cli/backend/src/types/v2/index.js.map +1 -0
- package/dist/cli/backend/src/types/v2/key-result.types.d.ts +279 -0
- package/dist/cli/backend/src/types/v2/key-result.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/v2/key-result.types.js +264 -0
- package/dist/cli/backend/src/types/v2/key-result.types.js.map +1 -0
- package/dist/cli/backend/src/types/v2/mission.types.d.ts +661 -0
- package/dist/cli/backend/src/types/v2/mission.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/v2/mission.types.js +713 -0
- package/dist/cli/backend/src/types/v2/mission.types.js.map +1 -0
- package/dist/cli/backend/src/types/v2/reconcile.types.d.ts +204 -0
- package/dist/cli/backend/src/types/v2/reconcile.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/v2/reconcile.types.js +121 -0
- package/dist/cli/backend/src/types/v2/reconcile.types.js.map +1 -0
- package/dist/cli/backend/src/types/v2/request.types.d.ts +192 -0
- package/dist/cli/backend/src/types/v2/request.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/v2/request.types.js +179 -0
- package/dist/cli/backend/src/types/v2/request.types.js.map +1 -0
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts +181 -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 +104 -17
- package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/workspace.types.d.ts +157 -0
- package/dist/cli/backend/src/types/v2/workspace.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/v2/workspace.types.js +173 -0
- package/dist/cli/backend/src/types/v2/workspace.types.js.map +1 -0
- package/dist/cli/backend/src/utils/async.utils.d.ts +68 -0
- package/dist/cli/backend/src/utils/async.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/async.utils.js +80 -0
- package/dist/cli/backend/src/utils/async.utils.js.map +1 -0
- package/dist/cli/backend/src/utils/native-binding.utils.d.ts +128 -0
- package/dist/cli/backend/src/utils/native-binding.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/native-binding.utils.js +206 -0
- package/dist/cli/backend/src/utils/native-binding.utils.js.map +1 -0
- package/dist/cli/backend/src/utils/team.utils.d.ts +40 -0
- package/dist/cli/backend/src/utils/team.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/team.utils.js +66 -0
- package/dist/cli/backend/src/utils/team.utils.js.map +1 -0
- package/dist/cli/backend/src/websocket/chat.gateway.d.ts +142 -0
- package/dist/cli/backend/src/websocket/chat.gateway.d.ts.map +1 -0
- package/dist/cli/backend/src/websocket/chat.gateway.js +327 -0
- package/dist/cli/backend/src/websocket/chat.gateway.js.map +1 -0
- package/dist/cli/backend/src/websocket/terminal.gateway.d.ts +341 -0
- package/dist/cli/backend/src/websocket/terminal.gateway.d.ts.map +1 -0
- package/dist/cli/backend/src/websocket/terminal.gateway.js +933 -0
- package/dist/cli/backend/src/websocket/terminal.gateway.js.map +1 -0
- package/dist/cli/cli/src/index.js +0 -0
- package/dist/cli/config/constants.d.ts +8 -0
- package/dist/cli/config/constants.d.ts.map +1 -1
- package/dist/cli/config/constants.js +8 -0
- package/dist/cli/config/constants.js.map +1 -1
- package/dist/cli/config/vitest-exclude.constants.d.ts +53 -0
- package/dist/cli/config/vitest-exclude.constants.d.ts.map +1 -0
- package/dist/cli/config/vitest-exclude.constants.js +55 -0
- package/dist/cli/config/vitest-exclude.constants.js.map +1 -0
- package/frontend/dist/assets/index-190a957f.js +4961 -0
- package/frontend/dist/assets/{index-8205ea5e.css → index-88feb412.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +2 -2
- package/packages/crewly-agent/src/runtime/agent-runner.service.test.ts +174 -30
- package/packages/crewly-agent/src/runtime/agent-runner.service.ts +121 -6
- package/packages/crewly-agent/src/runtime/types.ts +56 -5
- package/dist/backend/backend/src/controllers/knowledge/index.d.ts +0 -7
- package/dist/backend/backend/src/controllers/knowledge/index.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/knowledge/index.js +0 -7
- package/dist/backend/backend/src/controllers/knowledge/index.js.map +0 -1
- package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.d.ts +0 -71
- package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.js +0 -237
- package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.js.map +0 -1
- package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.d.ts +0 -24
- package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.js +0 -34
- package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.js.map +0 -1
- package/dist/backend/backend/src/controllers/scheduler/unified-scheduler.controller.d.ts +0 -91
- package/dist/backend/backend/src/controllers/scheduler/unified-scheduler.controller.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/scheduler/unified-scheduler.controller.js +0 -290
- package/dist/backend/backend/src/controllers/scheduler/unified-scheduler.controller.js.map +0 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +0 -169
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +0 -1779
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +0 -1
- package/dist/backend/backend/src/index.js.orc-bak-20260529 +0 -3130
- package/dist/backend/backend/src/routes/modules/unified-scheduler.routes.d.ts +0 -27
- package/dist/backend/backend/src/routes/modules/unified-scheduler.routes.d.ts.map +0 -1
- package/dist/backend/backend/src/routes/modules/unified-scheduler.routes.js +0 -40
- package/dist/backend/backend/src/routes/modules/unified-scheduler.routes.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts +0 -513
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js +0 -1568
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts +0 -86
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js +0 -147
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts +0 -68
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js +0 -131
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts +0 -130
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js +0 -263
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts +0 -74
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js +0 -140
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts +0 -29
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js +0 -279
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts +0 -340
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js +0 -1176
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts +0 -79
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js +0 -145
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts +0 -79
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js +0 -218
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts +0 -16
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js +0 -16
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts +0 -135
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js +0 -185
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +0 -141
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +0 -310
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts +0 -91
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js +0 -143
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts +0 -103
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js +0 -256
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts +0 -143
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js +0 -264
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts +0 -13
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js +0 -91
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts +0 -135
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js +0 -1937
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js.map +0 -1
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts +0 -429
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.js +0 -852
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.js.map +0 -1
- package/dist/backend/backend/src/services/knowledge/embedding-provider.d.ts +0 -78
- package/dist/backend/backend/src/services/knowledge/embedding-provider.d.ts.map +0 -1
- package/dist/backend/backend/src/services/knowledge/embedding-provider.js +0 -179
- package/dist/backend/backend/src/services/knowledge/embedding-provider.js.map +0 -1
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.d.ts +0 -118
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.js +0 -241
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.js.map +0 -1
- package/dist/backend/backend/src/services/knowledge/fts5-query-sanitizer.d.ts +0 -102
- package/dist/backend/backend/src/services/knowledge/fts5-query-sanitizer.d.ts.map +0 -1
- package/dist/backend/backend/src/services/knowledge/fts5-query-sanitizer.js +0 -118
- package/dist/backend/backend/src/services/knowledge/fts5-query-sanitizer.js.map +0 -1
- package/dist/backend/backend/src/services/knowledge/index.d.ts +0 -8
- package/dist/backend/backend/src/services/knowledge/index.d.ts.map +0 -1
- package/dist/backend/backend/src/services/knowledge/index.js +0 -8
- package/dist/backend/backend/src/services/knowledge/index.js.map +0 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts +0 -241
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +0 -590
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +0 -1
- package/dist/backend/backend/src/services/knowledge/knowledge.service.d.ts +0 -153
- package/dist/backend/backend/src/services/knowledge/knowledge.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/knowledge/knowledge.service.js +0 -409
- package/dist/backend/backend/src/services/knowledge/knowledge.service.js.map +0 -1
- package/dist/backend/backend/src/services/knowledge/vector-store.service.d.ts +0 -331
- package/dist/backend/backend/src/services/knowledge/vector-store.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/knowledge/vector-store.service.js +0 -830
- package/dist/backend/backend/src/services/knowledge/vector-store.service.js.map +0 -1
- package/dist/backend/backend/src/services/knowledge/wiki-compiler.service.d.ts +0 -115
- package/dist/backend/backend/src/services/knowledge/wiki-compiler.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/knowledge/wiki-compiler.service.js +0 -215
- package/dist/backend/backend/src/services/knowledge/wiki-compiler.service.js.map +0 -1
- package/dist/backend/backend/src/services/memory/embedding-provider.d.ts +0 -78
- package/dist/backend/backend/src/services/memory/embedding-provider.d.ts.map +0 -1
- package/dist/backend/backend/src/services/memory/embedding-provider.js +0 -185
- package/dist/backend/backend/src/services/memory/embedding-provider.js.map +0 -1
- package/dist/backend/backend/src/services/memory/vector-store.service.d.ts +0 -331
- package/dist/backend/backend/src/services/memory/vector-store.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/memory/vector-store.service.js +0 -825
- package/dist/backend/backend/src/services/memory/vector-store.service.js.map +0 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +0 -171
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.js +0 -725
- package/dist/backend/backend/src/services/project/task-tracking.service.js.map +0 -1
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts +0 -118
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.js +0 -326
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.js.map +0 -1
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts +0 -74
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js +0 -154
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js.map +0 -1
- package/dist/backend/backend/src/services/workflow/unified-scheduler.service.d.ts +0 -234
- package/dist/backend/backend/src/services/workflow/unified-scheduler.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/workflow/unified-scheduler.service.js +0 -636
- package/dist/backend/backend/src/services/workflow/unified-scheduler.service.js.map +0 -1
- package/dist/backend/backend/src/services/workflow/unified-scheduler.types.d.ts +0 -156
- package/dist/backend/backend/src/services/workflow/unified-scheduler.types.d.ts.map +0 -1
- package/dist/backend/backend/src/services/workflow/unified-scheduler.types.js +0 -81
- package/dist/backend/backend/src/services/workflow/unified-scheduler.types.js.map +0 -1
- package/dist/backend/backend/src/types/auto-assign.types.d.ts +0 -271
- package/dist/backend/backend/src/types/auto-assign.types.d.ts.map +0 -1
- package/dist/backend/backend/src/types/auto-assign.types.js +0 -136
- package/dist/backend/backend/src/types/auto-assign.types.js.map +0 -1
- package/dist/backend/backend/src/types/knowledge.types.d.ts +0 -195
- package/dist/backend/backend/src/types/knowledge.types.d.ts.map +0 -1
- package/dist/backend/backend/src/types/knowledge.types.js +0 -38
- package/dist/backend/backend/src/types/knowledge.types.js.map +0 -1
- package/dist/backend/backend/src/utils/esm-require.utils.d.ts +0 -111
- package/dist/backend/backend/src/utils/esm-require.utils.d.ts.map +0 -1
- package/dist/backend/backend/src/utils/esm-require.utils.js +0 -124
- package/dist/backend/backend/src/utils/esm-require.utils.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/embedding-provider.d.ts +0 -78
- package/dist/cli/backend/src/services/knowledge/embedding-provider.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/embedding-provider.js +0 -179
- package/dist/cli/backend/src/services/knowledge/embedding-provider.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.d.ts +0 -118
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.js +0 -241
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-query-sanitizer.d.ts +0 -102
- package/dist/cli/backend/src/services/knowledge/fts5-query-sanitizer.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-query-sanitizer.js +0 -118
- package/dist/cli/backend/src/services/knowledge/fts5-query-sanitizer.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts +0 -56
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js +0 -91
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts +0 -241
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +0 -590
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/knowledge.service.d.ts +0 -153
- package/dist/cli/backend/src/services/knowledge/knowledge.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/knowledge.service.js +0 -409
- package/dist/cli/backend/src/services/knowledge/knowledge.service.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts +0 -159
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.js +0 -304
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/vector-store.service.d.ts +0 -331
- package/dist/cli/backend/src/services/knowledge/vector-store.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/vector-store.service.js +0 -830
- package/dist/cli/backend/src/services/knowledge/vector-store.service.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts +0 -115
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js +0 -215
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js.map +0 -1
- package/dist/cli/backend/src/services/memory/embedding-provider.d.ts +0 -78
- package/dist/cli/backend/src/services/memory/embedding-provider.d.ts.map +0 -1
- package/dist/cli/backend/src/services/memory/embedding-provider.js +0 -179
- package/dist/cli/backend/src/services/memory/embedding-provider.js.map +0 -1
- package/dist/cli/backend/src/services/memory/vector-store.service.d.ts +0 -331
- package/dist/cli/backend/src/services/memory/vector-store.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/memory/vector-store.service.js +0 -814
- package/dist/cli/backend/src/services/memory/vector-store.service.js.map +0 -1
- package/dist/cli/backend/src/services/project/task-tracking.service.d.ts +0 -171
- package/dist/cli/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/project/task-tracking.service.js +0 -725
- package/dist/cli/backend/src/services/project/task-tracking.service.js.map +0 -1
- package/dist/cli/backend/src/types/auto-assign.types.d.ts +0 -271
- package/dist/cli/backend/src/types/auto-assign.types.d.ts.map +0 -1
- package/dist/cli/backend/src/types/auto-assign.types.js +0 -136
- package/dist/cli/backend/src/types/auto-assign.types.js.map +0 -1
- package/dist/cli/backend/src/types/knowledge.types.d.ts +0 -195
- package/dist/cli/backend/src/types/knowledge.types.d.ts.map +0 -1
- package/dist/cli/backend/src/types/knowledge.types.js +0 -38
- package/dist/cli/backend/src/types/knowledge.types.js.map +0 -1
- package/frontend/dist/assets/index-aa737fd3.js +0 -5254
|
@@ -0,0 +1,1388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slack Service
|
|
3
|
+
*
|
|
4
|
+
* Manages Slack bot connection and messaging using Bolt SDK.
|
|
5
|
+
* Enables bidirectional communication between Slack and Crewly.
|
|
6
|
+
*
|
|
7
|
+
* @module services/slack
|
|
8
|
+
*/
|
|
9
|
+
import { EventEmitter } from 'events';
|
|
10
|
+
import { createReadStream } from 'fs';
|
|
11
|
+
import { basename } from 'path';
|
|
12
|
+
import { isUserAllowed } from '../../types/slack.types.js';
|
|
13
|
+
import { CROSS_MACHINE_PREFIX } from '../../types/cross-machine.types.js';
|
|
14
|
+
import { SLACK_IMAGE_CONSTANTS, SLACK_FILE_UPLOAD_CONSTANTS, SLACK_DEDUP_CONSTANTS, SLACK_RECONNECT_CONSTANTS, SLACK_TEAM_CHANNEL_CONSTANTS, ORCHESTRATOR_SESSION_NAME } from '../../constants.js';
|
|
15
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
16
|
+
import { ContentApprovalService } from '../onboarding/content-approval.service.js';
|
|
17
|
+
import { getAgentBehaviorLogService } from '../observability/agent-behavior-log.singleton.js';
|
|
18
|
+
/**
|
|
19
|
+
* Slack Service singleton instance
|
|
20
|
+
*/
|
|
21
|
+
let slackServiceInstance = null;
|
|
22
|
+
/**
|
|
23
|
+
* SlackService class for managing Slack bot operations
|
|
24
|
+
*/
|
|
25
|
+
export class SlackService extends EventEmitter {
|
|
26
|
+
logger = LoggerService.getInstance().createComponentLogger('SlackService');
|
|
27
|
+
app = null;
|
|
28
|
+
client = null;
|
|
29
|
+
config = null;
|
|
30
|
+
/** Bot user id from `auth.test`, cached by getBotUserId(). */
|
|
31
|
+
cachedBotUserId = null;
|
|
32
|
+
/** Lower-cased handle/display name → Slack user id, filled by findUserByHandle(). */
|
|
33
|
+
userHandleCache = new Map();
|
|
34
|
+
status = {
|
|
35
|
+
connected: false,
|
|
36
|
+
socketMode: false,
|
|
37
|
+
messagesSent: 0,
|
|
38
|
+
messagesReceived: 0,
|
|
39
|
+
};
|
|
40
|
+
conversationContexts = new Map();
|
|
41
|
+
/** Cached Bolt App constructor from the first successful dynamic import */
|
|
42
|
+
cachedAppConstructor = null;
|
|
43
|
+
/** Cached Bolt LogLevel enum from the first successful dynamic import */
|
|
44
|
+
cachedLogLevelEnum = null;
|
|
45
|
+
/**
|
|
46
|
+
* Message deduplication tracker.
|
|
47
|
+
* Maps a fingerprint (channelId:threadTs:textHash) to the timestamp it was sent.
|
|
48
|
+
* Prevents identical messages from being sent to the same thread within a time window.
|
|
49
|
+
*/
|
|
50
|
+
recentMessageFingerprints = new Map();
|
|
51
|
+
/** Whether a reconnection attempt is currently in progress */
|
|
52
|
+
reconnecting = false;
|
|
53
|
+
/** Timer handle for the reconnection grace period */
|
|
54
|
+
reconnectGraceTimer = null;
|
|
55
|
+
/** Timer handle for the periodic health check */
|
|
56
|
+
healthCheckTimer = null;
|
|
57
|
+
/** Current consecutive reconnection attempt count */
|
|
58
|
+
reconnectAttempts = 0;
|
|
59
|
+
/** Whether the service has been intentionally shut down (skip auto-reconnect) */
|
|
60
|
+
intentionalDisconnect = false;
|
|
61
|
+
/** Timestamp of the last successful Slack API ping */
|
|
62
|
+
lastPingAt = 0;
|
|
63
|
+
/** Number of consecutive health-check ping failures */
|
|
64
|
+
consecutivePingFailures = 0;
|
|
65
|
+
/**
|
|
66
|
+
* Initialize the Slack service with configuration
|
|
67
|
+
*
|
|
68
|
+
* @param config - Slack bot configuration
|
|
69
|
+
* @returns Promise that resolves when connected
|
|
70
|
+
*/
|
|
71
|
+
async initialize(config) {
|
|
72
|
+
this.config = config;
|
|
73
|
+
this.intentionalDisconnect = false;
|
|
74
|
+
this.reconnectAttempts = 0;
|
|
75
|
+
try {
|
|
76
|
+
// Dynamic import of @slack/bolt (CJS module requires default import handling).
|
|
77
|
+
// Cache the constructor and LogLevel on first import for reuse in reconnect.
|
|
78
|
+
const boltModule = await import('@slack/bolt');
|
|
79
|
+
const defaultExport = boltModule.default;
|
|
80
|
+
const App = (boltModule.App ?? defaultExport?.App);
|
|
81
|
+
const LogLevel = (boltModule.LogLevel ?? defaultExport?.LogLevel);
|
|
82
|
+
this.cachedAppConstructor = App;
|
|
83
|
+
this.cachedLogLevelEnum = LogLevel ?? null;
|
|
84
|
+
this.app = new App({
|
|
85
|
+
token: config.botToken,
|
|
86
|
+
appToken: config.appToken,
|
|
87
|
+
signingSecret: config.signingSecret,
|
|
88
|
+
socketMode: config.socketMode,
|
|
89
|
+
logLevel: LogLevel?.INFO ?? 'info',
|
|
90
|
+
});
|
|
91
|
+
this.client = this.app.client;
|
|
92
|
+
// Set up event handlers
|
|
93
|
+
this.setupEventHandlers();
|
|
94
|
+
// Start the app
|
|
95
|
+
if (config.socketMode) {
|
|
96
|
+
await this.app.start();
|
|
97
|
+
this.status.connected = true;
|
|
98
|
+
this.status.socketMode = true;
|
|
99
|
+
// Monitor SocketModeClient connection state for logging and status tracking
|
|
100
|
+
this.setupConnectionMonitoring();
|
|
101
|
+
this.emit('connected');
|
|
102
|
+
this.logger.info('Connected in Socket Mode');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
// Ensure partially initialized Bolt app is torn down to avoid
|
|
107
|
+
// lingering socket retries/background tasks after failed startup.
|
|
108
|
+
if (this.app) {
|
|
109
|
+
try {
|
|
110
|
+
await this.app.stop();
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Ignore shutdown errors during failed initialization
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
this.app = null;
|
|
117
|
+
this.client = null;
|
|
118
|
+
this.status.connected = false;
|
|
119
|
+
this.status.socketMode = false;
|
|
120
|
+
this.status.lastError = error.message;
|
|
121
|
+
this.status.lastErrorAt = new Date().toISOString();
|
|
122
|
+
this.emit('error', error);
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Set up Slack event handlers
|
|
128
|
+
*/
|
|
129
|
+
setupEventHandlers() {
|
|
130
|
+
if (!this.app || !this.config)
|
|
131
|
+
return;
|
|
132
|
+
const config = this.config;
|
|
133
|
+
// Handle direct messages
|
|
134
|
+
this.app.message(async ({ message }) => {
|
|
135
|
+
// Allow messages with text or files (or both)
|
|
136
|
+
if (!message.text && (!message.files || message.files.length === 0))
|
|
137
|
+
return;
|
|
138
|
+
if (!message.user)
|
|
139
|
+
return;
|
|
140
|
+
// Bypass user permission check for cross-machine messages —
|
|
141
|
+
// these come from other bots and are authenticated by device ID,
|
|
142
|
+
// not Slack user ID. The CrossMachineMessageService handles its
|
|
143
|
+
// own security (device identity, target filtering, deduplication).
|
|
144
|
+
const isCrossMachine = message.text && message.text.startsWith(CROSS_MACHINE_PREFIX);
|
|
145
|
+
// Check user permissions (skip for cross-machine messages)
|
|
146
|
+
if (!isCrossMachine && !isUserAllowed(message.user, config)) {
|
|
147
|
+
this.logger.info('Unauthorized user', { userId: message.user });
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Pass ALL files through; downstream services handle image vs non-image distinction
|
|
151
|
+
const allFiles = (message.files || []);
|
|
152
|
+
const imageFiles = allFiles.filter(f => f.mimetype?.startsWith('image/'));
|
|
153
|
+
const incomingMessage = {
|
|
154
|
+
id: message.ts || '',
|
|
155
|
+
type: 'message',
|
|
156
|
+
text: message.text || '',
|
|
157
|
+
userId: message.user,
|
|
158
|
+
channelId: message.channel,
|
|
159
|
+
threadTs: message.thread_ts,
|
|
160
|
+
ts: message.ts || '',
|
|
161
|
+
teamId: message.team || '',
|
|
162
|
+
eventTs: message.ts || '',
|
|
163
|
+
files: allFiles.length > 0 ? allFiles : undefined,
|
|
164
|
+
hasImages: imageFiles.length > 0,
|
|
165
|
+
hasFiles: allFiles.length > 0,
|
|
166
|
+
};
|
|
167
|
+
this.status.messagesReceived++;
|
|
168
|
+
this.status.lastEventAt = new Date().toISOString();
|
|
169
|
+
this.emit('message', incomingMessage);
|
|
170
|
+
});
|
|
171
|
+
// Handle @mentions
|
|
172
|
+
this.app.event('app_mention', async ({ event }) => {
|
|
173
|
+
if (!isUserAllowed(event.user, config)) {
|
|
174
|
+
this.logger.info('Unauthorized user mention', { userId: event.user });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const incomingMessage = {
|
|
178
|
+
id: event.ts,
|
|
179
|
+
type: 'app_mention',
|
|
180
|
+
text: event.text,
|
|
181
|
+
userId: event.user,
|
|
182
|
+
channelId: event.channel,
|
|
183
|
+
threadTs: event.thread_ts,
|
|
184
|
+
ts: event.ts,
|
|
185
|
+
teamId: event.team || '',
|
|
186
|
+
eventTs: event.event_ts,
|
|
187
|
+
};
|
|
188
|
+
this.status.messagesReceived++;
|
|
189
|
+
this.status.lastEventAt = new Date().toISOString();
|
|
190
|
+
this.emit('message', incomingMessage);
|
|
191
|
+
});
|
|
192
|
+
// Handle content approval button clicks (Block Kit interactive actions)
|
|
193
|
+
this.app.action(/content_approval_(approve|reject)/, async ({ action, body, ack, respond }) => {
|
|
194
|
+
await ack();
|
|
195
|
+
const approvalId = action.value;
|
|
196
|
+
const actionType = action.action_id;
|
|
197
|
+
const slackUserName = body.user.name || body.user.username || body.user.id;
|
|
198
|
+
const channelId = body.channel?.id || body.container?.channel_id;
|
|
199
|
+
const messageTs = body.message?.ts || body.container?.message_ts;
|
|
200
|
+
if (!approvalId) {
|
|
201
|
+
await respond({ text: 'Error: Missing approval ID.', replace_original: false, response_type: 'ephemeral' });
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
const service = ContentApprovalService.getInstance();
|
|
206
|
+
const existing = service.get(approvalId);
|
|
207
|
+
if (!existing) {
|
|
208
|
+
await respond({ text: `Approval \`${approvalId.slice(0, 8)}\` not found.`, replace_original: false, response_type: 'ephemeral' });
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (existing.status !== 'pending') {
|
|
212
|
+
await respond({
|
|
213
|
+
text: `This approval has already been ${existing.status} by ${existing.resolvedBy ?? 'someone'}.`,
|
|
214
|
+
replace_original: false,
|
|
215
|
+
response_type: 'ephemeral',
|
|
216
|
+
});
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const isApprove = actionType === 'content_approval_approve';
|
|
220
|
+
const result = isApprove
|
|
221
|
+
? service.approve(approvalId, slackUserName)
|
|
222
|
+
: service.reject(approvalId, slackUserName);
|
|
223
|
+
if (!result) {
|
|
224
|
+
await respond({ text: 'Failed to resolve approval.', replace_original: false, response_type: 'ephemeral' });
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Update the original message to replace buttons with status
|
|
228
|
+
const statusEmoji = isApprove ? '\u2705' : '\u274c';
|
|
229
|
+
const statusText = isApprove ? 'Approved' : 'Rejected';
|
|
230
|
+
const updatedText = `${statusEmoji} ${statusText} by @${slackUserName}`;
|
|
231
|
+
if (channelId && messageTs) {
|
|
232
|
+
const updatedBlocks = [
|
|
233
|
+
{
|
|
234
|
+
type: 'section',
|
|
235
|
+
text: { type: 'mrkdwn', text: `~${existing.content.slice(0, 200)}~` },
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
type: 'context',
|
|
239
|
+
elements: [
|
|
240
|
+
{ type: 'mrkdwn', text: `${updatedText} \u2022 ${new Date().toLocaleString()}` },
|
|
241
|
+
],
|
|
242
|
+
},
|
|
243
|
+
];
|
|
244
|
+
await this.updateMessage(channelId, messageTs, updatedText, updatedBlocks);
|
|
245
|
+
}
|
|
246
|
+
this.emit('content_approval_resolved', {
|
|
247
|
+
approvalId,
|
|
248
|
+
action: isApprove ? 'approved' : 'rejected',
|
|
249
|
+
resolvedBy: slackUserName,
|
|
250
|
+
});
|
|
251
|
+
this.logger.info('Content approval resolved via Slack button', {
|
|
252
|
+
approvalId: approvalId.slice(0, 8),
|
|
253
|
+
action: statusText.toLowerCase(),
|
|
254
|
+
resolvedBy: slackUserName,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
this.logger.error('Content approval action handler error', {
|
|
259
|
+
approvalId: approvalId?.slice(0, 8),
|
|
260
|
+
error: err instanceof Error ? err.message : String(err),
|
|
261
|
+
});
|
|
262
|
+
await respond({
|
|
263
|
+
text: `Error processing approval: ${err instanceof Error ? err.message : 'Unknown error'}`,
|
|
264
|
+
replace_original: false,
|
|
265
|
+
response_type: 'ephemeral',
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
// Handle errors
|
|
270
|
+
this.app.error(async (error) => {
|
|
271
|
+
this.logger.error('Error', { error: error.message });
|
|
272
|
+
this.status.lastError = error.message;
|
|
273
|
+
this.status.lastErrorAt = new Date().toISOString();
|
|
274
|
+
this.emit('error', error);
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Attach listeners to the underlying SocketModeClient to track
|
|
279
|
+
* connection lifecycle (disconnected, reconnecting, connected).
|
|
280
|
+
* Updates `status.connected` so health checks reflect actual state.
|
|
281
|
+
*
|
|
282
|
+
* The Bolt App stores the receiver at `app.receiver`, and the
|
|
283
|
+
* SocketModeReceiver exposes `client` (SocketModeClient), which
|
|
284
|
+
* is an EventEmitter emitting: connected, reconnecting, disconnected, close.
|
|
285
|
+
*/
|
|
286
|
+
setupConnectionMonitoring() {
|
|
287
|
+
// Access the SocketModeClient from Bolt's internal receiver.
|
|
288
|
+
// This relies on Bolt's internal structure, so we guard with try/catch.
|
|
289
|
+
try {
|
|
290
|
+
const receiver = this.app?.receiver;
|
|
291
|
+
const socketClient = receiver?.client;
|
|
292
|
+
if (!socketClient) {
|
|
293
|
+
this.logger.warn('Could not access SocketModeClient for connection monitoring');
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
// Issue #548 — `@slack/socket-mode`'s finity state machine throws
|
|
297
|
+
// `Unhandled event 'server explicit disconnect' in state 'connecting'`
|
|
298
|
+
// when Slack sends a disconnect signal during the reconnect
|
|
299
|
+
// handshake window. The throw is SYNCHRONOUS inside the WebSocket
|
|
300
|
+
// message callback (WebSocket.onMessage → SocketModeClient.
|
|
301
|
+
// onWebSocketMessage → finity.handle → throw) so it surfaces as
|
|
302
|
+
// an uncaughtException that takes the process down on v1 hosts
|
|
303
|
+
// (no pm2/systemd to restart). CrewlyNode1 went dark for ~21
|
|
304
|
+
// hours on 2026-05-14 from exactly this.
|
|
305
|
+
//
|
|
306
|
+
// Wrap `onWebSocketMessage` with a synchronous try/catch that
|
|
307
|
+
// swallows the unhandled-event throw, logs it as a recoverable
|
|
308
|
+
// event, and triggers the reconnect path. Other throws still
|
|
309
|
+
// surface normally — we only suppress the specific finity
|
|
310
|
+
// "Unhandled event" signature.
|
|
311
|
+
const wrappedClient = socketClient;
|
|
312
|
+
const originalOnMessage = wrappedClient.onWebSocketMessage;
|
|
313
|
+
if (typeof originalOnMessage === 'function') {
|
|
314
|
+
wrappedClient.onWebSocketMessage = (...args) => {
|
|
315
|
+
try {
|
|
316
|
+
return originalOnMessage.apply(socketClient, args);
|
|
317
|
+
}
|
|
318
|
+
catch (err) {
|
|
319
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
320
|
+
if (/Unhandled event/.test(msg)) {
|
|
321
|
+
this.logger.warn('Suppressed finity unhandled-event from SocketModeClient (issue #548) — triggering reconnect', {
|
|
322
|
+
error: msg,
|
|
323
|
+
});
|
|
324
|
+
this.status.connected = false;
|
|
325
|
+
this.status.lastError = `SocketMode finity throw: ${msg}`;
|
|
326
|
+
this.status.lastErrorAt = new Date().toISOString();
|
|
327
|
+
this.scheduleReconnect();
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
throw err;
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
this.logger.info('SocketModeClient.onWebSocketMessage wrapped for #548 finity-throw recovery');
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
this.logger.warn('SocketModeClient.onWebSocketMessage not found — #548 finity-throw guard NOT installed');
|
|
337
|
+
}
|
|
338
|
+
socketClient.on('disconnected', () => {
|
|
339
|
+
this.status.connected = false;
|
|
340
|
+
this.status.lastError = 'Socket Mode connection lost';
|
|
341
|
+
this.status.lastErrorAt = new Date().toISOString();
|
|
342
|
+
this.logger.warn('Socket Mode disconnected');
|
|
343
|
+
this.emit('disconnected');
|
|
344
|
+
this.scheduleReconnect();
|
|
345
|
+
});
|
|
346
|
+
socketClient.on('reconnecting', () => {
|
|
347
|
+
this.status.connected = false;
|
|
348
|
+
this.logger.info('Socket Mode reconnecting (Bolt built-in)...');
|
|
349
|
+
});
|
|
350
|
+
socketClient.on('connected', () => {
|
|
351
|
+
this.status.connected = true;
|
|
352
|
+
this.reconnectAttempts = 0;
|
|
353
|
+
this.consecutivePingFailures = 0;
|
|
354
|
+
this.lastPingAt = Date.now();
|
|
355
|
+
this.cancelReconnectGrace();
|
|
356
|
+
this.logger.info('Socket Mode reconnected');
|
|
357
|
+
this.emit('connected');
|
|
358
|
+
});
|
|
359
|
+
socketClient.on('close', () => {
|
|
360
|
+
// 'close' fires on WebSocket close before reconnection kicks in
|
|
361
|
+
if (this.status.connected) {
|
|
362
|
+
this.status.connected = false;
|
|
363
|
+
this.logger.warn('Socket Mode WebSocket closed, awaiting reconnect...');
|
|
364
|
+
this.scheduleReconnect();
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
catch (err) {
|
|
369
|
+
this.logger.warn('Failed to set up connection monitoring', {
|
|
370
|
+
error: err instanceof Error ? err.message : String(err),
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
// Start periodic health check
|
|
374
|
+
this.startHealthCheck();
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Start a periodic health check that verifies the Socket Mode connection
|
|
378
|
+
* is alive and triggers reconnection if it has silently died.
|
|
379
|
+
*
|
|
380
|
+
* Uses an active Slack API ping (auth.test) to detect half-open sockets
|
|
381
|
+
* that appear connected but are actually dead after WiFi/network drops.
|
|
382
|
+
*/
|
|
383
|
+
startHealthCheck() {
|
|
384
|
+
this.stopHealthCheck();
|
|
385
|
+
this.lastPingAt = Date.now();
|
|
386
|
+
this.consecutivePingFailures = 0;
|
|
387
|
+
this.healthCheckTimer = setInterval(async () => {
|
|
388
|
+
if (this.intentionalDisconnect)
|
|
389
|
+
return;
|
|
390
|
+
// Case 1: Already known to be disconnected — trigger reconnect
|
|
391
|
+
if (!this.status.connected && !this.reconnecting) {
|
|
392
|
+
this.logger.warn('Health check: Socket Mode not connected and no reconnect in progress — triggering reconnect');
|
|
393
|
+
this.attemptReconnect();
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
// Case 2: Status says connected — verify with an active API ping
|
|
397
|
+
if (this.status.connected && this.client && !this.reconnecting) {
|
|
398
|
+
try {
|
|
399
|
+
const pingPromise = this.client.auth.test();
|
|
400
|
+
const timeoutMs = SLACK_RECONNECT_CONSTANTS.PING_TIMEOUT_MS;
|
|
401
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
402
|
+
const timer = setTimeout(() => reject(new Error('Ping timeout')), timeoutMs);
|
|
403
|
+
// Clear timer if ping resolves first to prevent leak
|
|
404
|
+
pingPromise.then(() => clearTimeout(timer), () => clearTimeout(timer));
|
|
405
|
+
});
|
|
406
|
+
await Promise.race([pingPromise, timeoutPromise]);
|
|
407
|
+
// Ping succeeded — connection is truly alive
|
|
408
|
+
this.lastPingAt = Date.now();
|
|
409
|
+
this.consecutivePingFailures = 0;
|
|
410
|
+
}
|
|
411
|
+
catch (err) {
|
|
412
|
+
this.consecutivePingFailures++;
|
|
413
|
+
this.logger.warn('Health check ping failed', {
|
|
414
|
+
consecutiveFailures: this.consecutivePingFailures,
|
|
415
|
+
error: err instanceof Error ? err.message : String(err),
|
|
416
|
+
});
|
|
417
|
+
// After consecutive failures, declare connection dead and reconnect
|
|
418
|
+
if (this.consecutivePingFailures >= SLACK_RECONNECT_CONSTANTS.PING_FAILURES_BEFORE_RECONNECT) {
|
|
419
|
+
this.logger.warn('Health check: connection appears dead after consecutive ping failures — forcing reconnect', {
|
|
420
|
+
consecutiveFailures: this.consecutivePingFailures,
|
|
421
|
+
lastPingAt: new Date(this.lastPingAt).toISOString(),
|
|
422
|
+
});
|
|
423
|
+
this.status.connected = false;
|
|
424
|
+
this.consecutivePingFailures = 0;
|
|
425
|
+
this.attemptReconnect();
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}, SLACK_RECONNECT_CONSTANTS.HEALTH_CHECK_INTERVAL_MS);
|
|
430
|
+
// Allow Node to exit even if health check timer is still active
|
|
431
|
+
if (this.healthCheckTimer && typeof this.healthCheckTimer === 'object' && 'unref' in this.healthCheckTimer) {
|
|
432
|
+
this.healthCheckTimer.unref();
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Stop the periodic health check timer.
|
|
437
|
+
*/
|
|
438
|
+
stopHealthCheck() {
|
|
439
|
+
if (this.healthCheckTimer) {
|
|
440
|
+
clearInterval(this.healthCheckTimer);
|
|
441
|
+
this.healthCheckTimer = null;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Schedule a reconnection attempt after a grace period.
|
|
446
|
+
* The grace period gives Bolt's built-in reconnect a chance to recover first.
|
|
447
|
+
* If the connection comes back within the grace period, the reconnect is cancelled.
|
|
448
|
+
*/
|
|
449
|
+
scheduleReconnect() {
|
|
450
|
+
if (this.intentionalDisconnect || this.reconnecting || this.reconnectGraceTimer)
|
|
451
|
+
return;
|
|
452
|
+
this.logger.info('Scheduling reconnect after grace period', {
|
|
453
|
+
gracePeriodMs: SLACK_RECONNECT_CONSTANTS.GRACE_PERIOD_MS,
|
|
454
|
+
});
|
|
455
|
+
this.reconnectGraceTimer = setTimeout(() => {
|
|
456
|
+
this.reconnectGraceTimer = null;
|
|
457
|
+
if (!this.status.connected && !this.intentionalDisconnect) {
|
|
458
|
+
this.logger.warn('Grace period expired, Bolt reconnect did not recover — starting manual reconnect');
|
|
459
|
+
this.attemptReconnect();
|
|
460
|
+
}
|
|
461
|
+
}, SLACK_RECONNECT_CONSTANTS.GRACE_PERIOD_MS);
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Cancel the reconnection grace period timer.
|
|
465
|
+
*/
|
|
466
|
+
cancelReconnectGrace() {
|
|
467
|
+
if (this.reconnectGraceTimer) {
|
|
468
|
+
clearTimeout(this.reconnectGraceTimer);
|
|
469
|
+
this.reconnectGraceTimer = null;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Attempt to reconnect by tearing down the current Bolt app and
|
|
474
|
+
* re-initializing from scratch with the saved config.
|
|
475
|
+
* Uses exponential backoff between attempts.
|
|
476
|
+
*/
|
|
477
|
+
async attemptReconnect() {
|
|
478
|
+
if (this.reconnecting || this.intentionalDisconnect || !this.config)
|
|
479
|
+
return;
|
|
480
|
+
const maxAttempts = SLACK_RECONNECT_CONSTANTS.MAX_ATTEMPTS;
|
|
481
|
+
if (maxAttempts > 0 && this.reconnectAttempts >= maxAttempts) {
|
|
482
|
+
this.logger.error('Max reconnection attempts reached, giving up', {
|
|
483
|
+
attempts: this.reconnectAttempts,
|
|
484
|
+
maxAttempts,
|
|
485
|
+
});
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
this.reconnecting = true;
|
|
489
|
+
this.reconnectAttempts++;
|
|
490
|
+
const delay = Math.min(SLACK_RECONNECT_CONSTANTS.INITIAL_DELAY_MS * Math.pow(SLACK_RECONNECT_CONSTANTS.BACKOFF_MULTIPLIER, this.reconnectAttempts - 1), SLACK_RECONNECT_CONSTANTS.MAX_DELAY_MS);
|
|
491
|
+
this.logger.info('Reconnecting to Slack Socket Mode', {
|
|
492
|
+
attempt: this.reconnectAttempts,
|
|
493
|
+
delayMs: delay,
|
|
494
|
+
});
|
|
495
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
496
|
+
// Bail out if we reconnected or intentionally disconnected while waiting
|
|
497
|
+
if (this.status.connected || this.intentionalDisconnect) {
|
|
498
|
+
this.reconnecting = false;
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
try {
|
|
502
|
+
// Guard: cached App constructor must be available from initialize()
|
|
503
|
+
if (!this.cachedAppConstructor) {
|
|
504
|
+
throw new Error('App constructor not cached — initialize() must be called before reconnect');
|
|
505
|
+
}
|
|
506
|
+
// Tear down existing app
|
|
507
|
+
if (this.app) {
|
|
508
|
+
try {
|
|
509
|
+
await this.app.stop();
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
// Ignore teardown errors
|
|
513
|
+
}
|
|
514
|
+
this.app = null;
|
|
515
|
+
this.client = null;
|
|
516
|
+
}
|
|
517
|
+
// Re-initialize using cached constructor (avoids stale dynamic import issues)
|
|
518
|
+
const App = this.cachedAppConstructor;
|
|
519
|
+
const LogLevel = this.cachedLogLevelEnum;
|
|
520
|
+
this.app = new App({
|
|
521
|
+
token: this.config.botToken,
|
|
522
|
+
appToken: this.config.appToken,
|
|
523
|
+
signingSecret: this.config.signingSecret,
|
|
524
|
+
socketMode: this.config.socketMode,
|
|
525
|
+
logLevel: LogLevel?.INFO ?? 'info',
|
|
526
|
+
});
|
|
527
|
+
this.client = this.app.client;
|
|
528
|
+
this.setupEventHandlers();
|
|
529
|
+
await this.app.start();
|
|
530
|
+
this.status.connected = true;
|
|
531
|
+
this.status.socketMode = true;
|
|
532
|
+
this.reconnectAttempts = 0;
|
|
533
|
+
this.reconnecting = false;
|
|
534
|
+
this.consecutivePingFailures = 0;
|
|
535
|
+
this.lastPingAt = Date.now();
|
|
536
|
+
this.setupConnectionMonitoring();
|
|
537
|
+
this.emit('connected');
|
|
538
|
+
this.logger.info('Successfully reconnected to Slack Socket Mode');
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
this.reconnecting = false;
|
|
542
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
543
|
+
this.status.lastError = `Reconnect failed: ${errorMessage}`;
|
|
544
|
+
this.status.lastErrorAt = new Date().toISOString();
|
|
545
|
+
// Classify error: fatal errors stop the loop, transient errors retry
|
|
546
|
+
if (this.isFatalReconnectError(error)) {
|
|
547
|
+
this.logger.error('Fatal reconnection error — stopping retry loop', {
|
|
548
|
+
attempt: this.reconnectAttempts,
|
|
549
|
+
error: errorMessage,
|
|
550
|
+
});
|
|
551
|
+
this.emit('error', error instanceof Error ? error : new Error(errorMessage));
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
this.logger.error('Transient reconnection error — will retry', {
|
|
555
|
+
attempt: this.reconnectAttempts,
|
|
556
|
+
error: errorMessage,
|
|
557
|
+
});
|
|
558
|
+
// Schedule next attempt — the health check will also retry if this doesn't fire
|
|
559
|
+
if (!this.intentionalDisconnect) {
|
|
560
|
+
this.scheduleReconnect();
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Classify whether a reconnection error is fatal (non-recoverable)
|
|
566
|
+
* or transient (may succeed on retry).
|
|
567
|
+
*
|
|
568
|
+
* Fatal errors: missing constructor, invalid config, auth errors.
|
|
569
|
+
* Transient errors: network timeouts, temporary server errors.
|
|
570
|
+
*
|
|
571
|
+
* @param error - The error caught during reconnection
|
|
572
|
+
* @returns True if the error is fatal and retrying would be futile
|
|
573
|
+
*/
|
|
574
|
+
isFatalReconnectError(error) {
|
|
575
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
576
|
+
const lowerMessage = message.toLowerCase();
|
|
577
|
+
/** Patterns that indicate a non-recoverable configuration or code error */
|
|
578
|
+
const fatalPatterns = [
|
|
579
|
+
'not a constructor',
|
|
580
|
+
'is not a function',
|
|
581
|
+
'constructor not cached',
|
|
582
|
+
'invalid_auth',
|
|
583
|
+
'token_revoked',
|
|
584
|
+
'account_inactive',
|
|
585
|
+
'missing required',
|
|
586
|
+
'config',
|
|
587
|
+
];
|
|
588
|
+
return fatalPatterns.some(pattern => lowerMessage.includes(pattern));
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Send a message to Slack with content-based deduplication.
|
|
592
|
+
*
|
|
593
|
+
* Generates a fingerprint from (channelId, threadTs, text) and suppresses
|
|
594
|
+
* duplicate sends within a configurable time window (default 30s).
|
|
595
|
+
* This is the single chokepoint for all Slack message sends — skill delivery,
|
|
596
|
+
* bridge fallback, and direct API calls all converge here.
|
|
597
|
+
*
|
|
598
|
+
* @param message - Message to send
|
|
599
|
+
* @returns Promise with message timestamp (empty string if deduplicated)
|
|
600
|
+
*/
|
|
601
|
+
async sendMessage(message) {
|
|
602
|
+
if (!this.client) {
|
|
603
|
+
throw new Error('Slack client not initialized');
|
|
604
|
+
}
|
|
605
|
+
// Content-based deduplication: suppress identical messages within time window
|
|
606
|
+
const fingerprint = this.buildMessageFingerprint(message);
|
|
607
|
+
const now = Date.now();
|
|
608
|
+
const lastSentAt = this.recentMessageFingerprints.get(fingerprint);
|
|
609
|
+
if (lastSentAt !== undefined && (now - lastSentAt) < SLACK_DEDUP_CONSTANTS.DEDUP_WINDOW_MS) {
|
|
610
|
+
this.logger.info('Slack message deduplicated — identical message sent recently', {
|
|
611
|
+
channelId: message.channelId,
|
|
612
|
+
threadTs: message.threadTs,
|
|
613
|
+
ageMs: now - lastSentAt,
|
|
614
|
+
});
|
|
615
|
+
return '';
|
|
616
|
+
}
|
|
617
|
+
try {
|
|
618
|
+
const result = await this.client.chat.postMessage({
|
|
619
|
+
channel: message.channelId,
|
|
620
|
+
text: message.text,
|
|
621
|
+
thread_ts: message.threadTs,
|
|
622
|
+
blocks: message.blocks,
|
|
623
|
+
attachments: message.attachments,
|
|
624
|
+
unfurl_links: message.unfurlLinks,
|
|
625
|
+
unfurl_media: message.unfurlMedia,
|
|
626
|
+
// Per-agent identity for team channels. A real agent bot token wins
|
|
627
|
+
// (the message is posted by that bot user); otherwise the cosmetic
|
|
628
|
+
// username/icon override. Only sent when set so the orchestrator's
|
|
629
|
+
// plain posts keep the app's default bot identity.
|
|
630
|
+
...(message.botToken
|
|
631
|
+
? { token: message.botToken }
|
|
632
|
+
: {
|
|
633
|
+
...(message.username ? { username: message.username } : {}),
|
|
634
|
+
...(message.iconEmoji
|
|
635
|
+
? { icon_emoji: message.iconEmoji }
|
|
636
|
+
: message.iconUrl
|
|
637
|
+
? { icon_url: message.iconUrl }
|
|
638
|
+
: {}),
|
|
639
|
+
}),
|
|
640
|
+
});
|
|
641
|
+
this.status.messagesSent++;
|
|
642
|
+
// Track this fingerprint for future dedup
|
|
643
|
+
this.trackMessageFingerprint(fingerprint, now);
|
|
644
|
+
// Mirror the outbound reply into chat-v2 so the Slack thread shows both
|
|
645
|
+
// sides ("收和发") in the consolidated chat. Best-effort, thread-only.
|
|
646
|
+
if (message.threadTs && !message.skipChatV2Mirror) {
|
|
647
|
+
void this.recordOutboundToChatV2(message);
|
|
648
|
+
}
|
|
649
|
+
return result.ts || '';
|
|
650
|
+
}
|
|
651
|
+
catch (error) {
|
|
652
|
+
this.logger.error('Send message error', { error: error instanceof Error ? error.message : String(error) });
|
|
653
|
+
// F14: record slack.delivery.failed event (best-effort — never
|
|
654
|
+
// changes retry semantics or throws). The wrapper swallows
|
|
655
|
+
// construction errors and `record()` itself swallows DB errors.
|
|
656
|
+
try {
|
|
657
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
658
|
+
getAgentBehaviorLogService()?.record({
|
|
659
|
+
type: 'slack.delivery.failed',
|
|
660
|
+
agent: '',
|
|
661
|
+
thread: `${message.channelId}:${message.threadTs ?? ''}`,
|
|
662
|
+
reason: 'api_error',
|
|
663
|
+
details: {
|
|
664
|
+
errorMessage: errMessage,
|
|
665
|
+
textLength: (message.text ?? '').length,
|
|
666
|
+
hasBlocks: Array.isArray(message.blocks) && message.blocks.length > 0,
|
|
667
|
+
},
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
catch {
|
|
671
|
+
/* observability is best-effort — never block the original throw */
|
|
672
|
+
}
|
|
673
|
+
throw error;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Mirror an outbound Slack reply into the canonical chat-v2 store so the
|
|
678
|
+
* Slack thread shows both inbound (user) and outbound (agent) messages in
|
|
679
|
+
* the consolidated /team-chat surface. Records against the SAME channel the
|
|
680
|
+
* inbound persisted to — `synthesizeSlackConversationId(channelId, threadTs)`.
|
|
681
|
+
*
|
|
682
|
+
* Best-effort: dynamic imports + try/catch so a chat-v2 failure never
|
|
683
|
+
* affects Slack delivery. Only called for threaded replies (threadTs set).
|
|
684
|
+
*
|
|
685
|
+
* @param message - The outbound Slack message that was just sent.
|
|
686
|
+
*/
|
|
687
|
+
async recordOutboundToChatV2(message) {
|
|
688
|
+
try {
|
|
689
|
+
if (!message.channelId || !message.threadTs || !(message.text ?? '').trim())
|
|
690
|
+
return;
|
|
691
|
+
const [{ getChatV2Service }, { synthesizeSlackConversationId, slackOutboundClientMessageId }] = await Promise.all([
|
|
692
|
+
import('../chat-v2/chat-v2.singleton.js'),
|
|
693
|
+
import('../chat-v2/legacy-dto.utils.js'),
|
|
694
|
+
]);
|
|
695
|
+
const chatV2 = getChatV2Service();
|
|
696
|
+
const conversationId = synthesizeSlackConversationId(message.channelId, message.threadTs);
|
|
697
|
+
const channel = chatV2.ensureChannelForLegacyConversation({
|
|
698
|
+
conversationId,
|
|
699
|
+
agentSession: ORCHESTRATOR_SESSION_NAME,
|
|
700
|
+
});
|
|
701
|
+
chatV2.recordTurn({
|
|
702
|
+
channelId: channel.id,
|
|
703
|
+
senderType: 'agent',
|
|
704
|
+
senderId: channel.agentSession || ORCHESTRATOR_SESSION_NAME,
|
|
705
|
+
content: message.text,
|
|
706
|
+
// Shared idempotency key with the /slack/send bookkeeping path so the
|
|
707
|
+
// same reply isn't persisted twice (duplicate bubbles in the merged
|
|
708
|
+
// Orchestrator timeline).
|
|
709
|
+
clientMessageId: slackOutboundClientMessageId(message.channelId, message.threadTs, message.text),
|
|
710
|
+
metadata: {
|
|
711
|
+
source: 'slack',
|
|
712
|
+
slackChannelId: message.channelId,
|
|
713
|
+
slackThreadTs: message.threadTs,
|
|
714
|
+
},
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
catch (err) {
|
|
718
|
+
this.logger.warn('Failed to mirror outbound Slack message to chat-v2', {
|
|
719
|
+
error: err instanceof Error ? err.message : String(err),
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Build a deduplication fingerprint for a Slack message.
|
|
725
|
+
* Combines channelId, threadTs, and a simple hash of the message text.
|
|
726
|
+
*
|
|
727
|
+
* @param message - Outgoing Slack message
|
|
728
|
+
* @returns Fingerprint string
|
|
729
|
+
*/
|
|
730
|
+
buildMessageFingerprint(message) {
|
|
731
|
+
// Simple string hash (djb2) — fast and sufficient for dedup
|
|
732
|
+
let hash = 5381;
|
|
733
|
+
const text = message.text || '';
|
|
734
|
+
for (let i = 0; i < text.length; i++) {
|
|
735
|
+
hash = ((hash << 5) + hash + text.charCodeAt(i)) | 0;
|
|
736
|
+
}
|
|
737
|
+
// Two agents saying the same thing in the same thread are two messages,
|
|
738
|
+
// so the sender identity is part of the key.
|
|
739
|
+
const sender = message.botToken ? `bot:${message.botToken.slice(-8)}` : message.username || '';
|
|
740
|
+
return `${message.channelId}:${message.threadTs || ''}:${sender}:${hash}`;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Track a message fingerprint and evict stale entries.
|
|
744
|
+
*
|
|
745
|
+
* @param fingerprint - Message fingerprint to track
|
|
746
|
+
* @param timestamp - Current timestamp in ms
|
|
747
|
+
*/
|
|
748
|
+
trackMessageFingerprint(fingerprint, timestamp) {
|
|
749
|
+
this.recentMessageFingerprints.set(fingerprint, timestamp);
|
|
750
|
+
// Evict expired entries and enforce size limit
|
|
751
|
+
if (this.recentMessageFingerprints.size > SLACK_DEDUP_CONSTANTS.MAX_TRACKED_MESSAGES) {
|
|
752
|
+
const windowMs = SLACK_DEDUP_CONSTANTS.DEDUP_WINDOW_MS;
|
|
753
|
+
for (const [key, ts] of this.recentMessageFingerprints) {
|
|
754
|
+
if (timestamp - ts > windowMs) {
|
|
755
|
+
this.recentMessageFingerprints.delete(key);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
// If still over limit after expiry cleanup, drop oldest
|
|
759
|
+
if (this.recentMessageFingerprints.size > SLACK_DEDUP_CONSTANTS.MAX_TRACKED_MESSAGES) {
|
|
760
|
+
const firstKey = this.recentMessageFingerprints.keys().next().value;
|
|
761
|
+
if (firstKey !== undefined) {
|
|
762
|
+
this.recentMessageFingerprints.delete(firstKey);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Send a notification to the default channel
|
|
769
|
+
*
|
|
770
|
+
* @param notification - Notification to send
|
|
771
|
+
*/
|
|
772
|
+
async sendNotification(notification) {
|
|
773
|
+
const targetChannelId = notification.channelId || this.config?.defaultChannelId;
|
|
774
|
+
if (!targetChannelId) {
|
|
775
|
+
this.logger.warn('No channel configured for notification');
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
const blocks = this.formatNotificationBlocks(notification);
|
|
779
|
+
await this.sendMessage({
|
|
780
|
+
channelId: targetChannelId,
|
|
781
|
+
text: `${notification.title}: ${notification.message}`,
|
|
782
|
+
blocks,
|
|
783
|
+
threadTs: notification.threadTs,
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Format notification as Slack blocks
|
|
788
|
+
*
|
|
789
|
+
* @param notification - Notification to format
|
|
790
|
+
* @returns Slack blocks for the notification
|
|
791
|
+
*/
|
|
792
|
+
formatNotificationBlocks(notification) {
|
|
793
|
+
const urgencyEmoji = {
|
|
794
|
+
low: ':white_circle:',
|
|
795
|
+
normal: ':large_blue_circle:',
|
|
796
|
+
high: ':large_orange_circle:',
|
|
797
|
+
critical: ':red_circle:',
|
|
798
|
+
};
|
|
799
|
+
const blocks = [
|
|
800
|
+
{
|
|
801
|
+
type: 'header',
|
|
802
|
+
text: {
|
|
803
|
+
type: 'plain_text',
|
|
804
|
+
text: `${urgencyEmoji[notification.urgency]} ${notification.title}`,
|
|
805
|
+
emoji: true,
|
|
806
|
+
},
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
type: 'section',
|
|
810
|
+
text: {
|
|
811
|
+
type: 'mrkdwn',
|
|
812
|
+
text: notification.message,
|
|
813
|
+
},
|
|
814
|
+
},
|
|
815
|
+
];
|
|
816
|
+
// Context block elements are text objects where `text` is a plain string.
|
|
817
|
+
// Using type assertion because SlackElement.text is typed as SlackTextObject
|
|
818
|
+
// but Slack API context elements use text objects directly as elements.
|
|
819
|
+
blocks.push({
|
|
820
|
+
type: 'context',
|
|
821
|
+
elements: [
|
|
822
|
+
{
|
|
823
|
+
type: 'mrkdwn',
|
|
824
|
+
text: `Sent at ${new Date(notification.timestamp).toLocaleString()}`,
|
|
825
|
+
},
|
|
826
|
+
],
|
|
827
|
+
});
|
|
828
|
+
return blocks;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Update a message
|
|
832
|
+
*
|
|
833
|
+
* @param channelId - Channel ID
|
|
834
|
+
* @param messageTs - Message timestamp
|
|
835
|
+
* @param text - New text
|
|
836
|
+
* @param blocks - Optional new blocks
|
|
837
|
+
*/
|
|
838
|
+
async updateMessage(channelId, messageTs, text, blocks) {
|
|
839
|
+
if (!this.client) {
|
|
840
|
+
throw new Error('Slack client not initialized');
|
|
841
|
+
}
|
|
842
|
+
await this.client.chat.update({
|
|
843
|
+
channel: channelId,
|
|
844
|
+
ts: messageTs,
|
|
845
|
+
text,
|
|
846
|
+
blocks,
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Add a reaction to a message
|
|
851
|
+
*
|
|
852
|
+
* @param channelId - Channel ID
|
|
853
|
+
* @param messageTs - Message timestamp
|
|
854
|
+
* @param emoji - Emoji name (without colons)
|
|
855
|
+
*/
|
|
856
|
+
async addReaction(channelId, messageTs, emoji) {
|
|
857
|
+
if (!this.client) {
|
|
858
|
+
throw new Error('Slack client not initialized');
|
|
859
|
+
}
|
|
860
|
+
await this.client.reactions.add({
|
|
861
|
+
channel: channelId,
|
|
862
|
+
timestamp: messageTs,
|
|
863
|
+
name: emoji,
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Get or create conversation context for a thread
|
|
868
|
+
*
|
|
869
|
+
* @param threadTs - Thread timestamp
|
|
870
|
+
* @param channelId - Channel ID
|
|
871
|
+
* @param userId - User ID
|
|
872
|
+
* @returns Conversation context
|
|
873
|
+
*/
|
|
874
|
+
getConversationContext(threadTs, channelId, userId) {
|
|
875
|
+
const key = `${channelId}:${threadTs}`;
|
|
876
|
+
// NOTE: This is intentionally NOT `synthesizeSlackConversationId`
|
|
877
|
+
// (chat-v2/legacy-dto.utils.ts). That helper produces the chat-v2
|
|
878
|
+
// channel id by replacing the single dot in the Slack ts. The id
|
|
879
|
+
// built here is for an in-memory `SlackConversationContext` map keyed
|
|
880
|
+
// by a broader sanitized form (any non-alphanumeric → `-`) and may
|
|
881
|
+
// diverge from the chat-v2 channel id by design. Do not "unify" —
|
|
882
|
+
// see the 2026-05-15 review of PR #547 for the discussion.
|
|
883
|
+
const conversationId = `slack-${channelId}-${threadTs}`.replace(/[^A-Za-z0-9_-]/g, '-');
|
|
884
|
+
let context = this.conversationContexts.get(key);
|
|
885
|
+
if (!context) {
|
|
886
|
+
context = {
|
|
887
|
+
threadTs,
|
|
888
|
+
channelId,
|
|
889
|
+
userId,
|
|
890
|
+
conversationId,
|
|
891
|
+
startedAt: new Date().toISOString(),
|
|
892
|
+
lastActivityAt: new Date().toISOString(),
|
|
893
|
+
messageCount: 0,
|
|
894
|
+
};
|
|
895
|
+
this.conversationContexts.set(key, context);
|
|
896
|
+
}
|
|
897
|
+
else if (context.conversationId !== conversationId) {
|
|
898
|
+
context.conversationId = conversationId;
|
|
899
|
+
}
|
|
900
|
+
context.lastActivityAt = new Date().toISOString();
|
|
901
|
+
context.messageCount++;
|
|
902
|
+
return context;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Get service status
|
|
906
|
+
*
|
|
907
|
+
* @returns Current service status
|
|
908
|
+
*/
|
|
909
|
+
getStatus() {
|
|
910
|
+
return { ...this.status };
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Check if service is connected
|
|
914
|
+
*
|
|
915
|
+
* @returns True if connected
|
|
916
|
+
*/
|
|
917
|
+
isConnected() {
|
|
918
|
+
return this.status.connected;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Get the bot token used to initialize the Slack client.
|
|
922
|
+
* Required for downloading private files from Slack.
|
|
923
|
+
*
|
|
924
|
+
* @returns The bot token string, or null if not initialized
|
|
925
|
+
*/
|
|
926
|
+
getBotToken() {
|
|
927
|
+
return this.config?.botToken || null;
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Resolve the bot user's Slack id (`U…`) via `auth.test`, cached after the
|
|
931
|
+
* first call. Team-channel routing uses it to ignore `<@bot>` mentions in
|
|
932
|
+
* inbound text and to invite the bot into linked channels.
|
|
933
|
+
*
|
|
934
|
+
* @returns The bot user id, or null when not connected or the API omits it
|
|
935
|
+
*/
|
|
936
|
+
async getBotUserId() {
|
|
937
|
+
if (this.cachedBotUserId)
|
|
938
|
+
return this.cachedBotUserId;
|
|
939
|
+
if (!this.client)
|
|
940
|
+
return null;
|
|
941
|
+
try {
|
|
942
|
+
const res = await this.client.auth.test();
|
|
943
|
+
const id = res?.user_id ?? null;
|
|
944
|
+
if (id)
|
|
945
|
+
this.cachedBotUserId = id;
|
|
946
|
+
return id;
|
|
947
|
+
}
|
|
948
|
+
catch (error) {
|
|
949
|
+
this.logger.warn('auth.test failed while resolving bot user id', {
|
|
950
|
+
error: error instanceof Error ? error.message : String(error),
|
|
951
|
+
});
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Create a public Slack channel. When Slack reports `name_taken`, the
|
|
957
|
+
* existing channel of that name is looked up and returned instead, so a
|
|
958
|
+
* team whose channel already exists (e.g. after a re-install) links to
|
|
959
|
+
* it rather than failing.
|
|
960
|
+
*
|
|
961
|
+
* Requires the `channels:manage` scope (and `channels:read` for the
|
|
962
|
+
* name-taken fallback).
|
|
963
|
+
*
|
|
964
|
+
* @param name - Channel name without `#`, already sanitised by the caller
|
|
965
|
+
* @returns The created (or pre-existing) channel
|
|
966
|
+
* @throws Error when the client is not initialised or Slack refuses
|
|
967
|
+
*/
|
|
968
|
+
async createChannel(name) {
|
|
969
|
+
const conversations = this.requireConversationsApi();
|
|
970
|
+
try {
|
|
971
|
+
const res = await conversations.create({ name, is_private: false });
|
|
972
|
+
const channel = SlackService.toChannelInfo(res.channel);
|
|
973
|
+
if (!channel)
|
|
974
|
+
throw new Error('conversations.create returned no channel');
|
|
975
|
+
return channel;
|
|
976
|
+
}
|
|
977
|
+
catch (error) {
|
|
978
|
+
if (SlackService.slackErrorCode(error) === 'name_taken') {
|
|
979
|
+
const existing = await this.findChannelByName(name);
|
|
980
|
+
if (existing) {
|
|
981
|
+
// The bot may not be in a channel it did not create; joining is
|
|
982
|
+
// idempotent and needed before it can post or read there.
|
|
983
|
+
await this.joinChannel(existing.id).catch(() => undefined);
|
|
984
|
+
return existing;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
throw error;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Find a public or private channel by exact name (case-insensitive),
|
|
992
|
+
* paging through `conversations.list`.
|
|
993
|
+
*
|
|
994
|
+
* @param name - Channel name without `#`
|
|
995
|
+
* @returns The channel, or null when no channel has that name
|
|
996
|
+
*/
|
|
997
|
+
async findChannelByName(name) {
|
|
998
|
+
const conversations = this.requireConversationsApi();
|
|
999
|
+
const wanted = name.toLowerCase();
|
|
1000
|
+
let cursor;
|
|
1001
|
+
// Bounded paging so a pathological workspace cannot spin forever.
|
|
1002
|
+
for (let page = 0; page < 20; page++) {
|
|
1003
|
+
const res = await conversations.list({
|
|
1004
|
+
types: 'public_channel,private_channel',
|
|
1005
|
+
limit: 200,
|
|
1006
|
+
cursor,
|
|
1007
|
+
exclude_archived: false,
|
|
1008
|
+
});
|
|
1009
|
+
for (const raw of res.channels ?? []) {
|
|
1010
|
+
if ((raw.name ?? '').toLowerCase() === wanted) {
|
|
1011
|
+
return SlackService.toChannelInfo(raw);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
cursor = res.response_metadata?.next_cursor || undefined;
|
|
1015
|
+
if (!cursor)
|
|
1016
|
+
break;
|
|
1017
|
+
}
|
|
1018
|
+
return null;
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Fetch a channel by id.
|
|
1022
|
+
*
|
|
1023
|
+
* @param channelId - Slack channel id
|
|
1024
|
+
* @returns The channel, or null when Slack reports `channel_not_found`
|
|
1025
|
+
*/
|
|
1026
|
+
async getChannelInfo(channelId) {
|
|
1027
|
+
const conversations = this.requireConversationsApi();
|
|
1028
|
+
try {
|
|
1029
|
+
const res = await conversations.info({ channel: channelId });
|
|
1030
|
+
return SlackService.toChannelInfo(res.channel);
|
|
1031
|
+
}
|
|
1032
|
+
catch (error) {
|
|
1033
|
+
if (SlackService.slackErrorCode(error) === 'channel_not_found')
|
|
1034
|
+
return null;
|
|
1035
|
+
throw error;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
/**
|
|
1039
|
+
* Join a public channel as the bot (idempotent). Requires `channels:join`.
|
|
1040
|
+
*
|
|
1041
|
+
* @param channelId - Slack channel id
|
|
1042
|
+
*/
|
|
1043
|
+
async joinChannel(channelId) {
|
|
1044
|
+
const conversations = this.requireConversationsApi();
|
|
1045
|
+
await conversations.join({ channel: channelId });
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Invite users (or other bots) into a channel the bot is a member of.
|
|
1049
|
+
*
|
|
1050
|
+
* @param channelId - Slack channel id
|
|
1051
|
+
* @param userIds - Slack user ids to invite
|
|
1052
|
+
*/
|
|
1053
|
+
async inviteToChannel(channelId, userIds) {
|
|
1054
|
+
if (userIds.length === 0)
|
|
1055
|
+
return;
|
|
1056
|
+
const conversations = this.requireConversationsApi();
|
|
1057
|
+
await conversations.invite({ channel: channelId, users: userIds.join(',') });
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Set a channel's purpose line. Requires `channels:manage`.
|
|
1061
|
+
*
|
|
1062
|
+
* @param channelId - Slack channel id
|
|
1063
|
+
* @param purpose - Purpose text (Slack caps it at 250 chars)
|
|
1064
|
+
*/
|
|
1065
|
+
async setChannelPurpose(channelId, purpose) {
|
|
1066
|
+
const conversations = this.requireConversationsApi();
|
|
1067
|
+
await conversations.setPurpose({
|
|
1068
|
+
channel: channelId,
|
|
1069
|
+
purpose: purpose.slice(0, SLACK_TEAM_CHANNEL_CONSTANTS.MAX_PURPOSE_LENGTH),
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Archive a channel. `already_archived` is treated as success so the
|
|
1074
|
+
* team-deleted path is idempotent.
|
|
1075
|
+
*
|
|
1076
|
+
* @param channelId - Slack channel id
|
|
1077
|
+
*/
|
|
1078
|
+
async archiveChannel(channelId) {
|
|
1079
|
+
const conversations = this.requireConversationsApi();
|
|
1080
|
+
try {
|
|
1081
|
+
await conversations.archive({ channel: channelId });
|
|
1082
|
+
}
|
|
1083
|
+
catch (error) {
|
|
1084
|
+
const code = SlackService.slackErrorCode(error);
|
|
1085
|
+
if (code === 'already_archived' || code === 'channel_not_found')
|
|
1086
|
+
return;
|
|
1087
|
+
throw error;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Open (or reuse) the DM channel with a person and return its id.
|
|
1092
|
+
*
|
|
1093
|
+
* Requires `im:write` on the token used. Pass `botToken` to open the DM as
|
|
1094
|
+
* an agent's own bot user — that is a different conversation from the one
|
|
1095
|
+
* the default Crewly bot has with the same person.
|
|
1096
|
+
*
|
|
1097
|
+
* @param userId - Slack user id of the person (`U…` / `W…`)
|
|
1098
|
+
* @param botToken - Optional per-call token override
|
|
1099
|
+
* @returns The DM channel id (`D…`)
|
|
1100
|
+
* @throws Error when the client is not initialised or Slack refuses
|
|
1101
|
+
*/
|
|
1102
|
+
async openDirectMessage(userId, botToken) {
|
|
1103
|
+
const conversations = this.requireConversationsApi();
|
|
1104
|
+
const res = await conversations.open({
|
|
1105
|
+
users: userId,
|
|
1106
|
+
...(botToken ? { token: botToken } : {}),
|
|
1107
|
+
});
|
|
1108
|
+
const id = res.channel?.id;
|
|
1109
|
+
if (!id)
|
|
1110
|
+
throw new Error(`conversations.open returned no channel for ${userId}`);
|
|
1111
|
+
return id;
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Resolve an `@handle` (or display / real name) to a Slack user id by
|
|
1115
|
+
* scanning the directory. Results are cached for the process lifetime —
|
|
1116
|
+
* handles change rarely and the listing is expensive.
|
|
1117
|
+
*
|
|
1118
|
+
* Bots and deactivated accounts are skipped so `@sam` never resolves to a
|
|
1119
|
+
* bot that happens to share the name.
|
|
1120
|
+
*
|
|
1121
|
+
* @param handle - Handle without `@`, case-insensitive
|
|
1122
|
+
* @returns The user id, or null when nobody matches
|
|
1123
|
+
* @throws Error when the client is not initialised or lacks `users:read`
|
|
1124
|
+
*/
|
|
1125
|
+
async findUserByHandle(handle) {
|
|
1126
|
+
const wanted = (handle ?? '').trim().replace(/^@/, '').toLowerCase();
|
|
1127
|
+
if (!wanted)
|
|
1128
|
+
return null;
|
|
1129
|
+
const cached = this.userHandleCache.get(wanted);
|
|
1130
|
+
if (cached)
|
|
1131
|
+
return cached;
|
|
1132
|
+
if (!this.client)
|
|
1133
|
+
throw new Error('Slack client not initialized');
|
|
1134
|
+
const list = this.client.users.list;
|
|
1135
|
+
if (!list)
|
|
1136
|
+
throw new Error('Slack client has no users.list API');
|
|
1137
|
+
let cursor;
|
|
1138
|
+
// Bounded paging: a very large workspace should fail loudly rather than
|
|
1139
|
+
// spin through the whole directory on every miss.
|
|
1140
|
+
for (let page = 0; page < 20; page++) {
|
|
1141
|
+
const res = await list({ limit: 200, cursor });
|
|
1142
|
+
for (const member of res.members ?? []) {
|
|
1143
|
+
if (!member.id || member.deleted || member.is_bot)
|
|
1144
|
+
continue;
|
|
1145
|
+
const names = [member.name, member.profile?.display_name, member.profile?.real_name, member.real_name]
|
|
1146
|
+
.filter((n) => !!n)
|
|
1147
|
+
.map((n) => n.toLowerCase());
|
|
1148
|
+
for (const n of names) {
|
|
1149
|
+
if (!this.userHandleCache.has(n))
|
|
1150
|
+
this.userHandleCache.set(n, member.id);
|
|
1151
|
+
}
|
|
1152
|
+
if (names.includes(wanted))
|
|
1153
|
+
return member.id;
|
|
1154
|
+
}
|
|
1155
|
+
cursor = res.response_metadata?.next_cursor || undefined;
|
|
1156
|
+
if (!cursor)
|
|
1157
|
+
break;
|
|
1158
|
+
}
|
|
1159
|
+
return null;
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* The conversations API of the live client, or throw when Slack is not
|
|
1163
|
+
* initialised. Centralised so every channel helper reports the same
|
|
1164
|
+
* error text.
|
|
1165
|
+
*/
|
|
1166
|
+
requireConversationsApi() {
|
|
1167
|
+
if (!this.client) {
|
|
1168
|
+
throw new Error('Slack client not initialized');
|
|
1169
|
+
}
|
|
1170
|
+
if (!this.client.conversations) {
|
|
1171
|
+
throw new Error('Slack client has no conversations API');
|
|
1172
|
+
}
|
|
1173
|
+
return this.client.conversations;
|
|
1174
|
+
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Extract Slack's machine-readable error code (`name_taken`,
|
|
1177
|
+
* `channel_not_found`, …) from a thrown Web API error.
|
|
1178
|
+
*
|
|
1179
|
+
* @param error - The caught value
|
|
1180
|
+
* @returns The code, or null when the error carries none
|
|
1181
|
+
*/
|
|
1182
|
+
static slackErrorCode(error) {
|
|
1183
|
+
const data = error?.data;
|
|
1184
|
+
return typeof data?.error === 'string' ? data.error : null;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Normalise a raw conversations-API channel object.
|
|
1188
|
+
*
|
|
1189
|
+
* @param raw - Slack's channel object
|
|
1190
|
+
* @returns The trimmed descriptor, or null when the id is missing
|
|
1191
|
+
*/
|
|
1192
|
+
static toChannelInfo(raw) {
|
|
1193
|
+
if (!raw?.id)
|
|
1194
|
+
return null;
|
|
1195
|
+
return {
|
|
1196
|
+
id: raw.id,
|
|
1197
|
+
name: raw.name ?? '',
|
|
1198
|
+
isArchived: raw.is_archived === true,
|
|
1199
|
+
isPrivate: raw.is_private === true,
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Upload an image file to a Slack channel.
|
|
1204
|
+
*
|
|
1205
|
+
* Delegates to the shared upload-with-retry logic.
|
|
1206
|
+
* Kept as a separate public method for backward compatibility
|
|
1207
|
+
* with callers that use the image-specific endpoint.
|
|
1208
|
+
*
|
|
1209
|
+
* @param options - Upload configuration
|
|
1210
|
+
* @returns Object with the uploaded file ID
|
|
1211
|
+
* @throws Error if the client is not initialized or upload fails
|
|
1212
|
+
*/
|
|
1213
|
+
async uploadImage(options) {
|
|
1214
|
+
return this.uploadWithRetry(options, SLACK_IMAGE_CONSTANTS);
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Upload any supported file to a Slack channel.
|
|
1218
|
+
*
|
|
1219
|
+
* Delegates to the shared upload-with-retry logic.
|
|
1220
|
+
* Works for PDFs, images, documents, and other file types supported by Slack.
|
|
1221
|
+
*
|
|
1222
|
+
* @param options - Upload configuration
|
|
1223
|
+
* @returns Object with the uploaded file ID
|
|
1224
|
+
* @throws Error if the client is not initialized or upload fails
|
|
1225
|
+
*/
|
|
1226
|
+
async uploadFile(options) {
|
|
1227
|
+
return this.uploadWithRetry(options, SLACK_FILE_UPLOAD_CONSTANTS);
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Shared upload logic with retry/backoff for Slack rate limits.
|
|
1231
|
+
*
|
|
1232
|
+
* Reads the file from disk and uploads via files.uploadV2.
|
|
1233
|
+
* Retries on 429 responses with exponential backoff capped at 60s.
|
|
1234
|
+
*
|
|
1235
|
+
* @param options - Upload configuration (channel, path, filename, etc.)
|
|
1236
|
+
* @param constants - Constants object providing UPLOAD_MAX_RETRIES and UPLOAD_DEFAULT_BACKOFF_MS
|
|
1237
|
+
* @returns Object with the uploaded file ID
|
|
1238
|
+
* @throws Error if the client is not initialized, retries exhausted, or a non-rate-limit error occurs
|
|
1239
|
+
*/
|
|
1240
|
+
async uploadWithRetry(options, constants) {
|
|
1241
|
+
if (!this.client) {
|
|
1242
|
+
throw new Error('Slack client not initialized');
|
|
1243
|
+
}
|
|
1244
|
+
const filename = options.filename || basename(options.filePath);
|
|
1245
|
+
const maxRetries = constants.UPLOAD_MAX_RETRIES;
|
|
1246
|
+
const MAX_BACKOFF_MS = 60_000;
|
|
1247
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1248
|
+
const fileStream = createReadStream(options.filePath);
|
|
1249
|
+
try {
|
|
1250
|
+
const result = await this.client.files.uploadV2({
|
|
1251
|
+
channel_id: options.channelId,
|
|
1252
|
+
file: fileStream,
|
|
1253
|
+
filename,
|
|
1254
|
+
title: options.title,
|
|
1255
|
+
initial_comment: options.initialComment,
|
|
1256
|
+
thread_ts: options.threadTs,
|
|
1257
|
+
});
|
|
1258
|
+
this.status.messagesSent++;
|
|
1259
|
+
return { fileId: result.files?.[0]?.id };
|
|
1260
|
+
}
|
|
1261
|
+
catch (error) {
|
|
1262
|
+
fileStream.destroy();
|
|
1263
|
+
const isRateLimit = this.isRateLimitError(error);
|
|
1264
|
+
if (isRateLimit && attempt < maxRetries) {
|
|
1265
|
+
const rawMs = this.extractRetryAfterMs(error) || constants.UPLOAD_DEFAULT_BACKOFF_MS;
|
|
1266
|
+
const retryAfterMs = Math.min(rawMs, MAX_BACKOFF_MS);
|
|
1267
|
+
this.logger.warn('Upload rate-limited (429), retrying', { retryAfterMs, attempt: attempt + 1, maxRetries });
|
|
1268
|
+
await new Promise(resolve => setTimeout(resolve, retryAfterMs));
|
|
1269
|
+
continue;
|
|
1270
|
+
}
|
|
1271
|
+
this.logger.error('Upload error', { error: error instanceof Error ? error.message : String(error) });
|
|
1272
|
+
throw error;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
throw new Error('Upload failed after maximum retries');
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Check if an error is a Slack 429 rate limit error.
|
|
1279
|
+
*
|
|
1280
|
+
* @param error - The caught error
|
|
1281
|
+
* @returns True if the error represents a 429 rate limit response
|
|
1282
|
+
*/
|
|
1283
|
+
isRateLimitError(error) {
|
|
1284
|
+
if (error && typeof error === 'object') {
|
|
1285
|
+
const err = error;
|
|
1286
|
+
// @slack/web-api throws errors with code 'slack_webapi_rate_limited_error'
|
|
1287
|
+
if (err.code === 'slack_webapi_rate_limited_error')
|
|
1288
|
+
return true;
|
|
1289
|
+
// Also check for status 429 in case of raw HTTP errors
|
|
1290
|
+
if (err.statusCode === 429 || err.status === 429)
|
|
1291
|
+
return true;
|
|
1292
|
+
}
|
|
1293
|
+
return false;
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* Extract the retry-after delay from a Slack rate limit error.
|
|
1297
|
+
*
|
|
1298
|
+
* @param error - The caught error
|
|
1299
|
+
* @returns Retry delay in milliseconds, or null if not found
|
|
1300
|
+
*/
|
|
1301
|
+
extractRetryAfterMs(error) {
|
|
1302
|
+
if (error && typeof error === 'object') {
|
|
1303
|
+
const err = error;
|
|
1304
|
+
// @slack/web-api attaches retryAfter (seconds) to the error
|
|
1305
|
+
if (typeof err.retryAfter === 'number') {
|
|
1306
|
+
return err.retryAfter * 1000;
|
|
1307
|
+
}
|
|
1308
|
+
// Check headers in case of raw response
|
|
1309
|
+
const headers = err.headers;
|
|
1310
|
+
if (headers?.['retry-after']) {
|
|
1311
|
+
const seconds = parseInt(headers['retry-after'], 10);
|
|
1312
|
+
if (!isNaN(seconds))
|
|
1313
|
+
return seconds * 1000;
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
return null;
|
|
1317
|
+
}
|
|
1318
|
+
/**
|
|
1319
|
+
* Disconnect from Slack
|
|
1320
|
+
*/
|
|
1321
|
+
async disconnect() {
|
|
1322
|
+
this.intentionalDisconnect = true;
|
|
1323
|
+
this.cancelReconnectGrace();
|
|
1324
|
+
this.stopHealthCheck();
|
|
1325
|
+
if (this.app) {
|
|
1326
|
+
await this.app.stop();
|
|
1327
|
+
this.status.connected = false;
|
|
1328
|
+
this.emit('disconnected');
|
|
1329
|
+
this.logger.info('Disconnected');
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* Get file info from Slack via the files.info API.
|
|
1334
|
+
* Requires the bot token to have `files:read` scope.
|
|
1335
|
+
*
|
|
1336
|
+
* @param fileId - Slack file ID (e.g., F0123ABC456)
|
|
1337
|
+
* @returns Object with private download URLs
|
|
1338
|
+
* @throws Error if the client is not initialized or API call fails
|
|
1339
|
+
*/
|
|
1340
|
+
async getFileInfo(fileId) {
|
|
1341
|
+
if (!this.client) {
|
|
1342
|
+
throw new Error('Slack client not initialized');
|
|
1343
|
+
}
|
|
1344
|
+
const result = await this.client.files.info({ file: fileId });
|
|
1345
|
+
return {
|
|
1346
|
+
url_private: result.file?.url_private || '',
|
|
1347
|
+
url_private_download: result.file?.url_private_download || '',
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Get user info from Slack
|
|
1352
|
+
*
|
|
1353
|
+
* @param userId - Slack user ID
|
|
1354
|
+
* @returns User info object
|
|
1355
|
+
*/
|
|
1356
|
+
async getUserInfo(userId) {
|
|
1357
|
+
if (!this.client) {
|
|
1358
|
+
throw new Error('Slack client not initialized');
|
|
1359
|
+
}
|
|
1360
|
+
const result = await this.client.users.info({ user: userId });
|
|
1361
|
+
return {
|
|
1362
|
+
name: result.user?.name || userId,
|
|
1363
|
+
realName: result.user?.real_name || userId,
|
|
1364
|
+
email: result.user?.profile?.email,
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
/**
|
|
1369
|
+
* Get the SlackService singleton instance
|
|
1370
|
+
*
|
|
1371
|
+
* @returns SlackService instance
|
|
1372
|
+
*/
|
|
1373
|
+
export function getSlackService() {
|
|
1374
|
+
if (!slackServiceInstance) {
|
|
1375
|
+
slackServiceInstance = new SlackService();
|
|
1376
|
+
}
|
|
1377
|
+
return slackServiceInstance;
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Reset the SlackService instance (for testing)
|
|
1381
|
+
*/
|
|
1382
|
+
export function resetSlackService() {
|
|
1383
|
+
if (slackServiceInstance) {
|
|
1384
|
+
slackServiceInstance.disconnect().catch(() => { });
|
|
1385
|
+
slackServiceInstance = null;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
//# sourceMappingURL=slack.service.js.map
|