@vibescope/mcp-server 0.0.1 → 0.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.
Files changed (173) hide show
  1. package/README.md +113 -98
  2. package/dist/api-client.d.ts +1169 -0
  3. package/dist/api-client.js +713 -0
  4. package/dist/cli.d.ts +1 -6
  5. package/dist/cli.js +39 -240
  6. package/dist/config/tool-categories.d.ts +31 -0
  7. package/dist/config/tool-categories.js +253 -0
  8. package/dist/handlers/blockers.js +57 -58
  9. package/dist/handlers/bodies-of-work.d.ts +2 -0
  10. package/dist/handlers/bodies-of-work.js +108 -477
  11. package/dist/handlers/cost.d.ts +1 -0
  12. package/dist/handlers/cost.js +35 -113
  13. package/dist/handlers/decisions.d.ts +2 -0
  14. package/dist/handlers/decisions.js +28 -27
  15. package/dist/handlers/deployment.js +113 -828
  16. package/dist/handlers/discovery.d.ts +3 -0
  17. package/dist/handlers/discovery.js +26 -627
  18. package/dist/handlers/fallback.d.ts +2 -0
  19. package/dist/handlers/fallback.js +56 -142
  20. package/dist/handlers/findings.d.ts +8 -1
  21. package/dist/handlers/findings.js +65 -68
  22. package/dist/handlers/git-issues.d.ts +9 -13
  23. package/dist/handlers/git-issues.js +80 -225
  24. package/dist/handlers/ideas.d.ts +3 -0
  25. package/dist/handlers/ideas.js +53 -134
  26. package/dist/handlers/index.d.ts +2 -0
  27. package/dist/handlers/index.js +6 -0
  28. package/dist/handlers/milestones.d.ts +2 -0
  29. package/dist/handlers/milestones.js +51 -98
  30. package/dist/handlers/organizations.js +79 -275
  31. package/dist/handlers/progress.d.ts +2 -0
  32. package/dist/handlers/progress.js +25 -123
  33. package/dist/handlers/project.js +42 -221
  34. package/dist/handlers/requests.d.ts +2 -0
  35. package/dist/handlers/requests.js +23 -83
  36. package/dist/handlers/session.js +119 -590
  37. package/dist/handlers/sprints.d.ts +32 -0
  38. package/dist/handlers/sprints.js +275 -0
  39. package/dist/handlers/tasks.d.ts +7 -10
  40. package/dist/handlers/tasks.js +245 -894
  41. package/dist/handlers/tool-docs.d.ts +9 -0
  42. package/dist/handlers/tool-docs.js +904 -0
  43. package/dist/handlers/types.d.ts +11 -3
  44. package/dist/handlers/validation.d.ts +1 -1
  45. package/dist/handlers/validation.js +38 -153
  46. package/dist/index.js +493 -162
  47. package/dist/knowledge.js +106 -9
  48. package/dist/tools.js +34 -4
  49. package/dist/validators.d.ts +21 -0
  50. package/dist/validators.js +91 -0
  51. package/package.json +2 -3
  52. package/src/api-client.ts +1822 -0
  53. package/src/cli.test.ts +128 -302
  54. package/src/cli.ts +41 -285
  55. package/src/handlers/__test-setup__.ts +215 -0
  56. package/src/handlers/__test-utils__.ts +4 -134
  57. package/src/handlers/blockers.test.ts +114 -124
  58. package/src/handlers/blockers.ts +68 -70
  59. package/src/handlers/bodies-of-work.test.ts +236 -831
  60. package/src/handlers/bodies-of-work.ts +210 -525
  61. package/src/handlers/cost.test.ts +149 -113
  62. package/src/handlers/cost.ts +44 -132
  63. package/src/handlers/decisions.test.ts +111 -209
  64. package/src/handlers/decisions.ts +35 -27
  65. package/src/handlers/deployment.test.ts +193 -239
  66. package/src/handlers/deployment.ts +143 -896
  67. package/src/handlers/discovery.test.ts +20 -67
  68. package/src/handlers/discovery.ts +29 -714
  69. package/src/handlers/fallback.test.ts +206 -361
  70. package/src/handlers/fallback.ts +81 -156
  71. package/src/handlers/findings.test.ts +229 -320
  72. package/src/handlers/findings.ts +76 -64
  73. package/src/handlers/git-issues.test.ts +623 -0
  74. package/src/handlers/git-issues.ts +174 -0
  75. package/src/handlers/ideas.test.ts +229 -343
  76. package/src/handlers/ideas.ts +69 -143
  77. package/src/handlers/index.ts +6 -0
  78. package/src/handlers/milestones.test.ts +167 -281
  79. package/src/handlers/milestones.ts +54 -93
  80. package/src/handlers/organizations.test.ts +275 -467
  81. package/src/handlers/organizations.ts +84 -294
  82. package/src/handlers/progress.test.ts +112 -218
  83. package/src/handlers/progress.ts +29 -142
  84. package/src/handlers/project.test.ts +203 -226
  85. package/src/handlers/project.ts +48 -238
  86. package/src/handlers/requests.test.ts +74 -342
  87. package/src/handlers/requests.ts +25 -83
  88. package/src/handlers/session.test.ts +276 -206
  89. package/src/handlers/session.ts +136 -662
  90. package/src/handlers/sprints.test.ts +711 -0
  91. package/src/handlers/sprints.ts +510 -0
  92. package/src/handlers/tasks.test.ts +669 -353
  93. package/src/handlers/tasks.ts +263 -1015
  94. package/src/handlers/tool-docs.ts +1024 -0
  95. package/src/handlers/types.ts +12 -4
  96. package/src/handlers/validation.test.ts +237 -568
  97. package/src/handlers/validation.ts +43 -167
  98. package/src/index.ts +493 -186
  99. package/src/tools.ts +2532 -0
  100. package/src/validators.test.ts +223 -223
  101. package/src/validators.ts +127 -0
  102. package/tsconfig.json +1 -1
  103. package/vitest.config.ts +14 -13
  104. package/dist/cli.test.d.ts +0 -1
  105. package/dist/cli.test.js +0 -367
  106. package/dist/handlers/__test-utils__.d.ts +0 -72
  107. package/dist/handlers/__test-utils__.js +0 -176
  108. package/dist/handlers/checkouts.d.ts +0 -37
  109. package/dist/handlers/checkouts.js +0 -377
  110. package/dist/handlers/knowledge-query.d.ts +0 -22
  111. package/dist/handlers/knowledge-query.js +0 -253
  112. package/dist/handlers/knowledge.d.ts +0 -12
  113. package/dist/handlers/knowledge.js +0 -108
  114. package/dist/handlers/roles.d.ts +0 -30
  115. package/dist/handlers/roles.js +0 -281
  116. package/dist/handlers/tasks.test.d.ts +0 -1
  117. package/dist/handlers/tasks.test.js +0 -431
  118. package/dist/utils.test.d.ts +0 -1
  119. package/dist/utils.test.js +0 -532
  120. package/dist/validators.test.d.ts +0 -1
  121. package/dist/validators.test.js +0 -176
  122. package/src/knowledge.ts +0 -132
  123. package/src/tmpclaude-0078-cwd +0 -1
  124. package/src/tmpclaude-0ee1-cwd +0 -1
  125. package/src/tmpclaude-2dd5-cwd +0 -1
  126. package/src/tmpclaude-344c-cwd +0 -1
  127. package/src/tmpclaude-3860-cwd +0 -1
  128. package/src/tmpclaude-4b63-cwd +0 -1
  129. package/src/tmpclaude-5c73-cwd +0 -1
  130. package/src/tmpclaude-5ee3-cwd +0 -1
  131. package/src/tmpclaude-6795-cwd +0 -1
  132. package/src/tmpclaude-709e-cwd +0 -1
  133. package/src/tmpclaude-9839-cwd +0 -1
  134. package/src/tmpclaude-d829-cwd +0 -1
  135. package/src/tmpclaude-e072-cwd +0 -1
  136. package/src/tmpclaude-f6ee-cwd +0 -1
  137. package/tmpclaude-0439-cwd +0 -1
  138. package/tmpclaude-132f-cwd +0 -1
  139. package/tmpclaude-15bb-cwd +0 -1
  140. package/tmpclaude-165a-cwd +0 -1
  141. package/tmpclaude-1ba9-cwd +0 -1
  142. package/tmpclaude-21a3-cwd +0 -1
  143. package/tmpclaude-2a38-cwd +0 -1
  144. package/tmpclaude-2adf-cwd +0 -1
  145. package/tmpclaude-2f56-cwd +0 -1
  146. package/tmpclaude-3626-cwd +0 -1
  147. package/tmpclaude-3727-cwd +0 -1
  148. package/tmpclaude-40bc-cwd +0 -1
  149. package/tmpclaude-436f-cwd +0 -1
  150. package/tmpclaude-4783-cwd +0 -1
  151. package/tmpclaude-4b6d-cwd +0 -1
  152. package/tmpclaude-4ba4-cwd +0 -1
  153. package/tmpclaude-51e6-cwd +0 -1
  154. package/tmpclaude-5ecf-cwd +0 -1
  155. package/tmpclaude-6f97-cwd +0 -1
  156. package/tmpclaude-7fb2-cwd +0 -1
  157. package/tmpclaude-825c-cwd +0 -1
  158. package/tmpclaude-8baf-cwd +0 -1
  159. package/tmpclaude-8d9f-cwd +0 -1
  160. package/tmpclaude-975c-cwd +0 -1
  161. package/tmpclaude-9983-cwd +0 -1
  162. package/tmpclaude-a045-cwd +0 -1
  163. package/tmpclaude-ac4a-cwd +0 -1
  164. package/tmpclaude-b593-cwd +0 -1
  165. package/tmpclaude-b891-cwd +0 -1
  166. package/tmpclaude-c032-cwd +0 -1
  167. package/tmpclaude-cf43-cwd +0 -1
  168. package/tmpclaude-d040-cwd +0 -1
  169. package/tmpclaude-dcdd-cwd +0 -1
  170. package/tmpclaude-dcee-cwd +0 -1
  171. package/tmpclaude-e16b-cwd +0 -1
  172. package/tmpclaude-ecd2-cwd +0 -1
  173. package/tmpclaude-f48d-cwd +0 -1
