@azumag/opencode-rate-limit-fallback 1.0.8 → 1.0.10
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.
- package/dist/index.js +146 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "fs";
|
|
1
|
+
import { existsSync, readFileSync, appendFileSync } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
|
+
// Debug log at module level
|
|
4
|
+
console.log("[rate-limit-fallback] Module loaded, version:", process.env.npm_package_version || "unknown");
|
|
3
5
|
const DEFAULT_FALLBACK_MODELS = [
|
|
4
6
|
{ providerID: "anthropic", modelID: "claude-sonnet-4-20250514" },
|
|
5
7
|
{ providerID: "google", modelID: "gemini-2.5-pro" },
|
|
@@ -71,7 +73,44 @@ function isRateLimitError(error) {
|
|
|
71
73
|
}
|
|
72
74
|
export const RateLimitFallback = async ({ client, directory }) => {
|
|
73
75
|
const config = loadConfig(directory);
|
|
76
|
+
const logFilePath = join(process.env.HOME || "", ".opencode", "rate-limit-fallback-debug.log");
|
|
77
|
+
// Write to file for debugging
|
|
78
|
+
const logToFile = (message) => {
|
|
79
|
+
try {
|
|
80
|
+
appendFileSync(logFilePath, `[${new Date().toISOString()}] ${message}\n`);
|
|
81
|
+
}
|
|
82
|
+
catch { }
|
|
83
|
+
};
|
|
84
|
+
logToFile(`Plugin loaded, config: ${JSON.stringify(config)}`);
|
|
85
|
+
console.log("[rate-limit-fallback] Plugin loaded, config:", config);
|
|
86
|
+
// Use client.app.log for better logging in both run and TUI modes
|
|
87
|
+
try {
|
|
88
|
+
await client.app.log({
|
|
89
|
+
body: {
|
|
90
|
+
service: "rate-limit-fallback",
|
|
91
|
+
level: "info",
|
|
92
|
+
message: `Plugin loaded, config: ${JSON.stringify(config)}`,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
logToFile(`client.app.log failed: ${e}`);
|
|
98
|
+
console.log("[rate-limit-fallback] Plugin loaded, config:", config);
|
|
99
|
+
}
|
|
74
100
|
if (!config.enabled) {
|
|
101
|
+
logToFile("Plugin disabled, returning empty object");
|
|
102
|
+
try {
|
|
103
|
+
await client.app.log({
|
|
104
|
+
body: {
|
|
105
|
+
service: "rate-limit-fallback",
|
|
106
|
+
level: "info",
|
|
107
|
+
message: "Plugin disabled, returning empty object",
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
console.log("[rate-limit-fallback] Plugin disabled, returning empty object");
|
|
113
|
+
}
|
|
75
114
|
return {};
|
|
76
115
|
}
|
|
77
116
|
const rateLimitedModels = new Map();
|
|
@@ -283,29 +322,135 @@ export const RateLimitFallback = async ({ client, directory }) => {
|
|
|
283
322
|
}
|
|
284
323
|
return {
|
|
285
324
|
event: async ({ event }) => {
|
|
325
|
+
// Log events to debug plugin execution
|
|
326
|
+
logToFile(`Event received: ${event.type}`);
|
|
327
|
+
try {
|
|
328
|
+
await client.app.log({
|
|
329
|
+
body: {
|
|
330
|
+
service: "rate-limit-fallback",
|
|
331
|
+
level: "debug",
|
|
332
|
+
message: `Event received: ${event.type}`,
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
catch (e) {
|
|
337
|
+
logToFile(`client.app.log failed for event: ${e}`);
|
|
338
|
+
console.log("[rate-limit-fallback] Event received:", event.type);
|
|
339
|
+
}
|
|
286
340
|
if (event.type === "session.error") {
|
|
287
341
|
const { sessionID, error } = event.properties;
|
|
342
|
+
logToFile(`session.error: sessionID=${sessionID}, error=${JSON.stringify(error)}`);
|
|
343
|
+
try {
|
|
344
|
+
await client.app.log({
|
|
345
|
+
body: {
|
|
346
|
+
service: "rate-limit-fallback",
|
|
347
|
+
level: "debug",
|
|
348
|
+
message: `session.error: sessionID=${sessionID}, error=${JSON.stringify(error)}`,
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
console.log("[rate-limit-fallback] session.error:", sessionID, error);
|
|
354
|
+
}
|
|
288
355
|
if (sessionID && error && isRateLimitError(error)) {
|
|
356
|
+
logToFile("Rate limit error detected, attempting fallback");
|
|
357
|
+
try {
|
|
358
|
+
await client.app.log({
|
|
359
|
+
body: {
|
|
360
|
+
service: "rate-limit-fallback",
|
|
361
|
+
level: "info",
|
|
362
|
+
message: "Rate limit error detected, attempting fallback",
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
console.log("[rate-limit-fallback] Rate limit error detected, attempting fallback");
|
|
368
|
+
}
|
|
289
369
|
await handleRateLimitFallback(sessionID, "", "");
|
|
290
370
|
}
|
|
291
371
|
}
|
|
292
372
|
if (event.type === "message.updated") {
|
|
293
373
|
const info = event.properties?.info;
|
|
374
|
+
logToFile(`message.updated: ${JSON.stringify(info)}`);
|
|
375
|
+
try {
|
|
376
|
+
await client.app.log({
|
|
377
|
+
body: {
|
|
378
|
+
service: "rate-limit-fallback",
|
|
379
|
+
level: "debug",
|
|
380
|
+
message: `message.updated: ${JSON.stringify(info)}`,
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
console.log("[rate-limit-fallback] message.updated:", info);
|
|
386
|
+
}
|
|
294
387
|
if (info?.error && isRateLimitError(info.error)) {
|
|
388
|
+
logToFile("Rate limit error in message, attempting fallback");
|
|
389
|
+
try {
|
|
390
|
+
await client.app.log({
|
|
391
|
+
body: {
|
|
392
|
+
service: "rate-limit-fallback",
|
|
393
|
+
level: "info",
|
|
394
|
+
message: "Rate limit error in message, attempting fallback",
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
catch {
|
|
399
|
+
console.log("[rate-limit-fallback] Rate limit error in message, attempting fallback");
|
|
400
|
+
}
|
|
295
401
|
await handleRateLimitFallback(info.sessionID, info.providerID || "", info.modelID || "");
|
|
296
402
|
}
|
|
297
403
|
}
|
|
298
404
|
if (event.type === "session.status") {
|
|
299
405
|
const props = event.properties;
|
|
300
406
|
const status = props?.status;
|
|
407
|
+
logToFile(`session.status: ${JSON.stringify(status)}`);
|
|
408
|
+
try {
|
|
409
|
+
await client.app.log({
|
|
410
|
+
body: {
|
|
411
|
+
service: "rate-limit-fallback",
|
|
412
|
+
level: "debug",
|
|
413
|
+
message: `session.status: ${JSON.stringify(status)}`,
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
console.log("[rate-limit-fallback] session.status:", status);
|
|
419
|
+
}
|
|
301
420
|
if (status?.type === "retry" && status?.message) {
|
|
302
421
|
const message = status.message.toLowerCase();
|
|
303
422
|
const isRateLimitRetry = message.includes("usage limit") ||
|
|
304
423
|
message.includes("rate limit") ||
|
|
305
424
|
message.includes("high concurrency") ||
|
|
306
425
|
message.includes("reduce concurrency");
|
|
426
|
+
logToFile(`Is rate limit retry: ${isRateLimitRetry}, message: ${message}`);
|
|
427
|
+
try {
|
|
428
|
+
await client.app.log({
|
|
429
|
+
body: {
|
|
430
|
+
service: "rate-limit-fallback",
|
|
431
|
+
level: "debug",
|
|
432
|
+
message: `Is rate limit retry: ${isRateLimitRetry}, message: ${message}`,
|
|
433
|
+
},
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
console.log("[rate-limit-fallback] Is rate limit retry:", isRateLimitRetry, "message:", message);
|
|
438
|
+
}
|
|
307
439
|
if (isRateLimitRetry) {
|
|
308
440
|
// Try fallback on any attempt, handleRateLimitFallback will manage state
|
|
441
|
+
logToFile("Attempting fallback for rate limit retry");
|
|
442
|
+
try {
|
|
443
|
+
await client.app.log({
|
|
444
|
+
body: {
|
|
445
|
+
service: "rate-limit-fallback",
|
|
446
|
+
level: "info",
|
|
447
|
+
message: "Attempting fallback for rate limit retry",
|
|
448
|
+
},
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
console.log("[rate-limit-fallback] Attempting fallback for rate limit retry");
|
|
453
|
+
}
|
|
309
454
|
await handleRateLimitFallback(props.sessionID, "", "");
|
|
310
455
|
}
|
|
311
456
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azumag/opencode-rate-limit-fallback",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "OpenCode plugin that automatically switches to fallback models when rate limited",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"build": "tsc",
|
|
8
9
|
"prepublishOnly": "npm run build"
|