@vibescope/mcp-server 0.0.1
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 +98 -0
- package/dist/cli.d.ts +34 -0
- package/dist/cli.js +356 -0
- package/dist/cli.test.d.ts +1 -0
- package/dist/cli.test.js +367 -0
- package/dist/handlers/__test-utils__.d.ts +72 -0
- package/dist/handlers/__test-utils__.js +176 -0
- package/dist/handlers/blockers.d.ts +18 -0
- package/dist/handlers/blockers.js +81 -0
- package/dist/handlers/bodies-of-work.d.ts +34 -0
- package/dist/handlers/bodies-of-work.js +614 -0
- package/dist/handlers/checkouts.d.ts +37 -0
- package/dist/handlers/checkouts.js +377 -0
- package/dist/handlers/cost.d.ts +39 -0
- package/dist/handlers/cost.js +247 -0
- package/dist/handlers/decisions.d.ts +16 -0
- package/dist/handlers/decisions.js +64 -0
- package/dist/handlers/deployment.d.ts +36 -0
- package/dist/handlers/deployment.js +1062 -0
- package/dist/handlers/discovery.d.ts +14 -0
- package/dist/handlers/discovery.js +870 -0
- package/dist/handlers/fallback.d.ts +18 -0
- package/dist/handlers/fallback.js +216 -0
- package/dist/handlers/findings.d.ts +18 -0
- package/dist/handlers/findings.js +110 -0
- package/dist/handlers/git-issues.d.ts +22 -0
- package/dist/handlers/git-issues.js +247 -0
- package/dist/handlers/ideas.d.ts +19 -0
- package/dist/handlers/ideas.js +188 -0
- package/dist/handlers/index.d.ts +29 -0
- package/dist/handlers/index.js +65 -0
- package/dist/handlers/knowledge-query.d.ts +22 -0
- package/dist/handlers/knowledge-query.js +253 -0
- package/dist/handlers/knowledge.d.ts +12 -0
- package/dist/handlers/knowledge.js +108 -0
- package/dist/handlers/milestones.d.ts +20 -0
- package/dist/handlers/milestones.js +179 -0
- package/dist/handlers/organizations.d.ts +36 -0
- package/dist/handlers/organizations.js +428 -0
- package/dist/handlers/progress.d.ts +14 -0
- package/dist/handlers/progress.js +149 -0
- package/dist/handlers/project.d.ts +20 -0
- package/dist/handlers/project.js +278 -0
- package/dist/handlers/requests.d.ts +16 -0
- package/dist/handlers/requests.js +131 -0
- package/dist/handlers/roles.d.ts +30 -0
- package/dist/handlers/roles.js +281 -0
- package/dist/handlers/session.d.ts +20 -0
- package/dist/handlers/session.js +791 -0
- package/dist/handlers/tasks.d.ts +52 -0
- package/dist/handlers/tasks.js +1111 -0
- package/dist/handlers/tasks.test.d.ts +1 -0
- package/dist/handlers/tasks.test.js +431 -0
- package/dist/handlers/types.d.ts +94 -0
- package/dist/handlers/types.js +1 -0
- package/dist/handlers/validation.d.ts +16 -0
- package/dist/handlers/validation.js +188 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2707 -0
- package/dist/knowledge.d.ts +6 -0
- package/dist/knowledge.js +121 -0
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +2498 -0
- package/dist/utils.d.ts +149 -0
- package/dist/utils.js +317 -0
- package/dist/utils.test.d.ts +1 -0
- package/dist/utils.test.js +532 -0
- package/dist/validators.d.ts +35 -0
- package/dist/validators.js +111 -0
- package/dist/validators.test.d.ts +1 -0
- package/dist/validators.test.js +176 -0
- package/package.json +44 -0
- package/src/cli.test.ts +442 -0
- package/src/cli.ts +439 -0
- package/src/handlers/__test-utils__.ts +217 -0
- package/src/handlers/blockers.test.ts +390 -0
- package/src/handlers/blockers.ts +110 -0
- package/src/handlers/bodies-of-work.test.ts +1276 -0
- package/src/handlers/bodies-of-work.ts +783 -0
- package/src/handlers/cost.test.ts +436 -0
- package/src/handlers/cost.ts +322 -0
- package/src/handlers/decisions.test.ts +401 -0
- package/src/handlers/decisions.ts +86 -0
- package/src/handlers/deployment.test.ts +516 -0
- package/src/handlers/deployment.ts +1289 -0
- package/src/handlers/discovery.test.ts +254 -0
- package/src/handlers/discovery.ts +969 -0
- package/src/handlers/fallback.test.ts +687 -0
- package/src/handlers/fallback.ts +260 -0
- package/src/handlers/findings.test.ts +565 -0
- package/src/handlers/findings.ts +153 -0
- package/src/handlers/ideas.test.ts +753 -0
- package/src/handlers/ideas.ts +247 -0
- package/src/handlers/index.ts +69 -0
- package/src/handlers/milestones.test.ts +584 -0
- package/src/handlers/milestones.ts +217 -0
- package/src/handlers/organizations.test.ts +997 -0
- package/src/handlers/organizations.ts +550 -0
- package/src/handlers/progress.test.ts +369 -0
- package/src/handlers/progress.ts +188 -0
- package/src/handlers/project.test.ts +562 -0
- package/src/handlers/project.ts +352 -0
- package/src/handlers/requests.test.ts +531 -0
- package/src/handlers/requests.ts +150 -0
- package/src/handlers/session.test.ts +459 -0
- package/src/handlers/session.ts +912 -0
- package/src/handlers/tasks.test.ts +602 -0
- package/src/handlers/tasks.ts +1393 -0
- package/src/handlers/types.ts +88 -0
- package/src/handlers/validation.test.ts +880 -0
- package/src/handlers/validation.ts +223 -0
- package/src/index.ts +3205 -0
- package/src/knowledge.ts +132 -0
- package/src/tmpclaude-0078-cwd +1 -0
- package/src/tmpclaude-0ee1-cwd +1 -0
- package/src/tmpclaude-2dd5-cwd +1 -0
- package/src/tmpclaude-344c-cwd +1 -0
- package/src/tmpclaude-3860-cwd +1 -0
- package/src/tmpclaude-4b63-cwd +1 -0
- package/src/tmpclaude-5c73-cwd +1 -0
- package/src/tmpclaude-5ee3-cwd +1 -0
- package/src/tmpclaude-6795-cwd +1 -0
- package/src/tmpclaude-709e-cwd +1 -0
- package/src/tmpclaude-9839-cwd +1 -0
- package/src/tmpclaude-d829-cwd +1 -0
- package/src/tmpclaude-e072-cwd +1 -0
- package/src/tmpclaude-f6ee-cwd +1 -0
- package/src/utils.test.ts +681 -0
- package/src/utils.ts +375 -0
- package/src/validators.test.ts +223 -0
- package/src/validators.ts +122 -0
- package/tmpclaude-0439-cwd +1 -0
- package/tmpclaude-132f-cwd +1 -0
- package/tmpclaude-15bb-cwd +1 -0
- package/tmpclaude-165a-cwd +1 -0
- package/tmpclaude-1ba9-cwd +1 -0
- package/tmpclaude-21a3-cwd +1 -0
- package/tmpclaude-2a38-cwd +1 -0
- package/tmpclaude-2adf-cwd +1 -0
- package/tmpclaude-2f56-cwd +1 -0
- package/tmpclaude-3626-cwd +1 -0
- package/tmpclaude-3727-cwd +1 -0
- package/tmpclaude-40bc-cwd +1 -0
- package/tmpclaude-436f-cwd +1 -0
- package/tmpclaude-4783-cwd +1 -0
- package/tmpclaude-4b6d-cwd +1 -0
- package/tmpclaude-4ba4-cwd +1 -0
- package/tmpclaude-51e6-cwd +1 -0
- package/tmpclaude-5ecf-cwd +1 -0
- package/tmpclaude-6f97-cwd +1 -0
- package/tmpclaude-7fb2-cwd +1 -0
- package/tmpclaude-825c-cwd +1 -0
- package/tmpclaude-8baf-cwd +1 -0
- package/tmpclaude-8d9f-cwd +1 -0
- package/tmpclaude-975c-cwd +1 -0
- package/tmpclaude-9983-cwd +1 -0
- package/tmpclaude-a045-cwd +1 -0
- package/tmpclaude-ac4a-cwd +1 -0
- package/tmpclaude-b593-cwd +1 -0
- package/tmpclaude-b891-cwd +1 -0
- package/tmpclaude-c032-cwd +1 -0
- package/tmpclaude-cf43-cwd +1 -0
- package/tmpclaude-d040-cwd +1 -0
- package/tmpclaude-dcdd-cwd +1 -0
- package/tmpclaude-dcee-cwd +1 -0
- package/tmpclaude-e16b-cwd +1 -0
- package/tmpclaude-ecd2-cwd +1 -0
- package/tmpclaude-f48d-cwd +1 -0
- package/tsconfig.json +16 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles background activities when idle:
|
|
5
|
+
* - start_fallback_activity
|
|
6
|
+
* - stop_fallback_activity
|
|
7
|
+
* - get_activity_history
|
|
8
|
+
* - get_activity_schedules
|
|
9
|
+
*/
|
|
10
|
+
import type { Handler, HandlerRegistry } from './types.js';
|
|
11
|
+
export declare const startFallbackActivity: Handler;
|
|
12
|
+
export declare const stopFallbackActivity: Handler;
|
|
13
|
+
export declare const getActivityHistory: Handler;
|
|
14
|
+
export declare const getActivitySchedules: Handler;
|
|
15
|
+
/**
|
|
16
|
+
* Fallback handlers registry
|
|
17
|
+
*/
|
|
18
|
+
export declare const fallbackHandlers: HandlerRegistry;
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles background activities when idle:
|
|
5
|
+
* - start_fallback_activity
|
|
6
|
+
* - stop_fallback_activity
|
|
7
|
+
* - get_activity_history
|
|
8
|
+
* - get_activity_schedules
|
|
9
|
+
*/
|
|
10
|
+
import { validateRequired, validateUUID } from '../validators.js';
|
|
11
|
+
import { FALLBACK_ACTIVITIES } from '../utils.js';
|
|
12
|
+
const VALID_ACTIVITIES = [
|
|
13
|
+
'feature_ideation',
|
|
14
|
+
'code_review',
|
|
15
|
+
'performance_audit',
|
|
16
|
+
'ux_review',
|
|
17
|
+
'cost_analysis',
|
|
18
|
+
'security_review',
|
|
19
|
+
'test_coverage',
|
|
20
|
+
'documentation_review',
|
|
21
|
+
'dependency_audit',
|
|
22
|
+
'validate_completed_tasks',
|
|
23
|
+
];
|
|
24
|
+
export const startFallbackActivity = async (args, ctx) => {
|
|
25
|
+
const { project_id, activity } = args;
|
|
26
|
+
validateRequired(project_id, 'project_id');
|
|
27
|
+
validateUUID(project_id, 'project_id');
|
|
28
|
+
validateRequired(activity, 'activity');
|
|
29
|
+
if (!VALID_ACTIVITIES.includes(activity)) {
|
|
30
|
+
throw new Error(`Invalid activity. Must be one of: ${VALID_ACTIVITIES.join(', ')}`);
|
|
31
|
+
}
|
|
32
|
+
const { supabase, session } = ctx;
|
|
33
|
+
const currentSessionId = session.currentSessionId;
|
|
34
|
+
// Update the current session's fallback activity
|
|
35
|
+
const { error: updateError } = await supabase
|
|
36
|
+
.from('agent_sessions')
|
|
37
|
+
.update({
|
|
38
|
+
current_fallback_activity: activity,
|
|
39
|
+
current_task_id: null, // Clear any task when starting fallback
|
|
40
|
+
status: 'active',
|
|
41
|
+
last_synced_at: new Date().toISOString(),
|
|
42
|
+
})
|
|
43
|
+
.eq('id', currentSessionId);
|
|
44
|
+
if (updateError)
|
|
45
|
+
throw updateError;
|
|
46
|
+
// Get the activity details for the response
|
|
47
|
+
const activityInfo = FALLBACK_ACTIVITIES.find((a) => a.activity === activity);
|
|
48
|
+
return {
|
|
49
|
+
result: {
|
|
50
|
+
success: true,
|
|
51
|
+
activity,
|
|
52
|
+
title: activityInfo?.title || activity,
|
|
53
|
+
description: activityInfo?.description || '',
|
|
54
|
+
prompt: activityInfo?.prompt || '',
|
|
55
|
+
message: `Started fallback activity: ${activityInfo?.title || activity}`,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export const stopFallbackActivity = async (args, ctx) => {
|
|
60
|
+
const { project_id, summary } = args;
|
|
61
|
+
validateRequired(project_id, 'project_id');
|
|
62
|
+
validateUUID(project_id, 'project_id');
|
|
63
|
+
const { supabase, session } = ctx;
|
|
64
|
+
const currentSessionId = session.currentSessionId;
|
|
65
|
+
// Get the current session's fallback activity before clearing it
|
|
66
|
+
const { data: sessionData, error: sessionError } = await supabase
|
|
67
|
+
.from('agent_sessions')
|
|
68
|
+
.select('current_fallback_activity')
|
|
69
|
+
.eq('id', currentSessionId)
|
|
70
|
+
.single();
|
|
71
|
+
if (sessionError)
|
|
72
|
+
throw sessionError;
|
|
73
|
+
const activityType = sessionData?.current_fallback_activity;
|
|
74
|
+
// Log the activity completion to history if there was an active activity
|
|
75
|
+
if (activityType) {
|
|
76
|
+
const completedAt = new Date().toISOString();
|
|
77
|
+
// Insert history record
|
|
78
|
+
await supabase.from('background_activity_history').insert({
|
|
79
|
+
project_id,
|
|
80
|
+
activity_type: activityType,
|
|
81
|
+
completed_at: completedAt,
|
|
82
|
+
completed_by_session_id: currentSessionId,
|
|
83
|
+
summary: summary || null,
|
|
84
|
+
});
|
|
85
|
+
// Update schedule if one exists for this activity
|
|
86
|
+
const { data: schedule } = await supabase
|
|
87
|
+
.from('background_activity_schedules')
|
|
88
|
+
.select('*')
|
|
89
|
+
.eq('project_id', project_id)
|
|
90
|
+
.eq('activity_type', activityType)
|
|
91
|
+
.eq('enabled', true)
|
|
92
|
+
.single();
|
|
93
|
+
if (schedule) {
|
|
94
|
+
let nextRunAt = null;
|
|
95
|
+
let enabled = true;
|
|
96
|
+
// Calculate next run time based on schedule type
|
|
97
|
+
const completedDate = new Date(completedAt);
|
|
98
|
+
switch (schedule.schedule_type) {
|
|
99
|
+
case 'once':
|
|
100
|
+
enabled = false;
|
|
101
|
+
break;
|
|
102
|
+
case 'daily':
|
|
103
|
+
completedDate.setDate(completedDate.getDate() + 1);
|
|
104
|
+
nextRunAt = completedDate.toISOString();
|
|
105
|
+
break;
|
|
106
|
+
case 'weekly':
|
|
107
|
+
completedDate.setDate(completedDate.getDate() + 7);
|
|
108
|
+
nextRunAt = completedDate.toISOString();
|
|
109
|
+
break;
|
|
110
|
+
case 'monthly':
|
|
111
|
+
completedDate.setDate(completedDate.getDate() + 30);
|
|
112
|
+
nextRunAt = completedDate.toISOString();
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
await supabase
|
|
116
|
+
.from('background_activity_schedules')
|
|
117
|
+
.update({ next_run_at: nextRunAt, enabled })
|
|
118
|
+
.eq('id', schedule.id);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Clear the current session's fallback activity
|
|
122
|
+
const { error: updateError } = await supabase
|
|
123
|
+
.from('agent_sessions')
|
|
124
|
+
.update({
|
|
125
|
+
current_fallback_activity: null,
|
|
126
|
+
status: 'idle',
|
|
127
|
+
last_synced_at: new Date().toISOString(),
|
|
128
|
+
})
|
|
129
|
+
.eq('id', currentSessionId);
|
|
130
|
+
if (updateError)
|
|
131
|
+
throw updateError;
|
|
132
|
+
return {
|
|
133
|
+
result: {
|
|
134
|
+
success: true,
|
|
135
|
+
message: activityType
|
|
136
|
+
? `Fallback activity '${activityType}' completed and logged to history`
|
|
137
|
+
: 'Fallback activity stopped',
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
export const getActivityHistory = async (args, ctx) => {
|
|
142
|
+
const { project_id, activity_type, limit = 50 } = args;
|
|
143
|
+
validateRequired(project_id, 'project_id');
|
|
144
|
+
validateUUID(project_id, 'project_id');
|
|
145
|
+
const { supabase } = ctx;
|
|
146
|
+
let query = supabase
|
|
147
|
+
.from('background_activity_history')
|
|
148
|
+
.select(`
|
|
149
|
+
id,
|
|
150
|
+
activity_type,
|
|
151
|
+
completed_at,
|
|
152
|
+
completed_by_session_id,
|
|
153
|
+
summary,
|
|
154
|
+
created_at,
|
|
155
|
+
agent_sessions!completed_by_session_id (
|
|
156
|
+
agent_name
|
|
157
|
+
)
|
|
158
|
+
`)
|
|
159
|
+
.eq('project_id', project_id)
|
|
160
|
+
.order('completed_at', { ascending: false })
|
|
161
|
+
.limit(limit);
|
|
162
|
+
if (activity_type) {
|
|
163
|
+
query = query.eq('activity_type', activity_type);
|
|
164
|
+
}
|
|
165
|
+
const { data: history, error } = await query;
|
|
166
|
+
if (error)
|
|
167
|
+
throw error;
|
|
168
|
+
// Also get the most recent completion for each activity type
|
|
169
|
+
const latestByType = {};
|
|
170
|
+
for (const entry of history || []) {
|
|
171
|
+
if (!latestByType[entry.activity_type]) {
|
|
172
|
+
latestByType[entry.activity_type] = entry;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
result: {
|
|
177
|
+
history: history || [],
|
|
178
|
+
latest_by_type: latestByType,
|
|
179
|
+
count: history?.length || 0,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
export const getActivitySchedules = async (args, ctx) => {
|
|
184
|
+
const { project_id } = args;
|
|
185
|
+
validateRequired(project_id, 'project_id');
|
|
186
|
+
validateUUID(project_id, 'project_id');
|
|
187
|
+
const { supabase } = ctx;
|
|
188
|
+
const { data: schedules, error } = await supabase
|
|
189
|
+
.from('background_activity_schedules')
|
|
190
|
+
.select('*')
|
|
191
|
+
.eq('project_id', project_id)
|
|
192
|
+
.order('activity_type');
|
|
193
|
+
if (error)
|
|
194
|
+
throw error;
|
|
195
|
+
// Identify which activities are "due" (next_run_at < now AND enabled)
|
|
196
|
+
const now = new Date();
|
|
197
|
+
const dueActivities = (schedules || [])
|
|
198
|
+
.filter((s) => s.enabled && s.next_run_at && new Date(s.next_run_at) < now)
|
|
199
|
+
.map((s) => s.activity_type);
|
|
200
|
+
return {
|
|
201
|
+
result: {
|
|
202
|
+
schedules: schedules || [],
|
|
203
|
+
due_activities: dueActivities,
|
|
204
|
+
count: schedules?.length || 0,
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* Fallback handlers registry
|
|
210
|
+
*/
|
|
211
|
+
export const fallbackHandlers = {
|
|
212
|
+
start_fallback_activity: startFallbackActivity,
|
|
213
|
+
stop_fallback_activity: stopFallbackActivity,
|
|
214
|
+
get_activity_history: getActivityHistory,
|
|
215
|
+
get_activity_schedules: getActivitySchedules,
|
|
216
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Findings Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles audit findings and knowledge base:
|
|
5
|
+
* - add_finding
|
|
6
|
+
* - get_findings
|
|
7
|
+
* - update_finding
|
|
8
|
+
* - delete_finding
|
|
9
|
+
*/
|
|
10
|
+
import type { Handler, HandlerRegistry } from './types.js';
|
|
11
|
+
export declare const addFinding: Handler;
|
|
12
|
+
export declare const getFindings: Handler;
|
|
13
|
+
export declare const updateFinding: Handler;
|
|
14
|
+
export declare const deleteFinding: Handler;
|
|
15
|
+
/**
|
|
16
|
+
* Findings handlers registry
|
|
17
|
+
*/
|
|
18
|
+
export declare const findingHandlers: HandlerRegistry;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Findings Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles audit findings and knowledge base:
|
|
5
|
+
* - add_finding
|
|
6
|
+
* - get_findings
|
|
7
|
+
* - update_finding
|
|
8
|
+
* - delete_finding
|
|
9
|
+
*/
|
|
10
|
+
import { validateRequired, validateUUID } from '../validators.js';
|
|
11
|
+
export const addFinding = async (args, ctx) => {
|
|
12
|
+
const { project_id, category, title, description, severity, file_path, line_number, related_task_id } = args;
|
|
13
|
+
validateRequired(project_id, 'project_id');
|
|
14
|
+
validateUUID(project_id, 'project_id');
|
|
15
|
+
validateRequired(title, 'title');
|
|
16
|
+
if (related_task_id)
|
|
17
|
+
validateUUID(related_task_id, 'related_task_id');
|
|
18
|
+
const { supabase, session } = ctx;
|
|
19
|
+
const { data, error } = await supabase
|
|
20
|
+
.from('findings')
|
|
21
|
+
.insert({
|
|
22
|
+
project_id,
|
|
23
|
+
category: category || 'other',
|
|
24
|
+
title,
|
|
25
|
+
description: description || null,
|
|
26
|
+
severity: severity || 'info',
|
|
27
|
+
file_path: file_path || null,
|
|
28
|
+
line_number: line_number || null,
|
|
29
|
+
related_task_id: related_task_id || null,
|
|
30
|
+
created_by: 'agent',
|
|
31
|
+
created_by_session_id: session.currentSessionId,
|
|
32
|
+
})
|
|
33
|
+
.select('id')
|
|
34
|
+
.single();
|
|
35
|
+
if (error)
|
|
36
|
+
throw new Error(`Failed to add finding: ${error.message}`);
|
|
37
|
+
return { result: { success: true, finding_id: data.id, title } };
|
|
38
|
+
};
|
|
39
|
+
export const getFindings = async (args, ctx) => {
|
|
40
|
+
const { project_id, category, severity, status, limit } = args;
|
|
41
|
+
validateRequired(project_id, 'project_id');
|
|
42
|
+
validateUUID(project_id, 'project_id');
|
|
43
|
+
const { supabase } = ctx;
|
|
44
|
+
let query = supabase
|
|
45
|
+
.from('findings')
|
|
46
|
+
.select('id, title, category, severity, status, file_path, created_at')
|
|
47
|
+
.eq('project_id', project_id)
|
|
48
|
+
.order('created_at', { ascending: false })
|
|
49
|
+
.limit(limit || 50);
|
|
50
|
+
if (category)
|
|
51
|
+
query = query.eq('category', category);
|
|
52
|
+
if (severity)
|
|
53
|
+
query = query.eq('severity', severity);
|
|
54
|
+
if (status)
|
|
55
|
+
query = query.eq('status', status);
|
|
56
|
+
const { data, error } = await query;
|
|
57
|
+
if (error)
|
|
58
|
+
throw new Error(`Failed to get findings: ${error.message}`);
|
|
59
|
+
return { result: { findings: data } };
|
|
60
|
+
};
|
|
61
|
+
export const updateFinding = async (args, ctx) => {
|
|
62
|
+
const { finding_id, status, resolution_note, title, description, severity } = args;
|
|
63
|
+
validateRequired(finding_id, 'finding_id');
|
|
64
|
+
validateUUID(finding_id, 'finding_id');
|
|
65
|
+
const { supabase, session } = ctx;
|
|
66
|
+
const updates = { updated_at: new Date().toISOString() };
|
|
67
|
+
if (title)
|
|
68
|
+
updates.title = title;
|
|
69
|
+
if (description)
|
|
70
|
+
updates.description = description;
|
|
71
|
+
if (severity)
|
|
72
|
+
updates.severity = severity;
|
|
73
|
+
if (status) {
|
|
74
|
+
updates.status = status;
|
|
75
|
+
if (status === 'addressed' || status === 'dismissed' || status === 'wontfix') {
|
|
76
|
+
updates.addressed_at = new Date().toISOString();
|
|
77
|
+
updates.addressed_by_session_id = session.currentSessionId;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (resolution_note)
|
|
81
|
+
updates.resolution_note = resolution_note;
|
|
82
|
+
const { error } = await supabase
|
|
83
|
+
.from('findings')
|
|
84
|
+
.update(updates)
|
|
85
|
+
.eq('id', finding_id);
|
|
86
|
+
if (error)
|
|
87
|
+
throw new Error(`Failed to update finding: ${error.message}`);
|
|
88
|
+
return { result: { success: true, finding_id } };
|
|
89
|
+
};
|
|
90
|
+
export const deleteFinding = async (args, ctx) => {
|
|
91
|
+
const { finding_id } = args;
|
|
92
|
+
validateRequired(finding_id, 'finding_id');
|
|
93
|
+
validateUUID(finding_id, 'finding_id');
|
|
94
|
+
const { error } = await ctx.supabase
|
|
95
|
+
.from('findings')
|
|
96
|
+
.delete()
|
|
97
|
+
.eq('id', finding_id);
|
|
98
|
+
if (error)
|
|
99
|
+
throw new Error(`Failed to delete finding: ${error.message}`);
|
|
100
|
+
return { result: { success: true } };
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Findings handlers registry
|
|
104
|
+
*/
|
|
105
|
+
export const findingHandlers = {
|
|
106
|
+
add_finding: addFinding,
|
|
107
|
+
get_findings: getFindings,
|
|
108
|
+
update_finding: updateFinding,
|
|
109
|
+
delete_finding: deleteFinding,
|
|
110
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Issues Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles git-related issue tracking:
|
|
5
|
+
* - get_git_issues
|
|
6
|
+
* - create_git_issue
|
|
7
|
+
* - resolve_git_issue
|
|
8
|
+
* - dismiss_git_issue
|
|
9
|
+
*/
|
|
10
|
+
import type { Handler, HandlerRegistry } from './types.js';
|
|
11
|
+
export declare const getGitIssues: Handler;
|
|
12
|
+
export declare const createGitIssue: Handler;
|
|
13
|
+
export declare const resolveGitIssue: Handler;
|
|
14
|
+
export declare const dismissGitIssue: Handler;
|
|
15
|
+
/**
|
|
16
|
+
* Auto-resolve git issues for a branch when it becomes mergeable
|
|
17
|
+
*/
|
|
18
|
+
export declare function autoResolveGitIssuesForBranch(supabase: import('@supabase/supabase-js').SupabaseClient, projectId: string, branchName: string, sessionId: string | null): Promise<number>;
|
|
19
|
+
/**
|
|
20
|
+
* Git Issues handlers registry
|
|
21
|
+
*/
|
|
22
|
+
export declare const gitIssuesHandlers: HandlerRegistry;
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Issues Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles git-related issue tracking:
|
|
5
|
+
* - get_git_issues
|
|
6
|
+
* - create_git_issue
|
|
7
|
+
* - resolve_git_issue
|
|
8
|
+
* - dismiss_git_issue
|
|
9
|
+
*/
|
|
10
|
+
import { validateRequired, validateUUID } from '../validators.js';
|
|
11
|
+
export const getGitIssues = async (args, ctx) => {
|
|
12
|
+
const { project_id, status = 'open', include_resolved = false } = args;
|
|
13
|
+
validateRequired(project_id, 'project_id');
|
|
14
|
+
validateUUID(project_id, 'project_id');
|
|
15
|
+
const { supabase } = ctx;
|
|
16
|
+
let query = supabase
|
|
17
|
+
.from('git_issues')
|
|
18
|
+
.select(`
|
|
19
|
+
id,
|
|
20
|
+
task_id,
|
|
21
|
+
issue_type,
|
|
22
|
+
severity,
|
|
23
|
+
branch_name,
|
|
24
|
+
pr_number,
|
|
25
|
+
pr_url,
|
|
26
|
+
target_branch,
|
|
27
|
+
conflicting_files,
|
|
28
|
+
error_message,
|
|
29
|
+
status,
|
|
30
|
+
created_at,
|
|
31
|
+
resolved_at,
|
|
32
|
+
auto_resolved,
|
|
33
|
+
resolution_note
|
|
34
|
+
`)
|
|
35
|
+
.eq('project_id', project_id)
|
|
36
|
+
.order('created_at', { ascending: false });
|
|
37
|
+
if (status !== 'all' && !include_resolved) {
|
|
38
|
+
query = query.eq('status', status);
|
|
39
|
+
}
|
|
40
|
+
const { data: issues, error } = await query.limit(50);
|
|
41
|
+
if (error)
|
|
42
|
+
throw new Error(`Failed to fetch git issues: ${error.message}`);
|
|
43
|
+
// Group by severity for summary
|
|
44
|
+
const summary = {
|
|
45
|
+
critical: 0,
|
|
46
|
+
high: 0,
|
|
47
|
+
medium: 0,
|
|
48
|
+
low: 0,
|
|
49
|
+
};
|
|
50
|
+
const openIssues = (issues || []).filter(i => i.status === 'open');
|
|
51
|
+
openIssues.forEach(issue => {
|
|
52
|
+
const sev = issue.severity;
|
|
53
|
+
if (sev in summary)
|
|
54
|
+
summary[sev]++;
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
result: {
|
|
58
|
+
issues: issues || [],
|
|
59
|
+
open_count: openIssues.length,
|
|
60
|
+
severity_summary: summary,
|
|
61
|
+
has_critical: summary.critical > 0,
|
|
62
|
+
has_blocking: summary.critical > 0 || summary.high > 0,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
export const createGitIssue = async (args, ctx) => {
|
|
67
|
+
const { project_id, task_id, issue_type, severity = 'medium', branch_name, pr_number, pr_url, target_branch, conflicting_files, error_message, } = args;
|
|
68
|
+
validateRequired(project_id, 'project_id');
|
|
69
|
+
validateUUID(project_id, 'project_id');
|
|
70
|
+
validateRequired(issue_type, 'issue_type');
|
|
71
|
+
const { supabase, session } = ctx;
|
|
72
|
+
// Check if similar issue already exists (avoid duplicates)
|
|
73
|
+
if (branch_name || pr_number) {
|
|
74
|
+
const { data: existing } = await supabase
|
|
75
|
+
.from('git_issues')
|
|
76
|
+
.select('id')
|
|
77
|
+
.eq('project_id', project_id)
|
|
78
|
+
.eq('status', 'open')
|
|
79
|
+
.eq('issue_type', issue_type)
|
|
80
|
+
.or(`branch_name.eq.${branch_name},pr_number.eq.${pr_number}`)
|
|
81
|
+
.limit(1)
|
|
82
|
+
.maybeSingle();
|
|
83
|
+
if (existing) {
|
|
84
|
+
return {
|
|
85
|
+
result: {
|
|
86
|
+
success: false,
|
|
87
|
+
already_exists: true,
|
|
88
|
+
existing_issue_id: existing.id,
|
|
89
|
+
message: 'A similar git issue already exists for this branch/PR',
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const { data: issue, error } = await supabase
|
|
95
|
+
.from('git_issues')
|
|
96
|
+
.insert({
|
|
97
|
+
project_id,
|
|
98
|
+
task_id: task_id || null,
|
|
99
|
+
issue_type,
|
|
100
|
+
severity,
|
|
101
|
+
branch_name: branch_name || null,
|
|
102
|
+
pr_number: pr_number || null,
|
|
103
|
+
pr_url: pr_url || null,
|
|
104
|
+
target_branch: target_branch || null,
|
|
105
|
+
conflicting_files: conflicting_files || [],
|
|
106
|
+
error_message: error_message || null,
|
|
107
|
+
created_by: 'agent',
|
|
108
|
+
created_by_session_id: session.currentSessionId,
|
|
109
|
+
})
|
|
110
|
+
.select('id, issue_type, severity, branch_name, pr_number')
|
|
111
|
+
.single();
|
|
112
|
+
if (error)
|
|
113
|
+
throw new Error(`Failed to create git issue: ${error.message}`);
|
|
114
|
+
// Log progress
|
|
115
|
+
await supabase.from('progress_logs').insert({
|
|
116
|
+
project_id,
|
|
117
|
+
task_id: task_id || null,
|
|
118
|
+
summary: `Git issue created: ${issue_type} on ${branch_name || `PR #${pr_number}`}`,
|
|
119
|
+
details: error_message || null,
|
|
120
|
+
created_by: 'agent',
|
|
121
|
+
created_by_session_id: session.currentSessionId,
|
|
122
|
+
});
|
|
123
|
+
return {
|
|
124
|
+
result: {
|
|
125
|
+
success: true,
|
|
126
|
+
issue_id: issue.id,
|
|
127
|
+
issue_type: issue.issue_type,
|
|
128
|
+
severity: issue.severity,
|
|
129
|
+
branch: issue.branch_name,
|
|
130
|
+
pr_number: issue.pr_number,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
export const resolveGitIssue = async (args, ctx) => {
|
|
135
|
+
const { issue_id, resolution_note, auto_resolved = false } = args;
|
|
136
|
+
validateRequired(issue_id, 'issue_id');
|
|
137
|
+
validateUUID(issue_id, 'issue_id');
|
|
138
|
+
const { supabase, session } = ctx;
|
|
139
|
+
// Get the issue first
|
|
140
|
+
const { data: issue, error: fetchError } = await supabase
|
|
141
|
+
.from('git_issues')
|
|
142
|
+
.select('id, project_id, task_id, issue_type, branch_name, pr_number, status')
|
|
143
|
+
.eq('id', issue_id)
|
|
144
|
+
.single();
|
|
145
|
+
if (fetchError || !issue)
|
|
146
|
+
throw new Error('Git issue not found');
|
|
147
|
+
if (issue.status !== 'open') {
|
|
148
|
+
return {
|
|
149
|
+
result: {
|
|
150
|
+
success: false,
|
|
151
|
+
error: `Issue is already ${issue.status}`,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const { error: updateError } = await supabase
|
|
156
|
+
.from('git_issues')
|
|
157
|
+
.update({
|
|
158
|
+
status: 'resolved',
|
|
159
|
+
resolved_at: new Date().toISOString(),
|
|
160
|
+
resolved_by_session_id: session.currentSessionId,
|
|
161
|
+
auto_resolved,
|
|
162
|
+
resolution_note: resolution_note || null,
|
|
163
|
+
})
|
|
164
|
+
.eq('id', issue_id);
|
|
165
|
+
if (updateError)
|
|
166
|
+
throw new Error(`Failed to resolve git issue: ${updateError.message}`);
|
|
167
|
+
// Log progress
|
|
168
|
+
await supabase.from('progress_logs').insert({
|
|
169
|
+
project_id: issue.project_id,
|
|
170
|
+
task_id: issue.task_id,
|
|
171
|
+
summary: `Git issue resolved: ${issue.issue_type} on ${issue.branch_name || `PR #${issue.pr_number}`}${auto_resolved ? ' (auto)' : ''}`,
|
|
172
|
+
details: resolution_note || null,
|
|
173
|
+
created_by: 'agent',
|
|
174
|
+
created_by_session_id: session.currentSessionId,
|
|
175
|
+
});
|
|
176
|
+
return {
|
|
177
|
+
result: {
|
|
178
|
+
success: true,
|
|
179
|
+
resolved_issue_id: issue_id,
|
|
180
|
+
auto_resolved,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
export const dismissGitIssue = async (args, ctx) => {
|
|
185
|
+
const { issue_id, reason } = args;
|
|
186
|
+
validateRequired(issue_id, 'issue_id');
|
|
187
|
+
validateUUID(issue_id, 'issue_id');
|
|
188
|
+
const { supabase, session } = ctx;
|
|
189
|
+
const { error } = await supabase
|
|
190
|
+
.from('git_issues')
|
|
191
|
+
.update({
|
|
192
|
+
status: 'dismissed',
|
|
193
|
+
resolved_at: new Date().toISOString(),
|
|
194
|
+
resolved_by_session_id: session.currentSessionId,
|
|
195
|
+
resolution_note: reason || 'Dismissed',
|
|
196
|
+
})
|
|
197
|
+
.eq('id', issue_id);
|
|
198
|
+
if (error)
|
|
199
|
+
throw new Error(`Failed to dismiss git issue: ${error.message}`);
|
|
200
|
+
return {
|
|
201
|
+
result: {
|
|
202
|
+
success: true,
|
|
203
|
+
dismissed_issue_id: issue_id,
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Auto-resolve git issues for a branch when it becomes mergeable
|
|
209
|
+
*/
|
|
210
|
+
export async function autoResolveGitIssuesForBranch(supabase, projectId, branchName, sessionId) {
|
|
211
|
+
const { data: issues } = await supabase
|
|
212
|
+
.from('git_issues')
|
|
213
|
+
.select('id')
|
|
214
|
+
.eq('project_id', projectId)
|
|
215
|
+
.eq('branch_name', branchName)
|
|
216
|
+
.eq('status', 'open')
|
|
217
|
+
.in('issue_type', ['merge_conflict', 'rebase_needed']);
|
|
218
|
+
if (!issues || issues.length === 0)
|
|
219
|
+
return 0;
|
|
220
|
+
const { error } = await supabase
|
|
221
|
+
.from('git_issues')
|
|
222
|
+
.update({
|
|
223
|
+
status: 'resolved',
|
|
224
|
+
resolved_at: new Date().toISOString(),
|
|
225
|
+
resolved_by_session_id: sessionId,
|
|
226
|
+
auto_resolved: true,
|
|
227
|
+
resolution_note: 'Auto-resolved: branch is now mergeable',
|
|
228
|
+
})
|
|
229
|
+
.eq('project_id', projectId)
|
|
230
|
+
.eq('branch_name', branchName)
|
|
231
|
+
.eq('status', 'open')
|
|
232
|
+
.in('issue_type', ['merge_conflict', 'rebase_needed']);
|
|
233
|
+
if (error) {
|
|
234
|
+
console.error('Failed to auto-resolve git issues:', error);
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
return issues.length;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Git Issues handlers registry
|
|
241
|
+
*/
|
|
242
|
+
export const gitIssuesHandlers = {
|
|
243
|
+
get_git_issues: getGitIssues,
|
|
244
|
+
create_git_issue: createGitIssue,
|
|
245
|
+
resolve_git_issue: resolveGitIssue,
|
|
246
|
+
dismiss_git_issue: dismissGitIssue,
|
|
247
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ideas Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles feature ideas tracking:
|
|
5
|
+
* - add_idea
|
|
6
|
+
* - update_idea
|
|
7
|
+
* - get_ideas
|
|
8
|
+
* - delete_idea
|
|
9
|
+
*/
|
|
10
|
+
import type { Handler, HandlerRegistry } from './types.js';
|
|
11
|
+
export declare const addIdea: Handler;
|
|
12
|
+
export declare const updateIdea: Handler;
|
|
13
|
+
export declare const getIdeas: Handler;
|
|
14
|
+
export declare const deleteIdea: Handler;
|
|
15
|
+
export declare const convertIdeaToTask: Handler;
|
|
16
|
+
/**
|
|
17
|
+
* Ideas handlers registry
|
|
18
|
+
*/
|
|
19
|
+
export declare const ideaHandlers: HandlerRegistry;
|