Skip to content

Commit 048701e

Browse files
authored
feat(gpt5): first draft (#242)
fix #241
1 parent b7985b9 commit 048701e

24 files changed

Lines changed: 7800 additions & 9613 deletions

.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,9 @@ PROXY_REVIEWER_TOKEN=ghp_your_token_here
3333
# Server Configuration (Probot v14)
3434
HOST=0.0.0.0
3535
PORT=3000
36+
37+
# OpenAI Configuration
38+
# Required when llmProvider is set to "openai"
39+
OPENAI_API_KEY=xxx
40+
# Optional: override model (defaults to "gpt-5")
41+
OPENAI_MODEL=gpt-5

CHANGELOG.md

Lines changed: 7137 additions & 9413 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,39 @@ WEBHOOK_PROXY_URL=https://smee.io/your-url
6868

6969
See [.env.example](.env.example) for an example.
7070

71+
## Choosing a provider (Anthropic or OpenAI)
72+
73+
Revu supports both Anthropic and OpenAI. Select the provider in `config.json`:
74+
75+
```json
76+
{
77+
"promptStrategy": "line-comments",
78+
"thinkingEnabled": true,
79+
"llmProvider": "openai"
80+
}
81+
```
82+
83+
- llmProvider: "anthropic" (default) or "openai"
84+
85+
Environment variables per provider:
86+
87+
- Anthropic (default):
88+
- Required: ANTHROPIC_API_KEY
89+
- Optional: ANTHROPIC_MODEL (default: claude-sonnet-4-5-20250929)
90+
- Optional: ANTHROPIC_EXTENDED_CONTEXT=true to enable 1M context (beta API)
91+
92+
- OpenAI (official endpoint):
93+
- Required: OPENAI_API_KEY
94+
- Optional: OPENAI_MODEL (default: gpt-5)
95+
96+
Example OpenAI env:
97+
98+
```env
99+
OPENAI_API_KEY=your_openai_key
100+
# Optional model override
101+
OPENAI_MODEL=gpt-5
102+
```
103+
71104
## Running Revu
72105

73106
### Local Development
@@ -106,8 +139,8 @@ thinkingEnabled: true
106139
107140
# Custom coding guidelines
108141
codingGuidelines:
109-
- "Use descriptive variable names"
110-
- "Add comments for complex logic"
142+
- 'Use descriptive variable names'
143+
- 'Add comments for complex logic'
111144
112145
# PR validation rules
113146
validation:
@@ -117,9 +150,9 @@ validation:
117150
# Branch filtering
118151
branches:
119152
patterns:
120-
- "!**"
121-
- "main"
122-
- "release/*"
153+
- '!**'
154+
- 'main'
155+
- 'release/*'
123156
```
124157

125158
## Contributing

__tests__/anthropic-senders/line-comments-sender.test.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { beforeEach, describe, expect, it, vi } from 'vitest'
2-
import { lineCommentsSender } from '../../src/anthropic-senders/line-comments-sender.ts'
2+
import { anthropicLineCommentsSender } from '../../src/senders/providers/anthropic/line-comments-sender.ts'
33

44
// Mock the Anthropic SDK
55
vi.mock('@anthropic-ai/sdk', () => {
@@ -113,7 +113,7 @@ const mockMixedResponse = (
113113
target.mockResolvedValue({ content })
114114
}
115115

116-
describe('lineCommentsSender', () => {
116+
describe('anthropicLineCommentsSender', () => {
117117
let mockAnthropic: {
118118
messages: {
119119
create: ReturnType<typeof vi.fn>
@@ -156,7 +156,7 @@ describe('lineCommentsSender', () => {
156156

157157
mockToolUseResponse(mockAnthropic, expectedResponse)
158158

159-
const result = await lineCommentsSender('test prompt')
159+
const result = await anthropicLineCommentsSender('test prompt')
160160
expect(result).toBe(JSON.stringify(expectedResponse))
161161
})
162162

@@ -165,7 +165,7 @@ describe('lineCommentsSender', () => {
165165

166166
mockToolUseResponse(mockAnthropic, expectedResponse)
167167

168-
const result = await lineCommentsSender('test prompt')
168+
const result = await anthropicLineCommentsSender('test prompt')
169169
expect(result).toBe(JSON.stringify(expectedResponse))
170170
})
171171

@@ -184,7 +184,7 @@ This is the code review result.`
184184

185185
mockTextResponse(mockAnthropic, textResponse)
186186

187-
const result = await lineCommentsSender('test prompt')
187+
const result = await anthropicLineCommentsSender('test prompt')
188188
expect(result).toBe(JSON.stringify(expectedJson, null, 2))
189189
})
190190

@@ -196,7 +196,7 @@ This is the code review result.`
196196
const jsonResponse = JSON.stringify(expectedJson)
197197
mockTextResponse(mockAnthropic, jsonResponse)
198198

199-
const result = await lineCommentsSender('test prompt')
199+
const result = await anthropicLineCommentsSender('test prompt')
200200
expect(result).toBe(jsonResponse)
201201
})
202202

@@ -215,7 +215,7 @@ Some text after that should be ignored`
215215

216216
mockTextResponse(mockAnthropic, textWithJson)
217217

218-
const result = await lineCommentsSender('test prompt')
218+
const result = await anthropicLineCommentsSender('test prompt')
219219
expect(result).toBe(JSON.stringify(expectedJson))
220220
})
221221

