Spaces:
Running
Running
Merge pull request #23 from anurag162008/codex/investigate-syncing-issue-with-huggingclaw-backup-qac4nq
Browse files- .env.example +4 -1
- README.md +2 -2
- multi-provider-key-rotator.cjs +13 -3
- openclaw-sync.py +1 -0
.env.example
CHANGED
|
@@ -132,7 +132,10 @@ LLM_MODEL=anthropic/claude-sonnet-4-5
|
|
| 132 |
# have multiple accounts or want to spread rate-limit quota.
|
| 133 |
#
|
| 134 |
# Pattern: <PROVIDER>_API_KEYS=key1,key2,key3
|
| 135 |
-
# Fallback order: plural pool β singular key β LLM_API_KEY
|
|
|
|
|
|
|
|
|
|
| 136 |
#
|
| 137 |
# Uncomment and fill in only the providers you use:
|
| 138 |
#
|
|
|
|
| 132 |
# have multiple accounts or want to spread rate-limit quota.
|
| 133 |
#
|
| 134 |
# Pattern: <PROVIDER>_API_KEYS=key1,key2,key3
|
| 135 |
+
# Fallback order: plural pool β singular key β LLM_API_KEY (optional)
|
| 136 |
+
# Set false only if you want to disable global LLM_API_KEY fallback
|
| 137 |
+
# across providers.
|
| 138 |
+
LLM_API_KEY_FALLBACK_ENABLED=true
|
| 139 |
#
|
| 140 |
# Uncomment and fill in only the providers you use:
|
| 141 |
#
|
README.md
CHANGED
|
@@ -250,10 +250,10 @@ GEMINI_API_KEYS=AIza-key1,AIza-key2
|
|
| 250 |
**Fallback chain** (per provider):
|
| 251 |
1. `{PROVIDER}_API_KEYS` β comma-separated pool *(preferred)*
|
| 252 |
2. `{PROVIDER}_API_KEY` β single dedicated key
|
| 253 |
-
3. `LLM_API_KEY` β universal fallback *(default
|
| 254 |
|
| 255 |
> [!TIP]
|
| 256 |
-
>
|
| 257 |
|
| 258 |
Supported per-provider variables: `ANTHROPIC_API_KEYS`, `OPENAI_API_KEYS`, `GEMINI_API_KEYS`, `DEEPSEEK_API_KEYS`, `GROQ_API_KEYS`, `MISTRAL_API_KEYS`, `OPENROUTER_API_KEYS`, `XAI_API_KEYS`, `NVIDIA_API_KEYS`, `COHERE_API_KEYS`, `TOGETHER_API_KEYS`, `CEREBRAS_API_KEYS`, and more β see `.env.example` for the full list.
|
| 259 |
|
|
|
|
| 250 |
**Fallback chain** (per provider):
|
| 251 |
1. `{PROVIDER}_API_KEYS` β comma-separated pool *(preferred)*
|
| 252 |
2. `{PROVIDER}_API_KEY` β single dedicated key
|
| 253 |
+
3. `LLM_API_KEY` β universal fallback *(enabled by default; disable with `LLM_API_KEY_FALLBACK_ENABLED=false`)*
|
| 254 |
|
| 255 |
> [!TIP]
|
| 256 |
+
> By default, `LLM_API_KEY` fallback is enabled for compatibility. Set `LLM_API_KEY_FALLBACK_ENABLED=false` if you want strict provider-only activation.
|
| 257 |
|
| 258 |
Supported per-provider variables: `ANTHROPIC_API_KEYS`, `OPENAI_API_KEYS`, `GEMINI_API_KEYS`, `DEEPSEEK_API_KEYS`, `GROQ_API_KEYS`, `MISTRAL_API_KEYS`, `OPENROUTER_API_KEYS`, `XAI_API_KEYS`, `NVIDIA_API_KEYS`, `COHERE_API_KEYS`, `TOGETHER_API_KEYS`, `CEREBRAS_API_KEYS`, and more β see `.env.example` for the full list.
|
| 259 |
|
multi-provider-key-rotator.cjs
CHANGED
|
@@ -8,7 +8,7 @@
|
|
| 8 |
*
|
| 9 |
* For each provider you can supply a comma-separated pool:
|
| 10 |
* ANTHROPIC_API_KEYS=key1,key2,key3
|
| 11 |
-
* Falls back to the singular env var,
|
| 12 |
*
|
| 13 |
* Keys are rotated round-robin per provider independently.
|
| 14 |
*
|
|
@@ -30,7 +30,9 @@ const log = (...args) => console.error(...args);
|
|
| 30 |
// envPlural β env var that holds a comma-separated key pool (preferred)
|
| 31 |
// envSingular β env var that holds a single key (fallback)
|
| 32 |
//
|
| 33 |
-
// LLM_API_KEY
|
|
|
|
|
|
|
| 34 |
//
|
| 35 |
const PROVIDERS = [
|
| 36 |
{
|
|
@@ -180,6 +182,8 @@ function normalizeKeys(...inputs) {
|
|
| 180 |
|
| 181 |
// Build per-provider key pools + rotation indices
|
| 182 |
const providerState = PROVIDERS.map(p => {
|
|
|
|
|
|
|
| 183 |
const dedicatedKeys = normalizeKeys(
|
| 184 |
process.env[p.envPlural] || '',
|
| 185 |
process.env[p.envSingular] || '',
|
|
@@ -187,7 +191,11 @@ const providerState = PROVIDERS.map(p => {
|
|
| 187 |
const hasDedicated = dedicatedKeys.length > 0;
|
| 188 |
const keys = hasDedicated
|
| 189 |
? dedicatedKeys
|
| 190 |
-
:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
|
| 192 |
if (hasDedicated) {
|
| 193 |
log(`[key-rotator] ${p.name}: ${keys.length} key${keys.length === 1 ? '' : 's'}`);
|
|
@@ -208,6 +216,8 @@ const fallbackCount = providerState.filter(p => {
|
|
| 208 |
}).length;
|
| 209 |
if (fallbackCount > 0) {
|
| 210 |
log(`[key-rotator] ${fallbackCount} provider(s) using LLM_API_KEY fallback`);
|
|
|
|
|
|
|
| 211 |
}
|
| 212 |
|
| 213 |
// βββ Runtime helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 8 |
*
|
| 9 |
* For each provider you can supply a comma-separated pool:
|
| 10 |
* ANTHROPIC_API_KEYS=key1,key2,key3
|
| 11 |
+
* Falls back to the singular env var, and optionally to LLM_API_KEY.
|
| 12 |
*
|
| 13 |
* Keys are rotated round-robin per provider independently.
|
| 14 |
*
|
|
|
|
| 30 |
// envPlural β env var that holds a comma-separated key pool (preferred)
|
| 31 |
// envSingular β env var that holds a single key (fallback)
|
| 32 |
//
|
| 33 |
+
// LLM_API_KEY fallback can be controlled via:
|
| 34 |
+
// LLM_API_KEY_FALLBACK_ENABLED=true|false
|
| 35 |
+
// Default is enabled for backwards compatibility.
|
| 36 |
//
|
| 37 |
const PROVIDERS = [
|
| 38 |
{
|
|
|
|
| 182 |
|
| 183 |
// Build per-provider key pools + rotation indices
|
| 184 |
const providerState = PROVIDERS.map(p => {
|
| 185 |
+
const llmFallbackRaw = String(process.env.LLM_API_KEY_FALLBACK_ENABLED || '').trim().toLowerCase();
|
| 186 |
+
const llmFallbackEnabled = !/^(0|false|no|off)$/.test(llmFallbackRaw);
|
| 187 |
const dedicatedKeys = normalizeKeys(
|
| 188 |
process.env[p.envPlural] || '',
|
| 189 |
process.env[p.envSingular] || '',
|
|
|
|
| 191 |
const hasDedicated = dedicatedKeys.length > 0;
|
| 192 |
const keys = hasDedicated
|
| 193 |
? dedicatedKeys
|
| 194 |
+
: (
|
| 195 |
+
llmFallbackEnabled
|
| 196 |
+
? normalizeKeys(process.env.LLM_API_KEY || '')
|
| 197 |
+
: []
|
| 198 |
+
);
|
| 199 |
|
| 200 |
if (hasDedicated) {
|
| 201 |
log(`[key-rotator] ${p.name}: ${keys.length} key${keys.length === 1 ? '' : 's'}`);
|
|
|
|
| 216 |
}).length;
|
| 217 |
if (fallbackCount > 0) {
|
| 218 |
log(`[key-rotator] ${fallbackCount} provider(s) using LLM_API_KEY fallback`);
|
| 219 |
+
} else if (process.env.LLM_API_KEY && /^(0|false|no|off)$/i.test(String(process.env.LLM_API_KEY_FALLBACK_ENABLED || ''))) {
|
| 220 |
+
log('[key-rotator] LLM_API_KEY fallback disabled (set LLM_API_KEY_FALLBACK_ENABLED=true to re-enable)');
|
| 221 |
}
|
| 222 |
|
| 223 |
// βββ Runtime helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
openclaw-sync.py
CHANGED
|
@@ -70,6 +70,7 @@ EXCLUDED_STATE_NAMES = {
|
|
| 70 |
"openclaw-app",
|
| 71 |
"gateway.log",
|
| 72 |
"browser",
|
|
|
|
| 73 |
}
|
| 74 |
WHATSAPP_CREDS_DIR = OPENCLAW_HOME / "credentials" / "whatsapp" / "default"
|
| 75 |
WHATSAPP_BACKUP_DIR = STATE_DIR / "credentials" / "whatsapp" / "default"
|
|
|
|
| 70 |
"openclaw-app",
|
| 71 |
"gateway.log",
|
| 72 |
"browser",
|
| 73 |
+
"npm",
|
| 74 |
}
|
| 75 |
WHATSAPP_CREDS_DIR = OPENCLAW_HOME / "credentials" / "whatsapp" / "default"
|
| 76 |
WHATSAPP_BACKUP_DIR = STATE_DIR / "credentials" / "whatsapp" / "default"
|