diff --git a/examples/cat-lounge/backend/app/widgets/name_suggestions_widget.py b/examples/cat-lounge/backend/app/widgets/name_suggestions_widget.py index e1c3ec9..3008b2e 100644 --- a/examples/cat-lounge/backend/app/widgets/name_suggestions_widget.py +++ b/examples/cat-lounge/backend/app/widgets/name_suggestions_widget.py @@ -5,11 +5,9 @@ from __future__ import annotations -from chatkit.widgets import WidgetRoot +from chatkit.widgets import WidgetRoot, WidgetTemplate from pydantic import BaseModel, Field -from .widget_template import WidgetTemplate - class CatNameSuggestion(BaseModel): """Name idea paired with a short blurb describing the cat it fits.""" diff --git a/examples/cat-lounge/backend/app/widgets/profile_card_widget.py b/examples/cat-lounge/backend/app/widgets/profile_card_widget.py index d03c892..b3bcfc2 100644 --- a/examples/cat-lounge/backend/app/widgets/profile_card_widget.py +++ b/examples/cat-lounge/backend/app/widgets/profile_card_widget.py @@ -5,10 +5,9 @@ from __future__ import annotations -from chatkit.widgets import WidgetRoot +from chatkit.widgets import WidgetRoot, WidgetTemplate from ..cat_state import CatState -from .widget_template import WidgetTemplate cat_profile_widget_template = WidgetTemplate.from_file("cat_profile.widget") diff --git a/examples/cat-lounge/backend/app/widgets/widget_template.py b/examples/cat-lounge/backend/app/widgets/widget_template.py deleted file mode 100644 index aa30a0e..0000000 --- a/examples/cat-lounge/backend/app/widgets/widget_template.py +++ /dev/null @@ -1,48 +0,0 @@ -import inspect -import json -from pathlib import Path -from typing import Any, TypeVar - -from chatkit.widgets import WidgetRoot -from jinja2 import Environment, StrictUndefined -from pydantic import BaseModel, TypeAdapter - -T = TypeVar("T", bound=BaseModel) -env = Environment(undefined=StrictUndefined) - - -class WidgetTemplate: - """Utility for loading and building widgets from a .widget file.""" - - adapter: TypeAdapter[WidgetRoot] = TypeAdapter(WidgetRoot) - - def __init__(self, definition: dict[str, Any]): - self.version = definition["version"] - if self.version != "1.0": - raise ValueError(f"Unsupported widget spec version: {self.version}") - - self.name = definition["name"] - self.template = env.from_string(definition["template"]) - self.data_schema = definition.get("jsonSchema", {}) - - @classmethod - def from_file(cls, file_path: str) -> "WidgetTemplate": - path = Path(file_path) - if not path.is_absolute(): - caller_frame = inspect.stack()[1] - caller_path = Path(caller_frame.filename).resolve() - path = caller_path.parent / path - - with path.open("r", encoding="utf-8") as file: - payload = json.load(file) - - return cls(payload) - - def build(self, data: dict[str, Any] | T | None = None) -> WidgetRoot: - if data is None: - data = {} - if isinstance(data, BaseModel): - data = data.model_dump() - rendered = self.template.render(**data) - widget_dict = json.loads(rendered) - return self.adapter.validate_python(widget_dict) diff --git a/examples/cat-lounge/backend/pyproject.toml b/examples/cat-lounge/backend/pyproject.toml index 651fba8..ef421fb 100644 --- a/examples/cat-lounge/backend/pyproject.toml +++ b/examples/cat-lounge/backend/pyproject.toml @@ -8,7 +8,7 @@ dependencies = [ "fastapi>=0.114.1,<0.116", "uvicorn[standard]>=0.36,<0.37", "openai>=1.40", - "openai-chatkit>=1.1.2,<2", + "openai-chatkit>=1.4.0,<2", "jinja2", ] diff --git a/examples/cat-lounge/backend/uv.lock b/examples/cat-lounge/backend/uv.lock index b9673cc..0e4cada 100644 --- a/examples/cat-lounge/backend/uv.lock +++ b/examples/cat-lounge/backend/uv.lock @@ -120,7 +120,7 @@ requires-dist = [ { name = "jinja2" }, { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.8,<2" }, { name = "openai", specifier = ">=1.40" }, - { name = "openai-chatkit", specifier = ">=1.1.2,<2" }, + { name = "openai-chatkit", specifier = ">=1.4.0,<2" }, { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.6.4,<0.7" }, { name = "uvicorn", extras = ["standard"], specifier = ">=0.36,<0.37" }, ] @@ -548,17 +548,18 @@ wheels = [ [[package]] name = "openai-chatkit" -version = "1.1.2" +version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "jinja2" }, { name = "openai" }, { name = "openai-agents" }, { name = "pydantic" }, { name = "uvicorn" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/36/cc/d395cfb7db9ac2b677c70a95483cf28f5b0c1de79b66e079e1c634d31a69/openai_chatkit-1.1.2.tar.gz", hash = "sha256:53d783ced5460be7adbd65b9a966ace969576cc7361171e511130ff576f4a61c", size = 49635, upload-time = "2025-11-07T22:15:35.362Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/89/bf2f094997c8e5cad5334e8a02e05fc458823e65fb2675f45b56b6d1ab73/openai_chatkit-1.4.0.tar.gz", hash = "sha256:e2527dffc3794a05596ad75efa66bdc4efb4ded5a77a013a55496cc989bcf2e6", size = 55269, upload-time = "2025-11-25T21:02:58.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/38/15e5651407cf81548a0549498f028127d81e7e985e18a7228e575d48dece/openai_chatkit-1.1.2-py3-none-any.whl", hash = "sha256:402d304b880be8d6b26e291484de62420e5f25d2c9fc3070b6807e840eb9e158", size = 35352, upload-time = "2025-11-07T22:15:33.987Z" }, + { url = "https://files.pythonhosted.org/packages/90/bf/68d42561dd8a674b6f8541d879dd165b5ac4d81fcf1027462e154de66a4f/openai_chatkit-1.4.0-py3-none-any.whl", hash = "sha256:35d00ca8398908bd70d63e2284adcd836641cc11746f68d7cfa91d276e3dad3d", size = 39077, upload-time = "2025-11-25T21:02:57.288Z" }, ] [[package]] diff --git a/examples/cat-lounge/frontend/package-lock.json b/examples/cat-lounge/frontend/package-lock.json index eac516d..80302cf 100644 --- a/examples/cat-lounge/frontend/package-lock.json +++ b/examples/cat-lounge/frontend/package-lock.json @@ -8,7 +8,7 @@ "name": "chatkit-frontend", "version": "0.1.0", "dependencies": { - "@openai/chatkit-react": "^1.0.0", + "@openai/chatkit-react": "^1.3.0", "canvas-confetti": "^1.9.4", "lucide-react": "^0.544.0", "react": "^19.2.0", @@ -785,16 +785,18 @@ } }, "node_modules/@openai/chatkit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@openai/chatkit/-/chatkit-1.0.1.tgz", - "integrity": "sha512-zU86yKX2wW/L0M6Tva30VKod4Djhq24BXEyDXr7aH1G/bJrgpNUjdinQ8VK41eJjwEdwDZlxJyq7o0JUTWgSOg==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@openai/chatkit/-/chatkit-1.1.0.tgz", + "integrity": "sha512-nLFX/syBdrKh+puKFlfUwSb4/t0F55ODrQNbHRV5/EeOhk4dX/uI8ZOA2GWuMEBVp2App9exx0KNMJiAjJ78ew==", + "license": "MIT" }, "node_modules/@openai/chatkit-react": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@openai/chatkit-react/-/chatkit-react-1.2.0.tgz", - "integrity": "sha512-qk466KfPuCh7gCU0Qqc6PygekV5eMitn4JE8P2XcS8U7aFMNYrS74zYXmJ2xBhugAiuYMycBC0kFiCaxtmVwXQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@openai/chatkit-react/-/chatkit-react-1.3.0.tgz", + "integrity": "sha512-nl/F8mh2uOUcbT8iCIh4+EWg2eRLdunAlNCEpEl0EEM0zakqsTdgFp6c2ttIE4yaHC3CpZwbCRRDU2o1akdQWg==", + "license": "MIT", "dependencies": { - "@openai/chatkit": "1.0.1" + "@openai/chatkit": "1.1.0" }, "peerDependencies": { "react": ">=18", diff --git a/examples/cat-lounge/frontend/package.json b/examples/cat-lounge/frontend/package.json index a4598e0..ed52d5e 100644 --- a/examples/cat-lounge/frontend/package.json +++ b/examples/cat-lounge/frontend/package.json @@ -14,7 +14,7 @@ "npm": ">=9" }, "dependencies": { - "@openai/chatkit-react": "^1.0.0", + "@openai/chatkit-react": "^1.3.0", "canvas-confetti": "^1.9.4", "lucide-react": "^0.544.0", "react": "^19.2.0", diff --git a/examples/metro-map/backend/app/widgets/line_select_widget.py b/examples/metro-map/backend/app/widgets/line_select_widget.py index 6775991..ba2135a 100644 --- a/examples/metro-map/backend/app/widgets/line_select_widget.py +++ b/examples/metro-map/backend/app/widgets/line_select_widget.py @@ -4,10 +4,9 @@ from __future__ import annotations -from chatkit.widgets import WidgetRoot +from chatkit.widgets import WidgetRoot, WidgetTemplate from ..data.metro_map_store import Line -from .widget_template import WidgetTemplate line_select_widget_template = WidgetTemplate.from_file("line_select.widget") diff --git a/examples/metro-map/backend/app/widgets/widget_template.py b/examples/metro-map/backend/app/widgets/widget_template.py deleted file mode 100644 index aa30a0e..0000000 --- a/examples/metro-map/backend/app/widgets/widget_template.py +++ /dev/null @@ -1,48 +0,0 @@ -import inspect -import json -from pathlib import Path -from typing import Any, TypeVar - -from chatkit.widgets import WidgetRoot -from jinja2 import Environment, StrictUndefined -from pydantic import BaseModel, TypeAdapter - -T = TypeVar("T", bound=BaseModel) -env = Environment(undefined=StrictUndefined) - - -class WidgetTemplate: - """Utility for loading and building widgets from a .widget file.""" - - adapter: TypeAdapter[WidgetRoot] = TypeAdapter(WidgetRoot) - - def __init__(self, definition: dict[str, Any]): - self.version = definition["version"] - if self.version != "1.0": - raise ValueError(f"Unsupported widget spec version: {self.version}") - - self.name = definition["name"] - self.template = env.from_string(definition["template"]) - self.data_schema = definition.get("jsonSchema", {}) - - @classmethod - def from_file(cls, file_path: str) -> "WidgetTemplate": - path = Path(file_path) - if not path.is_absolute(): - caller_frame = inspect.stack()[1] - caller_path = Path(caller_frame.filename).resolve() - path = caller_path.parent / path - - with path.open("r", encoding="utf-8") as file: - payload = json.load(file) - - return cls(payload) - - def build(self, data: dict[str, Any] | T | None = None) -> WidgetRoot: - if data is None: - data = {} - if isinstance(data, BaseModel): - data = data.model_dump() - rendered = self.template.render(**data) - widget_dict = json.loads(rendered) - return self.adapter.validate_python(widget_dict) diff --git a/examples/metro-map/backend/pyproject.toml b/examples/metro-map/backend/pyproject.toml index 8ad1e58..bc2e239 100644 --- a/examples/metro-map/backend/pyproject.toml +++ b/examples/metro-map/backend/pyproject.toml @@ -8,8 +8,8 @@ dependencies = [ "fastapi>=0.114.1,<0.116", "uvicorn[standard]>=0.36,<0.37", "openai>=1.40", - "openai-chatkit>=1.1.2,<2", - "Jinja2>=3.1,<4", + "openai-chatkit>=1.4.0,<2", + "jinja2>=3.1,<4", ] [project.optional-dependencies] diff --git a/examples/metro-map/backend/uv.lock b/examples/metro-map/backend/uv.lock index b39672b..83c65a1 100644 --- a/examples/metro-map/backend/uv.lock +++ b/examples/metro-map/backend/uv.lock @@ -120,7 +120,7 @@ requires-dist = [ { name = "jinja2", specifier = ">=3.1,<4" }, { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.8,<2" }, { name = "openai", specifier = ">=1.40" }, - { name = "openai-chatkit", specifier = ">=1.1.2,<2" }, + { name = "openai-chatkit", specifier = ">=1.4.0,<2" }, { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.6.4,<0.7" }, { name = "uvicorn", extras = ["standard"], specifier = ">=0.36,<0.37" }, ] @@ -548,17 +548,18 @@ wheels = [ [[package]] name = "openai-chatkit" -version = "1.1.2" +version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "jinja2" }, { name = "openai" }, { name = "openai-agents" }, { name = "pydantic" }, { name = "uvicorn" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/36/cc/d395cfb7db9ac2b677c70a95483cf28f5b0c1de79b66e079e1c634d31a69/openai_chatkit-1.1.2.tar.gz", hash = "sha256:53d783ced5460be7adbd65b9a966ace969576cc7361171e511130ff576f4a61c", size = 49635, upload-time = "2025-11-07T22:15:35.362Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/89/bf2f094997c8e5cad5334e8a02e05fc458823e65fb2675f45b56b6d1ab73/openai_chatkit-1.4.0.tar.gz", hash = "sha256:e2527dffc3794a05596ad75efa66bdc4efb4ded5a77a013a55496cc989bcf2e6", size = 55269, upload-time = "2025-11-25T21:02:58.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/38/15e5651407cf81548a0549498f028127d81e7e985e18a7228e575d48dece/openai_chatkit-1.1.2-py3-none-any.whl", hash = "sha256:402d304b880be8d6b26e291484de62420e5f25d2c9fc3070b6807e840eb9e158", size = 35352, upload-time = "2025-11-07T22:15:33.987Z" }, + { url = "https://files.pythonhosted.org/packages/90/bf/68d42561dd8a674b6f8541d879dd165b5ac4d81fcf1027462e154de66a4f/openai_chatkit-1.4.0-py3-none-any.whl", hash = "sha256:35d00ca8398908bd70d63e2284adcd836641cc11746f68d7cfa91d276e3dad3d", size = 39077, upload-time = "2025-11-25T21:02:57.288Z" }, ] [[package]] diff --git a/examples/metro-map/frontend/package.json b/examples/metro-map/frontend/package.json index c3dc4c1..5efa1ec 100644 --- a/examples/metro-map/frontend/package.json +++ b/examples/metro-map/frontend/package.json @@ -14,7 +14,7 @@ "npm": ">=9" }, "dependencies": { - "@openai/chatkit-react": "^1.0.0", + "@openai/chatkit-react": "^1.3.0", "clsx": "^2.1.1", "lucide-react": "^0.544.0", "react": "^19.2.0",