mirror of
https://github.com/rustfs/console.git
synced 2026-08-30 17:14:47 +08:00
fix:flow
This commit is contained in:
+111
-25
@@ -3,7 +3,19 @@ import { writeFile } from "node:fs/promises"
|
||||
|
||||
const anthropicToken = process.env.ANTHROPIC_AUTH_TOKEN
|
||||
const anthropicBaseUrl = process.env.ANTHROPIC_BASE_URL || "https://api.anthropic.com"
|
||||
const anthropicModel = process.env.ANTHROPIC_MODEL || "claude-opus-4.1"
|
||||
|
||||
const defaultHaikuModel = process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL || "claude-haiku-4.5"
|
||||
const defaultOpusModel = process.env.ANTHROPIC_DEFAULT_OPUS_MODEL || "claude-opus-4.6"
|
||||
const defaultSonnetModel = process.env.ANTHROPIC_DEFAULT_SONNET_MODEL || "claude-sonnet-4.6"
|
||||
|
||||
// Priority: explicit model override -> sonnet default -> haiku -> opus.
|
||||
const anthropicModel = process.env.ANTHROPIC_MODEL || defaultSonnetModel || defaultHaikuModel || defaultOpusModel
|
||||
|
||||
const timeoutMs = Number(process.env.ANTHROPIC_TIMEOUT_MS || "180000")
|
||||
const maxRetries = Number(process.env.ANTHROPIC_MAX_RETRIES || "3")
|
||||
const retryBaseMs = Number(process.env.ANTHROPIC_RETRY_BASE_MS || "2000")
|
||||
const maxTokens = Number(process.env.ANTHROPIC_MAX_TOKENS || "2048")
|
||||
|
||||
const issueNumber = process.env.ISSUE_NUMBER || ""
|
||||
const issueTitle = process.env.ISSUE_TITLE || ""
|
||||
const issueBody = process.env.ISSUE_BODY || ""
|
||||
@@ -15,6 +27,26 @@ if (!anthropicToken) {
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
||||
console.error(`Invalid ANTHROPIC_TIMEOUT_MS: ${process.env.ANTHROPIC_TIMEOUT_MS}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!Number.isFinite(maxRetries) || maxRetries < 1) {
|
||||
console.error(`Invalid ANTHROPIC_MAX_RETRIES: ${process.env.ANTHROPIC_MAX_RETRIES}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!Number.isFinite(retryBaseMs) || retryBaseMs < 0) {
|
||||
console.error(`Invalid ANTHROPIC_RETRY_BASE_MS: ${process.env.ANTHROPIC_RETRY_BASE_MS}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!Number.isFinite(maxTokens) || maxTokens < 1) {
|
||||
console.error(`Invalid ANTHROPIC_MAX_TOKENS: ${process.env.ANTHROPIC_MAX_TOKENS}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const prompt = [
|
||||
"You are a senior software engineer fixing a GitHub issue.",
|
||||
"Return ONLY strict JSON with keys: summary, patch.",
|
||||
@@ -29,33 +61,87 @@ const prompt = [
|
||||
issueBody || "(empty)",
|
||||
].join("\n")
|
||||
|
||||
const response = await fetch(`${anthropicBaseUrl.replace(/\/$/, "")}/v1/messages`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": anthropicToken,
|
||||
"anthropic-version": "2023-06-01",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: anthropicModel,
|
||||
max_tokens: 4096,
|
||||
temperature: 0.2,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: prompt,
|
||||
},
|
||||
],
|
||||
}),
|
||||
})
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errText = await response.text()
|
||||
console.error(`Anthropic API error: ${response.status} ${errText}`)
|
||||
function shouldRetry(status) {
|
||||
return status === 408 || status === 429 || status >= 500
|
||||
}
|
||||
|
||||
async function requestClaude() {
|
||||
const endpoint = `${anthropicBaseUrl.replace(/\/$/, "")}/v1/messages`
|
||||
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt += 1) {
|
||||
const controller = new AbortController()
|
||||
const timer = setTimeout(() => controller.abort(), timeoutMs)
|
||||
|
||||
try {
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": anthropicToken,
|
||||
"anthropic-version": "2023-06-01",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: anthropicModel,
|
||||
max_tokens: maxTokens,
|
||||
temperature: 0.2,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: prompt,
|
||||
},
|
||||
],
|
||||
}),
|
||||
signal: controller.signal,
|
||||
})
|
||||
|
||||
const rawText = await response.text()
|
||||
|
||||
if (!response.ok) {
|
||||
if (attempt < maxRetries && shouldRetry(response.status)) {
|
||||
const delay = retryBaseMs * 2 ** (attempt - 1)
|
||||
console.warn(`Anthropic returned ${response.status}, retrying in ${delay}ms (attempt ${attempt}/${maxRetries})`)
|
||||
await sleep(delay)
|
||||
continue
|
||||
}
|
||||
|
||||
console.error(`Anthropic API error: ${response.status} ${rawText}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(rawText)
|
||||
} catch {
|
||||
console.error("Anthropic API returned non-JSON response")
|
||||
console.error(rawText)
|
||||
process.exit(1)
|
||||
}
|
||||
} catch (error) {
|
||||
const isAbort = error instanceof Error && error.name === "AbortError"
|
||||
if (attempt < maxRetries) {
|
||||
const delay = retryBaseMs * 2 ** (attempt - 1)
|
||||
console.warn(
|
||||
`${isAbort ? "Request timed out" : "Request failed"}, retrying in ${delay}ms (attempt ${attempt}/${maxRetries})`,
|
||||
)
|
||||
await sleep(delay)
|
||||
continue
|
||||
}
|
||||
|
||||
console.error(isAbort ? `Anthropic request timeout after ${timeoutMs}ms` : `Anthropic request failed: ${String(error)}`)
|
||||
process.exit(1)
|
||||
} finally {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
}
|
||||
|
||||
console.error("Anthropic request exhausted retries")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
const data = await requestClaude()
|
||||
const outputText = Array.isArray(data?.content)
|
||||
? data.content
|
||||
.filter((part) => part?.type === "text" && typeof part?.text === "string")
|
||||
@@ -89,4 +175,4 @@ if (!parsed.patch || typeof parsed.patch !== "string") {
|
||||
|
||||
await writeFile("/tmp/issue-autofix.patch", parsed.patch)
|
||||
await writeFile("/tmp/issue-autofix-summary.txt", String(parsed.summary || ""))
|
||||
console.log("Generated patch at /tmp/issue-autofix.patch")
|
||||
console.log(`Generated patch at /tmp/issue-autofix.patch using model ${anthropicModel}`)
|
||||
|
||||
Reference in New Issue
Block a user