-
Notifications
You must be signed in to change notification settings - Fork 8
fix error -gpt and claude issues on prod #185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -557,6 +557,8 @@ app.post("/api/ai/chat", async (req, res) => { | |||||||||||||||||||||||||||||||||||||||||||||
| let buffer = "" | ||||||||||||||||||||||||||||||||||||||||||||||
| let inputTokens = 0 | ||||||||||||||||||||||||||||||||||||||||||||||
| let outputTokens = 0 | ||||||||||||||||||||||||||||||||||||||||||||||
| let fullContent = "" | ||||||||||||||||||||||||||||||||||||||||||||||
| let sawToolCalls = false | ||||||||||||||||||||||||||||||||||||||||||||||
| let pendingToolCalls: Record<number, { id: string; name: string; args: string }> = {} | ||||||||||||||||||||||||||||||||||||||||||||||
| while (true) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const { done, value } = await reader.read() | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -573,9 +575,11 @@ app.post("/api/ai/chat", async (req, res) => { | |||||||||||||||||||||||||||||||||||||||||||||
| const data = JSON.parse(jsonStr) | ||||||||||||||||||||||||||||||||||||||||||||||
| const delta = data.choices?.[0]?.delta | ||||||||||||||||||||||||||||||||||||||||||||||
| if (delta?.content) { | ||||||||||||||||||||||||||||||||||||||||||||||
| fullContent += delta.content | ||||||||||||||||||||||||||||||||||||||||||||||
| res.write(JSON.stringify({ type: "text", content: delta.content }) + "\n") | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (delta?.tool_calls) { | ||||||||||||||||||||||||||||||||||||||||||||||
| sawToolCalls = true | ||||||||||||||||||||||||||||||||||||||||||||||
| for (const tc of delta.tool_calls) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const index = tc.index ?? 0 | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!pendingToolCalls[index]) { | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -605,6 +609,45 @@ app.post("/api/ai/chat", async (req, res) => { | |||||||||||||||||||||||||||||||||||||||||||||
| } catch { /* skip malformed */ } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Fallback: if streaming returned no text and no tool calls, | ||||||||||||||||||||||||||||||||||||||||||||||
| // retry as non-streaming (ConcentrateAI's upstream intermittently | ||||||||||||||||||||||||||||||||||||||||||||||
| // drops content on streaming requests). | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!fullContent.trim() && !sawToolCalls) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const fbBody: any = { | ||||||||||||||||||||||||||||||||||||||||||||||
| model: modelName, | ||||||||||||||||||||||||||||||||||||||||||||||
| messages: nonSystemMessages.map((m: any) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| const msg: any = { | ||||||||||||||||||||||||||||||||||||||||||||||
| role: m.role, | ||||||||||||||||||||||||||||||||||||||||||||||
| content: m.content !== null && m.content !== undefined ? String(m.content) : "", | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (m.tool_calls) msg.tool_calls = m.tool_calls | ||||||||||||||||||||||||||||||||||||||||||||||
| if (m.tool_call_id) msg.tool_call_id = m.tool_call_id | ||||||||||||||||||||||||||||||||||||||||||||||
| return msg | ||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||
| max_tokens: getModelMaxTokens(modelName), | ||||||||||||||||||||||||||||||||||||||||||||||
| temperature: 0.7, | ||||||||||||||||||||||||||||||||||||||||||||||
| stream: false, | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (system && nonSystemMessages.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||
| fbBody.messages = [{ role: "system", content: system }, ...fbBody.messages] | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| const fbRes = await fetch("https://api.concentrate.ai/v1/chat/completions", { | ||||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||||
| headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }, | ||||||||||||||||||||||||||||||||||||||||||||||
| body: JSON.stringify(fbBody), | ||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||
| if (fbRes.ok) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const fbData: any = await fbRes.json() | ||||||||||||||||||||||||||||||||||||||||||||||
| const fbContent = fbData?.choices?.[0]?.message?.content ?? "" | ||||||||||||||||||||||||||||||||||||||||||||||
| if (fbContent) { | ||||||||||||||||||||||||||||||||||||||||||||||
| res.write(JSON.stringify({ type: "text", content: fbContent }) + "\n") | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| inputTokens = fbData?.usage?.prompt_tokens ?? 0 | ||||||||||||||||||||||||||||||||||||||||||||||
| outputTokens = fbData?.usage?.completion_tokens ?? 0 | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+640
to
+648
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Silent failure and token counter reset on fallback error. Two issues in this block:
🛡️ Proposed fix: handle non-OK and guard token overwrite if (fbRes.ok) {
const fbData: any = await fbRes.json()
const fbContent = fbData?.choices?.[0]?.message?.content ?? ""
if (fbContent) {
res.write(JSON.stringify({ type: "text", content: fbContent }) + "\n")
}
- inputTokens = fbData?.usage?.prompt_tokens ?? 0
- outputTokens = fbData?.usage?.completion_tokens ?? 0
+ if (fbData?.usage) {
+ inputTokens = fbData.usage.prompt_tokens ?? inputTokens
+ outputTokens = fbData.usage.completion_tokens ?? outputTokens
+ }
+ } else {
+ console.error(`ConcentrateAI fallback failed: ${fbRes.status}`)
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| recordUsage({ | ||||||||||||||||||||||||||||||||||||||||||||||
| provider: "concentrateai", model: modelName, | ||||||||||||||||||||||||||||||||||||||||||||||
| inputTokens, outputTokens, cachedInputTokens: 0, | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
Fallback fetch lacks a timeout and retry — can hang the request thread indefinitely.
The upstream
nonStreamingRequestinconcentrate-service.tsusesfetchWithRetrywithAbortSignal.timeout(60_000). The fallbackfetchhere has neither, so a slow or unresponsive ConcentrateAI gateway will hold the Express request thread open with no upper bound.🔒️ Proposed fix: add timeout to fallback fetch
📝 Committable suggestion
🤖 Prompt for AI Agents