@@ -224,7 +224,7 @@ Some text after that should be ignored`
224224

225225
mockTextResponse(mockAnthropic, plainTextResponse)
226226

227-
const result = await lineCommentsSender('test prompt')
227+
const result = await anthropicLineCommentsSender('test prompt')
228228
expect(result).toBe(plainTextResponse)
229229
})
230230

@@ -237,15 +237,15 @@ Some text after that should be ignored`
237237
}
238238
])
239239

240-
await expect(lineCommentsSender('test prompt')).rejects.toThrow(
240+
await expect(anthropicLineCommentsSender('test prompt')).rejects.toThrow(
241241
'Unexpected tool name: unexpected_tool'
242242
)
243243
})
244244

245245
it('should throw error when no content is found', async () => {
246246
mockMixedResponse(mockAnthropic, [])
247247

248-
await expect(lineCommentsSender('test prompt')).rejects.toThrow(
248+
await expect(anthropicLineCommentsSender('test prompt')).rejects.toThrow(
249249
'Unexpected response format from Anthropic inline comment - no content found'
250250
)
251251
})
@@ -270,7 +270,7 @@ This should fallback to the entire text since JSON is invalid.`
270270

271271
mockTextResponse(mockAnthropic, invalidJsonInCodeBlock)
272272

273-
const result = await lineCommentsSender('test prompt')
273+
const result = await anthropicLineCommentsSender('test prompt')
274274

275275
// Should return the invalid JSON string (not the whole text)
276276
// The validation happens later in lineCommentsHandler
@@ -283,7 +283,7 @@ This should fallback to the entire text since JSON is invalid.`
283283

284284
mockTextResponse(mockAnthropic, invalidJsonText)
285285

286-
const result = await lineCommentsSender('test prompt')
286+
const result = await anthropicLineCommentsSender('test prompt')
287287

288288
// Should return the invalid JSON string as-is
289289
// The validation/parsing happens in lineCommentsHandler
@@ -295,7 +295,7 @@ This should fallback to the entire text since JSON is invalid.`
295295

296296
mockTextResponse(mockAnthropic, malformedJson)
297297

298-
const result = await lineCommentsSender('test prompt')
298+
const result = await anthropicLineCommentsSender('test prompt')
299299

300300
// Should return the malformed JSON as-is
301301
expect(result).toBe(malformedJson)
@@ -318,7 +318,7 @@ More text after.`
318318

319319
mockTextResponse(mockAnthropic, textWithValidJsonInCodeBlock)
320320

321-
const result = await lineCommentsSender('test prompt')
321+
const result = await anthropicLineCommentsSender('test prompt')
322322

323323
// Should return the valid JSON from the code block, not the malformed JSON-like text
324324
expect(result).toBe(JSON.stringify(validJson, null, 2))
@@ -336,7 +336,7 @@ More text after.`
336336
createToolUseContent(expectedResponse)
337337
])
338338

339-
const result = await lineCommentsSender('test prompt', true)
339+
const result = await anthropicLineCommentsSender('test prompt', true)
340340

341341
// Should extract only the tool_use result, ignoring thinking blocks
342342
expect(result).toBe(JSON.stringify(expectedResponse))
@@ -360,7 +360,7 @@ More text after.`
360360

361361
mockToolUseResponse(mockAnthropic, expectedResponse)
362362

363-
const result = await lineCommentsSender('test prompt', false)
363+
const result = await anthropicLineCommentsSender('test prompt', false)
364364

365365
expect(result).toBe(JSON.stringify(expectedResponse))
366366

@@ -381,7 +381,7 @@ More text after.`
381381

382382
mockToolUseResponse(mockAnthropic, expectedResponse)
383383

384-
const result = await lineCommentsSender('test prompt')
384+
const result = await anthropicLineCommentsSender('test prompt')
385385

386386
expect(result).toBe(JSON.stringify(expectedResponse))
387387

@@ -401,7 +401,7 @@ More text after.`
401401

402402
mockToolUseResponse(mockAnthropic, expectedResponse)
403403

404-
const result = await lineCommentsSender('test prompt')
404+
const result = await anthropicLineCommentsSender('test prompt')
405405

406406
expect(result).toBe(JSON.stringify(expectedResponse))
407407

@@ -423,7 +423,7 @@ More text after.`
423423

424424
mockToolUseResponse(mockAnthropic, expectedResponse)
425425

426-
const result = await lineCommentsSender('test prompt')
426+
const result = await anthropicLineCommentsSender('test prompt')
427427

428428
expect(result).toBe(JSON.stringify(expectedResponse))
429429

@@ -448,7 +448,7 @@ More text after.`
448448

449449
mockToolUseResponse(mockAnthropic, expectedResponse, false)
450450

451-
const result = await lineCommentsSender('test prompt')
451+
const result = await anthropicLineCommentsSender('test prompt')
452452

453453
expect(result).toBe(JSON.stringify(expectedResponse))
454454

@@ -474,7 +474,7 @@ More text after.`
474474
createToolUseContent(expectedResponse)
475475
])
476476

477-
const result = await lineCommentsSender('test prompt', true)
477+
const result = await anthropicLineCommentsSender('test prompt', true)
478478

479479
expect(result).toBe(JSON.stringify(expectedResponse))
480480

@@ -507,7 +507,7 @@ More text after.`
507507
false
508508
)
509509

510-
const result = await lineCommentsSender('test prompt', true)
510+
const result = await anthropicLineCommentsSender('test prompt', true)
511511

512512
expect(result).toBe(JSON.stringify(expectedResponse))
513513

0 commit comments

Comments
 (0)