Commit 1d630e8

HPCesia <me@hpcesia.com>
2026-10-17 07:55:03
crush: cache cline pass models info
Assisted-by: crush:deepseek-v4.1-flash
1 parent 9c9d856
Changed files (1)
modules
dev
agents
modules/dev/agents/crush/provider-cline.sh
@@ -3,36 +3,23 @@ provider add cline \
   --base-url "https://api.cline.bot/api/v1/" \
   --discover-models false
 
+_cline_pass_ttl=86400
+_cline_pass_file="${XDG_DATA_HOME:-$HOME/.local/share}/crush/cline.json"
+
 # The feed lists ids without capabilities, so join it with OpenRouter for
 # capabilities and reasoning levels.
-_cline_pass_models="$(curl -fsSL --max-time 20 \
-  "https://api.cline.bot/api/v1/ai/cline/recommended-models" || true)"
-if [ -n "$_cline_pass_models" ]; then
-  curl -fsSL --max-time 30 \
-    "https://openrouter.ai/api/v1/models" |
-    jq -r --argjson cp "$_cline_pass_models" '
-      (.data // []
-        | map({key: (.id | split("/") | last), value: .})
-        | from_entries) as $or
-      | $cp.clinePass[]?
-      | (.id | sub("^cline-pass/"; "")) as $slug
-      | ($or[$slug] // {}) as $m
-      | [
-          $slug,
-          (($m.name // $slug) | sub("^[^:]+: "; "")),
-          ($m.context_length // 128000),
-          ($m.top_provider.max_completion_tokens // 8192),
-          (($m | length) == 0
-            or (($m.supported_parameters // []) | index("reasoning")) != null
-            or $m.reasoning != null),
-          ((($m.architecture.input_modalities // []) | index("image")) != null),
-          (($m.reasoning.supported_efforts // []) | join(",")),
-          ($m.reasoning.default_effort // "")
-        ]
-      | @tsv
-    ' |
-    while IFS=$'\t' read -r slug name ctx maxtokens canreason images levels effort; do
-      args=("cline/cline-pass/$slug" --name "$name" \
+_emit_cline_pass_models() {
+  jq -r '
+    .models[]
+    | [ .id, .name, .context_window, .default_max_tokens, .can_reason,
+        .supports_attachments,
+        ((.reasoning_levels // []) | join(",")),
+        (.default_reasoning_effort // "")
+      ]
+    | @tsv
+  ' "$_cline_pass_file" |
+    while IFS=$'\t' read -r id name ctx maxtokens canreason images levels effort; do
+      args=("cline/$id" --name "$name" \
         --context-window "$ctx" \
         --default-max-tokens "$maxtokens" \
         --can-reason "$canreason" \
@@ -41,4 +28,60 @@ if [ -n "$_cline_pass_models" ]; then
       if [ -n "$effort" ]; then args+=(--reasoning-effort "$effort"); fi
       model add "${args[@]}" </dev/null
     done
+}
+
+_cline_pass_usable() {
+  [ -f "$_cline_pass_file" ] &&
+    jq -e '.models | length > 0' "$_cline_pass_file" >/dev/null 2>&1
+}
+
+_cline_pass_fresh=false
+if _cline_pass_usable; then
+  if [ $(( $(date +%s) - $(stat -c %Y "$_cline_pass_file") )) -lt "$_cline_pass_ttl" ]; then
+    _cline_pass_fresh=true
+  fi
+fi
+
+if [ "$_cline_pass_fresh" = false ]; then
+  _cline_pass_models="$(curl -fsSL --max-time 8 \
+    "https://api.cline.bot/api/v1/ai/cline/recommended-models" || true)"
+  if [ -n "$_cline_pass_models" ]; then
+    _cline_pass_json="$(curl -fsSL --max-time 12 \
+      "https://openrouter.ai/api/v1/models" |
+      jq -c --argjson cp "$_cline_pass_models" '
+        (.data // [] | map({key: (.id | split("/") | last), value: .}) | from_entries) as $or
+        | {
+            name: "Cline", id: "cline", type: "openai-compat",
+            api_endpoint: "https://api.cline.bot/api/v1/",
+            models: [
+              $cp.clinePass[]?
+              | (.id | sub("^cline-pass/"; "")) as $slug
+              | ($or[$slug] // {}) as $m
+              | {
+                  id: ("cline-pass/" + $slug),
+                  name: (($m.name // $slug) | sub("^[^:]+: "; "")),
+                  context_window: ($m.context_length // 128000),
+                  default_max_tokens: ($m.top_provider.max_completion_tokens // 8192),
+                  can_reason: (($m | length) == 0
+                    or (($m.supported_parameters // []) | index("reasoning")) != null
+                    or $m.reasoning != null),
+                  reasoning_levels: ($m.reasoning.supported_efforts // []),
+                  default_reasoning_effort: ($m.reasoning.default_effort // ""),
+                  supports_attachments:
+                    ((($m.architecture.input_modalities // []) | index("image")) != null)
+                }
+            ]
+          }')"
+    if [ -n "$_cline_pass_json" ] &&
+      [ "$(printf '%s' "$_cline_pass_json" | jq '.models | length')" -gt 0 ]; then
+      mkdir -p "$(dirname "$_cline_pass_file")"
+      printf '%s\n' "$_cline_pass_json" > "$_cline_pass_file.tmp" &&
+        mv "$_cline_pass_file.tmp" "$_cline_pass_file"
+    fi
+  fi
+fi
+
+# Falls back to a stale cache when the fetch above did not refresh it.
+if _cline_pass_usable; then
+  _emit_cline_pass_models
 fi