diff --git a/pywry/pywry/chat/providers/deepagent.py b/pywry/pywry/chat/providers/deepagent.py index d65f991..93fd42e 100644 --- a/pywry/pywry/chat/providers/deepagent.py +++ b/pywry/pywry/chat/providers/deepagent.py @@ -161,65 +161,53 @@ def _step_in_call(self, ch: str) -> None: self._in_string = False self._escape = False - def _step_in_special(self, ch: str, out: list[str]) -> None: - """Advance the ``<|...|>`` state machine; recurse on tail after ``|>``.""" + def _step_in_special(self, ch: str, _out: list[str]) -> None: + """Advance the ``<|...|>`` state machine; close when ``|>`` arrives. + + Because ``feed()`` drives one character at a time and ``_in_special`` + is entered with an empty buffer, the close marker is always at the + tail of the buffer — there is no trailing text to recurse on. + """ self._buffer += ch - close_idx = self._buffer.find(self._SPECIAL_CLOSE) - if close_idx < 0: + if self._SPECIAL_CLOSE not in self._buffer: return - rest = self._buffer[close_idx + len(self._SPECIAL_CLOSE) :] self._buffer = "" self._in_special = False - if rest: - out.append(self.feed(rest)) - def _try_open_call(self, out: list[str]) -> bool: + def _try_open_call(self, _out: list[str]) -> bool: """If a complete ``functions....{`` opener sits in buffer, enter call mode. Returns True if the buffer was consumed (caller skips other checks); - False if the marker isn't fully present yet — caller must NOT keep - scanning the buffer for ``<|`` (the ``functions.`` prefix already - committed us to wait). + False if the marker isn't fully present yet. ``_flush_safe_prefix`` + guarantees ``functions.`` always sits at the buffer head when it's + present, and char-by-char feeding means ``{`` is always the tail — + no leading prefix to emit and no trailing text to recurse on. """ - call_idx = self._buffer.find(self._CALL_START) - if call_idx < 0: + if self._CALL_START not in self._buffer: return False - brace_idx = self._buffer.find("{", call_idx + len(self._CALL_START)) + brace_idx = self._buffer.find("{", len(self._CALL_START)) if brace_idx < 0: # Marker present but no ``{`` yet — keep buffering, do not # fall through to the ``<|`` check (it would never match # ``functions.`` and we'd over-emit). return True - if call_idx > 0: - out.append(self._buffer[:call_idx]) - rest = self._buffer[brace_idx + 1 :] self._buffer = "" self._in_call = True self._depth = 1 self._in_string = False self._escape = False - if rest: - out.append(self.feed(rest)) return True - def _try_open_special(self, out: list[str]) -> bool: - """If a ``<|...|>`` token (or its open) is in buffer, drop it; return True.""" - special_idx = self._buffer.find(self._SPECIAL_OPEN) - if special_idx < 0: + def _try_open_special(self, _out: list[str]) -> bool: + """If a ``<|`` opener sits in buffer, drop it and enter skip mode. + + ``_flush_safe_prefix`` guarantees only ``<|`` itself (no trailing + text) ever reaches us, and the closing ``|>`` is consumed later + by ``_step_in_special`` — so we only need to handle the "open + seen, no close yet" case. + """ + if self._SPECIAL_OPEN not in self._buffer: return False - close_idx = self._buffer.find(self._SPECIAL_CLOSE, special_idx + len(self._SPECIAL_OPEN)) - if close_idx >= 0: - if special_idx > 0: - out.append(self._buffer[:special_idx]) - rest = self._buffer[close_idx + len(self._SPECIAL_CLOSE) :] - self._buffer = "" - if rest: - out.append(self.feed(rest)) - return True - # Open seen but no close yet — drop everything from ``<|`` on, - # emit the prefix, enter token-skip mode. - if special_idx > 0: - out.append(self._buffer[:special_idx]) self._buffer = "" self._in_special = True return True diff --git a/pywry/pywry/cli.py b/pywry/pywry/cli.py index 65bafb9..1d85164 100644 --- a/pywry/pywry/cli.py +++ b/pywry/pywry/cli.py @@ -447,9 +447,6 @@ def show_config_sources() -> int: if forced_status is True: status = "✓ Active" path_display = "" - elif forced_status is False: - status = "✗ Not found" - path_display = path_str # Check if file exists elif name == "Environment variables": import os diff --git a/pywry/pywry/config.py b/pywry/pywry/config.py index ed4911c..42dbf6e 100644 --- a/pywry/pywry/config.py +++ b/pywry/pywry/config.py @@ -27,7 +27,7 @@ if sys.version_info >= (3, 11): import tomllib -else: +else: # pragma: no cover - python 3.10 fallback; cannot be exercised on 3.11+ try: import tomli as tomllib except ImportError: diff --git a/pywry/pywry/inline.py b/pywry/pywry/inline.py index 2d7cde6..abd25bb 100644 --- a/pywry/pywry/inline.py +++ b/pywry/pywry/inline.py @@ -80,16 +80,11 @@ def _get_default_theme() -> ThemeLiteral: return "system" if is_headless() else "dark" -try: - import uvicorn - - from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect - from fastapi.middleware.cors import CORSMiddleware - from fastapi.responses import HTMLResponse, Response +import uvicorn - HAS_FASTAPI = True -except ImportError: - HAS_FASTAPI = False +from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import HTMLResponse, Response try: from ipywidgets import Output @@ -1688,8 +1683,6 @@ def __init__( token: str | None = None, ) -> None: super().__init__() - if not HAS_FASTAPI: - raise ImportError("fastapi and uvicorn required: pip install fastapi uvicorn") # For browser_only mode, we don't need IPython (just the server + browser) self._browser_only = browser_only @@ -3337,8 +3330,6 @@ def generate_dataframe_html( } if grid_options: grid_config.update(grid_options) - if "rowData" not in grid_config: - grid_config["rowData"] = row_data assets = _build_aggrid_assets(aggrid_theme, theme_mode) # For system theme, default to dark AG Grid theme (JS will switch) @@ -3899,17 +3890,20 @@ def generate_tvchart_html( modal_html, modal_scripts = wrap_content_with_modals("", modals) modal_block = f"{modal_html}{modal_scripts}" + bridge_js = _get_pywry_bridge_js(widget_id, token) + return f""" {title} - {tvchart_script} - {tvchart_defaults_script} {pywry_style} {toast_style} {inline_style} {scrollbar_script} + {bridge_js} + {tvchart_script} + {tvchart_defaults_script}