@buoy-design/agents 0.1.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,194 @@
1
+ // packages/agents/src/generator.ts
2
+ // Generates code fixes and PR descriptions
3
+ import Anthropic from '@anthropic-ai/sdk';
4
+ const MODEL = 'claude-sonnet-4-20250514';
5
+ export class GeneratorAgent {
6
+ client;
7
+ constructor(apiKey) {
8
+ this.client = new Anthropic({
9
+ apiKey: apiKey ?? process.env.ANTHROPIC_API_KEY,
10
+ });
11
+ }
12
+ /**
13
+ * Generate fixes and PR description
14
+ */
15
+ async generate(input) {
16
+ try {
17
+ const prompt = this.buildPrompt(input);
18
+ const response = await this.client.messages.create({
19
+ model: MODEL,
20
+ max_tokens: 4000,
21
+ messages: [{ role: 'user', content: prompt }],
22
+ });
23
+ const textContent = response.content.find((c) => c.type === 'text');
24
+ const responseText = textContent?.type === 'text' ? textContent.text : '';
25
+ const parsed = this.parseResponse(responseText, input);
26
+ return {
27
+ success: true,
28
+ data: parsed,
29
+ confidence: parsed.confidence,
30
+ tokensUsed: response.usage.input_tokens + response.usage.output_tokens,
31
+ };
32
+ }
33
+ catch (error) {
34
+ return {
35
+ success: false,
36
+ error: error instanceof Error ? error.message : String(error),
37
+ confidence: 0,
38
+ };
39
+ }
40
+ }
41
+ /**
42
+ * Build the generation prompt
43
+ */
44
+ buildPrompt(input) {
45
+ const signalSummary = input.signals
46
+ .filter((s) => s.fixability.tier !== 'skip')
47
+ .map((s) => {
48
+ const fix = s.fixability.suggestedFix;
49
+ return `- ${s.signal.file}:${s.signal.line ?? '?'} - ${s.signal.type}
50
+ Message: ${s.signal.message}
51
+ Difficulty: ${s.fixability.difficulty}
52
+ ${fix ? `Suggested: ${fix.before} → ${fix.after}` : ''}
53
+ ${s.history ? `History: ${s.history.verdict} - ${s.history.context}` : ''}`;
54
+ })
55
+ .join('\n\n');
56
+ const tokenList = input.designTokens
57
+ ? Object.entries(input.designTokens)
58
+ .slice(0, 30)
59
+ .map(([name, value]) => `${name}: ${value}`)
60
+ .join('\n')
61
+ : 'No tokens provided';
62
+ return `You are generating a PR to fix design system drift.
63
+
64
+ ## Repository
65
+ ${input.repo.owner}/${input.repo.name}
66
+ ${input.repo.description ?? ''}
67
+
68
+ ## Acceptance Context
69
+ - Likelihood: ${input.acceptanceContext.likelihood} (${input.acceptanceContext.score}/100)
70
+ - Approach: ${input.acceptanceContext.suggestedApproach}
71
+ - Green flags: ${input.acceptanceContext.greenFlags.join(', ') || 'none'}
72
+ - Red flags: ${input.acceptanceContext.redFlags.join(', ') || 'none'}
73
+
74
+ ## Signals to Fix
75
+ ${signalSummary}
76
+
77
+ ## Available Design Tokens
78
+ ${tokenList}
79
+
80
+ ## Your Task
81
+
82
+ 1. Generate the exact code fixes for each signal
83
+ 2. Write a compelling PR title and description
84
+
85
+ For the PR description:
86
+ - Explain WHY this matters (maintainability, consistency, theming)
87
+ - Reference the git history if it shows these were accidental
88
+ - Be respectful and helpful, not preachy
89
+ - Mention Buoy subtly at the end
90
+ - If many files, add a cherry-pick note
91
+
92
+ Respond with JSON:
93
+ {
94
+ "fixes": [
95
+ {
96
+ "file": "path/to/file.tsx",
97
+ "line": 23,
98
+ "before": "exact code to replace",
99
+ "after": "replacement code",
100
+ "explanation": "why this fix"
101
+ }
102
+ ],
103
+ "prTitle": "Short, clear title",
104
+ "prBody": "Full markdown PR description",
105
+ "confidence": 0.0-1.0,
106
+ "cherryPickNote": "Optional note if PR is large"
107
+ }
108
+
109
+ Be precise with the fixes - they will be applied directly.`;
110
+ }
111
+ /**
112
+ * Parse Claude's response
113
+ */
114
+ parseResponse(response, input) {
115
+ try {
116
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
117
+ if (jsonMatch) {
118
+ const parsed = JSON.parse(jsonMatch[0]);
119
+ const fixes = this.validateFixes(parsed.fixes ?? []);
120
+ return {
121
+ fixes,
122
+ prTitle: String(parsed.prTitle ?? 'fix: Design system consistency'),
123
+ prBody: String(parsed.prBody ?? this.buildFallbackPRBody(input, fixes)),
124
+ confidence: Math.min(1, Math.max(0, Number(parsed.confidence) || 0.7)),
125
+ cherryPickNote: parsed.cherryPickNote
126
+ ? String(parsed.cherryPickNote)
127
+ : undefined,
128
+ filesChanged: new Set(fixes.map((f) => f.file)).size,
129
+ };
130
+ }
131
+ }
132
+ catch {
133
+ // Fall through
134
+ }
135
+ return {
136
+ fixes: [],
137
+ prTitle: 'fix: Design system consistency',
138
+ prBody: 'Unable to generate PR description',
139
+ confidence: 0,
140
+ filesChanged: 0,
141
+ };
142
+ }
143
+ /**
144
+ * Validate fixes array
145
+ */
146
+ validateFixes(fixes) {
147
+ const valid = [];
148
+ for (const f of fixes) {
149
+ if (!f || typeof f !== 'object')
150
+ continue;
151
+ const fix = f;
152
+ if (!fix['file'] || !fix['before'] || !fix['after'])
153
+ continue;
154
+ valid.push({
155
+ file: String(fix['file']),
156
+ line: Number(fix['line']) || 0,
157
+ before: String(fix['before']),
158
+ after: String(fix['after']),
159
+ explanation: String(fix['explanation'] ?? ''),
160
+ });
161
+ }
162
+ return valid;
163
+ }
164
+ /**
165
+ * Build fallback PR body if parsing fails
166
+ */
167
+ buildFallbackPRBody(input, fixes) {
168
+ const fileList = [...new Set(fixes.map((f) => f.file))];
169
+ return `## Summary
170
+
171
+ This PR improves design system consistency by replacing hardcoded values with their corresponding design tokens.
172
+
173
+ ### Changes
174
+
175
+ ${fixes.map((f) => `- \`${f.file}:${f.line}\`: ${f.explanation || 'Use design token'}`).join('\n')}
176
+
177
+ ### Files Changed
178
+
179
+ ${fileList.map((f) => `- \`${f}\``).join('\n')}
180
+
181
+ ### Why This Matters
182
+
183
+ Using design tokens instead of hardcoded values:
184
+ - Makes the codebase more maintainable
185
+ - Ensures consistency across the application
186
+ - Makes theming and updates easier
187
+
188
+ ---
189
+
190
+ *Found with [Buoy](https://github.com/buoy-design/buoy) - design drift detection for AI-generated code.*
191
+ `;
192
+ }
193
+ }
194
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { HistoryInput, HistoryResult, AgentResult } from './types.js';
2
+ export declare class HistoryAgent {
3
+ private client;
4
+ constructor(apiKey?: string);
5
+ /**
6
+ * Analyze git history for a file to understand why drift exists
7
+ */
8
+ analyze(input: HistoryInput): Promise<AgentResult<HistoryResult>>;
9
+ /**
10
+ * Extract PR number from commit message
11
+ */
12
+ private extractPRNumber;
13
+ /**
14
+ * Extract blame info for specific lines
15
+ */
16
+ private extractBlameForLines;
17
+ /**
18
+ * Build the analysis prompt
19
+ */
20
+ private buildPrompt;
21
+ /**
22
+ * Parse Claude's response
23
+ */
24
+ private parseResponse;
25
+ /**
26
+ * Validate verdict is a known value
27
+ */
28
+ private validateVerdict;
29
+ }
30
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EAGb,WAAW,EACZ,MAAM,YAAY,CAAC;AAIpB,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,CAAC,EAAE,MAAM;IAM3B;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IAgFvE;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,OAAO,CAAC,WAAW;IA4CnB;;OAEG;IACH,OAAO,CAAC,aAAa;IA0BrB;;OAEG;IACH,OAAO,CAAC,eAAe;CAWxB"}
@@ -0,0 +1,182 @@
1
+ // packages/agents/src/history.ts
2
+ // Analyzes git history to understand why drift exists
3
+ import Anthropic from '@anthropic-ai/sdk';
4
+ import { simpleGit } from 'simple-git';
5
+ const MODEL = 'claude-sonnet-4-20250514';
6
+ export class HistoryAgent {
7
+ client;
8
+ constructor(apiKey) {
9
+ this.client = new Anthropic({
10
+ apiKey: apiKey ?? process.env.ANTHROPIC_API_KEY,
11
+ });
12
+ }
13
+ /**
14
+ * Analyze git history for a file to understand why drift exists
15
+ */
16
+ async analyze(input) {
17
+ try {
18
+ const git = simpleGit(input.repoPath);
19
+ // Get git blame for the file
20
+ const blameRaw = await git.raw([
21
+ 'blame',
22
+ '--line-porcelain',
23
+ input.filePath,
24
+ ]).catch(() => '');
25
+ // Get commit history for the file
26
+ const logResult = await git.log({
27
+ file: input.filePath,
28
+ maxCount: 20,
29
+ });
30
+ // Parse commits into our format
31
+ const timeline = logResult.all.map((commit) => ({
32
+ hash: commit.hash.slice(0, 7),
33
+ date: commit.date,
34
+ author: commit.author_name,
35
+ email: commit.author_email,
36
+ message: commit.message,
37
+ prNumber: this.extractPRNumber(commit.message),
38
+ }));
39
+ // Extract unique authors
40
+ const authors = [...new Set(timeline.map((c) => c.author))];
41
+ // Get last modified date
42
+ const lastModified = timeline[0]?.date ?? 'unknown';
43
+ // If we have line range, extract relevant blame info
44
+ let focusedBlame = '';
45
+ if (input.lineRange && blameRaw) {
46
+ focusedBlame = this.extractBlameForLines(blameRaw, input.lineRange[0], input.lineRange[1]);
47
+ }
48
+ // Use Claude to analyze the history
49
+ const prompt = this.buildPrompt(input, timeline, focusedBlame);
50
+ const response = await this.client.messages.create({
51
+ model: MODEL,
52
+ max_tokens: 1500,
53
+ messages: [{ role: 'user', content: prompt }],
54
+ });
55
+ const textContent = response.content.find((c) => c.type === 'text');
56
+ const responseText = textContent?.type === 'text' ? textContent.text : '';
57
+ // Parse the response
58
+ const parsed = this.parseResponse(responseText);
59
+ return {
60
+ success: true,
61
+ data: {
62
+ verdict: parsed.verdict,
63
+ timeline,
64
+ context: parsed.context,
65
+ confidence: parsed.confidence,
66
+ lastModified,
67
+ authors,
68
+ },
69
+ confidence: parsed.confidence,
70
+ tokensUsed: response.usage.input_tokens + response.usage.output_tokens,
71
+ };
72
+ }
73
+ catch (error) {
74
+ return {
75
+ success: false,
76
+ error: error instanceof Error ? error.message : String(error),
77
+ confidence: 0,
78
+ };
79
+ }
80
+ }
81
+ /**
82
+ * Extract PR number from commit message
83
+ */
84
+ extractPRNumber(message) {
85
+ const match = message.match(/#(\d+)/);
86
+ return match ? parseInt(match[1], 10) : undefined;
87
+ }
88
+ /**
89
+ * Extract blame info for specific lines
90
+ */
91
+ extractBlameForLines(blameRaw, startLine, endLine) {
92
+ const lines = blameRaw.split('\n');
93
+ const relevant = [];
94
+ let currentLine = 0;
95
+ for (const line of lines) {
96
+ if (line.match(/^[a-f0-9]{40}/)) {
97
+ currentLine++;
98
+ if (currentLine >= startLine && currentLine <= endLine) {
99
+ relevant.push(line);
100
+ }
101
+ }
102
+ }
103
+ return relevant.join('\n');
104
+ }
105
+ /**
106
+ * Build the analysis prompt
107
+ */
108
+ buildPrompt(input, timeline, focusedBlame) {
109
+ const recentCommits = timeline
110
+ .slice(0, 10)
111
+ .map((c) => `- ${c.hash} (${c.date}) by ${c.author}: ${c.message.slice(0, 100)}`)
112
+ .join('\n');
113
+ return `You are analyzing git history to understand why a piece of code exists.
114
+
115
+ ## File
116
+ ${input.filePath}
117
+ ${input.lineRange ? `Lines ${input.lineRange[0]}-${input.lineRange[1]}` : ''}
118
+
119
+ ## Recent Commits
120
+ ${recentCommits}
121
+
122
+ ${focusedBlame ? `## Blame Info for Relevant Lines\n${focusedBlame}` : ''}
123
+
124
+ ## Your Task
125
+
126
+ Determine if the code in question was:
127
+ - **accidental**: Developer didn't know about existing patterns/tokens
128
+ - **intentional**: Deliberate choice (override, special case, commented reason)
129
+ - **ai-generated**: Looks like Copilot/Claude output (generic patterns, no context awareness)
130
+ - **unknown**: Cannot determine from available information
131
+
132
+ Analyze the commit messages, timing, and patterns to make your determination.
133
+
134
+ Respond with JSON:
135
+ {
136
+ "verdict": "accidental" | "intentional" | "ai-generated" | "unknown",
137
+ "context": "Explanation of your analysis (2-3 sentences)",
138
+ "confidence": 0.0-1.0
139
+ }
140
+
141
+ Be concise but specific. Reference actual commits or patterns you observed.`;
142
+ }
143
+ /**
144
+ * Parse Claude's response
145
+ */
146
+ parseResponse(response) {
147
+ try {
148
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
149
+ if (jsonMatch) {
150
+ const parsed = JSON.parse(jsonMatch[0]);
151
+ return {
152
+ verdict: this.validateVerdict(parsed.verdict),
153
+ context: String(parsed.context ?? ''),
154
+ confidence: Math.min(1, Math.max(0, Number(parsed.confidence) || 0.5)),
155
+ };
156
+ }
157
+ }
158
+ catch {
159
+ // Fall through to default
160
+ }
161
+ return {
162
+ verdict: 'unknown',
163
+ context: 'Unable to parse analysis response',
164
+ confidence: 0,
165
+ };
166
+ }
167
+ /**
168
+ * Validate verdict is a known value
169
+ */
170
+ validateVerdict(value) {
171
+ const valid = [
172
+ 'accidental',
173
+ 'intentional',
174
+ 'ai-generated',
175
+ 'unknown',
176
+ ];
177
+ return valid.includes(value)
178
+ ? value
179
+ : 'unknown';
180
+ }
181
+ }
182
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { HistoryAgent } from './history.js';
2
+ export { ReviewAgent } from './review.js';
3
+ export { AcceptanceAgent } from './acceptance.js';
4
+ export { FixabilityAgent } from './fixability.js';
5
+ export { GeneratorAgent } from './generator.js';
6
+ export type { RepoContext, SampledFile, AgentResult, HistoryInput, HistoryResult, HistoryVerdict, CommitInfo, ReviewInput, ReviewResult, MissedPattern, MissedPatternCategory, BuoyImprovement, AcceptanceInput, AcceptanceResult, AcceptanceLikelihood, FixabilityInput, FixabilityResult, FixTier, FixDifficulty, GeneratorInput, GeneratorResult, GeneratedFix, ContributionState, } from './types.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,YAAY,EAEV,WAAW,EACX,WAAW,EACX,WAAW,EAGX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,UAAU,EAGV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,qBAAqB,EACrB,eAAe,EAGf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EAGpB,eAAe,EACf,gBAAgB,EAChB,OAAO,EACP,aAAa,EAGb,cAAc,EACd,eAAe,EACf,YAAY,EAGZ,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // packages/agents/src/index.ts
2
+ // Main entry point for @buoy-design/agents
3
+ // Agents
4
+ export { HistoryAgent } from './history.js';
5
+ export { ReviewAgent } from './review.js';
6
+ export { AcceptanceAgent } from './acceptance.js';
7
+ export { FixabilityAgent } from './fixability.js';
8
+ export { GeneratorAgent } from './generator.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,2CAA2C;AAE3C,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { ReviewInput, ReviewResult, AgentResult } from './types.js';
2
+ export declare class ReviewAgent {
3
+ private client;
4
+ constructor(apiKey?: string);
5
+ /**
6
+ * Review what Buoy found vs what's in the repo
7
+ */
8
+ analyze(input: ReviewInput): Promise<AgentResult<ReviewResult>>;
9
+ /**
10
+ * Build the analysis prompt
11
+ */
12
+ private buildPrompt;
13
+ /**
14
+ * Parse Claude's response
15
+ */
16
+ private parseResponse;
17
+ /**
18
+ * Validate missed patterns array
19
+ */
20
+ private validateMissedPatterns;
21
+ /**
22
+ * Validate improvements array
23
+ */
24
+ private validateImprovements;
25
+ /**
26
+ * Get file extension for syntax highlighting
27
+ */
28
+ private getFileExtension;
29
+ /**
30
+ * Truncate content to max lines
31
+ */
32
+ private truncateContent;
33
+ }
34
+ //# sourceMappingURL=review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EAGZ,WAAW,EACZ,MAAM,YAAY,CAAC;AAIpB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,CAAC,EAAE,MAAM;IAM3B;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IA8BrE;;OAEG;IACH,OAAO,CAAC,WAAW;IAuFnB;;OAEG;IACH,OAAO,CAAC,aAAa;IA4BrB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA6B9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAuB5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH,OAAO,CAAC,eAAe;CASxB"}