Skip to content

Releases: tianye1999/callpilot

v0.3.1 — Fix: repeat suppression could silence the call

Choose a tag to compare

@tianye1999 tianye1999 released this 08 Jul 18:37

Fixed

  • Repeat suppression could silence the call (regression in 0.3.0, caught on
    real hardware): dropped audio wasn't communicated to the model, so when the
    other side asked it to repeat, the repeat was dropped again — the callee
    heard dead air until they hung up. Now the second occurrence plays (repeating
    once when asked is legitimate), from the third on the audio is dropped and
    the model is nudged to rephrase (8s cooldown); three consecutive suppressed
    repeats mark the call as stuck and end it politely instead of leaving
    silence.

v0.3.0 — One-click macOS installer & first-run wizard

Choose a tag to compare

@tianye1999 tianye1999 released this 08 Jul 17:34

Known issue: repeat suppression in this build can silence the call under IVR loops — fixed in v0.3.1. Please use v0.3.1 instead.

Added

  • One-click macOS installer: packaging/build_installer.sh produces a
    self-contained CallPilot.dmg — bundled Python runtime, ffmpeg and libusb,
    no Python/venv/Homebrew needed. First launch installs the launchd background
    services automatically (and re-points them if the app is moved); the tray
    menu gains an "Uninstall background services" item. Runtime data moves to
    ~/Library/Application Support/CallPilot/. Unsigned for now (right-click →
    Open on first launch); codesign/notarization hooks are in place.
  • First-run setup wizard: detects the modem (PyUSB/system_profiler on
    macOS, serial VID scan elsewhere), validates your API key online
    (distinguishes "invalid key" from "network unreachable"), sets owner name /
    persona / language / voice, and can send a test SMS — no manual .env
    editing. Missing credentials no longer crash the service: the web UI comes
    up and guides you instead.
  • Live listen in the browser: hear both call directions (AI + caller) in
    real time via WebSocket + Web Audio — works even where native audio is
    broken. Call recordings are also playable per-call from History (caller
    track auto-amplified).
  • LLM wrap-up judge: a cheap text model watches the transcript and decides
    "keep going vs wrap up" — ends calls that are stuck in circles, keeps
    waiting when the other side is still looking something up, and only counts
    the goal as reached when the substantive result was actually given. Replaces
    keyword heuristics entirely.
  • Repeat suppression: when an IVR broadcast forces the model to respond
    over and over, near-identical replies are detected by text similarity and
    dropped before they reach the line (REPEAT_SUPPRESS_SIMILARITY, 0 to
    disable).
  • Tool safety: shared SMS rate limit across the AI tool and the web API
    (SMS_RATE_LIMIT_PER_HOUR), an off switch for the OTP-reading tool
    (TOOL_QUERY_CODE_ENABLED), and desensitized audit logging for every tool
    call (message lengths, not contents; hit/miss, not the code).
  • Clear recordings: delete a single call or all call records from History
    (in-progress calls are protected); SMS sending restricted to numbers you've
    actually interacted with.
  • Modem primitives examples: examples/modem/ — minimal standalone demos
    for raw AT, device probe, dial, answer, SMS send/receive and DTMF.

Changed

  • Prompts rewritten scenario-style (describe the situation, don't
    enumerate rules): shorter opening line, introduce yourself once, speak
    short menu keywords to voice menus, say a complete goodbye before calling
    the hang-up tool, and politely steer back to the task until the substantive
    result is in hand.
  • Doubao provider is now labeled experimental in Settings and docs
    (outbound calls may be silent).
  • Frontend hardened against XSS: no HTML-injection APIs; all user-controlled
    content rendered via textContent (guarded by a static test).

Fixed

  • Incoming-SMS race: a +CMTI notification arriving while any AT command
    response was being read was silently discarded; all command responses now
    scan for URCs.
  • Installer first-run race: bootstrapping launchd agents right after removing
    old ones could silently fail; now waits for unload and retries with backoff,
    reporting failures via tray notification.

Engineering

  • ruff (E/F/W/I) and mypy gates wired into CI, warning-clean at
    introduction; zero behavior change.

v0.2.0 — Windows support, OpenAI provider, three-platform CI

Choose a tag to compare

@tianye1999 tianye1999 released this 08 Jul 17:33

