crewly 1.8.7 → 1.8.9

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.
Files changed (165) hide show
  1. package/dist/backend/backend/src/constants.d.ts +12 -0
  2. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  3. package/dist/backend/backend/src/constants.js +12 -0
  4. package/dist/backend/backend/src/constants.js.map +1 -1
  5. package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
  6. package/dist/backend/backend/src/controllers/browser/browser.controller.js +17 -0
  7. package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
  8. package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
  9. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +8 -1
  10. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
  11. package/dist/backend/backend/src/index.d.ts.map +1 -1
  12. package/dist/backend/backend/src/index.js +15 -7
  13. package/dist/backend/backend/src/index.js.map +1 -1
  14. package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +7 -0
  15. package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
  16. package/dist/backend/backend/src/services/browser/browser-bridge.service.js +69 -12
  17. package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
  18. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +122 -1
  19. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
  20. package/dist/backend/backend/src/services/browser/browser-proxy.service.js +252 -17
  21. package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
  22. package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts +37 -3
  23. package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts.map +1 -1
  24. package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js +140 -23
  25. package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js.map +1 -1
  26. package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts +75 -0
  27. package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
  28. package/dist/backend/backend/src/services/cloud/cloud-client.service.js +164 -12
  29. package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
  30. package/dist/cli/backend/src/constants.d.ts +12 -0
  31. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  32. package/dist/cli/backend/src/constants.js +12 -0
  33. package/dist/cli/backend/src/constants.js.map +1 -1
  34. package/dist/cli/cli/src/index.js +0 -0
  35. package/package.json +1 -1
  36. package/config/constants.d.ts.map +0 -1
  37. package/config/index.d.ts.map +0 -1
  38. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +0 -169
  39. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +0 -1
  40. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +0 -1779
  41. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +0 -1
  42. package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts +0 -513
  43. package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts.map +0 -1
  44. package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js +0 -1568
  45. package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js.map +0 -1
  46. package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts +0 -86
  47. package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts.map +0 -1
  48. package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js +0 -147
  49. package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js.map +0 -1
  50. package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts +0 -68
  51. package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts.map +0 -1
  52. package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js +0 -131
  53. package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js.map +0 -1
  54. package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts +0 -130
  55. package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts.map +0 -1
  56. package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js +0 -263
  57. package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js.map +0 -1
  58. package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts +0 -74
  59. package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts.map +0 -1
  60. package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js +0 -140
  61. package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js.map +0 -1
  62. package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts +0 -29
  63. package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts.map +0 -1
  64. package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js +0 -279
  65. package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js.map +0 -1
  66. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts +0 -340
  67. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts.map +0 -1
  68. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js +0 -1176
  69. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js.map +0 -1
  70. package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts +0 -79
  71. package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts.map +0 -1
  72. package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js +0 -145
  73. package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js.map +0 -1
  74. package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts +0 -79
  75. package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts.map +0 -1
  76. package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js +0 -218
  77. package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js.map +0 -1
  78. package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts +0 -16
  79. package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts.map +0 -1
  80. package/dist/backend/backend/src/services/agent/crewly-agent/index.js +0 -16
  81. package/dist/backend/backend/src/services/agent/crewly-agent/index.js.map +0 -1
  82. package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts +0 -135
  83. package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts.map +0 -1
  84. package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js +0 -185
  85. package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js.map +0 -1
  86. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +0 -141
  87. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +0 -1
  88. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +0 -310
  89. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +0 -1
  90. package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts +0 -91
  91. package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts.map +0 -1
  92. package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js +0 -143
  93. package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js.map +0 -1
  94. package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts +0 -103
  95. package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts.map +0 -1
  96. package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js +0 -256
  97. package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js.map +0 -1
  98. package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts +0 -143
  99. package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts.map +0 -1
  100. package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js +0 -264
  101. package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js.map +0 -1
  102. package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts +0 -13
  103. package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts.map +0 -1
  104. package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js +0 -91
  105. package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js.map +0 -1
  106. package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts +0 -135
  107. package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts.map +0 -1
  108. package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js +0 -1937
  109. package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js.map +0 -1
  110. package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts +0 -429
  111. package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts.map +0 -1
  112. package/dist/backend/backend/src/services/autonomous/auto-assign.service.js +0 -852
  113. package/dist/backend/backend/src/services/autonomous/auto-assign.service.js.map +0 -1
  114. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +0 -171
  115. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
  116. package/dist/backend/backend/src/services/project/task-tracking.service.js +0 -725
  117. package/dist/backend/backend/src/services/project/task-tracking.service.js.map +0 -1
  118. package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts +0 -118
  119. package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts.map +0 -1
  120. package/dist/backend/backend/src/services/v3/project-task-watcher.service.js +0 -326
  121. package/dist/backend/backend/src/services/v3/project-task-watcher.service.js.map +0 -1
  122. package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts +0 -74
  123. package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts.map +0 -1
  124. package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js +0 -154
  125. package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js.map +0 -1
  126. package/dist/backend/backend/src/types/auto-assign.types.d.ts +0 -271
  127. package/dist/backend/backend/src/types/auto-assign.types.d.ts.map +0 -1
  128. package/dist/backend/backend/src/types/auto-assign.types.js +0 -136
  129. package/dist/backend/backend/src/types/auto-assign.types.js.map +0 -1
  130. package/dist/backend/backend/src/utils/esm-require.utils.d.ts +0 -111
  131. package/dist/backend/backend/src/utils/esm-require.utils.d.ts.map +0 -1
  132. package/dist/backend/backend/src/utils/esm-require.utils.js +0 -124
  133. package/dist/backend/backend/src/utils/esm-require.utils.js.map +0 -1
  134. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +0 -220
  135. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +0 -1
  136. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js +0 -37
  137. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +0 -1
  138. package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts +0 -56
  139. package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts.map +0 -1
  140. package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js +0 -91
  141. package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js.map +0 -1
  142. package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts +0 -159
  143. package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts.map +0 -1
  144. package/dist/cli/backend/src/services/knowledge/learnings-index.service.js +0 -304
  145. package/dist/cli/backend/src/services/knowledge/learnings-index.service.js.map +0 -1
  146. package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts +0 -115
  147. package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts.map +0 -1
  148. package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js +0 -215
  149. package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js.map +0 -1
  150. package/dist/cli/backend/src/services/memory/embedding-provider.d.ts +0 -78
  151. package/dist/cli/backend/src/services/memory/embedding-provider.d.ts.map +0 -1
  152. package/dist/cli/backend/src/services/memory/embedding-provider.js +0 -179
  153. package/dist/cli/backend/src/services/memory/embedding-provider.js.map +0 -1
  154. package/dist/cli/backend/src/services/memory/vector-store.service.d.ts +0 -331
  155. package/dist/cli/backend/src/services/memory/vector-store.service.d.ts.map +0 -1
  156. package/dist/cli/backend/src/services/memory/vector-store.service.js +0 -814
  157. package/dist/cli/backend/src/services/memory/vector-store.service.js.map +0 -1
  158. package/dist/cli/backend/src/services/project/task-tracking.service.d.ts +0 -171
  159. package/dist/cli/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
  160. package/dist/cli/backend/src/services/project/task-tracking.service.js +0 -725
  161. package/dist/cli/backend/src/services/project/task-tracking.service.js.map +0 -1
  162. package/dist/cli/backend/src/types/auto-assign.types.d.ts +0 -271
  163. package/dist/cli/backend/src/types/auto-assign.types.d.ts.map +0 -1
  164. package/dist/cli/backend/src/types/auto-assign.types.js +0 -136
  165. package/dist/cli/backend/src/types/auto-assign.types.js.map +0 -1
