Skip to content

Latest commit

 

History

History
256 lines (195 loc) · 25.5 KB

File metadata and controls

256 lines (195 loc) · 25.5 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[0.6.1] - 2026-02-05

Fixed

  • Code formatting — applied ruff format to 8 files that failed CI formatting checks

[0.6.0] - 2026-02-04

Added

  • Generic telemetry events — all 230+ telemetry fields now produce OpenClaw events via a generic fallback in the emitter; unmapped fields are emitted as snake_case event types (e.g. PackVoltagepack_voltage) with field and value payload keys
  • Default filter for unconfigured fieldsDualGateFilter now applies a sensible default (any-change granularity, 5s throttle, 2min staleness) to unconfigured fields instead of silently dropping them; explicitly disabled fields are still blocked
  • telemetry.get handler — generic read handler in CommandDispatcher allows agents to read the latest value of any telemetry field from the in-memory store
  • telemetry_get MCP tool — exposes telemetry.get as an MCP tool so agent frameworks can read arbitrary telemetry fields
  • Trigger commands in capabilitiesNodeCapabilities now advertises telemetry.get, trigger.list, trigger.create, and trigger.delete to the gateway

Removed

  • trigger.poll endpoint and pending queue — trigger notifications are delivered exclusively via push callbacks over the OpenClaw WebSocket; the MCP trigger_poll tool, drain_pending(), and the in-memory pending notification queue have been removed

Changed

  • matches() is now a public API — renamed from _matches() in triggers/manager.py so cross-module consumers (MCP trigger tools) import a stable public symbol
  • Shared temperature conversion utility_internal/units.py provides fahrenheit_to_celsius() and celsius_to_fahrenheit() replacing three duplicate implementations across dispatcher.py, serve.py, and emitter.py
  • telemetry_get distinguishes store-unavailable from pending — returns {"error": "telemetry_store_unavailable", "pending": false} when no telemetry store is configured instead of the misleading {"pending": true}

Fixed

  • TUI panel widgets not updating — telemetry panel DataTables now update per-frame as data arrives instead of relying solely on a 1-second timer poll; header, server info, and trigger displays remain on the timer
  • Port-in-use crashtescmd serve now pre-checks port availability with _resolve_port() and auto-selects a free port when the default is occupied; explicit --port raises a clear UsageError with a suggested alternative
  • SystemExit killing the event loop — uvicorn's sys.exit(1) on bind failure is now caught by _safe_uvicorn_serve() and converted to OSError; clean shutdown (exit(0)) passes through without error
  • Empty "Error:" crash — generic error handler in main.py now shows "Unexpected {ExceptionType}" when str(exc) is empty and suggests --verbose for the full traceback
  • trigger.poll ValueError — removed the defunct trigger.poll handler that raised ValueError when called; system.run now returns None for unknown inner methods instead of raising
  • Trigger notification queue overflow silent data loss_pending_push deque now logs a warning when at capacity before evicting the oldest notification
  • flush_pending_push crash after reconnect — flush is now wrapped in try/except so a single malformed notification cannot break the reconnect recovery path
  • Notification serialization crash blocks all deliveries — event dict construction in both push callback and flush loop is now guarded per-notification; a bad entry is logged and discarded instead of blocking subsequent notifications
  • p.pop("field") mutates MCP params — generic trigger_create tool now uses p.get() with a filtered dict copy to avoid mutating the framework's params dict on retries
  • Unknown system.run method logged at wrong level — bumped from info to warning so operators monitoring at warning level see protocol mismatches
  • contextlib.suppress hiding conversion bugs — replaced with explicit try/except + debug-level logging in both dispatcher and MCP trigger list paths
  • Reconnect failure logged without traceback — added exc_info=True to reconnect and Tailscale auto-detection warning logs
  • Notification serialization guard too broad — narrowed except Exception to (AttributeError, TypeError, ValueError) in both push callback and flush loop so unexpected errors (e.g. ConnectionError) propagate instead of being silently discarded
  • system.run unknown method log missing resolved name — warning now includes both the raw and resolved method names for easier debugging
  • SystemExit(0) silent return — clean uvicorn shutdowns now log at debug level in both serve.py and server.py for traceability
  • Environment-sourced --port treated as auto-select — ports set via TESLA_MCP_PORT env var are now treated as explicit (error on conflict) instead of silently picking an alternative port

[0.5.0] - 2026-02-03

