crewly 1.1.2 → 1.2.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/README.md +6 -6
- package/config/roles/ops/prompt.md +140 -0
- package/config/roles/ops/role.json +13 -0
- package/config/skills/agent/browse-stealth/execute.sh +84 -0
- package/config/skills/agent/browse-stealth/instructions.md +108 -0
- package/config/skills/agent/browse-stealth/launch-chrome-cdp.sh +141 -0
- package/config/skills/agent/browse-stealth/skill.json +20 -0
- package/config/skills/agent/browse-stealth/stealth-browse.py +330 -0
- package/config/skills/agent/competitor-content-tracker/execute.sh +232 -0
- package/config/skills/agent/competitor-content-tracker/instructions.md +210 -0
- package/config/skills/agent/competitor-content-tracker/skill.json +22 -0
- package/config/skills/agent/content-calendar/execute.sh +294 -0
- package/config/skills/agent/content-calendar/instructions.md +122 -0
- package/config/skills/agent/content-calendar/skill.json +22 -0
- package/config/skills/agent/content-repurposer/execute.sh +194 -0
- package/config/skills/agent/content-repurposer/instructions.md +69 -0
- package/config/skills/agent/content-repurposer/skill.json +22 -0
- package/config/skills/agent/content-writer/execute.sh +311 -0
- package/config/skills/agent/content-writer/instructions.md +124 -0
- package/config/skills/agent/content-writer/skill.json +22 -0
- package/config/skills/agent/core/generate-pdf/execute.sh +88 -0
- package/config/skills/agent/core/generate-pdf/instructions.md +46 -0
- package/config/skills/agent/core/generate-pdf/skill.json +20 -0
- package/config/skills/agent/core/report-status/execute.sh +6 -0
- package/config/skills/agent/trend-monitor/execute.sh +211 -0
- package/config/skills/agent/trend-monitor/instructions.md +207 -0
- package/config/skills/agent/trend-monitor/skill.json +22 -0
- package/config/skills/agent/vnc-browser/execute.sh +261 -0
- package/config/skills/agent/vnc-browser/instructions.md +102 -0
- package/config/skills/agent/vnc-browser/skill.json +20 -0
- package/config/skills/orchestrator/delegate-task/execute.sh +63 -4
- package/config/skills/orchestrator/delegate-task/instructions.md +60 -0
- package/config/skills/orchestrator/delegate-task/skill.json +4 -4
- package/config/skills/orchestrator/reply-slack/execute.sh +2 -0
- package/config/skills/orchestrator/send-key/execute.sh +19 -6
- package/config/skills/orchestrator/send-key/instructions.md +44 -0
- package/config/skills/orchestrator/send-key/skill.json +20 -0
- package/config/skills/orchestrator/send-message/execute.sh +9 -1
- package/config/skills/registry.json +256 -0
- package/config/templates/code-review-team/README.md +176 -0
- package/config/templates/code-review-team/team-config.json +16 -0
- package/config/templates/code-review-team.json +62 -0
- package/config/templates/content-generation-team/README.md +128 -0
- package/config/templates/content-generation-team/team-config.json +21 -0
- package/config/templates/content-generation-team.json +67 -0
- package/config/templates/demo-team.json +22 -0
- package/config/templates/social-media-ops-team/README.md +145 -0
- package/config/templates/social-media-ops-team/team-config.json +21 -0
- package/config/templates/social-media-ops-team.json +67 -0
- package/dist/backend/backend/src/constants.d.ts +69 -6
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +75 -6
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/index.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/index.js +2 -0
- package/dist/backend/backend/src/controllers/index.js.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts +8 -0
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +110 -63
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.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 +31 -4
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts +8 -0
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.js +127 -111
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +34 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +219 -2
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/user/user.routes.d.ts +7 -0
- package/dist/backend/backend/src/controllers/user/user.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/user/user.routes.js +45 -38
- package/dist/backend/backend/src/controllers/user/user.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/whatsapp/index.d.ts +17 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.js +18 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.js.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js +185 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts +5 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +35 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.js +4 -0
- package/dist/backend/backend/src/routes/modules/task-management.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js +1 -1
- package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +14 -3
- 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 +160 -29
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts +4 -3
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js +29 -4
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js +11 -0
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts +32 -2
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +69 -8
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +14 -2
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js +11 -2
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.d.ts +18 -0
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.js +28 -4
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/slack-messenger.adapter.js +2 -2
- package/dist/backend/backend/src/services/messaging/adapters/slack-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts +18 -0
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js +26 -4
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts +28 -2
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.d.ts +33 -2
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.js +33 -0
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +4 -2
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js +4 -3
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js.map +1 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +27 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.js +54 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +36 -6
- 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 +238 -36
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +6 -4
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/backend/src/services/user/user-identity.service.d.ts +44 -0
- package/dist/backend/backend/src/services/user/user-identity.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/user/user-identity.service.js +75 -8
- package/dist/backend/backend/src/services/user/user-identity.service.js.map +1 -1
- package/dist/backend/backend/src/services/whatsapp/index.d.ts +11 -0
- package/dist/backend/backend/src/services/whatsapp/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/index.js +11 -0
- package/dist/backend/backend/src/services/whatsapp/index.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.d.ts +66 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.js +96 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts +109 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js +234 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.d.ts +127 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.js +347 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.js.map +1 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.js +4 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +1 -0
- package/dist/backend/backend/src/types/index.d.ts.map +1 -1
- package/dist/backend/backend/src/types/index.js.map +1 -1
- package/dist/backend/backend/src/types/slack.types.d.ts +24 -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/task-tracking.types.d.ts +4 -0
- package/dist/backend/backend/src/types/task-tracking.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/task-tracking.types.js.map +1 -1
- package/dist/backend/backend/src/types/whatsapp.types.d.ts +84 -0
- package/dist/backend/backend/src/types/whatsapp.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/whatsapp.types.js +33 -0
- package/dist/backend/backend/src/types/whatsapp.types.js.map +1 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +11 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js +35 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +69 -6
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +75 -6
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +14 -2
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +1 -0
- package/dist/cli/backend/src/types/index.d.ts.map +1 -1
- package/dist/cli/backend/src/types/index.js.map +1 -1
- package/dist/cli/cli/src/commands/publish.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/publish.js +17 -15
- package/dist/cli/cli/src/commands/publish.js.map +1 -1
- package/dist/cli/cli/src/index.js +2 -2
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/cli/src/utils/gh-submit.d.ts +46 -0
- package/dist/cli/cli/src/utils/gh-submit.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/gh-submit.js +167 -0
- package/dist/cli/cli/src/utils/gh-submit.js.map +1 -0
- package/dist/cli/cli/src/utils/marketplace.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/marketplace.js +13 -5
- package/dist/cli/cli/src/utils/marketplace.js.map +1 -1
- package/dist/cli/cli/src/utils/templates.d.ts +3 -2
- package/dist/cli/cli/src/utils/templates.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/templates.js +5 -4
- package/dist/cli/cli/src/utils/templates.js.map +1 -1
- package/frontend/dist/assets/{index-45eeea99.js → index-a23214ae.js} +241 -241
- package/frontend/dist/assets/{index-6972eeee.css → index-c407fe13.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +3 -1
|
@@ -1,127 +1,143 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { GOOGLE_OAUTH_CONSTANTS } from '../../constants.js';
|
|
2
4
|
import { UserIdentityService } from '../../services/user/user-identity.service.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { LoggerService } from '../../services/core/logger.service.js';
|
|
6
|
+
/**
|
|
7
|
+
* Build Google OAuth client config from environment variables.
|
|
8
|
+
*
|
|
9
|
+
* @param req - Express request (used to derive the default redirect URI)
|
|
10
|
+
* @returns Object with clientId, clientSecret, and redirectUri
|
|
11
|
+
*/
|
|
8
12
|
function getGoogleConfig(req) {
|
|
9
13
|
const clientId = process.env.GOOGLE_OAUTH_CLIENT_ID || '';
|
|
10
14
|
const clientSecret = process.env.GOOGLE_OAUTH_CLIENT_SECRET || '';
|
|
11
15
|
const redirectUri = process.env.GOOGLE_OAUTH_REDIRECT_URI || `${req.protocol}://${req.get('host')}/api/oauth/google/callback`;
|
|
12
16
|
return { clientId, clientSecret, redirectUri };
|
|
13
17
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
const code = req.query.code ? String(req.query.code) : '';
|
|
51
|
-
const state = req.query.state ? String(req.query.state) : '';
|
|
52
|
-
if (!code) {
|
|
53
|
-
res.status(400).json({ success: false, error: 'Missing code' });
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const { clientId, clientSecret, redirectUri } = getGoogleConfig(req);
|
|
57
|
-
if (!clientId || !clientSecret) {
|
|
58
|
-
res.status(500).json({ success: false, error: 'Google OAuth credentials are not configured' });
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const tokenResp = await fetch(GOOGLE_TOKEN_ENDPOINT, {
|
|
62
|
-
method: 'POST',
|
|
63
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
64
|
-
body: new URLSearchParams({
|
|
65
|
-
code,
|
|
66
|
-
client_id: clientId,
|
|
67
|
-
client_secret: clientSecret,
|
|
68
|
-
redirect_uri: redirectUri,
|
|
69
|
-
grant_type: 'authorization_code',
|
|
70
|
-
}),
|
|
71
|
-
});
|
|
72
|
-
if (!tokenResp.ok) {
|
|
73
|
-
const details = await tokenResp.text();
|
|
74
|
-
res.status(400).json({ success: false, error: `Failed to exchange OAuth code: ${details}` });
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const tokenData = await tokenResp.json();
|
|
78
|
-
const profileResp = await fetch(GOOGLE_USERINFO_ENDPOINT, {
|
|
79
|
-
headers: { Authorization: `Bearer ${tokenData.access_token}` },
|
|
80
|
-
});
|
|
81
|
-
if (!profileResp.ok) {
|
|
82
|
-
const details = await profileResp.text();
|
|
83
|
-
res.status(400).json({ success: false, error: `Failed to load Google profile: ${details}` });
|
|
84
|
-
return;
|
|
18
|
+
/**
|
|
19
|
+
* Create the OAuth API router.
|
|
20
|
+
*
|
|
21
|
+
* Provides Google OAuth start and callback endpoints for connecting
|
|
22
|
+
* user accounts to Google services.
|
|
23
|
+
*
|
|
24
|
+
* @returns Express Router with OAuth routes
|
|
25
|
+
*/
|
|
26
|
+
export function createOAuthRouter() {
|
|
27
|
+
const router = Router();
|
|
28
|
+
const users = UserIdentityService.getInstance();
|
|
29
|
+
const logger = LoggerService.getInstance().createComponentLogger('OAuthRoutes');
|
|
30
|
+
router.get('/google/start', async (req, res, next) => {
|
|
31
|
+
try {
|
|
32
|
+
const { clientId, redirectUri } = getGoogleConfig(req);
|
|
33
|
+
if (!clientId) {
|
|
34
|
+
res.status(500).json({ success: false, error: 'GOOGLE_OAUTH_CLIENT_ID is not configured' });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const slackUserId = req.query.slackUserId ? String(req.query.slackUserId) : undefined;
|
|
38
|
+
const statePayload = {
|
|
39
|
+
slackUserId,
|
|
40
|
+
t: Date.now(),
|
|
41
|
+
nonce: crypto.randomUUID(),
|
|
42
|
+
};
|
|
43
|
+
const state = Buffer.from(JSON.stringify(statePayload)).toString('base64url');
|
|
44
|
+
const url = new URL(GOOGLE_OAUTH_CONSTANTS.AUTH_BASE_URL);
|
|
45
|
+
url.searchParams.set('client_id', clientId);
|
|
46
|
+
url.searchParams.set('redirect_uri', redirectUri);
|
|
47
|
+
url.searchParams.set('response_type', 'code');
|
|
48
|
+
url.searchParams.set('access_type', 'offline');
|
|
49
|
+
url.searchParams.set('prompt', 'consent');
|
|
50
|
+
url.searchParams.set('scope', GOOGLE_OAUTH_CONSTANTS.DEFAULT_SCOPES.join(' '));
|
|
51
|
+
url.searchParams.set('state', state);
|
|
52
|
+
res.json({ success: true, data: { authUrl: url.toString(), state } });
|
|
85
53
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
res.status(400).json({ success: false, error: 'Google profile did not include email' });
|
|
89
|
-
return;
|
|
54
|
+
catch (error) {
|
|
55
|
+
next(error);
|
|
90
56
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
57
|
+
});
|
|
58
|
+
router.get('/google/callback', async (req, res, next) => {
|
|
59
|
+
try {
|
|
60
|
+
const code = req.query.code ? String(req.query.code) : '';
|
|
61
|
+
const state = req.query.state ? String(req.query.state) : '';
|
|
62
|
+
if (!code) {
|
|
63
|
+
res.status(400).json({ success: false, error: 'Missing code' });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const { clientId, clientSecret, redirectUri } = getGoogleConfig(req);
|
|
67
|
+
if (!clientId || !clientSecret) {
|
|
68
|
+
res.status(500).json({ success: false, error: 'Google OAuth credentials are not configured' });
|
|
69
|
+
return;
|
|
95
70
|
}
|
|
96
|
-
|
|
97
|
-
|
|
71
|
+
const tokenResp = await fetch(GOOGLE_OAUTH_CONSTANTS.TOKEN_ENDPOINT, {
|
|
72
|
+
method: 'POST',
|
|
73
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
74
|
+
body: new URLSearchParams({
|
|
75
|
+
code,
|
|
76
|
+
client_id: clientId,
|
|
77
|
+
client_secret: clientSecret,
|
|
78
|
+
redirect_uri: redirectUri,
|
|
79
|
+
grant_type: 'authorization_code',
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
if (!tokenResp.ok) {
|
|
83
|
+
const details = await tokenResp.text();
|
|
84
|
+
res.status(400).json({ success: false, error: `Failed to exchange OAuth code: ${details}` });
|
|
85
|
+
return;
|
|
98
86
|
}
|
|
87
|
+
const tokenData = await tokenResp.json();
|
|
88
|
+
const profileResp = await fetch(GOOGLE_OAUTH_CONSTANTS.USERINFO_ENDPOINT, {
|
|
89
|
+
headers: { Authorization: `Bearer ${tokenData.access_token}` },
|
|
90
|
+
});
|
|
91
|
+
if (!profileResp.ok) {
|
|
92
|
+
const details = await profileResp.text();
|
|
93
|
+
res.status(400).json({ success: false, error: `Failed to load Google profile: ${details}` });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const profile = await profileResp.json();
|
|
97
|
+
if (!profile.email) {
|
|
98
|
+
res.status(400).json({ success: false, error: 'Google profile did not include email' });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let statePayload = {};
|
|
102
|
+
if (state) {
|
|
103
|
+
try {
|
|
104
|
+
statePayload = JSON.parse(Buffer.from(state, 'base64url').toString('utf8'));
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
logger.warn('Failed to parse OAuth state parameter', {
|
|
108
|
+
error: err instanceof Error ? err.message : String(err),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const user = await users.createOrUpdateUser({
|
|
113
|
+
email: profile.email,
|
|
114
|
+
slackUserId: statePayload.slackUserId,
|
|
115
|
+
});
|
|
116
|
+
if (!tokenData.refresh_token) {
|
|
117
|
+
logger.warn('Google OAuth did not return a refresh_token — using access_token as fallback', {
|
|
118
|
+
email: profile.email,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
await users.connectService(user.id, 'google', {
|
|
122
|
+
refreshToken: tokenData.refresh_token || tokenData.access_token,
|
|
123
|
+
accessToken: tokenData.access_token,
|
|
124
|
+
scopes: (tokenData.scope || '').split(' ').filter(Boolean),
|
|
125
|
+
});
|
|
126
|
+
res.json({
|
|
127
|
+
success: true,
|
|
128
|
+
data: {
|
|
129
|
+
userId: user.id,
|
|
130
|
+
email: user.email,
|
|
131
|
+
connectedProvider: 'google',
|
|
132
|
+
slackUserId: user.slackUserId,
|
|
133
|
+
},
|
|
134
|
+
message: 'Google OAuth connected successfully',
|
|
135
|
+
});
|
|
99
136
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
await users.connectService(user.id, 'google', {
|
|
105
|
-
refreshToken: tokenData.refresh_token || tokenData.access_token,
|
|
106
|
-
accessToken: tokenData.access_token,
|
|
107
|
-
scopes: (tokenData.scope || '').split(' ').filter(Boolean),
|
|
108
|
-
});
|
|
109
|
-
res.json({
|
|
110
|
-
success: true,
|
|
111
|
-
data: {
|
|
112
|
-
userId: user.id,
|
|
113
|
-
email: user.email,
|
|
114
|
-
connectedProvider: 'google',
|
|
115
|
-
slackUserId: user.slackUserId,
|
|
116
|
-
},
|
|
117
|
-
message: 'Google OAuth connected successfully',
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
next(error);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
export function createOAuthRouter() {
|
|
137
|
+
catch (error) {
|
|
138
|
+
next(error);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
125
141
|
return router;
|
|
126
142
|
}
|
|
127
143
|
//# sourceMappingURL=oauth.routes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.routes.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/oauth/oauth.routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,
|
|
1
|
+
{"version":3,"file":"oauth.routes.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/oauth/oauth.routes.ts"],"names":[],"mappings":"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"}
|
package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { Request, Response } from 'express';
|
|
2
2
|
import type { ApiController } from '../api.controller.js';
|
|
3
3
|
import type { ApiContext } from '../types.js';
|
|
4
|
+
import type { EventBusService } from '../../services/event-bus/event-bus.service.js';
|
|
5
|
+
/**
|
|
6
|
+
* Set the EventBusService instance for task monitoring cleanup.
|
|
7
|
+
* Called during server initialization.
|
|
8
|
+
*
|
|
9
|
+
* @param service - The EventBusService instance
|
|
10
|
+
*/
|
|
11
|
+
export declare function setEventBusServiceForTaskCleanup(service: EventBusService): void;
|
|
12
|
+
/**
|
|
13
|
+
* Get the current EventBusService reference (exposed for testing).
|
|
14
|
+
*
|
|
15
|
+
* @returns The EventBusService or null
|
|
16
|
+
*/
|
|
17
|
+
export declare function getEventBusServiceForTaskCleanup(): EventBusService | null;
|
|
4
18
|
/**
|
|
5
19
|
* Creates a new task MD file in the project's .crewly/tasks/ directory.
|
|
6
20
|
* Optionally assigns it immediately if a sessionName is provided.
|
|
@@ -99,4 +113,24 @@ export declare function getTaskOutput(this: ApiController, req: Request, res: Re
|
|
|
99
113
|
* @param res - Response with { success, data: { message: string } }
|
|
100
114
|
*/
|
|
101
115
|
export declare function requestReview(this: ApiController, req: Request, res: Response): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Adds monitoring IDs (schedule and subscription IDs) to tasks for a given agent session.
|
|
118
|
+
* Called by delegate-task after setting up auto-monitoring to link monitoring resources
|
|
119
|
+
* to the task for auto-cleanup on completion.
|
|
120
|
+
*
|
|
121
|
+
* @param req - Request containing sessionName, scheduleIds, subscriptionIds
|
|
122
|
+
* @param res - Response with success status
|
|
123
|
+
*/
|
|
124
|
+
export declare function addMonitoring(this: ApiController, req: Request, res: Response): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Completes all tasks assigned to a given agent session.
|
|
127
|
+
*
|
|
128
|
+
* Called by the report-status skill when an agent reports status=done.
|
|
129
|
+
* Finds all in-progress/assigned tasks for the session, marks them as
|
|
130
|
+
* completed in task tracking, and cleans up monitoring resources.
|
|
131
|
+
*
|
|
132
|
+
* @param req - Request containing sessionName
|
|
133
|
+
* @param res - Response with list of completed tasks
|
|
134
|
+
*/
|
|
135
|
+
export declare function completeTasksBySession(this: ApiController, req: Request, res: Response): Promise<void>;
|
|
102
136
|
//# sourceMappingURL=task-management.controller.d.ts.map
|
package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-management.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/task-management/task-management.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"task-management.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/task-management/task-management.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,25 @@ import { LoggerService } from '../../services/core/logger.service.js';
|
|
|
8
8
|
import { TaskOutputValidatorService } from '../../services/quality/task-output-validator.service.js';
|
|
9
9
|
import { TASK_OUTPUT_CONSTANTS } from '../../types/task-output.types.js';
|
|
10
10
|
const logger = LoggerService.getInstance().createComponentLogger('TaskManagementController');
|
|
11
|
+
/** Module-level reference to EventBusService for auto-cleanup on task completion */
|
|
12
|
+
let eventBusService = null;
|
|
13
|
+
/**
|
|
14
|
+
* Set the EventBusService instance for task monitoring cleanup.
|
|
15
|
+
* Called during server initialization.
|
|
16
|
+
*
|
|
17
|
+
* @param service - The EventBusService instance
|
|
18
|
+
*/
|
|
19
|
+
export function setEventBusServiceForTaskCleanup(service) {
|
|
20
|
+
eventBusService = service;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the current EventBusService reference (exposed for testing).
|
|
24
|
+
*
|
|
25
|
+
* @returns The EventBusService or null
|
|
26
|
+
*/
|
|
27
|
+
export function getEventBusServiceForTaskCleanup() {
|
|
28
|
+
return eventBusService;
|
|
29
|
+
}
|
|
11
30
|
/**
|
|
12
31
|
* Creates a new task MD file in the project's .crewly/tasks/ directory.
|
|
13
32
|
* Optionally assigns it immediately if a sessionName is provided.
|
|
@@ -351,10 +370,12 @@ export async function completeTask(req, res) {
|
|
|
351
370
|
const updatedContent = addTaskCompletionInfo(taskContent);
|
|
352
371
|
await writeFile(doneTargetPath, updatedContent, 'utf-8');
|
|
353
372
|
await unlinkFile(taskPath);
|
|
354
|
-
// Remove from task tracking
|
|
373
|
+
// Remove from task tracking and clean up monitoring
|
|
355
374
|
const allTasksWithSchema = await this.taskTrackingService.getAllInProgressTasks();
|
|
356
375
|
const taskToRemoveWithSchema = allTasksWithSchema.find(t => t.taskFilePath === taskPath);
|
|
376
|
+
let cleanupResultSchema = { cancelledSchedules: 0, unsubscribedEvents: 0 };
|
|
357
377
|
if (taskToRemoveWithSchema) {
|
|
378
|
+
cleanupResultSchema = await cleanupTaskMonitoring(this, taskToRemoveWithSchema);
|
|
358
379
|
await this.taskTrackingService.removeTask(taskToRemoveWithSchema.id);
|
|
359
380
|
}
|
|
360
381
|
res.json({
|
|
@@ -365,6 +386,7 @@ export async function completeTask(req, res) {
|
|
|
365
386
|
outputPath: outputFilePath,
|
|
366
387
|
status: 'done',
|
|
367
388
|
completedAt: new Date().toISOString(),
|
|
389
|
+
monitoringCleanup: cleanupResultSchema,
|
|
368
390
|
});
|
|
369
391
|
return;
|
|
370
392
|
}
|
|
@@ -378,10 +400,12 @@ export async function completeTask(req, res) {
|
|
|
378
400
|
const updatedContent = addTaskCompletionInfo(taskContent);
|
|
379
401
|
await writeFile(targetPath, updatedContent, 'utf-8');
|
|
380
402
|
await unlinkFile(taskPath);
|
|
381
|
-
// Remove from task tracking
|
|
403
|
+
// Remove from task tracking and clean up monitoring
|
|
382
404
|
const allTasks = await this.taskTrackingService.getAllInProgressTasks();
|
|
383
405
|
const taskToRemove = allTasks.find(t => t.taskFilePath === taskPath);
|
|
406
|
+
let cleanupResult = { cancelledSchedules: 0, unsubscribedEvents: 0 };
|
|
384
407
|
if (taskToRemove) {
|
|
408
|
+
cleanupResult = await cleanupTaskMonitoring(this, taskToRemove);
|
|
385
409
|
await this.taskTrackingService.removeTask(taskToRemove.id);
|
|
386
410
|
}
|
|
387
411
|
res.json({
|
|
@@ -391,6 +415,7 @@ export async function completeTask(req, res) {
|
|
|
391
415
|
newPath: targetPath,
|
|
392
416
|
status: 'done',
|
|
393
417
|
completedAt: new Date().toISOString(),
|
|
418
|
+
monitoringCleanup: cleanupResult,
|
|
394
419
|
});
|
|
395
420
|
}
|
|
396
421
|
catch (error) {
|
|
@@ -1203,4 +1228,196 @@ export async function requestReview(req, res) {
|
|
|
1203
1228
|
});
|
|
1204
1229
|
}
|
|
1205
1230
|
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Cleans up monitoring resources (scheduled checks and event subscriptions)
|
|
1233
|
+
* linked to a task. Called automatically when a task is completed.
|
|
1234
|
+
*
|
|
1235
|
+
* @param controller - The ApiController instance (for schedulerService access)
|
|
1236
|
+
* @param task - The task whose monitoring to clean up
|
|
1237
|
+
* @returns Object with counts of cancelled schedules and unsubscribed events
|
|
1238
|
+
*/
|
|
1239
|
+
async function cleanupTaskMonitoring(controller, task) {
|
|
1240
|
+
let cancelledSchedules = 0;
|
|
1241
|
+
let unsubscribedEvents = 0;
|
|
1242
|
+
// Cancel linked schedules
|
|
1243
|
+
if (task.scheduleIds && task.scheduleIds.length > 0) {
|
|
1244
|
+
for (const scheduleId of task.scheduleIds) {
|
|
1245
|
+
try {
|
|
1246
|
+
controller.schedulerService.cancelCheck(scheduleId);
|
|
1247
|
+
cancelledSchedules++;
|
|
1248
|
+
}
|
|
1249
|
+
catch (error) {
|
|
1250
|
+
logger.warn('Failed to cancel schedule during task cleanup', {
|
|
1251
|
+
scheduleId,
|
|
1252
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1253
|
+
});
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
// Unsubscribe linked event subscriptions
|
|
1258
|
+
if (task.subscriptionIds && task.subscriptionIds.length > 0 && eventBusService) {
|
|
1259
|
+
for (const subscriptionId of task.subscriptionIds) {
|
|
1260
|
+
try {
|
|
1261
|
+
eventBusService.unsubscribe(subscriptionId);
|
|
1262
|
+
unsubscribedEvents++;
|
|
1263
|
+
}
|
|
1264
|
+
catch (error) {
|
|
1265
|
+
logger.warn('Failed to unsubscribe event during task cleanup', {
|
|
1266
|
+
subscriptionId,
|
|
1267
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
if (cancelledSchedules > 0 || unsubscribedEvents > 0) {
|
|
1273
|
+
logger.info('Task monitoring cleaned up', { cancelledSchedules, unsubscribedEvents });
|
|
1274
|
+
}
|
|
1275
|
+
return { cancelledSchedules, unsubscribedEvents };
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Adds monitoring IDs (schedule and subscription IDs) to tasks for a given agent session.
|
|
1279
|
+
* Called by delegate-task after setting up auto-monitoring to link monitoring resources
|
|
1280
|
+
* to the task for auto-cleanup on completion.
|
|
1281
|
+
*
|
|
1282
|
+
* @param req - Request containing sessionName, scheduleIds, subscriptionIds
|
|
1283
|
+
* @param res - Response with success status
|
|
1284
|
+
*/
|
|
1285
|
+
export async function addMonitoring(req, res) {
|
|
1286
|
+
try {
|
|
1287
|
+
const { sessionName, scheduleIds = [], subscriptionIds = [] } = req.body;
|
|
1288
|
+
if (!sessionName) {
|
|
1289
|
+
res.status(400).json({ success: false, error: 'sessionName is required' });
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
if (scheduleIds.length === 0 && subscriptionIds.length === 0) {
|
|
1293
|
+
res.status(400).json({ success: false, error: 'At least one scheduleId or subscriptionId is required' });
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
// Find the most recent task assigned to this session
|
|
1297
|
+
const tasks = await this.taskTrackingService.getTasksBySessionName(sessionName);
|
|
1298
|
+
if (tasks.length === 0) {
|
|
1299
|
+
// No tracked task found — store IDs anyway by finding any in_progress_tasks entry
|
|
1300
|
+
logger.warn('No tracked tasks found for session, storing monitoring IDs for session-level cleanup', { sessionName });
|
|
1301
|
+
res.json({
|
|
1302
|
+
success: true,
|
|
1303
|
+
message: 'No tracked task found for session; monitoring IDs noted but not linked to a task',
|
|
1304
|
+
sessionName,
|
|
1305
|
+
scheduleIds,
|
|
1306
|
+
subscriptionIds,
|
|
1307
|
+
});
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
// Link to the most recently assigned task
|
|
1311
|
+
const latestTask = tasks.sort((a, b) => new Date(b.assignedAt).getTime() - new Date(a.assignedAt).getTime())[0];
|
|
1312
|
+
await this.taskTrackingService.addMonitoringIds(latestTask.id, scheduleIds, subscriptionIds);
|
|
1313
|
+
res.json({
|
|
1314
|
+
success: true,
|
|
1315
|
+
message: 'Monitoring IDs linked to task',
|
|
1316
|
+
taskId: latestTask.id,
|
|
1317
|
+
taskName: latestTask.taskName,
|
|
1318
|
+
scheduleIds,
|
|
1319
|
+
subscriptionIds,
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
catch (error) {
|
|
1323
|
+
logger.error('Error adding monitoring IDs', { error: error instanceof Error ? error.message : String(error) });
|
|
1324
|
+
res.status(500).json({ success: false, error: 'Failed to add monitoring IDs' });
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Completes all tasks assigned to a given agent session.
|
|
1329
|
+
*
|
|
1330
|
+
* Called by the report-status skill when an agent reports status=done.
|
|
1331
|
+
* Finds all in-progress/assigned tasks for the session, marks them as
|
|
1332
|
+
* completed in task tracking, and cleans up monitoring resources.
|
|
1333
|
+
*
|
|
1334
|
+
* @param req - Request containing sessionName
|
|
1335
|
+
* @param res - Response with list of completed tasks
|
|
1336
|
+
*/
|
|
1337
|
+
export async function completeTasksBySession(req, res) {
|
|
1338
|
+
try {
|
|
1339
|
+
const { sessionName } = req.body;
|
|
1340
|
+
if (!sessionName) {
|
|
1341
|
+
res.status(400).json({ success: false, error: 'sessionName is required' });
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
const tasks = await this.taskTrackingService.getTasksBySessionName(sessionName);
|
|
1345
|
+
const activeTasks = tasks.filter(t => t.status === 'assigned' || t.status === 'active');
|
|
1346
|
+
if (activeTasks.length === 0) {
|
|
1347
|
+
res.json({
|
|
1348
|
+
success: true,
|
|
1349
|
+
message: 'No active tasks found for session',
|
|
1350
|
+
sessionName,
|
|
1351
|
+
completedCount: 0,
|
|
1352
|
+
completedTasks: [],
|
|
1353
|
+
});
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
const completedTasks = [];
|
|
1357
|
+
let totalCancelledSchedules = 0;
|
|
1358
|
+
let totalUnsubscribedEvents = 0;
|
|
1359
|
+
for (const task of activeTasks) {
|
|
1360
|
+
try {
|
|
1361
|
+
// Move task file from in_progress/ to done/ if it exists
|
|
1362
|
+
if (task.taskFilePath && task.taskFilePath.includes('/in_progress/') && existsSync(task.taskFilePath)) {
|
|
1363
|
+
try {
|
|
1364
|
+
const targetPath = task.taskFilePath.replace('/in_progress/', '/done/');
|
|
1365
|
+
const targetDir = dirname(targetPath);
|
|
1366
|
+
await ensureDirectoryExists(targetDir);
|
|
1367
|
+
const taskContent = await readFile(task.taskFilePath, 'utf-8');
|
|
1368
|
+
const updatedContent = addTaskCompletionInfo(taskContent);
|
|
1369
|
+
await writeFile(targetPath, updatedContent, 'utf-8');
|
|
1370
|
+
await unlink(task.taskFilePath);
|
|
1371
|
+
logger.debug('Moved task file to done', {
|
|
1372
|
+
taskId: task.id,
|
|
1373
|
+
from: task.taskFilePath,
|
|
1374
|
+
to: targetPath,
|
|
1375
|
+
});
|
|
1376
|
+
}
|
|
1377
|
+
catch (fileError) {
|
|
1378
|
+
logger.warn('Failed to move task file to done (continuing with tracking cleanup)', {
|
|
1379
|
+
taskId: task.id,
|
|
1380
|
+
taskFilePath: task.taskFilePath,
|
|
1381
|
+
error: fileError instanceof Error ? fileError.message : String(fileError),
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
// Clean up monitoring resources
|
|
1386
|
+
const cleanup = await cleanupTaskMonitoring(this, task);
|
|
1387
|
+
totalCancelledSchedules += cleanup.cancelledSchedules;
|
|
1388
|
+
totalUnsubscribedEvents += cleanup.unsubscribedEvents;
|
|
1389
|
+
// Remove from tracking
|
|
1390
|
+
await this.taskTrackingService.removeTask(task.id);
|
|
1391
|
+
completedTasks.push(task.taskName);
|
|
1392
|
+
logger.info('Auto-completed task for session', {
|
|
1393
|
+
taskId: task.id,
|
|
1394
|
+
taskName: task.taskName,
|
|
1395
|
+
sessionName,
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
catch (error) {
|
|
1399
|
+
logger.warn('Failed to auto-complete task', {
|
|
1400
|
+
taskId: task.id,
|
|
1401
|
+
taskName: task.taskName,
|
|
1402
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
res.json({
|
|
1407
|
+
success: true,
|
|
1408
|
+
message: `Completed ${completedTasks.length} task(s) for session ${sessionName}`,
|
|
1409
|
+
sessionName,
|
|
1410
|
+
completedCount: completedTasks.length,
|
|
1411
|
+
completedTasks,
|
|
1412
|
+
monitoringCleanup: {
|
|
1413
|
+
cancelledSchedules: totalCancelledSchedules,
|
|
1414
|
+
unsubscribedEvents: totalUnsubscribedEvents,
|
|
1415
|
+
},
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1418
|
+
catch (error) {
|
|
1419
|
+
logger.error('Error completing tasks by session', { error: error instanceof Error ? error.message : String(error) });
|
|
1420
|
+
res.status(500).json({ success: false, error: 'Failed to complete tasks by session' });
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1206
1423
|
//# sourceMappingURL=task-management.controller.js.map
|