Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.12"]
python-version: ["3.11", "3.12"]

steps:
- uses: actions/checkout@v7
Expand Down Expand Up @@ -51,12 +51,19 @@ jobs:
with:
python-version: "3.12"

- uses: astral-sh/setup-uv@v8.1.0
with:
version: "latest"

- uses: actions/setup-node@v7
with:
node-version: "22"

- name: Install bridge + test deps
run: pip install -e . pytest
run: |
uv pip install --system \
"inkbox @ git+https://github.com/inkbox-ai/inkbox.git@8f4b37c56cd153a2acc6cfabe27dbbeb43510f00#subdirectory=sdk/python" \
-e . pytest

# @alpha is the prerelease channel cut from codex main near-daily — the
# freshest main build available without compiling the host from source.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
## Prerequisites

- **Codex installed and logged in.** The bridge drives a real Codex session, so the `codex` CLI has to be on the machine and authenticated — install it ([developers.openai.com/codex](https://developers.openai.com/codex)), then either sign in with a ChatGPT/Codex login or set `OPENAI_API_KEY`. `inkbox-codex doctor` checks for it.
- **Python 3.10+.** The installer finds one and builds the bridge its own venv.
- **Python 3.11+.** The installer finds one and builds the bridge its own venv.
- **macOS or Linux.** Boot persistence uses a systemd user unit on Linux and a launchd agent on macOS.
- **An Inkbox agent** — nothing to set up in advance; the setup wizard self-signs up for you (or takes an existing API key).

## Get started — one command

This finds a Python 3.10+, installs the bridge in its own venv, puts `inkbox-codex` on your PATH, and runs the setup wizard:
This finds a Python 3.11+, installs the bridge in its own venv, puts `inkbox-codex` on your PATH, and runs the setup wizard:

```bash
curl -fsSL https://raw.githubusercontent.com/inkbox-ai/codex-plugin/main/install.sh | bash
Expand Down Expand Up @@ -70,7 +70,7 @@ you (phone) ── SMS / iMessage / email / call ──▶ Inkbox ──▶

## Manual install

If you'd rather not run the installer (any Python 3.10+ environment):
If you'd rather not run the installer (any Python 3.11+ environment):

```bash
pip install -e .
Expand Down
2 changes: 1 addition & 1 deletion inkbox_codex/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def run_doctor() -> List[Tuple[str, bool, str]]:
import inkbox # noqa: F401
checks.append(("inkbox SDK", True, "installed"))
except ImportError:
checks.append(("inkbox SDK", False, "pip install 'inkbox>=0.4.15,<1.0.0'"))
checks.append(("inkbox SDK", False, "pip install 'inkbox>=0.5.0,<1.0.0'"))

try:
import aiohttp # noqa: F401
Expand Down
2 changes: 1 addition & 1 deletion inkbox_codex/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ async def run(self) -> None:
if not AIOHTTP_AVAILABLE:
raise RuntimeError("aiohttp is not installed; run: pip install aiohttp")
if not INKBOX_AVAILABLE:
raise RuntimeError("inkbox SDK is not installed; run: pip install 'inkbox>=0.4.15,<1.0.0'")
raise RuntimeError("inkbox SDK is not installed; run: pip install 'inkbox>=0.5.0,<1.0.0'")
if not self.cfg.api_key or not self.cfg.identity:
raise RuntimeError("INKBOX_API_KEY and INKBOX_IDENTITY must be set (see README)")

Expand Down
4 changes: 2 additions & 2 deletions inkbox_codex/setup_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@

# Packages the wizard itself needs to talk to Inkbox during setup. The
# gateway's Codex CLI dependency is checked by doctor.
INKBOX_REQUIREMENTS = ("inkbox>=0.4.20,<1.0.0", "aiohttp>=3.9")
MIN_INKBOX_VERSION = (0, 4, 20)
INKBOX_REQUIREMENTS = ("inkbox>=0.5.0,<1.0.0", "aiohttp>=3.9")
MIN_INKBOX_VERSION = (0, 5, 0)
_BRACKETED_PASTE_PATTERN = re.compile(r"\x1b\[\s*200~|\x1b\[\s*201~")

# Bundled avatar attached to the agent's Inkbox contact card during setup.
Expand Down
12 changes: 6 additions & 6 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#
# ./install.sh
#
# Finds a Python 3.10+, sets up an isolated venv, installs the bridge, puts
# Finds a Python 3.11+, sets up an isolated venv, installs the bridge, puts
# `inkbox-codex` on your PATH, then runs the setup wizard. Re-runnable.
#
# Flags:
Expand Down Expand Up @@ -54,22 +54,22 @@ ok() { echo " ${GREEN}✓${RESET} $*"; }
warn() { echo " ${YELLOW}!${RESET} $*"; }
die() { echo "${RED}✗ $*${RESET}" >&2; exit 1; }

# --- 1. find Python 3.10+ --------------------------------------------------
# --- 1. find Python 3.11+ --------------------------------------------------
find_python() {
local c v maj min
for c in python3.13 python3.12 python3.11 python3.10 python3 python; do
for c in python3.13 python3.12 python3.11 python3 python; do
command -v "$c" >/dev/null 2>&1 || continue
v="$("$c" -c 'import sys;print("%d.%d"%sys.version_info[:2])' 2>/dev/null || echo 0.0)"
maj="${v%.*}"; min="${v#*.}"
if [ "$maj" = "3" ] && [ "$min" -ge 10 ] 2>/dev/null; then
if [ "$maj" = "3" ] && [ "$min" -ge 11 ] 2>/dev/null; then
echo "$c"; return 0
fi
done
return 1
}

step "Looking for Python 3.10+"
PY="$(find_python)" || die "No Python 3.10+ found. Install python3.11+ and re-run."
step "Looking for Python 3.11+"
PY="$(find_python)" || die "No Python 3.11+ found. Install Python 3.11 or newer and re-run."
ok "using $($PY --version 2>&1) at $(command -v "$PY")"

# --- 2. get the source -----------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
name = "codex-plugin"
version = "0.1.4"
description = "Inkbox bridge for Codex — talk to your coding agent over email, SMS, iMessage, and voice"
requires-python = ">=3.10"
requires-python = ">=3.11"
dependencies = [
"aiohttp>=3.9",
"inkbox>=0.4.24,<1.0.0",
"inkbox>=0.5.0,<1.0.0",
"segno>=1.5", # terminal QR codes for the iMessage connect step
]

Expand Down
4 changes: 2 additions & 2 deletions tests/live/test_sms.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,10 @@ def _settle_inbound(sms) -> set:


def _wait_new_inbound(sms, before: set, timeout_s: float, context: str) -> str:
"""Poll for the first inbound not in ``before``; return its body lowercased."""
"""Poll for the earliest inbound not in ``before``; return its body lowercased."""
deadline = time.monotonic() + timeout_s
while time.monotonic() < deadline:
for m in _inbound_from_aut(sms):
for m in reversed(_inbound_from_aut(sms)):
if m.id not in before:
body = getattr(m, "text", "") or ""
bad = [x for x in ERROR_MARKERS if x in body.lower()]
Expand Down
8 changes: 4 additions & 4 deletions tests/test_setup_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def test_install_command_prefers_uv_when_available(monkeypatch):
"install",
"--python",
"/tmp/venv/bin/python",
"inkbox>=0.4.20,<1.0.0",
"inkbox>=0.5.0,<1.0.0",
"aiohttp>=3.9",
]]

Expand All @@ -98,10 +98,10 @@ def test_install_command_falls_back_to_pip_and_ensurepip(monkeypatch):
monkeypatch.setattr(setup_wizard.shutil, "which", lambda _name: None)

assert setup_wizard._install_commands() == [
[["/tmp/venv/bin/python", "-m", "pip", "install", "inkbox>=0.4.20,<1.0.0", "aiohttp>=3.9"]],
[["/tmp/venv/bin/python", "-m", "pip", "install", "inkbox>=0.5.0,<1.0.0", "aiohttp>=3.9"]],
[
["/tmp/venv/bin/python", "-m", "ensurepip", "--upgrade"],
["/tmp/venv/bin/python", "-m", "pip", "install", "inkbox>=0.4.20,<1.0.0", "aiohttp>=3.9"],
["/tmp/venv/bin/python", "-m", "pip", "install", "inkbox>=0.5.0,<1.0.0", "aiohttp>=3.9"],
],
]

Expand All @@ -120,7 +120,7 @@ def fail_import():
out = capsys.readouterr().out
assert "/tmp/venv/bin/python" in out
assert "uv pip install --python" in out
assert "inkbox>=0.4.20,<1.0.0" in out
assert "inkbox>=0.5.0,<1.0.0" in out


# ----------------------------------------------------------------------
Expand Down