Skip to content

hosted-teleop: remove quest_hosted and cleanup#3173

Open
ruthwikdasyam wants to merge 9 commits into
mainfrom
ruthwik/hostedteleop/5
Open

hosted-teleop: remove quest_hosted and cleanup#3173
ruthwikdasyam wants to merge 9 commits into
mainfrom
ruthwik/hostedteleop/5

Conversation

@ruthwikdasyam

@ruthwikdasyam ruthwikdasyam commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Contribution path

  • Small, safe change that does not need a tracking issue
  • Linked issue or discussion: DIM-XXX / #XXX / URL

Problem

Cleanup deprecated quest_hosted module
fix needed - lifecycle races, E-STOP acks, blocking driver RPCs

Solution

  • Delete quest_hosted/ (superseded by teleop/hosted/)
  • only one generic TeleopRecorder, removed dublicate
  • adding exception-isolated teardown, restartable state after terminal heartbeat,
  • cancel-on-timeout in _run_sync, race-free loop-thread shutdown, prompt session close on worker teardown.
  • Command plane: estop/clear acks carry the real coordinator/driver result.
  • stop_movement/set_estop/Damp run on urgent threads off the provider loop.
  • future-stamp guard on the arm pose path.
  • safety-path tests (operator-lost, estop nack, busy-reject).
  • Latency stamp: 22-bit ms-modulo window - 416px min frame width (was 768) operator counterpart lands in dimensional-teleop.
  • Datachannel budget 16→32KB (~50% of CF's measured ~64KB silent-drop threshold);
  • go2 blueprints enable acrobatics as default

How to Test

dimos run teleop-hosted-go2-transport — drive, E-STOP, minimap, camera from
the operator page. pytest dimos/teleop dimos/protocol/pubsub/impl/webrtc

AI assistance

Claude Code with Opus 4.8 - audit, fixes, and tests written with heavy assistance; all changes reviewed by me.

Checklist

  • I have read and approved the CLA.

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

❌ 12 Tests Failed:

Tests completed Failed Passed Skipped
3232 12 3220 40
View the top 3 failed test(s) by shortest run time
dimos.web.relay_bridge.test_relay_e2e::test_large_frame_1mib
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_latest_channel_newest_wins
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_latest_writer_resets_stale_stream
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_malformed_robot_frame_is_dropped
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_reliable_channel_is_complete_and_intact
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_reset_burst_does_not_wedge_robot_leg
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_reset_stale_discards_partial_frame
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_robot_handshake_and_datagram_rtt
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_send_frame_paces_with_wait_delivered
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_stats_reflect_traffic
Stack Traces | 0.001s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_close_signal_stops_writer_and_wakes_waiter
Stack Traces | 0.02s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9501d490>
        response   = <http.client.HTTPResponse object at 0x7f6a9501cca0>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9501c6b0>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9501d490>
        response   = <http.client.HTTPResponse object at 0x7f6a9501cca0>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9501d490>, <http.client.HTTPResponse object at 0x7f6a9501cca0>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9501d490>, <http.client.HTTPResponse object at 0x7f6a9501cca0>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9501c6b0>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9501d490>, <http.client.HTTPResponse object at 0x7f6a9501cca0>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9501c6b0>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9501d490>
fp = <http.client.HTTPResponse object at 0x7f6a9501cca0>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9501c6b0>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a9501cca0>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9501c6b0>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9501d490>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture
    def own_relay() -> Iterator[RelayProcess]:
        """A started relay process the test may stop itself (stop() is idempotent)."""
        process = RelayProcess()
        try:
>           process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a95ed3260>

.../web/relay_bridge/test_relay_e2e.py:50: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a95ed3260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError
dimos.web.relay_bridge.test_relay_e2e::test_info_matches_ready_line
Stack Traces | 0.058s run time
def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
>           _require_immutable_release()

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/utils/deno.py:80: in _require_immutable_release
    with urllib.request.urlopen(url, timeout=60) as resp:
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:215: in urlopen
    return opener.open(url, data, timeout)
        cadefault  = False
        cafile     = None
        capath     = None
        context    = None
        data       = None
        opener     = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
        url        = 'https://api.github..../releases/tags/v2.6.10'
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:521: in open
    response = meth(req, response)
        data       = None
        fullurl    = 'https://api.github..../releases/tags/v2.6.10'
        meth       = <bound method HTTPErrorProcessor.http_response of <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>>
        meth_name  = 'https_response'
        processor  = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
        protocol   = 'https'
        req        = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
        timeout    = 60
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:630: in http_response
    response = self.parent.error(
        code       = 403
        hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
        msg        = 'rate limit exceeded'
        request    = <urllib.request.Request object at 0x7f6a9500b860>
        response   = <http.client.HTTPResponse object at 0x7f6a95029f00>
        self       = <urllib.request.HTTPErrorProcessor object at 0x7f6a9503b2f0>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:559: in error
    return self._call_chain(*args)
        args       = ({'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHa...ult', <urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, ...)
        dict       = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        http_err   = 1
        meth_name  = 'http_error_403'
        orig_args  = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        proto      = 403
        result     = None
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:492: in _call_chain
    result = func(*args)
        args       = (<urllib.request.Request object at 0x7f6a9500b860>, <http.client.HTTPResponse object at 0x7f6a95029f00>, 403, 'rate limit exceeded', <http.client.HTTPMessage object at 0x7f6a9503b890>)
        chain      = {'default': [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>], 301: [<urllib.request.HTTPRedirectHan...PRedirectHandler object at 0x7f6a9500b530>], 303: [<urllib.request.HTTPRedirectHandler object at 0x7f6a9500b530>], ...}
        func       = <bound method HTTPDefaultErrorHandler.http_error_default of <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>>
        handler    = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
        handlers   = [<urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>]
        kind       = 'default'
        meth_name  = 'http_error_default'
        self       = <urllib.request.OpenerDirector object at 0x7f6a9500b260>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>
req = <urllib.request.Request object at 0x7f6a9500b860>
fp = <http.client.HTTPResponse object at 0x7f6a95029f00>, code = 403
msg = 'rate limit exceeded'
hdrs = <http.client.HTTPMessage object at 0x7f6a9503b890>

    def http_error_default(self, req, fp, code, msg, hdrs):
>       raise HTTPError(req.full_url, code, msg, hdrs, fp)
E       urllib.error.HTTPError: HTTP Error 403: rate limit exceeded

code       = 403
fp         = <http.client.HTTPResponse object at 0x7f6a95029f00>
hdrs       = <http.client.HTTPMessage object at 0x7f6a9503b890>
msg        = 'rate limit exceeded'
req        = <urllib.request.Request object at 0x7f6a9500b860>
self       = <urllib.request.HTTPDefaultErrorHandler object at 0x7f6a95020a10>

.../hostedtoolcache/Python/3.12.13................../x64/lib/python3.12/urllib/request.py:639: HTTPError

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    def relay() -> Iterator[RelayReadyInfo]:
        process = RelayProcess()
        try:
>           yield process.start()

process    = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>

.../web/relay_bridge/test_relay_e2e.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../web/relay_bridge/relay_process.py:73: in start
    deno = ensure_deno()
        self       = <dimos.web.relay_bridge.relay_process.RelayProcess object at 0x7f6a9500b6e0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def ensure_deno() -> str:
        which = shutil.which("deno")
        if which:
            return which
    
        exe_name = "deno.exe" if platform.system() == "Windows" else "deno"
        deno_dir = STATE_DIR / "deno" / DENO_VERSION
        deno_path = deno_dir / exe_name
        if deno_path.exists():
            return str(deno_path)
    
        triple = _deno_triple()
        url = f"https://github..../deno/releases/download/{DENO_VERSION}/deno-{triple}.zip"
        logger.info(f"Downloading deno {DENO_VERSION} from {url}")
        deno_dir.mkdir(parents=True, exist_ok=True)
        try:
            _require_immutable_release()
            with tempfile.TemporaryDirectory(dir=str(deno_dir.parent)) as tmp:
                tmp_path = Path(tmp)
                zip_path = tmp_path / "deno.zip"
                with urllib.request.urlopen(url, timeout=60) as resp, open(zip_path, "wb") as f:
                    shutil.copyfileobj(resp, f)
                with zipfile.ZipFile(zip_path) as z:
                    z.extractall(tmp_path)
                extracted = tmp_path / exe_name
                if not extracted.exists():
                    raise RuntimeError(f"deno binary not found in archive from {url}")
                extracted.chmod(extracted.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                extracted.replace(deno_path)
        except Exception as e:
>           raise RuntimeError(
                f"deno is required. Auto-download failed: {e}. Install manually from https://deno.com/"
            ) from e
E           RuntimeError: deno is required. Auto-download failed: HTTP Error 403: rate limit exceeded. Install manually from https://deno.com/

deno_dir   = PosixPath('.../dimos/deno/v2.6.10')
deno_path  = PosixPath('.../dimos/deno/v2.6.10/deno')
exe_name   = 'deno'
triple     = 'x86_64-unknown-linux-gnu'
url        = 'https://github..../deno/releases/download/v2.6.10/deno-x86_64-unknown-linux-gnu.zip'
which      = None

dimos/utils/deno.py:65: RuntimeError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@ruthwikdasyam ruthwikdasyam changed the title hosted-teleop: remove quest_hosted hosted-teleop: remove quest_hosted and cleanup Jul 24, 2026
@ruthwikdasyam
ruthwikdasyam marked this pull request as ready for review July 24, 2026 23:33
@ruthwikdasyam
ruthwikdasyam marked this pull request as draft July 24, 2026 23:34
@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR removes the deprecated quest_hosted implementation and consolidates hosted teleoperation around the newer modular architecture.

  • Adds lifecycle and teardown handling for WebRTC providers and worker shutdown.
  • Moves blocking and urgent robot commands off provider loops and propagates command outcomes through acknowledgements.
  • Adds hosted arm command handling, camera multiplexing safeguards, telemetry utilities, and safety-path tests.
  • Updates hosted robot blueprints, transport limits, documentation, and blueprint registries.

Confidence Score: 5/5

The PR appears safe to merge because no additional blocking failure eligible for this follow-up review remains.

No blocking failure remains beyond the issue already communicated in the existing inline thread.

Important Files Changed

Filename Overview
dimos/teleop/hosted/arm_command.py Adds hosted arm command dispatch, timestamp guards, coordinator E-STOP integration, acknowledgements, and authoritative robot-state publication.
dimos/teleop/hosted/command_executor.py Provides background execution, command serialization, nonce handling, safety fencing, and urgent command dispatch.
dimos/protocol/pubsub/impl/webrtc/providers/spec.py Makes provider-loop shutdown race-safe and cancels timed-out asynchronous work.
dimos/protocol/pubsub/impl/webrtc/providers/broker.py Improves broker teardown, terminal-heartbeat recovery, audio-task replacement, diagnostics, and data-channel size warnings.
dimos/teleop/hosted/blueprints/cloudflare.py Updates hosted Go2 and xArm composition, transport wiring, and default acrobatics configuration.
dimos/robot/all_blueprints.py Removes registry entries backed by the deleted deprecated hosted-teleop implementation.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Operator[Hosted operator] --> Broker[WebRTC broker provider]
  Broker --> Commands[Go2 / Arm command modules]
  Broker --> Camera[Camera mux]
  Broker --> Stats[Hosted stats]
  Commands --> Executor[Serialized command executor]
  Executor --> Driver[Robot driver / coordinator]
  Camera --> Broker
  Stats --> Broker
Loading

Reviews (2): Last reviewed commit: "Merge branch 'main' into ruthwik/hostedt..." | Re-trigger Greptile

Comment on lines +243 to 245
def _apply_coordinator_latch(self, _epoch: int) -> bool:
estopped = self._estopped
try:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 E-STOP transition state is lost

When an E-STOP is followed quickly by a clear, the independent urgent callbacks both read the latest _estopped value instead of their requested transitions. Both can therefore call coordinator.set_estop(False) and acknowledge success without ever latching the coordinator, leaving its arm tasks operational.

Knowledge Base Used: Teleop Flow: From Input Device to Robot Control Commands

@ruthwikdasyam
ruthwikdasyam marked this pull request as ready for review July 24, 2026 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant