From 6d1fdf496f0feec3cf09823ebbbd0b87833c31ef Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 8 Apr 2026 07:26:26 +0000 Subject: [PATCH 1/3] Update plugin dependencies: decart 0.0.33, turbopuffer 1.21.0, deepgram-sdk 6.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - decart: ==0.0.8 → >=0.0.33 (API migration: enrich→enhance, mirror removed) - turbopuffer: <1.18 → <1.22 (1.17.0→1.21.0, backward-compatible rewrite) - deepgram-sdk: <6.1.0 → <6.2.0 (6.0.1→6.1.1, adds agent features) Co-authored-by: Neevash Ramdial (Nash) --- plugins/decart/pyproject.toml | 2 +- plugins/decart/tests/test_decart_restyling.py | 42 +++------------- .../decart/decart_restyling_processor.py | 50 +++++-------------- plugins/deepgram/pyproject.toml | 2 +- plugins/turbopuffer/pyproject.toml | 2 +- uv.lock | 24 ++++----- 6 files changed, 33 insertions(+), 89 deletions(-) diff --git a/plugins/decart/pyproject.toml b/plugins/decart/pyproject.toml index f3846f113..6200f68ac 100644 --- a/plugins/decart/pyproject.toml +++ b/plugins/decart/pyproject.toml @@ -12,7 +12,7 @@ requires-python = ">=3.10" license = "MIT" dependencies = [ "vision-agents", - "decart==0.0.8", + "decart>=0.0.33", ] [project.urls] diff --git a/plugins/decart/tests/test_decart_restyling.py b/plugins/decart/tests/test_decart_restyling.py index 0b00c75de..a79119bd0 100644 --- a/plugins/decart/tests/test_decart_restyling.py +++ b/plugins/decart/tests/test_decart_restyling.py @@ -104,9 +104,9 @@ async def test_update_prompt_when_connected(self, mock_decart_client): processor._realtime_client = mock_client processor._connected = True - await processor.update_prompt("new style", enrich=False) + await processor.update_prompt("new style", enhance=False) - mock_client.set_prompt.assert_called_once_with("new style", enrich=False) + mock_client.set_prompt.assert_called_once_with("new style", enhance=False) assert processor.initial_prompt == "new style" await processor.close() @@ -127,48 +127,18 @@ async def test_update_prompt_noop_when_disconnected(self, mock_decart_client): await processor.close() @pytest.mark.asyncio - async def test_update_prompt_uses_default_enrich(self, mock_decart_client): - """Test update_prompt uses default enrich value when not specified.""" + async def test_update_prompt_uses_default_enhance(self, mock_decart_client): + """Test update_prompt uses default enhance value when not specified.""" with patch( "vision_agents.plugins.decart.decart_restyling_processor.RealtimeClient" ): - processor = RestylingProcessor(api_key="test_key", enrich=True) + processor = RestylingProcessor(api_key="test_key", enhance=True) mock_client = AsyncMock() processor._realtime_client = mock_client await processor.update_prompt("new style") - mock_client.set_prompt.assert_called_once_with("new style", enrich=True) - await processor.close() - - @pytest.mark.asyncio - async def test_set_mirror_when_connected(self, mock_decart_client): - """Test set_mirror updates mirror mode when connected.""" - with patch( - "vision_agents.plugins.decart.decart_restyling_processor.RealtimeClient" - ): - processor = RestylingProcessor(api_key="test_key", mirror=True) - mock_client = AsyncMock() - processor._realtime_client = mock_client - - await processor.set_mirror(False) - - mock_client.set_mirror.assert_called_once_with(False) - assert processor.mirror is False - await processor.close() - - @pytest.mark.asyncio - async def test_set_mirror_noop_when_disconnected(self, mock_decart_client): - """Test set_mirror is no-op when disconnected.""" - with patch( - "vision_agents.plugins.decart.decart_restyling_processor.RealtimeClient" - ): - processor = RestylingProcessor(api_key="test_key", mirror=True) - processor._realtime_client = None - - await processor.set_mirror(False) - - assert processor.mirror is True + mock_client.set_prompt.assert_called_once_with("new style", enhance=True) await processor.close() diff --git a/plugins/decart/vision_agents/plugins/decart/decart_restyling_processor.py b/plugins/decart/vision_agents/plugins/decart/decart_restyling_processor.py index f7515a45e..180a8b43b 100644 --- a/plugins/decart/vision_agents/plugins/decart/decart_restyling_processor.py +++ b/plugins/decart/vision_agents/plugins/decart/decart_restyling_processor.py @@ -64,8 +64,7 @@ def __init__( api_key: Optional[str] = None, model: RealTimeModels = "mirage_v2", initial_prompt: str = "Cyberpunk city", - enrich: bool = True, - mirror: bool = True, + enhance: bool = True, width: int = 1280, # Model preferred height: int = 720, **kwargs, @@ -76,8 +75,7 @@ def __init__( api_key: Decart API key. Uses DECART_API_KEY env var if not provided. model: Decart model name (default: "mirage_v2"). initial_prompt: Initial style prompt text. - enrich: Whether to enrich prompt (default: True). - mirror: Mirror mode for front camera (default: True). + enhance: Whether to enhance prompt (default: True). width: Output video width (default: 1280). height: Output video height (default: 720). **kwargs: Additional arguments passed to parent class. @@ -92,8 +90,7 @@ def __init__( self.model_name = model self.initial_prompt = initial_prompt - self.enrich = enrich - self.mirror = mirror + self.enhance = enhance self.width = width self.height = height @@ -124,45 +121,23 @@ def publish_video_track(self) -> VideoStreamTrack: return self._video_track async def update_prompt( - self, prompt_text: str, enrich: Optional[bool] = None + self, prompt_text: str, enhance: Optional[bool] = None ) -> None: - """ - Updates the prompt used for the Decart real-time client. This method allows - changing the current prompt and optionally specifies whether to enrich the - prompt content. The operation is performed asynchronously and requires an - active connection to the Decart client. - - If the `enrich` parameter is not provided, the method uses the default - `self.enrich` value. - - Parameters: - prompt_text: str - The text of the new prompt to be applied. - enrich: Optional[bool] - Specifies whether to enrich the prompt content. If not provided, - defaults to the object's `enrich` attribute. - - Returns: - None + """Updates the prompt used for the Decart real-time client. + + Args: + prompt_text: The text of the new prompt to be applied. + enhance: Whether to enhance the prompt. Defaults to self.enhance. """ if not self._realtime_client: logger.debug("Cannot set prompt: not connected to Decart") return - enrich_value = enrich if enrich is not None else self.enrich - await self._realtime_client.set_prompt(prompt_text, enrich=enrich_value) + enhance_value = enhance if enhance is not None else self.enhance + await self._realtime_client.set_prompt(prompt_text, enhance=enhance_value) self.initial_prompt = prompt_text logger.info(f"Updated Decart prompt: {prompt_text[:50]}...") - async def set_mirror(self, enabled: bool) -> None: - if not self._realtime_client: - logger.debug("Cannot set mirror: not connected to Decart") - return - - await self._realtime_client.set_mirror(enabled) - self.mirror = enabled - logger.debug(f"Updated Decart mirror mode: {enabled}") - async def _connect_to_decart(self, local_track: MediaStreamTrack) -> None: if self._connecting: logger.debug("Already connecting to Decart, skipping") @@ -178,9 +153,8 @@ async def _connect_to_decart(self, local_track: MediaStreamTrack) -> None: initial_state = ModelState( prompt=Prompt( text=self.initial_prompt, - enrich=self.enrich, + enhance=self.enhance, ), - mirror=self.mirror, ) self._realtime_client = await RealtimeClient.connect( diff --git a/plugins/deepgram/pyproject.toml b/plugins/deepgram/pyproject.toml index c7d944199..e57bb3ea0 100644 --- a/plugins/deepgram/pyproject.toml +++ b/plugins/deepgram/pyproject.toml @@ -12,7 +12,7 @@ requires-python = ">=3.10" license = "MIT" dependencies = [ "vision-agents", - "deepgram-sdk>=6.0.1,<6.1.0", + "deepgram-sdk>=6.0.1,<6.2.0", ] [project.urls] diff --git a/plugins/turbopuffer/pyproject.toml b/plugins/turbopuffer/pyproject.toml index 53d903062..8646b8fa5 100644 --- a/plugins/turbopuffer/pyproject.toml +++ b/plugins/turbopuffer/pyproject.toml @@ -12,7 +12,7 @@ requires-python = ">=3.10" license = "MIT" dependencies = [ "vision-agents", - "turbopuffer>=1.17.0,<1.18", + "turbopuffer>=1.17.0,<1.22", "langchain-google-genai>=4.2.1", "langchain-text-splitters>=1.1.1", ] diff --git a/uv.lock b/uv.lock index 15837bece..9781170cb 100644 --- a/uv.lock +++ b/uv.lock @@ -1394,7 +1394,7 @@ wheels = [ [[package]] name = "decart" -version = "0.0.8" +version = "0.0.33" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiofiles" }, @@ -1404,9 +1404,9 @@ dependencies = [ { name = "pydantic" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/86/86/75e55da0dc56528b232e31186c02bf409ba9bce888e5520507a9737cdc36/decart-0.0.8.tar.gz", hash = "sha256:95ea6fc0af5896198ce76abf7d2ecf39feec77e3ebf7c5fa55e2f239879d5545", size = 198620, upload-time = "2025-11-12T17:02:42.627Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/cf/1ff0e1e13ecb744cd15eb0bd5d67285eac0907c88bbfbd29673295ece14f/decart-0.0.33.tar.gz", hash = "sha256:75479e850acc550968c5b7c9c765c5425f28261e9cd40d9b1d4d0b9d76a9cc43", size = 194239, upload-time = "2026-04-06T23:00:10.202Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/e2/e128f098aaf0981849da4684a30d53b9a84be84fc372709de14557d135e9/decart-0.0.8-py3-none-any.whl", hash = "sha256:3f1ab43ced32edcd5a494673bc8f899a559f6a5c59796da88d71c5f48b8422dc", size = 20263, upload-time = "2025-11-12T17:02:40.913Z" }, + { url = "https://files.pythonhosted.org/packages/6a/cb/84830615797bc83f61f7d7cc63838cf42e60d4606e6690078c33c029e637/decart-0.0.33-py3-none-any.whl", hash = "sha256:225bd1ec2881f701b6a7272351a5f3620aa80fc699f8245378a0b9cf4365e8fb", size = 38326, upload-time = "2026-04-06T23:00:08.558Z" }, ] [[package]] @@ -1420,7 +1420,7 @@ wheels = [ [[package]] name = "deepgram-sdk" -version = "6.0.1" +version = "6.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -1429,9 +1429,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/73/46/6dc45de574d766a20853452d7beccf17cb0cfeb685a0f03460f1fe49b48e/deepgram_sdk-6.0.1.tar.gz", hash = "sha256:88558a43d6173a861c8b6d6491b9ee8805679fb09fb81ef51eeb6871dad77767", size = 176743, upload-time = "2026-02-24T13:52:17.163Z" } +sdist = { url = "https://files.pythonhosted.org/packages/29/91/85360d998685fee6b570e12250e5ac74ca43420d5d22b44a865b6c3f2469/deepgram_sdk-6.1.1.tar.gz", hash = "sha256:78726f42b2386f80d9fdd92a22ac59ad5558b6c0475b29bb57273ddaaa344794", size = 202224, upload-time = "2026-03-27T19:59:57.202Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/58/a4/53b9075816edc566694aed014d9864febedf232677b74f5d30bdde64b5de/deepgram_sdk-6.0.1-py3-none-any.whl", hash = "sha256:1b33d621b1c0b1d7a6a7b46fdc393aef4212e670521fada99764f5fb3f9d55fd", size = 490751, upload-time = "2026-02-24T13:52:15.998Z" }, + { url = "https://files.pythonhosted.org/packages/6f/7f/818ac35b40e38f225858cea38808c7fdd57292553479cabf0bebf7fcdc91/deepgram_sdk-6.1.1-py3-none-any.whl", hash = "sha256:329f45f2a084e8786d3e90d4a4aee630b85cf8770a3b2ee6323bedb176c47113", size = 576299, upload-time = "2026-03-27T19:59:55.949Z" }, ] [[package]] @@ -6724,7 +6724,7 @@ wheels = [ [[package]] name = "turbopuffer" -version = "1.17.0" +version = "1.21.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -6737,9 +6737,9 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5a/af/ef0fb14e0b8715dcd7658ac97dce6d08faa7dba57956cc0b17f98606fefd/turbopuffer-1.17.0.tar.gz", hash = "sha256:89c18dd535e88545e75ebfef98bbd06e8bb8c3b02abf853a550319d1ca1698f7", size = 154867, upload-time = "2026-03-03T04:27:15.734Z" } +sdist = { url = "https://files.pythonhosted.org/packages/17/e5/c7df3bde9efbbafdcf10ba5ae2a0159e4a894183393e2dc02d2cb1c19792/turbopuffer-1.21.0.tar.gz", hash = "sha256:988ddfceab082190673a097edb1e32636a8958cc6ad6c5260b2990513c12ded9", size = 337493, upload-time = "2026-04-07T15:47:34.586Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/70/08/f442616e4e4ecf098f03f69a8354e2db51a277742e0ca3317997fd143dea/turbopuffer-1.17.0-py3-none-any.whl", hash = "sha256:49236d9b2f40035057fa377065ede581fbd52ee36a232a69407f11bdb521a892", size = 116628, upload-time = "2026-03-03T04:27:14.261Z" }, + { url = "https://files.pythonhosted.org/packages/39/30/995ae0edbb748d6a98bcbb0040ed354e2df31a06092a60e986763de52893/turbopuffer-1.21.0-py3-none-any.whl", hash = "sha256:adbea8fc118138e311047571f1438b4a2ce0d67aa759c1dd33fc3b90bdf2c424", size = 122566, upload-time = "2026-04-07T15:47:35.941Z" }, ] [[package]] @@ -7403,7 +7403,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "decart", specifier = "==0.0.8" }, + { name = "decart", specifier = ">=0.0.33" }, { name = "vision-agents", editable = "agents-core" }, ] @@ -7432,7 +7432,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "deepgram-sdk", specifier = ">=6.0.1,<6.1.0" }, + { name = "deepgram-sdk", specifier = ">=6.0.1,<6.2.0" }, { name = "vision-agents", editable = "agents-core" }, ] @@ -8072,7 +8072,7 @@ dev = [ requires-dist = [ { name = "langchain-google-genai", specifier = ">=4.2.1" }, { name = "langchain-text-splitters", specifier = ">=1.1.1" }, - { name = "turbopuffer", specifier = ">=1.17.0,<1.18" }, + { name = "turbopuffer", specifier = ">=1.17.0,<1.22" }, { name = "vision-agents", editable = "agents-core" }, ] From 32cbc2c297faa72ce149ca86401253fa9e253a79 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 8 Apr 2026 07:34:59 +0000 Subject: [PATCH 2/3] Fix mypy errors: SpeakV1Text type param, turbopuffer RowParam typing Co-authored-by: Neevash Ramdial (Nash) --- .../vision_agents/plugins/deepgram/tts.py | 4 ++-- .../plugins/turbopuffer/turbopuffer_rag.py | 20 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/deepgram/vision_agents/plugins/deepgram/tts.py b/plugins/deepgram/vision_agents/plugins/deepgram/tts.py index ee984452f..b88e6bd0b 100644 --- a/plugins/deepgram/vision_agents/plugins/deepgram/tts.py +++ b/plugins/deepgram/vision_agents/plugins/deepgram/tts.py @@ -102,13 +102,13 @@ async def stream_audio(self, text: str, *_, **__) -> AsyncIterator[PcmData]: self._stop_event.clear() try: - await socket.send_text(SpeakV1Text(text=text)) + await socket.send_text(SpeakV1Text(type="Speak", text=text)) await socket.send_flush() except (websockets.exceptions.ConnectionClosed, ConnectionError): logger.warning("Deepgram TTS websocket dropped, reconnecting") await self._reset_connection() socket = await self._ensure_connection() - await socket.send_text(SpeakV1Text(text=text)) + await socket.send_text(SpeakV1Text(type="Speak", text=text)) await socket.send_flush() self._generation += 1 diff --git a/plugins/turbopuffer/vision_agents/plugins/turbopuffer/turbopuffer_rag.py b/plugins/turbopuffer/vision_agents/plugins/turbopuffer/turbopuffer_rag.py index 877d89ee9..e45e5fb4c 100644 --- a/plugins/turbopuffer/vision_agents/plugins/turbopuffer/turbopuffer_rag.py +++ b/plugins/turbopuffer/vision_agents/plugins/turbopuffer/turbopuffer_rag.py @@ -46,6 +46,7 @@ from langchain_google_genai import GoogleGenerativeAIEmbeddings from langchain_text_splitters import RecursiveCharacterTextSplitter from turbopuffer import AsyncTurbopuffer, NotFoundError +from turbopuffer.types import RowParam from vision_agents.core.rag import RAG, Document @@ -181,19 +182,18 @@ async def add_documents(self, documents: list[Document]) -> int: None, self._embeddings.embed_documents, all_chunks ) - rows = [] + rows: list[RowParam] = [] for chunk, embedding, (source, idx) in zip( all_chunks, embeddings, chunk_sources ): - rows.append( - { - "id": f"{source}_{idx}", - "vector": embedding, - "text": chunk, - "source": source, - "chunk_index": idx, - } - ) + row: RowParam = { + "id": f"{source}_{idx}", + "vector": embedding, + "text": chunk, + "source": source, + "chunk_index": idx, + } + rows.append(row) ns = self._client.namespace(self._namespace_name) await ns.write( From 7048c37eee745b7a8502667f2ec98ceed65388ab Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 8 Apr 2026 07:43:09 +0000 Subject: [PATCH 3/3] Revert RowParam import, use type: ignore for turbopuffer dict rows Co-authored-by: Neevash Ramdial (Nash) --- .../plugins/turbopuffer/turbopuffer_rag.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/turbopuffer/vision_agents/plugins/turbopuffer/turbopuffer_rag.py b/plugins/turbopuffer/vision_agents/plugins/turbopuffer/turbopuffer_rag.py index e45e5fb4c..9f2f1f392 100644 --- a/plugins/turbopuffer/vision_agents/plugins/turbopuffer/turbopuffer_rag.py +++ b/plugins/turbopuffer/vision_agents/plugins/turbopuffer/turbopuffer_rag.py @@ -46,7 +46,6 @@ from langchain_google_genai import GoogleGenerativeAIEmbeddings from langchain_text_splitters import RecursiveCharacterTextSplitter from turbopuffer import AsyncTurbopuffer, NotFoundError -from turbopuffer.types import RowParam from vision_agents.core.rag import RAG, Document @@ -182,22 +181,23 @@ async def add_documents(self, documents: list[Document]) -> int: None, self._embeddings.embed_documents, all_chunks ) - rows: list[RowParam] = [] + rows = [] for chunk, embedding, (source, idx) in zip( all_chunks, embeddings, chunk_sources ): - row: RowParam = { - "id": f"{source}_{idx}", - "vector": embedding, - "text": chunk, - "source": source, - "chunk_index": idx, - } - rows.append(row) + rows.append( + { + "id": f"{source}_{idx}", + "vector": embedding, + "text": chunk, + "source": source, + "chunk_index": idx, + } + ) ns = self._client.namespace(self._namespace_name) await ns.write( - upsert_rows=rows, + upsert_rows=rows, # type: ignore[arg-type] distance_metric="cosine_distance", schema=HYBRID_SCHEMA, # type: ignore[arg-type] )