Changed

  • Slim node capabilities — node now advertises only location.get + system.run to the gateway (was 29 individual commands); all 34 handlers remain available via system.run meta-dispatch, reducing handshake payload and simplifying capability negotiation
  • Explicit send_connected() lifecyclenode.connected event is now sent explicitly after connect_with_backoff() and after successful reconnection, replacing the implicit first-frame trigger; CLI callers show a warning if the lifecycle event fails while the connection itself succeeded
  • send_connected() returns bool — callers can now detect lifecycle event failure; both openclaw bridge and serve commands display a yellow warning when the event fails to send
  • Separated reconnect error handling_maybe_reconnect() now handles connection failure and lifecycle event failure independently; a failed node.connected no longer incorrectly doubles the reconnect backoff timer

Added

  • on_reconnect gateway callbackGatewayClient accepts an on_reconnect callback invoked after the receive loop successfully reconnects, ensuring node.connected is sent on every reconnection (not just the initial connect)
  • system.run activity logging — dispatcher logs the resolved inner method when routing through system.run, so operational logs show system.run → door.lock instead of just system.run

Fixed

  • send_connected() false-positive logging — no longer logs "Sent node.connected event" when the gateway is disconnected (the event was being silently dropped by send_event())
  • OpenClawPipeline.dispatcher typing — changed from Any to CommandDispatcher for static analysis support

[0.4.0] - 2026-02-02

