anurag008w commited on
Commit
71f6985
·
unverified ·
2 Parent(s): b3c3254d8f6d4f

Merge pull request #26 from anurag162008/codex/investigate-syncing-issue-with-huggingclaw-backup

Browse files
Files changed (4) hide show
  1. .env.example +7 -0
  2. ENV_VARIABLES_FULL_LIST.md +35 -0
  3. openclaw-sync.py +25 -0
  4. start.sh +103 -0
.env.example CHANGED
@@ -175,6 +175,13 @@ LLM_API_KEY_FALLBACK_ENABLED=true
175
  # is also picked up by OpenClaw → that provider's models become
176
  # available in the Control UI for manual selection.
177
  # 3. Rotation pools (*_API_KEYS) work for every active provider
 
 
 
 
 
 
 
178
  # independently and in parallel.
179
  #
180
  # EXAMPLE — default Anthropic, also use OpenAI and Groq:
 
175
  # is also picked up by OpenClaw → that provider's models become
176
  # available in the Control UI for manual selection.
177
  # 3. Rotation pools (*_API_KEYS) work for every active provider
178
+ #
179
+ # Optional: explicitly pin model lists per provider for Control UI visibility
180
+ # when provider keys are configured.
181
+ # Format: comma-separated model IDs
182
+ # NVIDIA_MODELS=meta/llama-3.1-70b-instruct,nvidia/llama-3.1-nemotron-70b-instruct
183
+ # OPENAI_MODELS=gpt-4o-mini,gpt-4.1
184
+ # GROQ_MODELS=llama-3.3-70b-versatile,deepseek-r1-distill-llama-70b
185
  # independently and in parallel.
186
  #
187
  # EXAMPLE — default Anthropic, also use OpenAI and Groq:
ENV_VARIABLES_FULL_LIST.md CHANGED
@@ -75,6 +75,9 @@ Full list:
75
  - `XIAOMI_API_KEYS`
76
  - `VOLCANO_ENGINE_API_KEYS`
77
  - `BYTEPLUS_API_KEYS`
 
 
 
78
  - `MISTRAL_API_KEYS`
79
  - `XAI_API_KEYS`
80
  - `NVIDIA_API_KEYS`
@@ -84,6 +87,38 @@ Full list:
84
  - `CEREBRAS_API_KEYS`
85
  - `HUGGINGFACE_HUB_TOKENS`
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  ### Telegram / WhatsApp
88
  - `TELEGRAM_BOT_TOKEN` — bot token string. Example: `TELEGRAM_BOT_TOKEN=123456:ABC...`
89
  - `TELEGRAM_ALLOWED_USERS` — comma-separated numeric IDs. Example: `TELEGRAM_ALLOWED_USERS=12345,67890`
 
75
  - `XIAOMI_API_KEYS`
76
  - `VOLCANO_ENGINE_API_KEYS`
77
  - `BYTEPLUS_API_KEYS`
78
+ - `QIANFAN_API_KEYS`
79
+ - `MODELSTUDIO_API_KEYS`
80
+ - `KIMI_API_KEYS`
81
  - `MISTRAL_API_KEYS`
82
  - `XAI_API_KEYS`
83
  - `NVIDIA_API_KEYS`
 
87
  - `CEREBRAS_API_KEYS`
88
  - `HUGGINGFACE_HUB_TOKENS`
89
 
90
+ ### Provider model lists (optional, for Control UI visibility)
91
+ Format: comma-separated model IDs; used only when that provider has key(s) configured.
92
+ Examples:
93
+ - `NVIDIA_MODELS=meta/llama-3.1-70b-instruct,nvidia/llama-3.1-nemotron-70b-instruct`
94
+ - `OPENAI_MODELS=gpt-4o-mini,gpt-4.1`
95
+ - `GROQ_MODELS=llama-3.3-70b-versatile,deepseek-r1-distill-llama-70b`
96
+
97
+ Supported:
98
+ - `ANTHROPIC_MODELS`
99
+ - `OPENAI_MODELS`
100
+ - `GEMINI_MODELS`
101
+ - `DEEPSEEK_MODELS`
102
+ - `OPENROUTER_MODELS`
103
+ - `KILOCODE_MODELS`
104
+ - `OPENCODE_MODELS`
105
+ - `ZAI_MODELS`
106
+ - `MOONSHOT_MODELS`
107
+ - `KIMI_MODELS`
108
+ - `MINIMAX_MODELS`
109
+ - `MODELSTUDIO_MODELS`
110
+ - `XIAOMI_MODELS`
111
+ - `VOLCANO_ENGINE_MODELS`
112
+ - `BYTEPLUS_MODELS`
113
+ - `QIANFAN_MODELS`
114
+ - `GROQ_MODELS`
115
+ - `MISTRAL_MODELS`
116
+ - `XAI_MODELS`
117
+ - `NVIDIA_MODELS`
118
+ - `COHERE_MODELS`
119
+ - `TOGETHER_MODELS`
120
+ - `CEREBRAS_MODELS`
121
+
122
  ### Telegram / WhatsApp
