Skip to content

Commit d05d7a1

Browse files
committed
charge user even if client disconnects
1 parent 270ae77 commit d05d7a1

File tree

1 file changed

+37
-11
lines changed

1 file changed

+37
-11
lines changed

web/src/llm-api/openrouter.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export async function handleOpenRouterStream({
7878

7979
let heartbeatInterval: NodeJS.Timeout
8080
let state: StreamState = { responseText: '', reasoningText: '' }
81+
let clientDisconnected = false
8182

8283
// Create a ReadableStream that Next.js can handle
8384
const stream = new ReadableStream({
@@ -92,11 +93,17 @@ export async function handleOpenRouterStream({
9293

9394
// Start heartbeat
9495
heartbeatInterval = setInterval(() => {
95-
controller.enqueue(
96-
new TextEncoder().encode(
97-
`: heartbeat ${new Date().toISOString()}\n\n`
98-
)
99-
)
96+
if (!clientDisconnected) {
97+
try {
98+
controller.enqueue(
99+
new TextEncoder().encode(
100+
`: heartbeat ${new Date().toISOString()}\n\n`
101+
)
102+
)
103+
} catch {
104+
// client disconnected, ignore error
105+
}
106+
}
100107
}, 30000)
101108

102109
try {
@@ -125,24 +132,43 @@ export async function handleOpenRouterStream({
125132
state,
126133
})
127134

128-
// Forward the line to the client
129-
controller.enqueue(new TextEncoder().encode(line))
135+
if (!clientDisconnected) {
136+
try {
137+
controller.enqueue(new TextEncoder().encode(line))
138+
} catch (error) {
139+
logger.warn(
140+
'Client disconnected during stream, continuing for billing'
141+
)
142+
clientDisconnected = true
143+
}
144+
}
130145

131146
lineEnd = buffer.indexOf('\n')
132147
}
133148
}
134149

135-
controller.close()
150+
if (!clientDisconnected) {
151+
controller.close()
152+
}
136153
} catch (error) {
137-
controller.error(error)
154+
if (!clientDisconnected) {
155+
controller.error(error)
156+
} else {
157+
logger.warn(
158+
getErrorObject(error),
159+
'Error after client disconnect in OpenRouter stream'
160+
)
161+
}
138162
} finally {
139163
clearInterval(heartbeatInterval)
140-
reader.cancel()
141164
}
142165
},
143166
cancel() {
144167
clearInterval(heartbeatInterval)
145-
reader.cancel()
168+
clientDisconnected = true
169+
logger.warn(
170+
'Client cancelled stream, continuing OpenRouter consumption for billing'
171+
)
146172
},
147173
})
148174

0 commit comments

Comments
 (0)