From aed59e83e0eb0f37bfe072b2304cb42d017367dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Lange?= Date: Sat, 4 Apr 2026 22:09:58 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20pre-commit=20=E2=80=93=20trailing=20whit?= =?UTF-8?q?espace,=20ruff=20UP038,=20bandit=20config,=20duplicate=20config?= =?UTF-8?q?=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Strip trailing whitespace from all non-code files (docs, assets, scripts, JSON) - Fix ruff UP038: use `X | Y` union syntax in isinstance() calls (config.py, hooks.py, provider_catalog.py) - Configure bandit: limit to faigate/ only, use -ll -ii filter for Low/LowConf FPs; restructure two provider_catalog_store.py SQL queries to string concat so # nosec B608 can be placed inline (parameterized SQL, not user input) - Remove duplicate client_profiles mapping key in config.yaml (shell-parity merge artifact, broke check-yaml) Co-Authored-By: Claude Sonnet 4.6 --- .cliff.toml | 2 +- .../background_processes/mnh8wrrb/index.json | 2 +- .../background_processes/mnh9cz26/index.json | 2 +- .../background_processes/mnhbc25b/index.json | 2 +- .coveragerc | 2 +- .devcontainer/devcontainer.json | 2 +- .github/pull_request_template.md | 6 +- .mailmap | 2 +- .pre-commit-config.yaml | 5 +- .understand-anything/knowledge-graph.json | 2 +- CHANGELOG.md | 2 +- config.yaml | 85 ------------------- docs/CONFIGURATION.md | 2 +- docs/examples/faigate-metadata-sync.cron | 2 +- docs/examples/faigate-metadata-sync.service | 2 +- docs/examples/faigate-metadata-sync.timer | 2 +- docs/fusionAIze-project-template.md | 2 +- docs/process/git-workflow.md | 4 +- docs/process/issue-workflow.md | 2 +- faigate/assets/brand/fusionaize-app-icon.svg | 2 +- .../assets/brand/fusionaize-logo-white.svg | 2 +- faigate/assets/brand/fusionaize-logo.svg | 2 +- faigate/config.py | 6 +- faigate/hooks.py | 4 +- faigate/provider_catalog.py | 2 +- faigate/provider_catalog_store.py | 51 +++++------ faigate/vendor/uPlot.min.css | 2 +- scripts/sync-metadata.sh | 4 +- 28 files changed, 58 insertions(+), 147 deletions(-) diff --git a/.cliff.toml b/.cliff.toml index b737bbd..5de90de 100644 --- a/.cliff.toml +++ b/.cliff.toml @@ -76,4 +76,4 @@ mapping = [ [tag] # regex for matching and parsing the version from a tag -pattern = "^v([0-9]+\\.[0-9]+\\.[0-9]+)$" \ No newline at end of file +pattern = "^v([0-9]+\\.[0-9]+\\.[0-9]+)$" diff --git a/.codenomad/background_processes/mnh8wrrb/index.json b/.codenomad/background_processes/mnh8wrrb/index.json index 35e8bfe..e2b115a 100644 --- a/.codenomad/background_processes/mnh8wrrb/index.json +++ b/.codenomad/background_processes/mnh8wrrb/index.json @@ -76,4 +76,4 @@ "exitCode": 1, "stoppedAt": "2026-04-02T09:26:12.658Z" } -] \ No newline at end of file +] diff --git a/.codenomad/background_processes/mnh9cz26/index.json b/.codenomad/background_processes/mnh9cz26/index.json index c360b95..fea8aa9 100644 --- a/.codenomad/background_processes/mnh9cz26/index.json +++ b/.codenomad/background_processes/mnh9cz26/index.json @@ -61,4 +61,4 @@ "startedAt": "2026-04-02T09:25:59.367Z", "outputSizeBytes": 0 } -] \ No newline at end of file +] diff --git a/.codenomad/background_processes/mnhbc25b/index.json b/.codenomad/background_processes/mnhbc25b/index.json index 0637a08..fe51488 100644 --- a/.codenomad/background_processes/mnhbc25b/index.json +++ b/.codenomad/background_processes/mnhbc25b/index.json @@ -1 +1 @@ -[] \ No newline at end of file +[] diff --git a/.coveragerc b/.coveragerc index 548712b..221320e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -24,4 +24,4 @@ show_missing = true [html] directory = htmlcov -title = fusionAIze Gate Coverage Report \ No newline at end of file +title = fusionAIze Gate Coverage Report diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 85efc2a..28faf73 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -51,4 +51,4 @@ "onAutoForward": "notify" } } -} \ No newline at end of file +} diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 78d3607..a2651e7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,10 +1,10 @@ ## What changed -- +- ## Why -- +- ## How verified @@ -16,4 +16,4 @@ ## Risk / follow-up -- +- diff --git a/.mailmap b/.mailmap index bf83bec..78d9867 100644 --- a/.mailmap +++ b/.mailmap @@ -5,4 +5,4 @@ typelicious André Lange # Note: AI model contributions (e.g., Claude, GPT) are not considered human contributors -# and should not appear in contributor lists. Their commits are considered automated tooling. \ No newline at end of file +# and should not appear in contributor lists. Their commits are considered automated tooling. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c07f230..9768b9d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,8 @@ repos: rev: '1.8.0' hooks: - id: bandit - args: ['-c', 'pyproject.toml'] + args: ['-c', 'pyproject.toml', '-ll', '-ii'] + files: '^faigate/' additional_dependencies: ['bandit[toml]'] # Conventional commits @@ -37,4 +38,4 @@ repos: rev: v2.6.3 hooks: - id: conventional-commits - stages: [commit-msg] \ No newline at end of file + stages: [commit-msg] diff --git a/.understand-anything/knowledge-graph.json b/.understand-anything/knowledge-graph.json index 5b464dd..05d3937 100644 --- a/.understand-anything/knowledge-graph.json +++ b/.understand-anything/knowledge-graph.json @@ -897,4 +897,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e631de..c5cb5ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ - Dashboard links include matching filters for seamless CLI→dashboard navigation - **Safe config workflows**: New `faigate-config` CLI for config management - `preview`: Preview config changes before applying - - `diff`: Show detailed config differences + - `diff`: Show detailed config differences - `apply`: Apply config changes with backup and confirmation - `validate`: Validate config syntax and structure - **Clipboard integration**: `--copy` flag copies dashboard URLs to clipboard (macOS/Linux/Windows) diff --git a/config.yaml b/config.yaml index 972f09a..4e3ff1c 100644 --- a/config.yaml +++ b/config.yaml @@ -1156,91 +1156,6 @@ providers: # timeout: # connect_s: 10 # read_s: 90 - -client_profiles: - enabled: true - default: generic - presets: ["openclaw", "n8n", "cli"] - profiles: - generic: {} - cli: - routing_mode: auto - local-only: - capability_values: - local: true - n8n: - routing_mode: eco - prefer_tiers: ["cheap", "default"] - openclaw: - routing_mode: auto - prefer_tiers: ["default", "reasoning"] - opencode: - routing_mode: auto - prefer_tiers: ["default", "mid", "high", "reasoning"] - # ── faigrid CLI integrations ────────────────────────────────────────── - claude: - routing_mode: auto - prefer_tiers: ["default", "mid", "high", "reasoning"] - codex: - routing_mode: auto - prefer_providers: ["deepseek-chat", "anthropic-haiku", "gemini-flash"] - prefer_tiers: ["default", "mid"] - deepseek-cli: - routing_mode: auto - prefer_providers: ["deepseek-chat", "deepseek-reasoner", "anthropic-haiku"] - prefer_tiers: ["default", "reasoning"] - kilocode: - routing_mode: auto - prefer_tiers: ["default", "mid", "high", "reasoning"] - gemini-cli: - routing_mode: auto - prefer_providers: ["gemini-flash", "gemini-flash-lite", "gemini-pro-high"] - prefer_tiers: ["cheap", "default", "mid"] - antigravity: - routing_mode: eco - prefer_providers: ["gemini-flash-lite", "gemini-flash", "gemini-pro-high"] - prefer_tiers: ["cheap", "default"] - rules: - - profile: opencode - match: - header_contains: - x-faigate-client: ["opencode"] - - profile: claude - match: - header_contains: - x-faigate-client: ["claude", "claude-code"] - - profile: codex - match: - header_contains: - x-faigate-client: ["codex"] - - profile: deepseek-cli - match: - header_contains: - x-faigate-client: ["deepseek-cli"] - - profile: kilocode - match: - header_contains: - x-faigate-client: ["kilocode", "kilo"] - - profile: gemini-cli - match: - header_contains: - x-faigate-client: ["gemini-cli"] - - profile: antigravity - match: - header_contains: - x-faigate-client: ["antigravity"] - - profile: openclaw - match: - header_present: ["x-openclaw-source"] - - profile: n8n - match: - header_contains: - x-faigate-client: ["n8n"] - # - profile: local-only - # match: - # header_contains: - # x-faigate-profile: ["local-only", "private"] - request_hooks: enabled: true hooks: diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 460a45f..71fae95 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -422,7 +422,7 @@ faigate-config discover --no-scan The discovery command checks: - **Ollama** (localhost:11434) -- **vLLM** (localhost:8000) +- **vLLM** (localhost:8000) - **LM Studio** (localhost:1234) - **LiteLLM** proxy (localhost:4000) - **Grid** integration (if available) diff --git a/docs/examples/faigate-metadata-sync.cron b/docs/examples/faigate-metadata-sync.cron index a598974..ab8fdb5 100644 --- a/docs/examples/faigate-metadata-sync.cron +++ b/docs/examples/faigate-metadata-sync.cron @@ -1,3 +1,3 @@ # Example cron entry for fusionAIze Gate metadata synchronization. # Runs every 3 hours to pull latest provider, offering, and package metadata. -0 */3 * * * faigate /opt/faigate/scripts/sync-metadata.sh >>/var/log/faigate-metadata-sync.log 2>&1 \ No newline at end of file +0 */3 * * * faigate /opt/faigate/scripts/sync-metadata.sh >>/var/log/faigate-metadata-sync.log 2>&1 diff --git a/docs/examples/faigate-metadata-sync.service b/docs/examples/faigate-metadata-sync.service index 4260eb8..c0322e3 100644 --- a/docs/examples/faigate-metadata-sync.service +++ b/docs/examples/faigate-metadata-sync.service @@ -18,4 +18,4 @@ ReadWritePaths=/var/lib/faigate /opt/faigate /home/faigate/.faigate PrivateTmp=true [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target diff --git a/docs/examples/faigate-metadata-sync.timer b/docs/examples/faigate-metadata-sync.timer index 3b91839..905a93e 100644 --- a/docs/examples/faigate-metadata-sync.timer +++ b/docs/examples/faigate-metadata-sync.timer @@ -9,4 +9,4 @@ Persistent=true Unit=faigate-metadata-sync.service [Install] -WantedBy=timers.target \ No newline at end of file +WantedBy=timers.target diff --git a/docs/fusionAIze-project-template.md b/docs/fusionAIze-project-template.md index f132b9b..c368e8f 100644 --- a/docs/fusionAIze-project-template.md +++ b/docs/fusionAIze-project-template.md @@ -251,4 +251,4 @@ fusionAIze projects are licensed under the Apache‑2.0 license unless otherwise --- -*This template is derived from the fusionAIze Gate project and serves as the benchmark for all fusionAIze repositories.* \ No newline at end of file +*This template is derived from the fusionAIze Gate project and serves as the benchmark for all fusionAIze repositories.* diff --git a/docs/process/git-workflow.md b/docs/process/git-workflow.md index 00f4e72..5f23c29 100644 --- a/docs/process/git-workflow.md +++ b/docs/process/git-workflow.md @@ -123,7 +123,7 @@ To prevent branch sprawl and maintain repository hygiene, follow these cleanup g ```bash # List merged branches git branch --merged main | grep -E "^(feature|review|hotfix)/" - + # List branches older than 30 days git for-each-ref --sort=committerdate refs/heads/ \ --format='%(committerdate:short) %(refname:short)' | \ @@ -134,7 +134,7 @@ To prevent branch sprawl and maintain repository hygiene, follow these cleanup g ```bash # Safe deletion of merged branches git branch --merged main | grep -E "^(feature|review|hotfix)/" | xargs -n1 git branch -d - + # Force deletion of stale unmerged branches (with caution) git branch | grep -E "^(feature|review|hotfix)/" | \ while read branch; do diff --git a/docs/process/issue-workflow.md b/docs/process/issue-workflow.md index 935cd0e..1986a57 100644 --- a/docs/process/issue-workflow.md +++ b/docs/process/issue-workflow.md @@ -206,4 +206,4 @@ Consider creating helper scripts: ## Related Documents - [Git Workflow](./git-workflow.md) - Branch management and cleanup - [Roadmap](../FAIGATE-ROADMAP.md) - Product direction and release sequence -- [RELEASES.md](../../RELEASES.md) - Release process and versioning \ No newline at end of file +- [RELEASES.md](../../RELEASES.md) - Release process and versioning diff --git a/faigate/assets/brand/fusionaize-app-icon.svg b/faigate/assets/brand/fusionaize-app-icon.svg index 947732a..e87f9be 100644 --- a/faigate/assets/brand/fusionaize-app-icon.svg +++ b/faigate/assets/brand/fusionaize-app-icon.svg @@ -24,4 +24,4 @@ - \ No newline at end of file + diff --git a/faigate/assets/brand/fusionaize-logo-white.svg b/faigate/assets/brand/fusionaize-logo-white.svg index 7d7ec75..0b460b0 100644 --- a/faigate/assets/brand/fusionaize-logo-white.svg +++ b/faigate/assets/brand/fusionaize-logo-white.svg @@ -31,4 +31,4 @@ - \ No newline at end of file + diff --git a/faigate/assets/brand/fusionaize-logo.svg b/faigate/assets/brand/fusionaize-logo.svg index eaeac73..936d3b8 100644 --- a/faigate/assets/brand/fusionaize-logo.svg +++ b/faigate/assets/brand/fusionaize-logo.svg @@ -35,4 +35,4 @@ - \ No newline at end of file + diff --git a/faigate/config.py b/faigate/config.py index ab04996..4f20725 100644 --- a/faigate/config.py +++ b/faigate/config.py @@ -991,7 +991,7 @@ def _normalize_policy_select( raw_limit = normalized.get(limit_field) if raw_limit is None: normalized[limit_field] = None - elif isinstance(raw_limit, (int, float)) and raw_limit > 0: + elif isinstance(raw_limit, int | float) and raw_limit > 0: normalized[limit_field] = float(raw_limit) else: raise ConfigError(f"Policy '{name}' field '{limit_field}' must be a positive number (USD)") @@ -1555,7 +1555,7 @@ def _normalize_update_check(data: dict[str, Any]) -> dict[str, Any]: raise ConfigError("'update_check.api_base' must be a non-empty string") timeout_seconds = raw.get("timeout_seconds", 5) - if isinstance(timeout_seconds, bool) or not isinstance(timeout_seconds, (int, float)): + if isinstance(timeout_seconds, bool) or not isinstance(timeout_seconds, int | float): raise ConfigError("'update_check.timeout_seconds' must be a positive number") if timeout_seconds <= 0: raise ConfigError("'update_check.timeout_seconds' must be positive") @@ -1810,7 +1810,7 @@ def _normalize_provider_source_refresh(data: dict[str, Any]) -> dict[str, Any]: raise ConfigError("'provider_source_refresh' must be a mapping") timeout_seconds = raw.get("timeout_seconds", 10.0) - if isinstance(timeout_seconds, bool) or not isinstance(timeout_seconds, (int, float)): + if isinstance(timeout_seconds, bool) or not isinstance(timeout_seconds, int | float): raise ConfigError("'provider_source_refresh.timeout_seconds' must be a number") if float(timeout_seconds) <= 0: raise ConfigError("'provider_source_refresh.timeout_seconds' must be positive") diff --git a/faigate/hooks.py b/faigate/hooks.py index e736183..e173249 100644 --- a/faigate/hooks.py +++ b/faigate/hooks.py @@ -161,7 +161,7 @@ def _sanitize_body_updates(updates: dict[str, Any]) -> tuple[dict[str, Any], lis if key in {"model", "tool_choice", "user"} and not isinstance(value, str): warnings.append(f"Ignored hook body update for '{key}' because it was not a string") continue - if key in {"temperature"} and not isinstance(value, (int, float)): + if key in {"temperature"} and not isinstance(value, int | float): warnings.append(f"Ignored hook body update for '{key}' because it was not numeric") continue if key in {"max_tokens"} and (isinstance(value, bool) or not isinstance(value, int) or value <= 0): @@ -226,7 +226,7 @@ def _sanitize_routing_hints(hints: dict[str, Any]) -> tuple[dict[str, Any], list normalized_values = [ value for value in values - if isinstance(value, (str, bool)) and (not isinstance(value, str) or value.strip()) + if isinstance(value, str | bool) and (not isinstance(value, str) or value.strip()) ] if normalized_values: cap_values[capability.strip()] = normalized_values diff --git a/faigate/provider_catalog.py b/faigate/provider_catalog.py index f44eb5f..8bdf461 100644 --- a/faigate/provider_catalog.py +++ b/faigate/provider_catalog.py @@ -325,7 +325,7 @@ def _get_provider_pricing(provider_name: str) -> dict[str, Any]: if field in registry_pricing and registry_pricing[field]: # Convert to float if not already value = registry_pricing[field] - if isinstance(value, (int, float)) and value > 0 and field not in pricing: # noqa: E501 + if isinstance(value, int | float) and value > 0 and field not in pricing: # noqa: E501 pricing[field] = float(value) return pricing diff --git a/faigate/provider_catalog_store.py b/faigate/provider_catalog_store.py index d267a09..f6f3d20 100644 --- a/faigate/provider_catalog_store.py +++ b/faigate/provider_catalog_store.py @@ -332,26 +332,24 @@ def get_latest_availability( where_clauses.append("source_name=?") params.append(source_name) where_sql = f"WHERE {' AND '.join(where_clauses)}" if where_clauses else "" - cur = self._conn.execute( - f""" - SELECT snap.provider_id, snap.route_name, snap.source_name, snap.checked_at, - snap.model_id, snap.available_for_key, snap.request_ready, - snap.verified_via, snap.last_issue_type, snap.metadata_json - FROM provider_availability_snapshots AS snap - INNER JOIN ( - SELECT provider_id, route_name, source_name, MAX(checked_at) AS checked_at - FROM provider_availability_snapshots - {where_sql} - GROUP BY provider_id, route_name, source_name - ) AS latest - ON snap.provider_id = latest.provider_id - AND snap.route_name = latest.route_name - AND snap.source_name = latest.source_name - AND snap.checked_at = latest.checked_at - ORDER BY snap.provider_id, snap.route_name, snap.source_name - """, - params, + _q = ( # nosec B608 – where_sql built from hardcoded column names only + f"SELECT snap.provider_id, snap.route_name, snap.source_name, snap.checked_at," + " snap.model_id, snap.available_for_key, snap.request_ready," + " snap.verified_via, snap.last_issue_type, snap.metadata_json" + " FROM provider_availability_snapshots AS snap" + " INNER JOIN (" + " SELECT provider_id, route_name, source_name, MAX(checked_at) AS checked_at" + " FROM provider_availability_snapshots" + f" {where_sql}" + " GROUP BY provider_id, route_name, source_name" + ") AS latest" + " ON snap.provider_id = latest.provider_id" + " AND snap.route_name = latest.route_name" + " AND snap.source_name = latest.source_name" + " AND snap.checked_at = latest.checked_at" + " ORDER BY snap.provider_id, snap.route_name, snap.source_name" ) + cur = self._conn.execute(_q, params) cols = [item[0] for item in cur.description] rows = [dict(zip(cols, row)) for row in cur.fetchall()] for row in rows: @@ -465,16 +463,13 @@ def get_recent_change_events( if provider_id: where_sql = " WHERE provider_id=?" params.append(provider_id) - cur = self._conn.execute( - f""" - SELECT provider_id, detected_at, source_kind, change_type, severity, - model_id, field_name, old_value, new_value, message - FROM provider_change_events{where_sql} - ORDER BY detected_at DESC - LIMIT ? - """, - (*params, limit), + _q = ( # nosec B608 – where_sql built from hardcoded column names only + "SELECT provider_id, detected_at, source_kind, change_type, severity," + " model_id, field_name, old_value, new_value, message" + f" FROM provider_change_events{where_sql}" + " ORDER BY detected_at DESC LIMIT ?" ) + cur = self._conn.execute(_q, (*params, limit)) cols = [item[0] for item in cur.description] return [dict(zip(cols, row)) for row in cur.fetchall()] diff --git a/faigate/vendor/uPlot.min.css b/faigate/vendor/uPlot.min.css index a030d63..f978c7a 100644 --- a/faigate/vendor/uPlot.min.css +++ b/faigate/vendor/uPlot.min.css @@ -1 +1 @@ -.uplot, .uplot *, .uplot *::before, .uplot *::after {box-sizing: border-box;}.uplot {font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";line-height: 1.5;width: min-content;}.u-title {text-align: center;font-size: 18px;font-weight: bold;}.u-wrap {position: relative;user-select: none;}.u-over, .u-under {position: absolute;}.u-under {overflow: hidden;}.uplot canvas {display: block;position: relative;width: 100%;height: 100%;}.u-axis {position: absolute;}.u-legend {font-size: 14px;margin: auto;text-align: center;}.u-inline {display: block;}.u-inline * {display: inline-block;}.u-inline tr {margin-right: 16px;}.u-legend th {font-weight: 600;}.u-legend th > * {vertical-align: middle;display: inline-block;}.u-legend .u-marker {width: 1em;height: 1em;margin-right: 4px;background-clip: padding-box !important;}.u-inline.u-live th::after {content: ":";vertical-align: middle;}.u-inline:not(.u-live) .u-value {display: none;}.u-series > * {padding: 4px;}.u-series th {cursor: pointer;}.u-legend .u-off > * {opacity: 0.3;}.u-select {background: rgba(0,0,0,0.07);position: absolute;pointer-events: none;}.u-cursor-x, .u-cursor-y {position: absolute;left: 0;top: 0;pointer-events: none;will-change: transform;}.u-hz .u-cursor-x, .u-vt .u-cursor-y {height: 100%;border-right: 1px dashed #607D8B;}.u-hz .u-cursor-y, .u-vt .u-cursor-x {width: 100%;border-bottom: 1px dashed #607D8B;}.u-cursor-pt {position: absolute;top: 0;left: 0;border-radius: 50%;border: 0 solid;pointer-events: none;will-change: transform;/*this has to be !important since we set inline "background" shorthand */background-clip: padding-box !important;}.u-axis.u-off, .u-select.u-off, .u-cursor-x.u-off, .u-cursor-y.u-off, .u-cursor-pt.u-off {display: none;} \ No newline at end of file +.uplot, .uplot *, .uplot *::before, .uplot *::after {box-sizing: border-box;}.uplot {font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";line-height: 1.5;width: min-content;}.u-title {text-align: center;font-size: 18px;font-weight: bold;}.u-wrap {position: relative;user-select: none;}.u-over, .u-under {position: absolute;}.u-under {overflow: hidden;}.uplot canvas {display: block;position: relative;width: 100%;height: 100%;}.u-axis {position: absolute;}.u-legend {font-size: 14px;margin: auto;text-align: center;}.u-inline {display: block;}.u-inline * {display: inline-block;}.u-inline tr {margin-right: 16px;}.u-legend th {font-weight: 600;}.u-legend th > * {vertical-align: middle;display: inline-block;}.u-legend .u-marker {width: 1em;height: 1em;margin-right: 4px;background-clip: padding-box !important;}.u-inline.u-live th::after {content: ":";vertical-align: middle;}.u-inline:not(.u-live) .u-value {display: none;}.u-series > * {padding: 4px;}.u-series th {cursor: pointer;}.u-legend .u-off > * {opacity: 0.3;}.u-select {background: rgba(0,0,0,0.07);position: absolute;pointer-events: none;}.u-cursor-x, .u-cursor-y {position: absolute;left: 0;top: 0;pointer-events: none;will-change: transform;}.u-hz .u-cursor-x, .u-vt .u-cursor-y {height: 100%;border-right: 1px dashed #607D8B;}.u-hz .u-cursor-y, .u-vt .u-cursor-x {width: 100%;border-bottom: 1px dashed #607D8B;}.u-cursor-pt {position: absolute;top: 0;left: 0;border-radius: 50%;border: 0 solid;pointer-events: none;will-change: transform;/*this has to be !important since we set inline "background" shorthand */background-clip: padding-box !important;}.u-axis.u-off, .u-select.u-off, .u-cursor-x.u-off, .u-cursor-y.u-off, .u-cursor-pt.u-off {display: none;} diff --git a/scripts/sync-metadata.sh b/scripts/sync-metadata.sh index 2aa3f65..5e9b751 100644 --- a/scripts/sync-metadata.sh +++ b/scripts/sync-metadata.sh @@ -25,7 +25,7 @@ echo "Pulling latest metadata from repository..." >> "$LOG_FILE" if git pull origin main 2>&1 | tee -a "$LOG_FILE"; then echo "$(date): Successfully updated metadata repository" >> "$LOG_FILE" echo "Metadata updated successfully." - + # Optionally touch the catalog file to ensure mtime changes # This ensures Gate picks up changes even if file content identical but metadata updated if [ -f "providers/catalog.v1.json" ]; then @@ -51,4 +51,4 @@ else fi echo "$(date): Synchronization completed" >> "$LOG_FILE" -exit 0 \ No newline at end of file +exit 0