123
  - `TELEGRAM_BOT_TOKEN` — bot token string. Example: `TELEGRAM_BOT_TOKEN=123456:ABC...`
124
  - `TELEGRAM_ALLOWED_USERS` — comma-separated numeric IDs. Example: `TELEGRAM_ALLOWED_USERS=12345,67890`
openclaw-sync.py CHANGED
@@ -360,6 +360,30 @@ def create_snapshot_dir(source_root: Path) -> Path:
360
  return staging_root
361
 
362
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  def restore_workspace() -> bool:
364
  if not HF_TOKEN:
365
  write_status("disabled", "HF_TOKEN is not configured.")
@@ -459,6 +483,7 @@ def _sync_once_unlocked(
459
  commit_message=f"HuggingClaw sync {time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}",
460
  ignore_patterns=[".git/*", ".git"],
461
  )
 
462
  finally:
463
  shutil.rmtree(snapshot_dir, ignore_errors=True)
464
 
 
360
  return staging_root
361
 
362
 
363
+ def prune_remote_deleted_files(repo_id: str, snapshot_dir: Path) -> None:
364
+ if HF_API is None:
365
+ return
366
+
367
+ local_files = {
368
+ path.relative_to(snapshot_dir).as_posix()
369
+ for path in snapshot_dir.rglob("*")
370
+ if path.is_file()
371
+ }
372
+
373
+ remote_files = HF_API.list_repo_files(repo_id=repo_id, repo_type="dataset")
374
+ stale_files = [
375
+ path for path in remote_files
376
+ if path not in local_files and path not in {".gitattributes"}
377
+ ]
378
+ for stale_path in stale_files:
379
+ HF_API.delete_file(
380
+ path_in_repo=stale_path,
381
+ repo_id=repo_id,
382
+ repo_type="dataset",
383
+ commit_message=f"Delete stale file {stale_path}",
384
+ )
385
+
386
+
387
  def restore_workspace() -> bool:
388
  if not HF_TOKEN:
389
  write_status("disabled", "HF_TOKEN is not configured.")
 
483
  commit_message=f"HuggingClaw sync {time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}",
484
  ignore_patterns=[".git/*", ".git"],
485
  )
486
+ prune_remote_deleted_files(repo_id, snapshot_dir)
487
  finally:
488
  shutil.rmtree(snapshot_dir, ignore_errors=True)
489
 
start.sh CHANGED
@@ -131,6 +131,48 @@ case "$LLM_PROVIDER" in
131
  ;;
132
  esac
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  # ── Setup directories ──
135
  mkdir -p /home/node/.openclaw/agents/main/sessions
136
  mkdir -p /home/node/.openclaw/credentials
