resolve-solo 0.3.0 → 0.5.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.
@@ -0,0 +1,65 @@
1
+ /**
2
+ * M8: Weekly Report Generation
3
+ *
4
+ * Generates weekly reports for IT/Security stakeholders showing:
5
+ * - Command usage
6
+ * - Time saved
7
+ * - Services touched (hashed)
8
+ * - Blockers encountered
9
+ */
10
+ export interface WeeklyReportData {
11
+ weekNumber: string;
12
+ dateRange: {
13
+ start: string;
14
+ end: string;
15
+ };
16
+ usage: {
17
+ totalInvestigations: number;
18
+ closedInvestigations: number;
19
+ openInvestigations: number;
20
+ notesAdded: number;
21
+ detailsViewed: number;
22
+ };
23
+ timeSaved: {
24
+ totalMinutes: number;
25
+ distribution: {
26
+ '0-10': number;
27
+ '10-30': number;
28
+ '30-60': number;
29
+ '60+': number;
30
+ };
31
+ averageMinutes: number;
32
+ };
33
+ services: {
34
+ touched: string[];
35
+ count: number;
36
+ };
37
+ sources: {
38
+ demo: number;
39
+ real: number;
40
+ };
41
+ blockers: string[];
42
+ }
43
+ export interface WeeklyReport {
44
+ data: WeeklyReportData;
45
+ markdownPath: string;
46
+ jsonPath: string;
47
+ }
48
+ /**
49
+ * Aggregate data from SQLite for the given week
50
+ */
51
+ export declare function aggregateWeeklyData(weekOffset?: number): WeeklyReportData;
52
+ /**
53
+ * Generate markdown report
54
+ */
55
+ export declare function generateMarkdownReport(data: WeeklyReportData): string;
56
+ /**
57
+ * Save report to disk (both markdown and JSON)
58
+ */
59
+ export declare function saveReport(data: WeeklyReportData): WeeklyReport;
60
+ /**
61
+ * Generate and save weekly report
62
+ * @param weekOffset 0 = current week, 1 = last week, etc.
63
+ */
64
+ export declare function generateWeeklyReport(weekOffset?: number): WeeklyReport;
65
+ //# sourceMappingURL=reporting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporting.d.ts","sourceRoot":"","sources":["../src/reporting.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE;QACT,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,KAAK,EAAE;QACL,mBAAmB,EAAE,MAAM,CAAC;QAC5B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,SAAS,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE;YACZ,MAAM,EAAE,MAAM,CAAC;YACf,OAAO,EAAE,MAAM,CAAC;YAChB,OAAO,EAAE,MAAM,CAAC;YAChB,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QACF,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAyCD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,GAAE,MAAU,GAAG,gBAAgB,CAoH5E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAkDrE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAwB/D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,GAAE,MAAU,GAAG,YAAY,CAGzE"}
@@ -0,0 +1,225 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as crypto from 'node:crypto';
4
+ import { getDatabase } from './database.js';
5
+ /**
6
+ * Get the ISO week number for a date
7
+ * Returns format: YYYY-Www (e.g., "2026-W04")
8
+ */
9
+ function getISOWeek(date) {
10
+ const target = new Date(date.valueOf());
11
+ const dayNr = (date.getDay() + 6) % 7; // Monday = 0
12
+ target.setDate(target.getDate() - dayNr + 3);
13
+ const firstThursday = target.valueOf();
14
+ target.setMonth(0, 1);
15
+ if (target.getDay() !== 4) {
16
+ target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
17
+ }
18
+ const weekNumber = 1 + Math.ceil((firstThursday - target.valueOf()) / 604800000);
19
+ return `${target.getFullYear()}-W${String(weekNumber).padStart(2, '0')}`;
20
+ }
21
+ /**
22
+ * Get start and end dates for an ISO week
23
+ */
24
+ function getWeekDateRange(weekString) {
25
+ const [year, week] = weekString.split('-W').map(Number);
26
+ const jan4 = new Date(year, 0, 4);
27
+ const jan4Day = (jan4.getDay() + 6) % 7; // Monday = 0
28
+ const weekStart = new Date(jan4.valueOf());
29
+ weekStart.setDate(jan4.getDate() - jan4Day + (week - 1) * 7);
30
+ const weekEnd = new Date(weekStart.valueOf());
31
+ weekEnd.setDate(weekStart.getDate() + 6);
32
+ weekEnd.setHours(23, 59, 59, 999);
33
+ return { start: weekStart, end: weekEnd };
34
+ }
35
+ /**
36
+ * Hash a service name for privacy
37
+ */
38
+ function hashServiceName(service) {
39
+ return crypto.createHash('sha256').update(service).digest('hex').substring(0, 8);
40
+ }
41
+ /**
42
+ * Aggregate data from SQLite for the given week
43
+ */
44
+ export function aggregateWeeklyData(weekOffset = 0) {
45
+ const db = getDatabase();
46
+ // Calculate target week
47
+ const now = new Date();
48
+ now.setDate(now.getDate() - (weekOffset * 7));
49
+ const weekNumber = getISOWeek(now);
50
+ const { start, end } = getWeekDateRange(weekNumber);
51
+ // Query sessions in date range
52
+ const sessions = db.prepare(`
53
+ SELECT id, query, mode, created_at, closed_at, time_saved_minutes
54
+ FROM sessions
55
+ WHERE created_at >= ? AND created_at <= ?
56
+ `).all(start.toISOString(), end.toISOString());
57
+ // Count investigations
58
+ const totalInvestigations = sessions.length;
59
+ const closedInvestigations = sessions.filter(s => s.closed_at != null).length;
60
+ const openInvestigations = sessions.filter(s => s.closed_at == null).length;
61
+ // Count notes
62
+ const notesAdded = db.prepare(`
63
+ SELECT COUNT(*) as count
64
+ FROM session_notes
65
+ WHERE timestamp >= ? AND timestamp <= ?
66
+ `).get(start.toISOString(), end.toISOString());
67
+ // Count details views (we don't track this yet, so estimate from timeline queries)
68
+ const detailsViewed = 0; // TODO: Add tracking in M8.1
69
+ // Calculate time saved
70
+ const timeSavedSessions = sessions.filter(s => s.time_saved_minutes != null);
71
+ const totalMinutes = timeSavedSessions.reduce((sum, s) => sum + (s.time_saved_minutes || 0), 0);
72
+ const averageMinutes = timeSavedSessions.length > 0
73
+ ? Math.round(totalMinutes / timeSavedSessions.length)
74
+ : 0;
75
+ // Distribution
76
+ const distribution = {
77
+ '0-10': timeSavedSessions.filter(s => s.time_saved_minutes >= 0 && s.time_saved_minutes < 10).length,
78
+ '10-30': timeSavedSessions.filter(s => s.time_saved_minutes >= 10 && s.time_saved_minutes < 30).length,
79
+ '30-60': timeSavedSessions.filter(s => s.time_saved_minutes >= 30 && s.time_saved_minutes < 60).length,
80
+ '60+': timeSavedSessions.filter(s => s.time_saved_minutes >= 60).length,
81
+ };
82
+ // Extract services from timeline items (parse JSON to get target)
83
+ const timelineItems = db.prepare(`
84
+ SELECT item_data
85
+ FROM session_timeline st
86
+ JOIN sessions s ON st.session_id = s.id
87
+ WHERE s.created_at >= ? AND s.created_at <= ?
88
+ `).all(start.toISOString(), end.toISOString());
89
+ // Parse JSON data to extract targets
90
+ const targets = timelineItems
91
+ .map(row => {
92
+ try {
93
+ const item = JSON.parse(row.item_data);
94
+ return item.target;
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ })
100
+ .filter(Boolean);
101
+ const uniqueServices = new Set(targets);
102
+ const hashedServices = Array.from(uniqueServices).map(hashServiceName);
103
+ // Detect sources (demo vs real)
104
+ // In demo mode, all queries contain "demo" label in timeline
105
+ const demoCount = sessions.filter(s => s.query?.includes('demo') || s.query?.includes('payment')).length;
106
+ const realCount = sessions.length - demoCount;
107
+ // Collect common blockers (from session notes mentioning "blocked", "no access", etc.)
108
+ const blockerKeywords = ['blocked', 'no access', 'missing', 'permission', 'unavailable'];
109
+ const notes = db.prepare(`
110
+ SELECT note
111
+ FROM session_notes sn
112
+ JOIN sessions s ON sn.session_id = s.id
113
+ WHERE s.created_at >= ? AND s.created_at <= ?
114
+ `).all(start.toISOString(), end.toISOString());
115
+ const blockers = notes
116
+ .filter(n => blockerKeywords.some(keyword => n.note.toLowerCase().includes(keyword)))
117
+ .map(n => n.note)
118
+ .slice(0, 5); // Top 5 blockers
119
+ return {
120
+ weekNumber,
121
+ dateRange: {
122
+ start: start.toISOString().split('T')[0],
123
+ end: end.toISOString().split('T')[0],
124
+ },
125
+ usage: {
126
+ totalInvestigations,
127
+ closedInvestigations,
128
+ openInvestigations,
129
+ notesAdded: notesAdded.count,
130
+ detailsViewed,
131
+ },
132
+ timeSaved: {
133
+ totalMinutes,
134
+ distribution,
135
+ averageMinutes,
136
+ },
137
+ services: {
138
+ touched: hashedServices,
139
+ count: hashedServices.length,
140
+ },
141
+ sources: {
142
+ demo: demoCount,
143
+ real: realCount,
144
+ },
145
+ blockers,
146
+ };
147
+ }
148
+ /**
149
+ * Generate markdown report
150
+ */
151
+ export function generateMarkdownReport(data) {
152
+ const { weekNumber, dateRange, usage, timeSaved, services, sources, blockers } = data;
153
+ let md = `# Resolve Solo - Weekly Report\n\n`;
154
+ md += `**Week**: ${weekNumber} (${dateRange.start} to ${dateRange.end})\n\n`;
155
+ md += `---\n\n`;
156
+ // Usage section
157
+ md += `## Usage\n\n`;
158
+ md += `- **Total Investigations**: ${usage.totalInvestigations}\n`;
159
+ md += `- **Closed**: ${usage.closedInvestigations}\n`;
160
+ md += `- **Open**: ${usage.openInvestigations}\n`;
161
+ md += `- **Notes Added**: ${usage.notesAdded}\n`;
162
+ md += `- **Details Viewed**: ${usage.detailsViewed}\n\n`;
163
+ // Time saved section
164
+ md += `## Time Saved\n\n`;
165
+ md += `- **Total**: ${timeSaved.totalMinutes} minutes\n`;
166
+ md += `- **Average**: ${timeSaved.averageMinutes} minutes per investigation\n\n`;
167
+ md += `**Distribution**:\n`;
168
+ md += `- 0-10 min: ${timeSaved.distribution['0-10']}\n`;
169
+ md += `- 10-30 min: ${timeSaved.distribution['10-30']}\n`;
170
+ md += `- 30-60 min: ${timeSaved.distribution['30-60']}\n`;
171
+ md += `- 60+ min: ${timeSaved.distribution['60+']}\n\n`;
172
+ // Services section
173
+ md += `## Services Touched\n\n`;
174
+ md += `- **Count**: ${services.count} unique services\n`;
175
+ md += `- **Hashed IDs**: ${services.touched.join(', ')}\n\n`;
176
+ md += `*Service names are hashed for privacy.*\n\n`;
177
+ // Sources section
178
+ md += `## Data Sources\n\n`;
179
+ md += `- **Demo Data**: ${sources.demo} investigations\n`;
180
+ md += `- **Real Data**: ${sources.real} investigations\n\n`;
181
+ // Blockers section
182
+ if (blockers.length > 0) {
183
+ md += `## Blockers Encountered\n\n`;
184
+ blockers.forEach((blocker, i) => {
185
+ md += `${i + 1}. ${blocker}\n`;
186
+ });
187
+ md += `\n`;
188
+ }
189
+ // Footer
190
+ md += `---\n\n`;
191
+ md += `*Generated by Resolve Solo*\n`;
192
+ return md;
193
+ }
194
+ /**
195
+ * Save report to disk (both markdown and JSON)
196
+ */
197
+ export function saveReport(data) {
198
+ const reportsDir = path.join(process.cwd(), '.resolveai', 'reports');
199
+ // Ensure directory exists
200
+ if (!fs.existsSync(reportsDir)) {
201
+ fs.mkdirSync(reportsDir, { recursive: true });
202
+ }
203
+ // Generate filenames
204
+ const markdownPath = path.join(reportsDir, `weekly-${data.weekNumber}.md`);
205
+ const jsonPath = path.join(reportsDir, `weekly-${data.weekNumber}.json`);
206
+ // Generate markdown content
207
+ const markdown = generateMarkdownReport(data);
208
+ // Save files
209
+ fs.writeFileSync(markdownPath, markdown, 'utf-8');
210
+ fs.writeFileSync(jsonPath, JSON.stringify(data, null, 2), 'utf-8');
211
+ return {
212
+ data,
213
+ markdownPath,
214
+ jsonPath,
215
+ };
216
+ }
217
+ /**
218
+ * Generate and save weekly report
219
+ * @param weekOffset 0 = current week, 1 = last week, etc.
220
+ */
221
+ export function generateWeeklyReport(weekOffset = 0) {
222
+ const data = aggregateWeeklyData(weekOffset);
223
+ return saveReport(data);
224
+ }
225
+ //# sourceMappingURL=reporting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporting.js","sourceRoot":"","sources":["../src/reporting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAoD5C;;;GAGG;AACH,SAAS,UAAU,CAAC,IAAU;IAC5B,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa;IACpD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC;IAC7C,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IACvC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtB,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,aAAa,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;IACjF,OAAO,GAAG,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,UAAkB;IAC1C,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa;IACtD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3C,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IAClC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACnF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,aAAqB,CAAC;IACxD,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IAEzB,wBAAwB;IACxB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAEpD,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC;;;;GAI3B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,WAAW,EAAE,CAAU,CAAC;IAExD,uBAAuB;IACvB,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC5C,MAAM,oBAAoB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC;IAE5E,cAAc;IACd,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;;;GAI7B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,WAAW,EAAE,CAAsB,CAAC;IAEpE,mFAAmF;IACnF,MAAM,aAAa,GAAG,CAAC,CAAC,CAAC,6BAA6B;IAEtD,uBAAuB;IACvB,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,IAAI,IAAI,CAAC,CAAC;IAC7E,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChG,MAAM,cAAc,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC;QACjD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC;QACrD,CAAC,CAAC,CAAC,CAAC;IAEN,eAAe;IACf,MAAM,YAAY,GAAG;QACnB,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC,MAAM;QACpG,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,IAAI,EAAE,IAAI,CAAC,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC,MAAM;QACtG,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,IAAI,EAAE,IAAI,CAAC,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC,MAAM;QACtG,KAAK,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,MAAM;KACxE,CAAC;IAEF,kEAAkE;IAClE,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;GAKhC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,WAAW,EAAE,CAA4B,CAAC;IAE1E,qCAAqC;IACrC,MAAM,OAAO,GAAG,aAAa;SAC1B,GAAG,CAAC,GAAG,CAAC,EAAE;QACT,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACvC,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnB,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAEvE,gCAAgC;IAChC,6DAA6D;IAC7D,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IACzG,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC;IAE9C,uFAAuF;IACvF,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;IACzF,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;GAKxB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,WAAW,EAAE,CAAuB,CAAC;IAErE,MAAM,QAAQ,GAAG,KAAK;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;SACpF,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAChB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,iBAAiB;IAEjC,OAAO;QACL,UAAU;QACV,SAAS,EAAE;YACT,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACxC,GAAG,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACrC;QACD,KAAK,EAAE;YACL,mBAAmB;YACnB,oBAAoB;YACpB,kBAAkB;YAClB,UAAU,EAAE,UAAU,CAAC,KAAK;YAC5B,aAAa;SACd;QACD,SAAS,EAAE;YACT,YAAY;YACZ,YAAY;YACZ,cAAc;SACf;QACD,QAAQ,EAAE;YACR,OAAO,EAAE,cAAc;YACvB,KAAK,EAAE,cAAc,CAAC,MAAM;SAC7B;QACD,OAAO,EAAE;YACP,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;SAChB;QACD,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAsB;IAC3D,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAEtF,IAAI,EAAE,GAAG,oCAAoC,CAAC;IAC9C,EAAE,IAAI,aAAa,UAAU,KAAK,SAAS,CAAC,KAAK,OAAO,SAAS,CAAC,GAAG,OAAO,CAAC;IAC7E,EAAE,IAAI,SAAS,CAAC;IAEhB,gBAAgB;IAChB,EAAE,IAAI,cAAc,CAAC;IACrB,EAAE,IAAI,+BAA+B,KAAK,CAAC,mBAAmB,IAAI,CAAC;IACnE,EAAE,IAAI,iBAAiB,KAAK,CAAC,oBAAoB,IAAI,CAAC;IACtD,EAAE,IAAI,eAAe,KAAK,CAAC,kBAAkB,IAAI,CAAC;IAClD,EAAE,IAAI,sBAAsB,KAAK,CAAC,UAAU,IAAI,CAAC;IACjD,EAAE,IAAI,yBAAyB,KAAK,CAAC,aAAa,MAAM,CAAC;IAEzD,qBAAqB;IACrB,EAAE,IAAI,mBAAmB,CAAC;IAC1B,EAAE,IAAI,gBAAgB,SAAS,CAAC,YAAY,YAAY,CAAC;IACzD,EAAE,IAAI,kBAAkB,SAAS,CAAC,cAAc,gCAAgC,CAAC;IACjF,EAAE,IAAI,qBAAqB,CAAC;IAC5B,EAAE,IAAI,eAAe,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;IACxD,EAAE,IAAI,gBAAgB,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1D,EAAE,IAAI,gBAAgB,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1D,EAAE,IAAI,cAAc,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC;IAExD,mBAAmB;IACnB,EAAE,IAAI,yBAAyB,CAAC;IAChC,EAAE,IAAI,gBAAgB,QAAQ,CAAC,KAAK,oBAAoB,CAAC;IACzD,EAAE,IAAI,qBAAqB,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC7D,EAAE,IAAI,6CAA6C,CAAC;IAEpD,kBAAkB;IAClB,EAAE,IAAI,qBAAqB,CAAC;IAC5B,EAAE,IAAI,oBAAoB,OAAO,CAAC,IAAI,mBAAmB,CAAC;IAC1D,EAAE,IAAI,oBAAoB,OAAO,CAAC,IAAI,qBAAqB,CAAC;IAE5D,mBAAmB;IACnB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,IAAI,6BAA6B,CAAC;QACpC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE;YAC9B,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,OAAO,IAAI,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,EAAE,IAAI,IAAI,CAAC;IACb,CAAC;IAED,SAAS;IACT,EAAE,IAAI,SAAS,CAAC;IAChB,EAAE,IAAI,+BAA+B,CAAC;IAEtC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAsB;IAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;IAErE,0BAA0B;IAC1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,qBAAqB;IACrB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,IAAI,CAAC,UAAU,OAAO,CAAC,CAAC;IAEzE,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAE9C,aAAa;IACb,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAEnE,OAAO;QACL,IAAI;QACJ,YAAY;QACZ,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,aAAqB,CAAC;IACzD,MAAM,IAAI,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Claude Code Integration Setup
3
+ *
4
+ * Automatically configures Claude Code to use resolve-solo MCP server.
5
+ */
6
+ interface SetupResult {
7
+ success: boolean;
8
+ message: string;
9
+ method?: 'claude-mcp' | 'manual-json' | 'manual-instructions';
10
+ configPath?: string;
11
+ }
12
+ /**
13
+ * Attempt to automatically configure Claude Code integration
14
+ */
15
+ export declare function setupClaudeIntegration(): SetupResult;
16
+ /**
17
+ * Get manual setup instructions for user
18
+ */
19
+ export declare function getManualInstructions(): string;
20
+ /**
21
+ * Verify that resolve-solo-mcp binary is accessible
22
+ */
23
+ export declare function verifyBinaryAccessible(): boolean;
24
+ export {};
25
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,WAAW;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,YAAY,GAAG,aAAa,GAAG,qBAAqB,CAAC;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,CA0DpD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAyB9C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAOhD"}
package/dist/setup.js ADDED
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Claude Code Integration Setup
3
+ *
4
+ * Automatically configures Claude Code to use resolve-solo MCP server.
5
+ */
6
+ import * as fs from 'node:fs';
7
+ import * as path from 'node:path';
8
+ import * as os from 'node:os';
9
+ import { execSync } from 'node:child_process';
10
+ /**
11
+ * Attempt to automatically configure Claude Code integration
12
+ */
13
+ export function setupClaudeIntegration() {
14
+ // Method 1: Try using `claude mcp add` if available
15
+ try {
16
+ execSync('claude mcp add resolve-solo-mcp', { stdio: 'pipe' });
17
+ return {
18
+ success: true,
19
+ message: 'Successfully configured Claude Code via `claude mcp add`',
20
+ method: 'claude-mcp',
21
+ };
22
+ }
23
+ catch (error) {
24
+ // Claude CLI not available or command failed, try manual config
25
+ }
26
+ // Method 2: Try editing Claude Code config file directly
27
+ const configPaths = [
28
+ path.join(os.homedir(), '.config', 'claude', 'config.json'),
29
+ path.join(os.homedir(), '.claude', 'config.json'),
30
+ path.join(os.homedir(), '.claude.json'),
31
+ ];
32
+ for (const configPath of configPaths) {
33
+ if (fs.existsSync(configPath)) {
34
+ try {
35
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
36
+ // Initialize mcpServers if needed
37
+ if (!config.mcpServers) {
38
+ config.mcpServers = {};
39
+ }
40
+ // Add resolve-solo server
41
+ config.mcpServers['resolve-solo'] = {
42
+ command: 'resolve-solo-mcp',
43
+ description: 'On-call investigation assistant for incident response',
44
+ };
45
+ // Write back
46
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
47
+ return {
48
+ success: true,
49
+ message: `Successfully configured Claude Code by editing ${configPath}`,
50
+ method: 'manual-json',
51
+ configPath,
52
+ };
53
+ }
54
+ catch (error) {
55
+ // Config file exists but couldn't be edited, continue to next
56
+ continue;
57
+ }
58
+ }
59
+ }
60
+ // Method 3: Couldn't auto-configure, return manual instructions
61
+ return {
62
+ success: false,
63
+ message: 'Could not auto-configure. Manual setup required.',
64
+ method: 'manual-instructions',
65
+ };
66
+ }
67
+ /**
68
+ * Get manual setup instructions for user
69
+ */
70
+ export function getManualInstructions() {
71
+ return `
72
+ Manual Setup Instructions:
73
+
74
+ 1. Locate your Claude Code configuration file:
75
+ - Linux/Mac: ~/.config/claude/config.json or ~/.claude.json
76
+ - Windows: %USERPROFILE%\\.claude\\config.json
77
+
78
+ 2. Add the resolve-solo MCP server:
79
+ {
80
+ "mcpServers": {
81
+ "resolve-solo": {
82
+ "command": "resolve-solo-mcp",
83
+ "description": "On-call investigation assistant"
84
+ }
85
+ }
86
+ }
87
+
88
+ 3. Restart Claude Code
89
+
90
+ 4. Test by asking: "investigate timeout issues"
91
+
92
+ Alternatively, if your Claude Code CLI supports it:
93
+ claude mcp add resolve-solo-mcp
94
+ `;
95
+ }
96
+ /**
97
+ * Verify that resolve-solo-mcp binary is accessible
98
+ */
99
+ export function verifyBinaryAccessible() {
100
+ try {
101
+ execSync('which resolve-solo-mcp', { stdio: 'pipe' });
102
+ return true;
103
+ }
104
+ catch (error) {
105
+ return false;
106
+ }
107
+ }
108
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAS9C;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,oDAAoD;IACpD,IAAI,CAAC;QACH,QAAQ,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/D,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,0DAA0D;YACnE,MAAM,EAAE,YAAY;SACrB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gEAAgE;IAClE,CAAC;IAED,yDAAyD;IACzD,MAAM,WAAW,GAAG;QAClB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC;KACxC,CAAC;IAEF,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;gBAEhE,kCAAkC;gBAClC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;oBACvB,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;gBACzB,CAAC;gBAED,0BAA0B;gBAC1B,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG;oBAClC,OAAO,EAAE,kBAAkB;oBAC3B,WAAW,EAAE,uDAAuD;iBACrE,CAAC;gBAEF,aAAa;gBACb,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBAE9D,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,kDAAkD,UAAU,EAAE;oBACvE,MAAM,EAAE,aAAa;oBACrB,UAAU;iBACX,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,8DAA8D;gBAC9D,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,OAAO;QACL,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,kDAAkD;QAC3D,MAAM,EAAE,qBAAqB;KAC9B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;CAuBR,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC;QACH,QAAQ,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Core types for Resolve Solo
3
3
  */
4
- export type Intent = 'help' | 'demo' | 'demo-seed' | 'demo-reset' | 'investigate' | 'details' | 'note' | 'close' | 'report-weekly' | 'doctor' | 'uninstall' | 'unknown';
4
+ export type Intent = 'help' | 'demo' | 'demo-seed' | 'demo-reset' | 'investigate' | 'details' | 'note' | 'close' | 'report-weekly' | 'setup' | 'doctor' | 'uninstall' | 'unknown';
5
5
  export interface ParsedCommand {
6
6
  intent: Intent;
7
7
  args: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,MAAM,GACd,MAAM,GACN,MAAM,GACN,WAAW,GACX,YAAY,GACZ,aAAa,GACb,SAAS,GACT,MAAM,GACN,OAAO,GACP,eAAe,GACf,QAAQ,GACR,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,MAAM,GACd,MAAM,GACN,MAAM,GACN,WAAW,GACX,YAAY,GACZ,aAAa,GACb,SAAS,GACT,MAAM,GACN,OAAO,GACP,eAAe,GACf,OAAO,GACP,QAAQ,GACR,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "resolve-solo",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Local-first CLI on-call assistant for individual engineers",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
- "resolveai": "./dist/cli.js"
8
+ "resolveai": "./dist/cli.js",
9
+ "resolve-solo-mcp": "./dist/mcp-cli.js"
9
10
  },
10
11
  "scripts": {
11
12
  "dev": "tsx src/cli.ts",
@@ -42,7 +43,9 @@
42
43
  },
43
44
  "dependencies": {
44
45
  "chalk": "^5.3.0",
45
- "commander": "^12.1.0"
46
+ "commander": "^12.1.0",
47
+ "@modelcontextprotocol/sdk": "^0.5.0",
48
+ "zod": "^3.23.8"
46
49
  },
47
50
  "optionalDependencies": {
48
51
  "better-sqlite3": "^11.7.0"