Releases: tianye1999/callpilot
Release list
v0.3.1 — Fix: repeat suppression could silence the call
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
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.shproduces a
self-containedCallPilot.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 viatextContent(guarded by a static test).
Fixed
- Incoming-SMS race: a
+CMTInotification 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) andmypygates wired into CI, warning-clean at
introduction; zero behavior change.
v0.2.0 — Windows support, OpenAI provider, three-platform CI
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=autoscans for the
Quectel vendor ID), a PortAudio/WASAPI audio path, a scheduled-task
installer (scripts/windows/install.ps1), andCallPilot.exepackaging. - 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), andRECORDING_ENABLED=onbeing 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
PATHexplicitly, soffmpeg
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.envon 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.exampledocuments 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
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's10000IVR — 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_ffmpegis the only verified audio mode (nmeacrashes 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
.appis 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.