Added

  • Unique app name generation — setup wizard generates a tescmd-<hex> application name to prevent collisions on the Tesla Developer Portal; reused on re-runs unless --force is passed
  • In-process KeyServer — ephemeral HTTP server (KeyServer) serves the PEM public key on localhost during interactive setup so Tailscale Funnel can proxy it without writing to the serve directory
  • Key mismatch warning — setup wizard detects when the remote public key (GitHub Pages or Tailscale) differs from the local key and warns before Phase 2, so the user knows a redeploy is coming
  • fetch_tailscale_key_pem() — synchronous helper in the deploy module to fetch the raw PEM from a Tailscale Funnel URL, mirroring github_pages.fetch_key_pem()
  • TailscaleManager.start_proxy() — reverse-proxy mode (tailscale serve --bg http://127.0.0.1:<port>) for forwarding to a local HTTP server, distinct from the static-file start_serve()

Changed

  • Setup phase reorder — phases now run: keys → Fleet API registration → OAuth login → key enrollment (was: keys → enrollment → registration → OAuth); registration happens while credentials are fresh, enrollment is last so the user finishes in the Tesla app
  • Credentials always required — both Client ID and Client Secret are mandatory with retry loops (3 attempts each); empty input no longer silently skips setup
  • Auto-save credentials.env file is written automatically after credential entry; removed the "Save to .env?" prompt
  • --force regenerates app name — passing --force to setup now generates a fresh tescmd-<hex> name instead of reusing the saved one
  • Atomic Tailscale serve + Funnelstart_key_serving() uses a single tailscale serve --bg --funnel --set-path / <dir> command instead of separate serve + funnel calls
  • TailscaleManager.start_serve() API — added port and funnel keyword arguments for configurable HTTPS port and inline Funnel enablement
  • Enrollment messaging — streamlined to focus on QR code scanning; removed duplicate URL display and the "Open in browser?" prompt (browser opens automatically)
  • GitHub Pages note — clarified that Tailscale is used alongside GitHub Pages for telemetry streaming, not as a replacement
  • Funnel cleanup uses stop_funnel() — finally block in _interactive_setup now calls the proper TailscaleManager.stop_funnel() method instead of the low-level _run() static method, preserving state tracking and idempotency

Fixed

  • CLI module HTTP isolation — moved direct httpx.get() call out of setup.py into tailscale_serve.fetch_tailscale_key_pem() to comply with single-responsibility layering (CLI handles args + output, deploy modules handle HTTP)

[0.3.2] - 2026-02-02

Fixed

  • OAuth URL printed for manual fallbacklogin_flow() now prints the authorization URL before opening the browser so users can copy-paste it when webbrowser.open() fails
  • 422 "already registered" treated as successregister_partner_account() now treats HTTP 422 with "already been taken" as idempotent success instead of raising AuthError; re-running setup or auth register shows "Already registered — no action needed"
  • GitHub key comparison on re-deploy_deploy_key_github() fetches the remote public key and compares it to the local key; if they match, deployment is skipped; if they differ, the user is prompted before overwriting

[0.3.1] - 2026-02-02

Added

  • README overhaul — header banner, logo, new "What It Does" summary section, expanded Prerequisites table with Python 3.11+, pip, Tesla account, and helpful links
  • Tailscale Funnel auto-detection in auth setup_interactive_setup now detects Tailscale and offers to start Funnel so Tesla can verify the origin URL during Developer Portal configuration; cleans up Funnel on exit
  • Tailscale hostname passthrough — setup wizard forwards detected Tailscale hostname to auth flow, showing a concrete "Also add" origin URL instead of the generic placeholder
  • Comprehensive agent skill documentation — expanded skill covering all command groups, triggers, and OpenClaw dispatch

Fixed

  • Cross-platform file permissions — OpenClaw gateway key file now uses secure_file() from _internal.permissions instead of raw chmod(0o600), adding proper Windows support via icacls
  • 12-factor app compliance — config, disposability, and concurrency improvements across the codebase
  • Documentation accuracy — corrected media_adjust_volume tool name in MCP docs; emphasized MCP/OpenClaw over direct CLI for cost savings in agent skill

[0.3.0] - 2026-02-01

Added

  • Unified tescmd serve — single command combining MCP server, Fleet Telemetry streaming, cache warming, and optional OpenClaw bridge; full-screen TUI dashboard shows live telemetry, MCP status, tunnel URL, sink count, and connection health
  • TUI dashboard — 8-panel Textual layout with telemetry field table, server info sidebar, activity log, request log, and filter status; command palette (ctrl+p), keybindings (q to quit, f to toggle filters), clean graceful shutdown
  • OpenClaw Bridgetescmd openclaw bridge [VIN] streams Fleet Telemetry to an OpenClaw Gateway with configurable delta+throttle filtering per field; supports --dry-run for JSONL output without a gateway connection
  • OpenClaw node role — bidirectional command dispatch over the gateway WebSocket; bots send commands via the gateway that are forwarded as node.invoke.request events, routed through CommandDispatcher with read/write separation, tier enforcement, and VCSEC signing guards
  • Trigger subscription systemtrigger.create, trigger.delete, trigger.list, trigger.poll commands let bots register conditions on any telemetry field; supports operators lt, gt, lte, gte, eq, neq, changed, enter, leave; one-shot and persistent modes with configurable cooldown; max 100 triggers, 500 pending notifications
  • Geofence triggersenter/leave operators on Location field detect boundary crossings using haversine distance; fires only on actual crossing (not "already inside"), requires previous position for comparison
  • Trigger convenience aliasescabin_temp.trigger, outside_temp.trigger, battery.trigger, location.trigger pre-fill the field name so bots don't need to know raw telemetry field names
  • Trigger notification delivery — dual-channel: OpenClaw push events (trigger.fired) for connected bots, and MCP polling via trigger_poll tool for agent frameworks
  • system.run meta-dispatch — allows bots to invoke any registered handler by name with alias mapping (e.g., door_lockdoor.lock, auto_conditioning_startclimate.on); guards against recursive self-dispatch
  • MCP Servertescmd mcp serve exposes all tescmd commands as MCP tools for Claude Desktop/Code and other agent frameworks; supports stdio and streamable-http transports with OAuth 2.1 authentication
  • MCP custom tool registryMCPServer.register_custom_tool() allows runtime registration of non-CLI tools (used by trigger system); custom tools appear alongside CLI-backed tools with proper schemas
  • Agent skillskills/tescmd/SKILL.md teaches AI agents how to use every tescmd command group with examples, parameter types, and common patterns
  • Reusable telemetry session — extracted shared telemetry lifecycle (server → tunnel → partner registration → fleet config → cleanup) into telemetry/setup.py for use by serve, stream, and bridge commands
  • Dual-gate telemetry filteropenclaw/filters.py combines delta threshold (value change) and throttle interval (minimum time between emissions) to reduce noise in telemetry streams; includes haversine distance for location fields
  • OpenClaw event emitter — maps telemetry fields to OpenClaw req:agent event payloads (location, battery, temperature, speed, charge state transitions, security changes)
  • Gateway WebSocket client — implements the OpenClaw operator protocol (challenge → connect → hello-ok handshake) with Ed25519 device key signing and exponential backoff reconnection
  • Bridge configurationBridgeConfig pydantic model with per-field filter settings, loadable from JSON file or CLI flags
  • CSV telemetry logging — wide-format CSV log with one row per frame and one column per subscribed field; written to ~/.config/tescmd/logs/ by default, disable with --no-log
  • Cache sink — telemetry-driven cache warming keeps read-command cache fresh while telemetry is active, making agent reads free
  • Frame fanoutFrameFanout distributes decoded telemetry frames to multiple sinks (dashboard, CSV, cache, OpenClaw bridge, triggers) in parallel
  • Telemetry field mappertelemetry/mapper.py maps protobuf field names to tescmd model field names with unit conversion
  • Command guards in dispatcher — extracted check_command_guards() (tier check + VCSEC signing requirement) into a shared function called by both CLI and OpenClaw dispatcher paths
  • Standard dependencieswebsockets>=14.0, mcp>=1.0, and textual>=1.0 now included in default install

Changed

  • Refactored _cmd_telemetry_stream in cli/vehicle.py to use the shared telemetry_session() context manager (no behavioral change)
  • Proto-aligned telemetry field definitions with proper interval_seconds for delta fields
  • Separated JSON serialization errors from WebSocket connection errors in gateway send path for clearer diagnostics
  • Raised trigger push notification and lifecycle event failures from debug to warning level for observability

Fixed

  • Fixed prompt for re-authentication when refresh token is expired or revoked (was failing silently)
  • Fixed delta fields requiring interval_seconds configuration
  • Fixed log file paths not shown on quit
  • Added exc_info to MCP custom tool error logging for full stack traces
  • Added JSON parse guards and explicit parameter validation in MCP tool wrappers
  • Added system.run recursive self-dispatch guard

[0.2.0] - 2026-01-31

Added

  • Fleet Telemetry Streamingtescmd vehicle telemetry stream [VIN] starts a local WebSocket server, exposes it via Tailscale Funnel, configures the vehicle to push real-time telemetry, and displays it in an interactive Rich Live dashboard (TTY) or JSONL stream (piped)
  • Telemetry dashboard — Rich Live TUI with field name, value, and last-update columns; unit conversion (°F/°C, mi/km, psi/bar); connection status; frame counter; uptime display
  • Protobuf telemetry decoder — official Tesla protobuf definitions (vehicle_data, vehicle_alert, vehicle_error, vehicle_metric, vehicle_connectivity) for fully typed telemetry message parsing
  • FlatBuffer telemetry supportflatbuf.py parser for Tesla's FlatBuffer-encoded telemetry payloads alongside protobuf
  • Field presets--fields option accepts preset names (default, driving, charging, climate, all) or comma-separated field names with 120+ registered telemetry fields
  • Interval override--interval option overrides the polling interval for all fields
  • Tailscale Funnel integration — automatic Funnel start/stop with cert retrieval for Fleet Telemetry HTTPS requirement
  • JSONL output — piped mode emits one JSON line per telemetry frame for scripting and log ingestion
  • TunnelError hierarchyTunnelError parent with TailscaleError subtype; actionable install/setup guidance
  • websockets dependencywebsockets>=14.0 now included in default install
  • Tailscale key hostingtescmd key deploy --method tailscale hosts the public key via Tailscale Funnel at https://<machine>.tailnet.ts.net/.well-known/appspecific/com.tesla.3p.public-key.pem; auto-detected as second priority after GitHub Pages
  • Key hosting priority chain — setup wizard and key deploy auto-detect the best hosting method: GitHub Pages → Tailscale Funnel → manual; --method flag overrides auto-detection
  • TESLA_HOSTING_METHOD setting — persists the chosen key hosting method (github, tailscale) across sessions
  • Schnorr signature supportcrypto/schnorr.py for Schnorr-based authentication challenges used in telemetry server handshake
  • auth import commandtescmd auth import < tokens.json imports tokens from a JSON file for headless/CI environments
  • Setup guidedocs/setup.md with step-by-step walkthrough of all 7 setup phases
  • FAQdocs/faq.md covering common questions about tescmd, costs, hosting, and configuration
  • CI/CD workflows — GitHub Actions for test-on-push (Python 3.11–3.13) and publish-to-PyPI-on-release via trusted publishing
  • README badges — PyPI version, Python versions, CI build status, license, and GitHub release badges
  • E2E smoke teststests/cli/test_e2e_smoke.py provides 179 pytest-based end-to-end tests covering every CLI command against the live Fleet API, with JSON envelope validation and save/restore for write commands (pytest -m e2e)

Fixed

  • Fixed telemetry dashboard uptime counter not incrementing
  • Improved tunnel start/stop success messages for clarity

[0.1.2] - 2025-01-31

Added

  • Universal read-command caching — every read command is now transparently cached with tiered TTLs (STATIC 1h, SLOW 5m, DEFAULT 1m, FAST 30s); bots can call tescmd as often as needed — within the TTL window, responses are instant and free
  • Generic cache key schemegeneric_cache_key(scope, identifier, endpoint, params) generates scope-aware keys (vin, site, account, partner) for any API endpoint
  • cached_api_call() helper — unified async helper that handles cache lookup, fetch, serialisation (Pydantic/dict/list/scalar), and storage for all non-vehicle-state read commands
  • Site-scoped cache invalidationinvalidate_cache_for_site() clears energy site entries after write commands; invalidate_cache_for_vin() now also clears generic vin-scoped keys
  • cache clear options--site SITE_ID and --scope {account,partner} flags for targeted cache clearing alongside existing --vin
  • Partner endpointspartner public-key, partner telemetry-error-vins, partner telemetry-errors for partner account data (require client credentials)
  • Billing endpointsbilling history, billing sessions, billing invoice for Supercharger charging data
  • Cross-platform file permissions_internal/permissions.py provides secure_file() using chmod 0600 on Unix and icacls on Windows
  • Token store file backend_FileBackend with atomic writes and restricted permissions as fallback when keyring is unavailable
  • Spec-driven Fleet API validationscripts/validate_fleet_api.py validates implementation against spec/fleet_api_spec.json using AST introspection
  • 6 missing Fleet API commands — added managed_charging_set_amps, managed_charging_set_location, managed_charging_set_schedule, add_charge_schedule, remove_charge_schedule, clear_charge_schedules
  • Configurable display units--units metric flag switches all display values to °C/km/bar; individual env vars (TESLA_TEMP_UNIT, TESLA_DISTANCE_UNIT, TESLA_PRESSURE_UNIT) for granular control

Fixed

  • Aligned schedule/departure command parameters with Tesla Go SDK (correct param names and types)
  • Fixed energy endpoint paths to match Fleet API spec
  • Fixed Rich markup escaping bug in command output
  • Aligned command parameters (3 param gaps) with Go SDK specs

Changed

  • Response cache documentation in CLAUDE.md expanded to cover universal caching, TTL tiers, and generic cache key scheme

[0.1.1]

Added

  • status commandtescmd status shows current configuration, auth, cache, and key status at a glance
  • Retry option in wake prompt — when a vehicle is asleep, the interactive prompt now offers [R] Retry alongside [W] Wake via API and [C] Cancel, allowing users to wake the vehicle for free via the Tesla app and retry without restarting the command
  • Key enrollmenttescmd key enroll <VIN> sends the public key to the vehicle and guides the user through Tesla app approval with interactive [C]heck/[R]esend/[Q]uit prompt, --wait auto-polling, and JSON mode support
  • Tier enforcement — readonly tier now blocks write commands with a clear error and upgrade guidance (tescmd setup)
  • Vehicle Command Protocol — ECDH session management, HMAC-SHA256 command signing, and protobuf RoutableMessage encoding for the signed_command endpoint; commands are automatically signed when keys are available (command_protocol=auto)
  • SignedCommandAPI — composition wrapper that transparently routes signed commands through the Vehicle Command Protocol while falling back to unsigned REST for wake_up and unknown commands
  • command_protocol settingauto (default), signed, or unsigned to control command routing; configurable via TESLA_COMMAND_PROTOCOL env var
  • Enrollment step in setup wizard — full-tier setup now offers to enroll the key on a vehicle after key generation
  • Friendly command output — all vehicle commands now display descriptive success messages (e.g. "Climate control turned on.", "Doors locked.") instead of bare "OK"
  • E2E smoke teststests/cli/test_e2e_smoke.py provides 179 pytest-based end-to-end tests covering every CLI command against the live Fleet API, with JSON envelope validation and save/restore for write commands (pytest -m e2e)

[0.1.0]

Added

  • OAuth2 PKCE authentication with browser-based login flow
  • Vehicle state queries: battery, charge, climate, drive, location, doors, windows, trunks, tire pressure
  • Vehicle commands: charge start/stop/limit/schedule, climate on/off/set/seats/wheel, lock/unlock, sentry, trunk/frunk, windows, media, navigation, software updates, HomeLink, speed limits, PIN management
  • Energy products: Powerwall live status, site info, backup reserve, operation mode, storm mode, TOU settings, charging history, calendar history, grid config
  • User account: profile info, region, orders, feature config
  • Vehicle sharing: add/remove drivers, create/redeem/revoke invites
  • Rich terminal output with tables, panels, and status indicators
  • JSON output mode for scripting and agent integration
  • Configurable display units (F/C, mi/km, PSI/bar)
  • Response caching with configurable TTL for API cost reduction
  • Cost-aware wake confirmation (interactive prompt or --wake flag)
  • Multi-profile configuration support
  • EC key generation and Tesla Developer Portal registration
  • Raw API access (raw get, raw post) for uncovered endpoints
  • First-run setup wizard with Fleet Telemetry cost guidance