@@ -1,108 +0,0 @@
1
- /**
2
- * Knowledge Handlers
3
- *
4
- * Unified knowledge query to reduce tool calls and token costs.
5
- * Aggregates decisions, findings, blockers, Q&A, and task history.
6
- */
7
- import { validateRequired, validateUUID } from '../validators.js';
8
- const VALID_QUERY_TYPES = ['context', 'architecture', 'issues', 'history', 'qa'];
9
- const QUERY_TYPE_DESCRIPTIONS = {
10
- context: 'Key decisions, open blockers, recent Q&As, critical findings - use when starting work',
11
- architecture: 'All decisions + architecture-related findings - use when understanding codebase',
12
- issues: 'Open findings + blockers sorted by severity - use when fixing bugs',
13
- history: 'Completed tasks with summaries - use when understanding what was done',
14
- qa: 'Answered questions as Q&A pairs - use when looking for common questions',
15
- };
16
- export const queryKnowledge = async (args, ctx) => {
17
- const { project_id, query_type = 'context', limit = 20 } = args;
18
- validateRequired(project_id, 'project_id');
19
- validateUUID(project_id, 'project_id');
20
- if (!VALID_QUERY_TYPES.includes(query_type)) {
21
- throw new Error(`Invalid query_type '${query_type}'. Must be one of: ${VALID_QUERY_TYPES.join(', ')}`);
22
- }
23
- const { supabase } = ctx;
24
- // Call the database function
25
- const { data, error } = await supabase.rpc('query_knowledge', {
26
- p_project_id: project_id,
27
- p_query_type: query_type,
28
- p_limit: Math.min(limit, 50), // Cap at 50 to limit response size
29
- });
30
- if (error) {
31
- throw new Error(`Failed to query knowledge: ${error.message}`);
32
- }
33
- // Map database results to typed items
34
- const items = (data || []).map((row) => ({
35
- type: row.item_type,
36
- id: row.id,
37
- title: row.title,
38
- content: row.content,
39
- ...(row.severity && { severity: row.severity }),
40
- ...(row.status && { status: row.status }),
41
- created_at: row.created_at,
42
- }));
43
- // Generate summary based on query type and results
44
- const summary = generateSummary(query_type, items);
45
- // Estimate tokens (rough: ~4 chars per token)
46
- const responseJson = JSON.stringify({ items, summary });
47
- const tokenEstimate = Math.ceil(responseJson.length / 4);
48
- return {
49
- result: {
50
- query_type,
51
- project_id,
52
- description: QUERY_TYPE_DESCRIPTIONS[query_type],
53
- summary,
54
- items,
55
- count: items.length,
56
- token_estimate: tokenEstimate,
57
- },
58
- };
59
- };
60
- function generateSummary(queryType, items) {
61
- const counts = items.reduce((acc, item) => {
62
- acc[item.type] = (acc[item.type] || 0) + 1;
63
- return acc;
64
- }, {});
65
- const parts = [];
66
- switch (queryType) {
67
- case 'context':
68
- if (counts.blocker)
69
- parts.push(`${counts.blocker} open blocker(s)`);
70
- if (counts.finding)
71
- parts.push(`${counts.finding} critical/high finding(s)`);
72
- if (counts.decision)
73
- parts.push(`${counts.decision} recent decision(s)`);
74
- if (counts.qa)
75
- parts.push(`${counts.qa} answered question(s)`);
76
- break;
77
- case 'architecture':
78
- if (counts.decision)
79
- parts.push(`${counts.decision} architectural decision(s)`);
80
- if (counts.finding)
81
- parts.push(`${counts.finding} architecture finding(s)`);
82
- break;
83
- case 'issues':
84
- if (counts.blocker)
85
- parts.push(`${counts.blocker} blocker(s)`);
86
- if (counts.finding)
87
- parts.push(`${counts.finding} open finding(s)`);
88
- break;
89
- case 'history':
90
- if (counts.task)
91
- parts.push(`${counts.task} completed task(s)`);
92
- break;
93
- case 'qa':
94
- if (counts.qa)
95
- parts.push(`${counts.qa} Q&A pair(s)`);
96
- break;
97
- }
98
- if (parts.length === 0) {
99
- return `No ${queryType} items found.`;
100
- }
101
- return `Found ${parts.join(', ')}.`;
102
- }
103
- /**
104
- * Knowledge handlers registry
105
- */
106
- export const knowledgeHandlers = {
107
- query_knowledge: queryKnowledge,
108
- };
@@ -1,30 +0,0 @@
1
- /**
2
- * Role Handlers
3
- *
4
- * Manages agent roles for specialized work:
5
- * - get_role_settings: Get role configuration for a project
6
- * - update_role_settings: Update role settings
7
- * - set_session_role: Change the current session's role
8
- * - get_agents_by_role: Get active agents grouped by role
9
- */
10
- import type { Handler, HandlerRegistry } from './types.js';
11
- /**
12
- * Get role settings for a project
13
- */
14
- export declare const getRoleSettings: Handler;
15
- /**
16
- * Update role settings for a project
17
- */
18
- export declare const updateRoleSettings: Handler;
19
- /**
20
- * Set the current session's role
21
- */
22
- export declare const setSessionRole: Handler;
23
- /**
24
- * Get active agents grouped by role
25
- */
26
- export declare const getAgentsByRole: Handler;
27
- /**
28
- * Role handlers registry
29
- */
30
- export declare const roleHandlers: HandlerRegistry;
@@ -1,281 +0,0 @@
1
- /**
2
- * Role Handlers
3
- *
4
- * Manages agent roles for specialized work:
5
- * - get_role_settings: Get role configuration for a project
6
- * - update_role_settings: Update role settings
7
- * - set_session_role: Change the current session's role
8
- * - get_agents_by_role: Get active agents grouped by role
9
- */
10
- import { validateUUID, validateRequired } from '../validators.js';
11
- // Valid agent roles - must match AgentRole type in types.ts and database enum
12
- const VALID_ROLES = ['developer', 'validator', 'deployer', 'reviewer', 'maintainer'];
13
- function isValidRole(role) {
14
- return VALID_ROLES.includes(role);
15
- }
16
- /**
17
- * Verify the user owns or has access to the project
18
- * This is needed because MCP server uses service_role which bypasses RLS
19
- */
20
- async function verifyProjectAccess(ctx, projectId) {
21
- const { supabase, auth } = ctx;
22
- // Check if user owns the project
23
- const { data: ownedProject } = await supabase
24
- .from('projects')
25
- .select('id')
26
- .eq('id', projectId)
27
- .eq('user_id', auth.userId)
28
- .single();
29
- if (ownedProject)
30
- return;
31
- // Check if project is shared with user's organization (for org-scoped keys)
32
- if (auth.scope === 'organization' && auth.organizationId) {
33
- const { data: sharedProject } = await supabase
34
- .from('project_shares')
35
- .select('project_id')
36
- .eq('project_id', projectId)
37
- .eq('organization_id', auth.organizationId)
38
- .single();
39
- if (sharedProject)
40
- return;
41
- }
42
- throw new Error('Project not found or access denied');
43
- }
44
- /**
45
- * Get role settings for a project
46
- */
47
- export const getRoleSettings = async (args, ctx) => {
48
- const { project_id } = args;
49
- const { supabase } = ctx;
50
- validateRequired(project_id, 'project_id');
51
- validateUUID(project_id, 'project_id');
52
- // Verify user has access to this project
53
- await verifyProjectAccess(ctx, project_id);
54
- const { data: settings, error } = await supabase
55
- .from('project_role_settings')
56
- .select('*')
57
- .eq('project_id', project_id)
58
- .order('role');
59
- if (error) {
60
- throw new Error(`Failed to get role settings: ${error.message}`);
61
- }
62
- // If no settings exist, return defaults
63
- if (!settings || settings.length === 0) {
64
- return {
65
- result: {
66
- project_id,
67
- settings: VALID_ROLES.map(role => ({
68
- role,
69
- enabled: true,
70
- display_name: role.charAt(0).toUpperCase() + role.slice(1),
71
- description: getRoleDescription(role),
72
- })),
73
- note: 'Using default settings. Call update_role_settings to customize.',
74
- },
75
- };
76
- }
77
- return {
78
- result: {
79
- project_id,
80
- settings,
81
- },
82
- };
83
- };
84
- function getRoleDescription(role) {
85
- const descriptions = {
86
- developer: 'General development work, picks up any available task',
87
- validator: 'Focuses on validating completed tasks',
88
- deployer: 'Handles deployment coordination and monitoring',
89
- reviewer: 'Code review and quality checks',
90
- maintainer: 'Task management, git orchestration, housekeeping',
91
- };
92
- return descriptions[role];
93
- }
94
- /**
95
- * Update role settings for a project
96
- */
97
- export const updateRoleSettings = async (args, ctx) => {
98
- const { project_id, role, enabled, display_name, description, priority_filter, fallback_activities, auto_assign_validation, auto_assign_deployment, } = args;
99
- const { supabase } = ctx;
100
- validateRequired(project_id, 'project_id');
101
- validateUUID(project_id, 'project_id');
102
- validateRequired(role, 'role');
103
- if (!isValidRole(role)) {
104
- throw new Error(`Invalid role: ${role}. Valid roles: ${VALID_ROLES.join(', ')}`);
105
- }
106
- // Verify user has access to this project
107
- await verifyProjectAccess(ctx, project_id);
108
- const updates = {
109
- updated_at: new Date().toISOString(),
110
- };
111
- if (enabled !== undefined)
112
- updates.enabled = enabled;
113
- if (display_name !== undefined)
114
- updates.display_name = display_name;
115
- if (description !== undefined)
116
- updates.description = description;
117
- if (priority_filter !== undefined)
118
- updates.priority_filter = priority_filter;
119
- if (fallback_activities !== undefined)
120
- updates.fallback_activities = fallback_activities;
121
- if (auto_assign_validation !== undefined)
122
- updates.auto_assign_validation = auto_assign_validation;
123
- if (auto_assign_deployment !== undefined)
124
- updates.auto_assign_deployment = auto_assign_deployment;
125
- // Upsert the role settings
126
- const { data, error } = await supabase
127
- .from('project_role_settings')
128
- .upsert({
129
- project_id,
130
- role,
131
- ...updates,
132
- }, {
133
- onConflict: 'project_id,role',
134
- })
135
- .select()
136
- .single();
137
- if (error) {
138
- throw new Error(`Failed to update role settings: ${error.message}`);
139
- }
140
- return {
141
- result: {
142
- success: true,
143
- settings: data,
144
- },
145
- };
146
- };
147
- /**
148
- * Set the current session's role
149
- */
150
- export const setSessionRole = async (args, ctx) => {
151
- const { role, role_config } = args;
152
- const { supabase, session, updateSession } = ctx;
153
- validateRequired(role, 'role');
154
- if (!isValidRole(role)) {
155
- throw new Error(`Invalid role: ${role}. Valid roles: ${VALID_ROLES.join(', ')}`);
156
- }
157
- const sessionId = session.currentSessionId;
158
- if (!sessionId) {
159
- throw new Error('No active session. Call start_work_session first.');
160
- }
161
- const updates = {
162
- role,
163
- updated_at: new Date().toISOString(),
164
- };
165
- // Allow role_config for custom configurations (e.g., maintainer with specific focus areas)
166
- if (role_config) {
167
- updates.role_config = role_config;
168
- }
169
- const { error } = await supabase
170
- .from('agent_sessions')
171
- .update(updates)
172
- .eq('id', sessionId);
173
- if (error) {
174
- throw new Error(`Failed to set role: ${error.message}`);
175
- }
176
- // Update session state
177
- updateSession({ currentRole: role });
178
- // Get role-specific guidance
179
- const guidance = getRoleGuidance(role);
180
- return {
181
- result: {
182
- success: true,
183
- role,
184
- persona: session.currentPersona,
185
- guidance,
186
- },
187
- };
188
- };
189
- function getRoleGuidance(role) {
190
- const guidance = {
191
- developer: 'Focus on implementing features and fixing bugs. Use get_next_task to find work.',
192
- validator: 'Prioritize validation tasks. Use get_tasks_awaiting_validation to find completed tasks to review.',
193
- deployer: 'Monitor deployment status with check_deployment_status. Handle deployment requests and coordination.',
194
- reviewer: 'Run code reviews using code_review fallback activity. Check for security and quality issues.',
195
- maintainer: 'Handle task management, git orchestration. Run performance_audit, dependency_audit when idle.',
196
- };
197
- return guidance[role];
198
- }
199
- /**
200
- * Get active agents grouped by role
201
- */
202
- export const getAgentsByRole = async (args, ctx) => {
203
- const { project_id } = args;
204
- const { supabase } = ctx;
205
- validateRequired(project_id, 'project_id');
206
- validateUUID(project_id, 'project_id');
207
- // Verify user has access to this project
208
- await verifyProjectAccess(ctx, project_id);
209
- const { data: agents, error } = await supabase
210
- .from('agent_sessions')
211
- .select(`
212
- id,
213
- agent_name,
214
- role,
215
- status,
216
- current_task_id,
217
- last_synced_at,
218
- role_config
219
- `)
220
- .eq('project_id', project_id)
221
- .neq('status', 'disconnected')
222
- .gte('last_synced_at', new Date(Date.now() - 5 * 60 * 1000).toISOString());
223
- if (error) {
224
- throw new Error(`Failed to get agents: ${error.message}`);
225
- }
226
- // Group by role
227
- const byRole = {};
228
- for (const agent of agents || []) {
229
- const role = agent.role || 'developer';
230
- if (!byRole[role]) {
231
- byRole[role] = [];
232
- }
233
- byRole[role].push(agent);
234
- }
235
- // Get current task titles
236
- const taskIds = (agents || [])
237
- .map(a => a.current_task_id)
238
- .filter((id) => !!id);
239
- let taskTitles = {};
240
- if (taskIds.length > 0) {
241
- const { data: tasks } = await supabase
242
- .from('tasks')
243
- .select('id, title')
244
- .in('id', taskIds);
245
- taskTitles = (tasks || []).reduce((acc, t) => {
246
- acc[t.id] = t.title;
247
- return acc;
248
- }, {});
249
- }
250
- // Enrich agents with task titles
251
- const enrichedByRole = {};
252
- for (const [role, roleAgents] of Object.entries(byRole)) {
253
- enrichedByRole[role] = roleAgents.map(agent => ({
254
- id: agent.id,
255
- agent_name: agent.agent_name,
256
- role: agent.role || 'developer',
257
- status: agent.status,
258
- current_task: agent.current_task_id
259
- ? { id: agent.current_task_id, title: taskTitles[agent.current_task_id] || 'Unknown' }
260
- : null,
261
- last_synced_at: agent.last_synced_at,
262
- }));
263
- }
264
- return {
265
- result: {
266
- project_id,
267
- total_agents: agents?.length || 0,
268
- by_role: enrichedByRole,
269
- available_roles: VALID_ROLES,
270
- },
271
- };
272
- };
273
- /**
274
- * Role handlers registry
275
- */
276
- export const roleHandlers = {
277
- get_role_settings: getRoleSettings,
278
- update_role_settings: updateRoleSettings,
279
- set_session_role: setSessionRole,
280
- get_agents_by_role: getAgentsByRole,
281
- };
@@ -1 +0,0 @@
1
- export {};