@@ -285,6 +327,67 @@ if [ -n "$CUSTOM_PROVIDER_NAME" ] || [ -n "$CUSTOM_BASE_URL" ] || [ -n "$CUSTOM_
285
  fi
286
  fi
287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  # Browser configuration (managed local Chromium in HF/Docker)
289
  BROWSER_EXECUTABLE_PATH=""
290
  for candidate in /usr/bin/chromium /usr/bin/chromium-browser /snap/bin/chromium; do
 
131
  ;;
132
  esac
133
 
134
+ # Ensure OpenClaw provider discovery can see per-provider keys even when users
135
+ # configure only *_API_KEYS pools. Mirror first pool key into singular env.
136
+ promote_first_pool_key() {
137
+ local singular_var="$1"
138
+ local pool_var="$2"
139
+ local singular_val="${!singular_var:-}"
140
+ local pool_val="${!pool_var:-}"
141
+
142
+ [ -n "$singular_val" ] && return 0
143
+ [ -n "$pool_val" ] || return 0
144
+
145
+ local first
146
+ first=$(printf '%s' "$pool_val" | tr ',' '\n' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | awk 'NF{print; exit}')
147
+ [ -n "$first" ] || return 0
148
+ export "${singular_var}=$first"
149
+ }
150
+
151
+ promote_first_pool_key "ANTHROPIC_API_KEY" "ANTHROPIC_API_KEYS"
152
+ promote_first_pool_key "OPENAI_API_KEY" "OPENAI_API_KEYS"
153
+ promote_first_pool_key "GEMINI_API_KEY" "GEMINI_API_KEYS"
154
+ promote_first_pool_key "DEEPSEEK_API_KEY" "DEEPSEEK_API_KEYS"
155
+ promote_first_pool_key "OPENROUTER_API_KEY" "OPENROUTER_API_KEYS"
156
+ promote_first_pool_key "KILOCODE_API_KEY" "KILOCODE_API_KEYS"
157
+ promote_first_pool_key "OPENCODE_API_KEY" "OPENCODE_API_KEYS"
158
+ promote_first_pool_key "ZAI_API_KEY" "ZAI_API_KEYS"
159
+ promote_first_pool_key "MOONSHOT_API_KEY" "MOONSHOT_API_KEYS"
160
+ promote_first_pool_key "MINIMAX_API_KEY" "MINIMAX_API_KEYS"
161
+ promote_first_pool_key "XIAOMI_API_KEY" "XIAOMI_API_KEYS"
162
+ promote_first_pool_key "VOLCANO_ENGINE_API_KEY" "VOLCANO_ENGINE_API_KEYS"
163
+ promote_first_pool_key "BYTEPLUS_API_KEY" "BYTEPLUS_API_KEYS"
164
+ promote_first_pool_key "QIANFAN_API_KEY" "QIANFAN_API_KEYS"
165
+ promote_first_pool_key "MODELSTUDIO_API_KEY" "MODELSTUDIO_API_KEYS"
166
+ promote_first_pool_key "KIMI_API_KEY" "KIMI_API_KEYS"
167
+ promote_first_pool_key "MISTRAL_API_KEY" "MISTRAL_API_KEYS"
168
+ promote_first_pool_key "XAI_API_KEY" "XAI_API_KEYS"
169
+ promote_first_pool_key "NVIDIA_API_KEY" "NVIDIA_API_KEYS"
170
+ promote_first_pool_key "GROQ_API_KEY" "GROQ_API_KEYS"
171
+ promote_first_pool_key "COHERE_API_KEY" "COHERE_API_KEYS"
172
+ promote_first_pool_key "TOGETHER_API_KEY" "TOGETHER_API_KEYS"
173
+ promote_first_pool_key "CEREBRAS_API_KEY" "CEREBRAS_API_KEYS"
174
+ promote_first_pool_key "HUGGINGFACE_HUB_TOKEN" "HUGGINGFACE_HUB_TOKENS"
175
+
176
  # ── Setup directories ──
177
  mkdir -p /home/node/.openclaw/agents/main/sessions
178
  mkdir -p /home/node/.openclaw/credentials
 
327
  fi
328
  fi
329
 
330
+ # Optional: explicitly expose provider model lists in Control UI when
331
+ # provider keys are configured. Format:
332
+ # NVIDIA_MODELS=model1,model2
333
+ # OPENAI_MODELS=gpt-4o-mini,gpt-4.1
334
+ # This helps when provider auto-discovery does not populate models reliably.
335
+ inject_provider_models_from_env() {
336
+ local provider="$1"
337
+ local models_env="$2"
338
+ local key_env_single="$3"
339
+ local key_env_pool="$4"
340
+ local models_csv="${!models_env:-}"
341
+ local single_key="${!key_env_single:-}"
342
+ local pool_keys="${!key_env_pool:-}"
343
+
344
+ # Only inject when both:
345
+ # 1) provider has at least one configured key
346
+ # 2) explicit model list env is provided
347
+ if [ -z "$models_csv" ] || { [ -z "$single_key" ] && [ -z "$pool_keys" ]; }; then
348
+ return 0
349
+ fi
350
+
351
+ local models_json
352
+ models_json=$(printf '%s' "$models_csv" \
353
+ | tr ',' '\n' \
354
+ | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' \
355
+ | awk 'NF' \
356
+ | jq -R . \
357
+ | jq -s 'map({id: ., name: .}) | unique_by(.id)')
358
+
359
+ CONFIG_JSON=$(jq \
360
+ --arg provider "$provider" \
361
+ --argjson models "$models_json" \
362
+ '.models.mode = "merge"
363
+ | .models.providers[$provider] = ((.models.providers[$provider] // {}) + {models: $models})' <<<"$CONFIG_JSON")
364
+ }
365
+
366
+ # Built-in provider model envs (optional)
367
+ inject_provider_models_from_env "anthropic" "ANTHROPIC_MODELS" "ANTHROPIC_API_KEY" "ANTHROPIC_API_KEYS"
368
+ inject_provider_models_from_env "openai" "OPENAI_MODELS" "OPENAI_API_KEY" "OPENAI_API_KEYS"
369
+ inject_provider_models_from_env "google" "GEMINI_MODELS" "GEMINI_API_KEY" "GEMINI_API_KEYS"
370
+ inject_provider_models_from_env "deepseek" "DEEPSEEK_MODELS" "DEEPSEEK_API_KEY" "DEEPSEEK_API_KEYS"
371
+ inject_provider_models_from_env "openrouter" "OPENROUTER_MODELS" "OPENROUTER_API_KEY" "OPENROUTER_API_KEYS"
372
+ inject_provider_models_from_env "kilocode" "KILOCODE_MODELS" "KILOCODE_API_KEY" "KILOCODE_API_KEYS"
373
+ inject_provider_models_from_env "opencode" "OPENCODE_MODELS" "OPENCODE_API_KEY" "OPENCODE_API_KEYS"
374
+ inject_provider_models_from_env "zai" "ZAI_MODELS" "ZAI_API_KEY" "ZAI_API_KEYS"
375
+ inject_provider_models_from_env "moonshot" "MOONSHOT_MODELS" "MOONSHOT_API_KEY" "MOONSHOT_API_KEYS"
376
+ inject_provider_models_from_env "kimi-coding" "KIMI_MODELS" "KIMI_API_KEY" "KIMI_API_KEYS"
377
+ inject_provider_models_from_env "minimax" "MINIMAX_MODELS" "MINIMAX_API_KEY" "MINIMAX_API_KEYS"
378
+ inject_provider_models_from_env "modelstudio" "MODELSTUDIO_MODELS" "MODELSTUDIO_API_KEY" "MODELSTUDIO_API_KEYS"
379
+ inject_provider_models_from_env "xiaomi" "XIAOMI_MODELS" "XIAOMI_API_KEY" "XIAOMI_API_KEYS"
380
+ inject_provider_models_from_env "volcengine" "VOLCANO_ENGINE_MODELS" "VOLCANO_ENGINE_API_KEY" "VOLCANO_ENGINE_API_KEYS"
381
+ inject_provider_models_from_env "byteplus" "BYTEPLUS_MODELS" "BYTEPLUS_API_KEY" "BYTEPLUS_API_KEYS"
382
+ inject_provider_models_from_env "qianfan" "QIANFAN_MODELS" "QIANFAN_API_KEY" "QIANFAN_API_KEYS"
383
+ inject_provider_models_from_env "groq" "GROQ_MODELS" "GROQ_API_KEY" "GROQ_API_KEYS"
384
+ inject_provider_models_from_env "mistral" "MISTRAL_MODELS" "MISTRAL_API_KEY" "MISTRAL_API_KEYS"
385
+ inject_provider_models_from_env "xai" "XAI_MODELS" "XAI_API_KEY" "XAI_API_KEYS"
386
+ inject_provider_models_from_env "nvidia" "NVIDIA_MODELS" "NVIDIA_API_KEY" "NVIDIA_API_KEYS"
387
+ inject_provider_models_from_env "cohere" "COHERE_MODELS" "COHERE_API_KEY" "COHERE_API_KEYS"
388
+ inject_provider_models_from_env "together" "TOGETHER_MODELS" "TOGETHER_API_KEY" "TOGETHER_API_KEYS"
389
+ inject_provider_models_from_env "cerebras" "CEREBRAS_MODELS" "CEREBRAS_API_KEY" "CEREBRAS_API_KEYS"
390
+
391
  # Browser configuration (managed local Chromium in HF/Docker)
392
  BROWSER_EXECUTABLE_PATH=""
393
  for candidate in /usr/bin/chromium /usr/bin/chromium-browser /snap/bin/chromium; do