@@ -1,852 +0,0 @@
1
- /**
2
- * Auto-Assignment Service
3
- *
4
- * Automatically assigns tasks to idle agents based on role matching,
5
- * priority, and dependency rules.
6
- *
7
- * @module services/autonomous/auto-assign.service
8
- */
9
- import * as path from 'path';
10
- import * as fs from 'fs/promises';
11
- import { existsSync } from 'fs';
12
- import { EventEmitter } from 'events';
13
- import { parse as parseYAML } from 'yaml';
14
- import { LoggerService } from '../core/logger.service.js';
15
- import { TaskService } from '../project/task.service.js';
16
- import { TaskTrackingService } from '../project/task-tracking.service.js';
17
- import { AUTO_ASSIGN_CONSTANTS, DEFAULT_AUTO_ASSIGN_CONFIG, DEFAULT_ASSIGNMENT_STRATEGY, } from '../../types/auto-assign.types.js';
18
- /**
19
- * Service for automatic task assignment to agents
20
- *
21
- * @example
22
- * ```typescript
23
- * const service = AutoAssignService.getInstance();
24
- * await service.initialize('/path/to/project');
25
- *
26
- * // Assign next task to an idle agent
27
- * const result = await service.assignNextTask('agent-session');
28
- * if (result) {
29
- * console.log(`Assigned task ${result.taskId} to agent`);
30
- * }
31
- * ```
32
- */
33
- export class AutoAssignService extends EventEmitter {
34
- static instance = null;
35
- logger;
36
- taskService = null;
37
- taskTrackingService = null;
38
- /** Configuration cache per project */
39
- configs = new Map();
40
- /** Task queue cache per project */
41
- queues = new Map();
42
- /** Paused projects */
43
- paused = new Set();
44
- /** Agent to project mapping */
45
- agentProjects = new Map();
46
- /** Assignment history per project */
47
- assignmentHistory = new Map();
48
- /** Daily assignment counts per agent */
49
- dailyAssignments = new Map();
50
- /** Last assignment time per agent */
51
- lastAssignmentTime = new Map();
52
- /**
53
- * Private constructor for singleton pattern
54
- */
55
- constructor() {
56
- super();
57
- this.logger = LoggerService.getInstance().createComponentLogger('AutoAssignService');
58
- }
59
- /**
60
- * Gets the singleton instance
61
- *
62
- * @returns The AutoAssignService instance
63
- */
64
- static getInstance() {
65
- if (!AutoAssignService.instance) {
66
- AutoAssignService.instance = new AutoAssignService();
67
- }
68
- return AutoAssignService.instance;
69
- }
70
- /**
71
- * Clears the singleton instance (for testing)
72
- */
73
- static clearInstance() {
74
- AutoAssignService.instance = null;
75
- }
76
- /**
77
- * Set the task service (for dependency injection/testing)
78
- *
79
- * @param service - Task service instance
80
- */
81
- setTaskService(service) {
82
- this.taskService = service;
83
- }
84
- /**
85
- * Set the task tracking service (for dependency injection/testing)
86
- *
87
- * @param service - Task tracking service instance
88
- */
89
- setTaskTrackingService(service) {
90
- this.taskTrackingService = service;
91
- }
92
- /**
93
- * Get the task service, creating one if needed
94
- *
95
- * @param projectPath - Project path
96
- * @returns Task service
97
- */
98
- getTaskService(projectPath) {
99
- if (!this.taskService) {
100
- this.taskService = new TaskService(projectPath);
101
- }
102
- return this.taskService;
103
- }
104
- /**
105
- * Get the task tracking service, creating one if needed
106
- *
107
- * @returns Task tracking service
108
- */
109
- getTaskTrackingService() {
110
- if (!this.taskTrackingService) {
111
- this.taskTrackingService = new TaskTrackingService();
112
- }
113
- return this.taskTrackingService;
114
- }
115
- /**
116
- * Initialize the service for a project
117
- *
118
- * @param projectPath - Path to the project
119
- */
120
- async initialize(projectPath) {
121
- // Load or create config
122
- const config = await this.loadConfig(projectPath);
123
- this.configs.set(projectPath, config);
124
- // Build initial queue
125
- await this.refreshQueue(projectPath);
126
- // Subscribe to task events
127
- this.subscribeToEvents(projectPath);
128
- this.logger.info('AutoAssignService initialized', { projectPath });
129
- }
130
- /**
131
- * Load configuration from file or return defaults
132
- *
133
- * @param projectPath - Project path
134
- * @returns Auto-assign configuration
135
- */
136
- async loadConfig(projectPath) {
137
- const configPath = path.join(projectPath, AUTO_ASSIGN_CONSTANTS.PATHS.CONFIG_DIR, AUTO_ASSIGN_CONSTANTS.PATHS.CONFIG_FILE);
138
- try {
139
- if (existsSync(configPath)) {
140
- const content = await fs.readFile(configPath, 'utf-8');
141
- const parsed = parseYAML(content);
142
- // Merge with defaults
143
- return {
144
- enabled: parsed.enabled ?? DEFAULT_AUTO_ASSIGN_CONFIG.enabled,
145
- strategy: {
146
- ...DEFAULT_ASSIGNMENT_STRATEGY,
147
- ...parsed.strategy,
148
- roleMatching: parsed.strategy?.roleMatching ?? DEFAULT_ASSIGNMENT_STRATEGY.roleMatching,
149
- loadBalancing: {
150
- ...DEFAULT_ASSIGNMENT_STRATEGY.loadBalancing,
151
- ...parsed.strategy?.loadBalancing,
152
- },
153
- dependencies: {
154
- ...DEFAULT_ASSIGNMENT_STRATEGY.dependencies,
155
- ...parsed.strategy?.dependencies,
156
- },
157
- },
158
- notifications: {
159
- ...DEFAULT_AUTO_ASSIGN_CONFIG.notifications,
160
- ...parsed.notifications,
161
- },
162
- limits: {
163
- ...DEFAULT_AUTO_ASSIGN_CONFIG.limits,
164
- ...parsed.limits,
165
- },
166
- };
167
- }
168
- }
169
- catch (error) {
170
- this.logger.warn('Failed to load config, using defaults', { projectPath, error });
171
- }
172
- return { ...DEFAULT_AUTO_ASSIGN_CONFIG };
173
- }
174
- /**
175
- * Get the assignment strategy configuration for a project
176
- *
177
- * @param projectPath - Path to the project
178
- * @returns Assignment strategy configuration
179
- */
180
- async getConfig(projectPath) {
181
- if (!this.configs.has(projectPath)) {
182
- const config = await this.loadConfig(projectPath);
183
- this.configs.set(projectPath, config);
184
- }
185
- return this.configs.get(projectPath).strategy;
186
- }
187
- /**
188
- * Update the assignment strategy configuration
189
- *
190
- * @param projectPath - Path to the project
191
- * @param config - Partial configuration to merge
192
- */
193
- async setConfig(projectPath, config) {
194
- const existing = this.configs.get(projectPath) || { ...DEFAULT_AUTO_ASSIGN_CONFIG };
195
- existing.strategy = {
196
- ...existing.strategy,
197
- ...config,
198
- };
199
- this.configs.set(projectPath, existing);
200
- this.logger.info('Config updated', { projectPath });
201
- }
202
- /**
203
- * Assign the next available task to an agent
204
- *
205
- * @param sessionName - Agent session name
206
- * @returns Assignment result or null if no task available
207
- */
208
- async assignNextTask(sessionName) {
209
- const projectPath = this.agentProjects.get(sessionName);
210
- if (!projectPath) {
211
- this.logger.warn('No project associated with agent', { sessionName });
212
- return null;
213
- }
214
- // Check if auto-assign is enabled and not paused
215
- if (!(await this.isAutoAssignEnabled(projectPath))) {
216
- this.logger.debug('Auto-assign disabled or paused', { projectPath });
217
- return null;
218
- }
219
- // Check agent workload
220
- const workload = await this.getAgentWorkload(sessionName);
221
- const config = await this.getConfig(projectPath);
222
- if (workload.currentTasks.length >= config.loadBalancing.maxConcurrentTasks) {
223
- this.logger.debug('Agent at max capacity', { sessionName, currentTasks: workload.currentTasks.length });
224
- return null;
225
- }
226
- // Check cooldown
227
- const lastTime = this.lastAssignmentTime.get(sessionName) || 0;
228
- const fullConfig = this.configs.get(projectPath) || DEFAULT_AUTO_ASSIGN_CONFIG;
229
- const cooldownMs = fullConfig.limits.cooldownBetweenTasks * 1000;
230
- if (Date.now() - lastTime < cooldownMs) {
231
- this.logger.debug('Agent in cooldown period', { sessionName });
232
- return null;
233
- }
234
- // Check daily limit
235
- const dailyRecord = this.dailyAssignments.get(sessionName);
236
- const today = new Date().toISOString().split('T')[0];
237
- if (dailyRecord && dailyRecord.date === today) {
238
- if (dailyRecord.count >= fullConfig.limits.maxAssignmentsPerDay) {
239
- this.logger.debug('Agent at daily limit', { sessionName, count: dailyRecord.count });
240
- return null;
241
- }
242
- }
243
- // Find next task
244
- const result = await this.findNextTask({
245
- sessionName,
246
- role: workload.role,
247
- projectPath,
248
- });
249
- if (!result.found || !result.task) {
250
- this.emitEvent({
251
- type: 'no_tasks',
252
- agentId: workload.agentId,
253
- sessionName,
254
- timestamp: new Date().toISOString(),
255
- metadata: { reason: result.reason },
256
- });
257
- return null;
258
- }
259
- // Assign the task
260
- return this.assignTask(result.task.taskPath, sessionName);
261
- }
262
- /**
263
- * Find the next task suitable for a role
264
- *
265
- * @param params - Search parameters
266
- * @returns Search result with task or reason for no match
267
- */
268
- async findNextTask(params) {
269
- const { role, projectPath, preferredTaskTypes } = params;
270
- const queue = await this.getTaskQueue(projectPath);
271
- const config = await this.getConfig(projectPath);
272
- // Filter tasks by eligibility
273
- const eligibleTasks = queue.tasks.filter((task) => {
274
- // Check role match
275
- if (task.requiredRole && task.requiredRole !== role) {
276
- if (!this.canRoleHandleTask(role, task, config)) {
277
- return false;
278
- }
279
- }
280
- // Check if task type matches role capabilities
281
- if (task.taskType && !this.canRoleHandleTaskType(role, task.taskType, config)) {
282
- // Check if it's an exclusive task type for another role
283
- if (this.isExclusiveForOtherRole(role, task.taskType, config)) {
284
- return false;
285
- }
286
- }
287
- // Check dependencies
288
- if (config.dependencies.respectBlocking && task.blockedBy.length > 0) {
289
- return false;
290
- }
291
- return true;
292
- });
293
- if (eligibleTasks.length === 0) {
294
- // Determine reason
295
- if (queue.tasks.length === 0) {
296
- return { found: false, reason: 'no_tasks' };
297
- }
298
- const blockedCount = queue.tasks.filter((t) => t.blockedBy.length > 0).length;
299
- if (blockedCount === queue.tasks.length) {
300
- return { found: false, reason: 'all_blocked' };
301
- }
302
- return { found: false, reason: 'role_mismatch' };
303
- }
304
- // Sort by priority and preference
305
- const sorted = this.sortTasks(eligibleTasks, config, preferredTaskTypes);
306
- return {
307
- found: true,
308
- task: sorted[0],
309
- };
310
- }
311
- /**
312
- * Sort tasks by priority and preferences
313
- *
314
- * @param tasks - Tasks to sort
315
- * @param config - Assignment strategy
316
- * @param preferredTypes - Preferred task types
317
- * @returns Sorted tasks
318
- */
319
- sortTasks(tasks, config, preferredTypes) {
320
- return [...tasks].sort((a, b) => {
321
- // Preferred types first
322
- if (preferredTypes && preferredTypes.length > 0) {
323
- const aPreferred = a.taskType && preferredTypes.includes(a.taskType);
324
- const bPreferred = b.taskType && preferredTypes.includes(b.taskType);
325
- if (aPreferred && !bPreferred)
326
- return -1;
327
- if (!aPreferred && bPreferred)
328
- return 1;
329
- }
330
- // Then by prioritization strategy
331
- if (config.prioritization === 'priority') {
332
- // Lower priority number = more important (CRITICAL=1 is highest priority)
333
- return a.priority - b.priority;
334
- }
335
- else if (config.prioritization === 'fifo') {
336
- return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
337
- }
338
- else if (config.prioritization === 'deadline') {
339
- // Tasks with estimated hours should be done sooner
340
- const aHours = a.estimatedHours ?? Infinity;
341
- const bHours = b.estimatedHours ?? Infinity;
342
- return aHours - bHours;
343
- }
344
- return 0;
345
- });
346
- }
347
- /**
348
- * Check if a role can handle a specific task
349
- *
350
- * @param role - Agent role
351
- * @param task - Task to check
352
- * @param config - Assignment strategy
353
- * @returns True if role can handle the task
354
- */
355
- canRoleHandleTask(role, task, config) {
356
- // If task requires a specific role and it doesn't match, check if the role can substitute
357
- if (task.requiredRole && task.requiredRole !== role) {
358
- // Check if the current role can substitute for the required role
359
- // For example, 'developer' can do generic dev work, but not 'qa' tasks
360
- const roleHierarchy = {
361
- 'frontend-developer': ['developer'],
362
- 'backend-developer': ['developer'],
363
- developer: [],
364
- pm: [],
365
- tpm: [],
366
- pgm: [],
367
- qa: ['tester'],
368
- tester: [],
369
- orchestrator: [],
370
- designer: [],
371
- devops: [],
372
- };
373
- // Check if the agent's role is in the hierarchy chain for required role
374
- const canSubstitute = roleHierarchy[role]?.includes(task.requiredRole) || false;
375
- if (!canSubstitute) {
376
- return false;
377
- }
378
- }
379
- // Check task type compatibility if present
380
- const rule = config.roleMatching.find((r) => r.role === role);
381
- if (!rule)
382
- return false;
383
- if (task.taskType && !rule.taskTypes.includes(task.taskType)) {
384
- return false;
385
- }
386
- return true;
387
- }
388
- /**
389
- * Check if a role can handle a task type
390
- *
391
- * @param role - Agent role
392
- * @param taskType - Task type
393
- * @param config - Assignment strategy
394
- * @returns True if role can handle the task type
395
- */
396
- canRoleHandleTaskType(role, taskType, config) {
397
- const rule = config.roleMatching.find((r) => r.role === role);
398
- if (!rule)
399
- return false;
400
- return rule.taskTypes.includes(taskType);
401
- }
402
- /**
403
- * Check if a task type is exclusive to another role
404
- *
405
- * @param role - Current role
406
- * @param taskType - Task type
407
- * @param config - Assignment strategy
408
- * @returns True if exclusive to another role
409
- */
410
- isExclusiveForOtherRole(role, taskType, config) {
411
- for (const rule of config.roleMatching) {
412
- if (rule.role !== role && rule.exclusive && rule.taskTypes.includes(taskType)) {
413
- return true;
414
- }
415
- }
416
- return false;
417
- }
418
- /**
419
- * Assign a specific task to an agent
420
- *
421
- * @param taskPath - Path to the task file
422
- * @param sessionName - Agent session name
423
- * @returns Assignment result
424
- */
425
- async assignTask(taskPath, sessionName) {
426
- const workload = await this.getAgentWorkload(sessionName);
427
- const projectPath = this.agentProjects.get(sessionName);
428
- if (!projectPath) {
429
- throw new Error(`No project associated with session: ${sessionName}`);
430
- }
431
- // Get task info
432
- const taskService = this.getTaskService(projectPath);
433
- const tasks = await taskService.getAllTasks();
434
- const task = tasks.find((t) => t.filePath === taskPath);
435
- if (!task) {
436
- throw new Error(`Task not found: ${taskPath}`);
437
- }
438
- const now = new Date().toISOString();
439
- // Create assignment record
440
- const assignment = {
441
- taskId: task.id,
442
- agentId: workload.agentId,
443
- sessionName,
444
- assignedAt: now,
445
- status: 'active',
446
- };
447
- // Add to assignment history
448
- const history = this.assignmentHistory.get(projectPath) || [];
449
- history.push(assignment);
450
- this.assignmentHistory.set(projectPath, history);
451
- // Update daily count
452
- const today = now.split('T')[0];
453
- const dailyRecord = this.dailyAssignments.get(sessionName);
454
- if (dailyRecord && dailyRecord.date === today) {
455
- dailyRecord.count++;
456
- }
457
- else {
458
- this.dailyAssignments.set(sessionName, { date: today, count: 1 });
459
- }
460
- // Update last assignment time
461
- this.lastAssignmentTime.set(sessionName, Date.now());
462
- const result = {
463
- taskId: task.id,
464
- taskPath,
465
- agentId: workload.agentId,
466
- sessionName,
467
- assignedAt: now,
468
- };
469
- // Emit event
470
- this.emitEvent({
471
- type: 'task_assigned',
472
- agentId: workload.agentId,
473
- sessionName,
474
- taskId: task.id,
475
- timestamp: now,
476
- metadata: {
477
- taskPath,
478
- taskTitle: task.title,
479
- priority: task.priority,
480
- },
481
- });
482
- // Refresh queue to reflect assignment
483
- await this.refreshQueue(projectPath);
484
- this.logger.info('Task assigned', {
485
- taskId: task.id,
486
- sessionName,
487
- taskTitle: task.title,
488
- });
489
- return result;
490
- }
491
- /**
492
- * Get the task queue for a project
493
- *
494
- * @param projectPath - Path to the project
495
- * @returns Task queue
496
- */
497
- async getTaskQueue(projectPath) {
498
- if (!this.queues.has(projectPath)) {
499
- await this.refreshQueue(projectPath);
500
- }
501
- return this.queues.get(projectPath);
502
- }
503
- /**
504
- * Refresh the task queue from the filesystem
505
- *
506
- * @param projectPath - Path to the project
507
- */
508
- async refreshQueue(projectPath) {
509
- const taskService = this.getTaskService(projectPath);
510
- const allTasks = await taskService.getAllTasks();
511
- // Get open tasks
512
- const openTasks = allTasks.filter((t) => t.status === 'open');
513
- // Get in-progress task IDs to check dependencies
514
- const inProgressTasks = allTasks.filter((t) => t.status === 'in_progress');
515
- const inProgressIds = new Set(inProgressTasks.map((t) => t.id));
516
- const openIds = new Set(openTasks.map((t) => t.id));
517
- // Build queue
518
- const queuedTasks = openTasks.map((task) => {
519
- // Parse dependencies from task content if available
520
- const dependencies = this.extractDependencies(task);
521
- // Calculate blocked by - tasks that are dependencies and not yet done
522
- const blockedBy = dependencies.filter((d) => inProgressIds.has(d) || openIds.has(d));
523
- return {
524
- taskId: task.id,
525
- taskPath: task.filePath,
526
- title: task.title,
527
- priority: this.getPriorityValue(task.priority),
528
- taskType: this.extractTaskType(task),
529
- requiredRole: task.assignee,
530
- dependencies,
531
- blockedBy,
532
- createdAt: task.createdAt,
533
- estimatedHours: this.extractEstimatedHours(task),
534
- labels: this.extractLabels(task),
535
- };
536
- });
537
- // Get assignment history
538
- const assignments = this.assignmentHistory.get(projectPath) || [];
539
- const config = await this.getConfig(projectPath);
540
- this.queues.set(projectPath, {
541
- projectPath,
542
- tasks: queuedTasks,
543
- assignments,
544
- config,
545
- lastUpdated: new Date().toISOString(),
546
- });
547
- this.logger.debug('Queue refreshed', {
548
- projectPath,
549
- taskCount: queuedTasks.length,
550
- });
551
- }
552
- /**
553
- * Convert priority string to numeric value
554
- *
555
- * @param priority - Priority string
556
- * @returns Numeric priority value
557
- */
558
- getPriorityValue(priority) {
559
- const values = {
560
- critical: AUTO_ASSIGN_CONSTANTS.PRIORITY.CRITICAL,
561
- high: AUTO_ASSIGN_CONSTANTS.PRIORITY.HIGH,
562
- medium: AUTO_ASSIGN_CONSTANTS.PRIORITY.MEDIUM,
563
- low: AUTO_ASSIGN_CONSTANTS.PRIORITY.LOW,
564
- backlog: AUTO_ASSIGN_CONSTANTS.PRIORITY.BACKLOG,
565
- };
566
- return values[priority.toLowerCase()] ?? AUTO_ASSIGN_CONSTANTS.PRIORITY.MEDIUM;
567
- }
568
- /**
569
- * Extract task type from task
570
- *
571
- * @param task - Task object
572
- * @returns Task type or undefined
573
- */
574
- extractTaskType(task) {
575
- // Try to infer from title or labels
576
- const title = task.title.toLowerCase();
577
- const taskTypes = Object.values(AUTO_ASSIGN_CONSTANTS.TASK_TYPES).flat();
578
- for (const type of taskTypes) {
579
- if (title.includes(type)) {
580
- return type;
581
- }
582
- }
583
- return undefined;
584
- }
585
- /**
586
- * Extract dependencies from task
587
- *
588
- * @param task - Task object
589
- * @returns Array of dependency task IDs
590
- */
591
- extractDependencies(task) {
592
- // Look for dependency patterns in description
593
- const depPattern = /depends on:?\s*([^\n]+)/i;
594
- const match = task.description.match(depPattern);
595
- if (match) {
596
- return match[1]
597
- .split(/[,\s]+/)
598
- .map((d) => d.trim())
599
- .filter((d) => d.length > 0);
600
- }
601
- return [];
602
- }
603
- /**
604
- * Extract estimated hours from task
605
- *
606
- * @param task - Task object
607
- * @returns Estimated hours or undefined
608
- */
609
- extractEstimatedHours(task) {
610
- const estPattern = /estimated:?\s*(\d+)\s*(hours?|h)/i;
611
- const match = task.description.match(estPattern);
612
- if (match) {
613
- return parseInt(match[1], 10);
614
- }
615
- return undefined;
616
- }
617
- /**
618
- * Extract labels from task
619
- *
620
- * @param task - Task object
621
- * @returns Array of labels
622
- */
623
- extractLabels(task) {
624
- // Look for label patterns
625
- const labelPattern = /labels?:?\s*([^\n]+)/i;
626
- const match = task.description.match(labelPattern);
627
- if (match) {
628
- return match[1]
629
- .split(/[,\s]+/)
630
- .map((l) => l.trim())
631
- .filter((l) => l.length > 0);
632
- }
633
- return [];
634
- }
635
- /**
636
- * Get an agent's current workload
637
- *
638
- * @param sessionName - Agent session name
639
- * @returns Agent workload information
640
- */
641
- async getAgentWorkload(sessionName) {
642
- const trackingService = this.getTaskTrackingService();
643
- const tasks = await trackingService.getAllInProgressTasks() || [];
644
- // Filter tasks for this agent
645
- const agentTasks = tasks.filter((t) => t.assignedSessionName === sessionName &&
646
- (t.status === 'assigned' || t.status === 'active'));
647
- // Calculate completed today
648
- const today = new Date().toISOString().split('T')[0];
649
- const dailyRecord = this.dailyAssignments.get(sessionName);
650
- const completedToday = dailyRecord?.date === today ? dailyRecord.count : 0;
651
- return {
652
- sessionName,
653
- agentId: agentTasks[0]?.assignedTeamMemberId || sessionName,
654
- role: this.getAgentRole(sessionName),
655
- currentTasks: agentTasks.map((t) => t.id),
656
- completedToday,
657
- averageIterations: 0, // Would need iteration tracking to calculate
658
- };
659
- }
660
- /**
661
- * Get the role for an agent session
662
- *
663
- * @param sessionName - Session name
664
- * @returns Role string
665
- */
666
- getAgentRole(sessionName) {
667
- // Parse role from session name convention (e.g., "project-developer-1")
668
- const parts = sessionName.split('-');
669
- if (parts.length >= 2) {
670
- // Common role patterns
671
- const roleKeywords = [
672
- 'developer',
673
- 'frontend-developer',
674
- 'backend-developer',
675
- 'qa',
676
- 'tester',
677
- 'pm',
678
- 'tpm',
679
- 'pgm',
680
- 'designer',
681
- 'orchestrator',
682
- ];
683
- for (const keyword of roleKeywords) {
684
- if (sessionName.includes(keyword)) {
685
- return keyword;
686
- }
687
- }
688
- }
689
- return 'developer'; // Default role
690
- }
691
- /**
692
- * Register an agent with a project
693
- *
694
- * @param sessionName - Agent session name
695
- * @param projectPath - Project path
696
- */
697
- registerAgent(sessionName, projectPath) {
698
- this.agentProjects.set(sessionName, projectPath);
699
- this.logger.debug('Agent registered', { sessionName, projectPath });
700
- }
701
- /**
702
- * Unregister an agent
703
- *
704
- * @param sessionName - Agent session name
705
- */
706
- unregisterAgent(sessionName) {
707
- this.agentProjects.delete(sessionName);
708
- this.logger.debug('Agent unregistered', { sessionName });
709
- }
710
- /**
711
- * Emit an assignment event
712
- *
713
- * @param event - Event to emit
714
- */
715
- emitEvent(event) {
716
- this.emit(event.type, event);
717
- this.emit('assignment_event', event);
718
- this.logger.debug('Event emitted', { type: event.type, taskId: event.taskId });
719
- }
720
- /**
721
- * Register a handler for task assignment events
722
- *
723
- * @param handler - Event handler function
724
- */
725
- onTaskAssigned(handler) {
726
- this.on('task_assigned', handler);
727
- }
728
- /**
729
- * Register a handler for agent idle events
730
- *
731
- * @param handler - Event handler function
732
- */
733
- onAgentIdle(handler) {
734
- this.on('agent_idle', handler);
735
- }
736
- /**
737
- * Subscribe to task tracking events for a project
738
- *
739
- * @param projectPath - Project path
740
- */
741
- subscribeToEvents(projectPath) {
742
- const trackingService = this.getTaskTrackingService();
743
- // Listen for task completions
744
- trackingService.on('task_completed', async (task) => {
745
- const sessionName = task.assignedSessionName;
746
- const agentProjectPath = this.agentProjects.get(sessionName);
747
- if (agentProjectPath === projectPath) {
748
- // Update assignment history
749
- const history = this.assignmentHistory.get(projectPath) || [];
750
- const assignment = history.find((a) => a.taskId === task.id && a.status === 'active');
751
- if (assignment) {
752
- assignment.status = 'completed';
753
- assignment.completedAt = new Date().toISOString();
754
- }
755
- // Emit completion event
756
- this.emitEvent({
757
- type: 'task_completed',
758
- agentId: task.assignedTeamMemberId,
759
- sessionName,
760
- taskId: task.id,
761
- timestamp: new Date().toISOString(),
762
- });
763
- // Try to assign next task
764
- await this.assignNextTask(sessionName);
765
- }
766
- });
767
- }
768
- /**
769
- * Pause auto-assignment for a project
770
- *
771
- * @param projectPath - Path to the project
772
- */
773
- async pauseAutoAssign(projectPath) {
774
- this.paused.add(projectPath);
775
- this.logger.info('Auto-assign paused', { projectPath });
776
- }
777
- /**
778
- * Resume auto-assignment for a project
779
- *
780
- * @param projectPath - Path to the project
781
- */
782
- async resumeAutoAssign(projectPath) {
783
- this.paused.delete(projectPath);
784
- this.logger.info('Auto-assign resumed', { projectPath });
785
- }
786
- /**
787
- * Check if auto-assignment is enabled for a project
788
- *
789
- * @param projectPath - Path to the project
790
- * @returns True if enabled and not paused
791
- */
792
- async isAutoAssignEnabled(projectPath) {
793
- if (this.paused.has(projectPath)) {
794
- return false;
795
- }
796
- const config = this.configs.get(projectPath);
797
- return config?.enabled ?? false;
798
- }
799
- /**
800
- * Mark a task as failed
801
- *
802
- * @param taskId - Task ID
803
- * @param sessionName - Agent session name
804
- * @param reason - Failure reason
805
- */
806
- async markTaskFailed(taskId, sessionName, reason) {
807
- const projectPath = this.agentProjects.get(sessionName);
808
- if (projectPath) {
809
- const history = this.assignmentHistory.get(projectPath) || [];
810
- const assignment = history.find((a) => a.taskId === taskId && a.status === 'active');
811
- if (assignment) {
812
- assignment.status = 'failed';
813
- }
814
- this.emitEvent({
815
- type: 'task_failed',
816
- agentId: assignment?.agentId || sessionName,
817
- sessionName,
818
- taskId,
819
- timestamp: new Date().toISOString(),
820
- metadata: { reason },
821
- });
822
- }
823
- }
824
- /**
825
- * Get assignment statistics for a project
826
- *
827
- * @param projectPath - Project path
828
- * @returns Assignment statistics
829
- */
830
- getStatistics(projectPath) {
831
- const history = this.assignmentHistory.get(projectPath) || [];
832
- return {
833
- totalAssigned: history.length,
834
- completed: history.filter((a) => a.status === 'completed').length,
835
- failed: history.filter((a) => a.status === 'failed').length,
836
- active: history.filter((a) => a.status === 'active').length,
837
- };
838
- }
839
- /**
840
- * Clear all cached data (for testing)
841
- */
842
- clearCache() {
843
- this.configs.clear();
844
- this.queues.clear();
845
- this.paused.clear();
846
- this.agentProjects.clear();
847
- this.assignmentHistory.clear();
848
- this.dailyAssignments.clear();
849
- this.lastAssignmentTime.clear();
850
- }
851
- }
852
- //# sourceMappingURL=auto-assign.service.js.map