Added

  • Windows 10/11 support (code-complete, awaiting hardware reports).
    Windows uses the official Quectel driver's native COM port — no USB bridge
    needed. Ships with automatic port detection (MODEM_PORT=auto scans for the
    Quectel vendor ID), a PortAudio/WASAPI audio path, a scheduled-task
    installer (scripts/windows/install.ps1), and CallPilot.exe packaging.
  • OpenAI Realtime provider — new in this release: use OpenAI's realtime
    speech-to-speech API as the AI brain, alongside Alibaba Qwen Omni (default)
    and ByteDance Doubao.
  • Three-platform CI: every change now runs the full zero-hardware test
    suite on Ubuntu, macOS, and Windows.
  • Language menu: UI language switching moved to a globe-icon dropdown,
    making room for more languages beyond English and Chinese.

Fixed

  • Five P0 correctness bugs caught in a three-way code review, including:
    dashboard occasionally missing live events (broadcast tasks could be
    garbage-collected mid-flight), a hangup race with call-status polling, a
    delayed hangup scheduled during one call cutting off the next call (calls
    now carry a generation number), and RECORDING_ENABLED=on being interpreted
    differently in two places.
  • Zombie sessions: if the modem's serial link dies mid-call, the session
    now ends itself within seconds instead of rejecting all new calls until a
    manual hangup.
  • launchd PATH: the launchd units now set PATH explicitly, so ffmpeg
    is found and call audio works when CallPilot starts at login.
  • Dial input validation: invalid phone numbers are rejected up front
    instead of tying up the session for a 45-second timeout, and dialing with no
    modem connected reports a clear error instead of pretending a call was
    placed.

Changed

  • Call-session core refactored for contributors: prompt building and
    in-call AI tools split into their own modules, outbound call tasks passed
    explicitly instead of through the environment (batch dialing no longer
    rewrites .env on every call), and web API error handling unified. No
    intended behavior changes, backed by the full offline test suite.
  • Configuration consolidated into a single registry: every setting's
    default value lives in one place, .env.example documents all editable
    settings, and a regression test keeps the two from drifting apart.
  • Platform differences centralized in one module — per-OS defaults and
    paths are no longer scattered through the code.
  • macOS app is now a menu-bar tray (phone-handset icon — green when the
    service is running, grey when stopped — with an open-console / restart-service
    / quit menu) instead of a standalone desktop window.
  • Outbound wind-down polish: on reaching the goal, the AI now speaks a full
    goodbye before it invokes hang-up, and stays silent during the hang-up delay
    (no stray "call ended" line played to the other side).

CallPilot v0.1.0 — Developer Preview

Choose a tag to compare

@tianye1999 tianye1999 released this 07 Jul 20:12

Your calls, handled by AI. First public release of CallPilot — an open-source AI phone agent on a Quectel EC20/EG25 4G modem: auto-answers calls with a realtime voice AI, dials out, sends/receives SMS, presses IVR menus (DTMF), and records + summarizes every call. All on your own hardware and API keys.

Developer Preview. Verified end-to-end on real hardware (EC20 EC20CEFAGR08A03M4G, macOS): both audio directions confirmed against China Telecom's 10000 IVR — the AI held a multi-turn conversation with the voice menu and pressed keys autonomously — plus SMS balance-query round-trip. This release targets developers; we want your hardware reproduction reports.

Highlights

  • 📞 Auto-answer + outbound dialing (single with per-call topic, batch with whitelist) via hardware AT events — not screen automation
  • 🧠 Cloud realtime speech-to-speech (Alibaba Qwen Omni default, Doubao scaffolding) with function calling: send SMS, hang up, read OTP, press DTMF
  • 💬 SMS send/receive with Chinese UCS2
  • 🖥️ Desktop app — phosphor-green dark UI, live transcript, call history, recordings + AI summaries, bilingual EN/中文
  • 🛡️ Reliability: starts without a modem attached (background supervisor reconnects), USB drop-off storm root-caused (system sleep → endpoint stall) and mitigated (caffeinate -s, dev.reset(), backoff + cold-restart)

Known limitations

  • macOS only in practice; uac_ffmpeg is the only verified audio mode (nmea crashes EC20 USB — don't use it)
  • Windows/Linux serial paths exist but are unverified — reports welcome
  • Half-duplex (no barge-in); no self-contained installer yet (the .app is a thin shell over your checkout)
  • Bring your own DashScope API key + SIM with voice/SMS service

Get started

See the README quick start. Full details in CHANGELOG.md.

Have an EC20/EG25? Please file a hardware report — firmware version, OS, what worked and what didn't.