Skip to content

refactor(api): type Tenant custom config with TypedDict and tighten MCP headers type#34670

Merged
asukaminato0721 merged 1 commit intolanggenius:mainfrom
YB0y:refactor/typed-dict-models-file-and-tools
Apr 7, 2026
Merged

refactor(api): type Tenant custom config with TypedDict and tighten MCP headers type#34670
asukaminato0721 merged 1 commit intolanggenius:mainfrom
YB0y:refactor/typed-dict-models-file-and-tools

Conversation

@YB0y
Copy link
Copy Markdown
Contributor

@YB0y YB0y commented Apr 7, 2026

Summary

  • Add TenantCustomConfigDict TypedDict (total=False) with keys remove_webapp_brand (bool) and replace_webapp_logo (str | None)
  • Annotate Tenant.custom_config_dict property and setter with TenantCustomConfigDict (was dict[str, Any])
  • Tighten MCPToolProvider.headers return type from dict[str, Any] to dict[str, str] (HTTP headers are string-valued)
  • Remove unused Any import from account.py

Why this change

Tenant.custom_config_dict stores workspace branding config with two well-known keys accessed by name across 4 call sites (remove_webapp_brand, replace_webapp_logo). The TypedDict makes this contract explicit.

MCPToolProvider.headers returns HTTP headers which are always str: strdict[str, Any] was overly broad.

Changes

  • models/account.py: Define TenantCustomConfigDict, update property/setter types
  • models/tools.py: Tighten headers return type to dict[str, str]

Test plan

  • ruff check passes

Part of #32863 (models/account.py, models/tools.py)

@YB0y YB0y requested a review from QuantumGhost as a code owner April 7, 2026 11:42
@dosubot dosubot Bot added size:S This PR changes 10-29 lines, ignoring generated files. refactor labels Apr 7, 2026
asukaminato0721
asukaminato0721 previously approved these changes Apr 7, 2026
@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Apr 7, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-04-07 11:43:28.297344380 +0000
+++ /tmp/pyrefly_pr.txt	2026-04-07 11:43:18.313505027 +0000
@@ -14,6 +14,8 @@
   --> controllers/console/setup.py:65:2
 ERROR Object of class `MissingRouter` has no attribute `get` [missing-attribute]
   --> controllers/console/version.py:30:2
+ERROR Argument `dict[str, bool | str | None]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+   --> controllers/console/workspace/workspace.py:250:37
 ERROR Class member `EasyUIBasedGenerateTaskPipeline._application_generate_entity` overrides parent class `BasedGenerateTaskPipeline` in an inconsistent manner [bad-override]
   --> core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py:75:5
 ERROR `+=` is not supported between `list[PromptMessageContentUnionTypes]` and `str` [unsupported-operation]
@@ -765,6 +767,14 @@
     --> tests/test_containers_integration_tests/services/test_account_service.py:1998:16
 ERROR Object of class `NoneType` has no attribute `id` [missing-attribute]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2144:16
+ERROR Argument `dict[str, dict[str, bool] | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2311:37
+ERROR TypedDict `TenantCustomConfigDict` does not have key `theme` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2319:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `language` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2320:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature_flags` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2321:33
 ERROR Argument `Literal['pending']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2854:35
 ERROR Argument `Literal['active']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
@@ -6133,6 +6143,12 @@
   --> tests/unit_tests/libs/test_token.py:29:37
 ERROR Argument `MockRequest` is not assignable to parameter `request` with type `Request` in function `libs.token.extract_webapp_access_token` [bad-argument-type]
   --> tests/unit_tests/libs/test_token.py:30:44
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature1` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:736:23
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature2` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:737:23
+ERROR Argument `dict[str, bool | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+   --> tests/unit_tests/models/test_account_models.py:758:37
 ERROR `None` is not subscriptable [unsupported-operation]
     --> tests/unit_tests/models/test_app_models.py:1293:20
 ERROR `None` is not subscriptable [unsupported-operation]

auto-merge was automatically disabled April 7, 2026 11:51

Head branch was pushed to by a user without write access

@YB0y YB0y force-pushed the refactor/typed-dict-models-file-and-tools branch from e86c96c to d13a157 Compare April 7, 2026 11:51
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-04-07 11:52:08.850509901 +0000
+++ /tmp/pyrefly_pr.txt	2026-04-07 11:51:59.804495742 +0000
@@ -14,6 +14,8 @@
   --> controllers/console/setup.py:65:2
 ERROR Object of class `MissingRouter` has no attribute `get` [missing-attribute]
   --> controllers/console/version.py:30:2
+ERROR `bool | None` is not assignable to TypedDict key `remove_webapp_brand` with type `bool` [bad-typed-dict-key]
+   --> controllers/console/workspace/workspace.py:244:36
 ERROR Class member `EasyUIBasedGenerateTaskPipeline._application_generate_entity` overrides parent class `BasedGenerateTaskPipeline` in an inconsistent manner [bad-override]
   --> core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py:75:5
 ERROR `+=` is not supported between `list[PromptMessageContentUnionTypes]` and `str` [unsupported-operation]
@@ -765,6 +767,14 @@
     --> tests/test_containers_integration_tests/services/test_account_service.py:1998:16
 ERROR Object of class `NoneType` has no attribute `id` [missing-attribute]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2144:16
+ERROR Argument `dict[str, dict[str, bool] | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2311:37
+ERROR TypedDict `TenantCustomConfigDict` does not have key `theme` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2319:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `language` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2320:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature_flags` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2321:33
 ERROR Argument `Literal['pending']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2854:35
 ERROR Argument `Literal['active']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
@@ -6133,6 +6143,12 @@
   --> tests/unit_tests/libs/test_token.py:29:37
 ERROR Argument `MockRequest` is not assignable to parameter `request` with type `Request` in function `libs.token.extract_webapp_access_token` [bad-argument-type]
   --> tests/unit_tests/libs/test_token.py:30:44
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature1` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:736:23
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature2` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:737:23
+ERROR Argument `dict[str, bool | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+   --> tests/unit_tests/models/test_account_models.py:758:37
 ERROR `None` is not subscriptable [unsupported-operation]
     --> tests/unit_tests/models/test_app_models.py:1293:20
 ERROR `None` is not subscriptable [unsupported-operation]

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-04-07 11:52:13.638230134 +0000
+++ /tmp/pyrefly_pr.txt	2026-04-07 11:52:04.956224355 +0000
@@ -14,6 +14,8 @@
   --> controllers/console/setup.py:65:2
 ERROR Object of class `MissingRouter` has no attribute `get` [missing-attribute]
   --> controllers/console/version.py:30:2
+ERROR `bool | None` is not assignable to TypedDict key `remove_webapp_brand` with type `bool` [bad-typed-dict-key]
+   --> controllers/console/workspace/workspace.py:244:36
 ERROR Class member `EasyUIBasedGenerateTaskPipeline._application_generate_entity` overrides parent class `BasedGenerateTaskPipeline` in an inconsistent manner [bad-override]
   --> core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py:75:5
 ERROR `+=` is not supported between `list[PromptMessageContentUnionTypes]` and `str` [unsupported-operation]
@@ -765,6 +767,14 @@
     --> tests/test_containers_integration_tests/services/test_account_service.py:1998:16
 ERROR Object of class `NoneType` has no attribute `id` [missing-attribute]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2144:16
+ERROR Argument `dict[str, dict[str, bool] | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2311:37
+ERROR TypedDict `TenantCustomConfigDict` does not have key `theme` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2319:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `language` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2320:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature_flags` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2321:33
 ERROR Argument `Literal['pending']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2854:35
 ERROR Argument `Literal['active']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
@@ -6133,6 +6143,12 @@
   --> tests/unit_tests/libs/test_token.py:29:37
 ERROR Argument `MockRequest` is not assignable to parameter `request` with type `Request` in function `libs.token.extract_webapp_access_token` [bad-argument-type]
   --> tests/unit_tests/libs/test_token.py:30:44
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature1` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:736:23
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature2` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:737:23
+ERROR Argument `dict[str, bool | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+   --> tests/unit_tests/models/test_account_models.py:758:37
 ERROR `None` is not subscriptable [unsupported-operation]
     --> tests/unit_tests/models/test_app_models.py:1293:20
 ERROR `None` is not subscriptable [unsupported-operation]

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-04-07 11:57:41.925715044 +0000
+++ /tmp/pyrefly_pr.txt	2026-04-07 11:57:32.267632639 +0000
@@ -14,6 +14,8 @@
   --> controllers/console/setup.py:65:2
 ERROR Object of class `MissingRouter` has no attribute `get` [missing-attribute]
   --> controllers/console/version.py:30:2
+ERROR `bool | None` is not assignable to TypedDict key `remove_webapp_brand` with type `bool` [bad-typed-dict-key]
+   --> controllers/console/workspace/workspace.py:244:36
 ERROR Class member `EasyUIBasedGenerateTaskPipeline._application_generate_entity` overrides parent class `BasedGenerateTaskPipeline` in an inconsistent manner [bad-override]
   --> core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py:75:5
 ERROR `+=` is not supported between `list[PromptMessageContentUnionTypes]` and `str` [unsupported-operation]
@@ -765,6 +767,14 @@
     --> tests/test_containers_integration_tests/services/test_account_service.py:1998:16
 ERROR Object of class `NoneType` has no attribute `id` [missing-attribute]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2144:16
+ERROR Argument `dict[str, dict[str, bool] | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2311:37
+ERROR TypedDict `TenantCustomConfigDict` does not have key `theme` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2319:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `language` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2320:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature_flags` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2321:33
 ERROR Argument `Literal['pending']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2854:35
 ERROR Argument `Literal['active']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
@@ -6133,6 +6143,12 @@
   --> tests/unit_tests/libs/test_token.py:29:37
 ERROR Argument `MockRequest` is not assignable to parameter `request` with type `Request` in function `libs.token.extract_webapp_access_token` [bad-argument-type]
   --> tests/unit_tests/libs/test_token.py:30:44
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature1` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:736:23
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature2` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:737:23
+ERROR Argument `dict[str, bool | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+   --> tests/unit_tests/models/test_account_models.py:758:37
 ERROR `None` is not subscriptable [unsupported-operation]
     --> tests/unit_tests/models/test_app_models.py:1293:20
 ERROR `None` is not subscriptable [unsupported-operation]

auto-merge was automatically disabled April 7, 2026 12:10

Head branch was pushed to by a user without write access

@YB0y YB0y force-pushed the refactor/typed-dict-models-file-and-tools branch from a5f4046 to 348f58b Compare April 7, 2026 12:10
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-04-07 12:11:07.054074220 +0000
+++ /tmp/pyrefly_pr.txt	2026-04-07 12:10:58.554135861 +0000
@@ -765,6 +765,14 @@
     --> tests/test_containers_integration_tests/services/test_account_service.py:1998:16
 ERROR Object of class `NoneType` has no attribute `id` [missing-attribute]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2144:16
+ERROR Argument `dict[str, dict[str, bool] | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2311:37
+ERROR TypedDict `TenantCustomConfigDict` does not have key `theme` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2319:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `language` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2320:33
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature_flags` [bad-typed-dict-key]
+    --> tests/test_containers_integration_tests/services/test_account_service.py:2321:33
 ERROR Argument `Literal['pending']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
     --> tests/test_containers_integration_tests/services/test_account_service.py:2854:35
 ERROR Argument `Literal['active']` is not assignable to parameter `value` with type `AccountStatus | SQLCoreOperations[AccountStatus]` in function `sqlalchemy.orm.base.Mapped.__set__` [bad-argument-type]
@@ -6133,6 +6141,12 @@
   --> tests/unit_tests/libs/test_token.py:29:37
 ERROR Argument `MockRequest` is not assignable to parameter `request` with type `Request` in function `libs.token.extract_webapp_access_token` [bad-argument-type]
   --> tests/unit_tests/libs/test_token.py:30:44
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature1` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:736:23
+ERROR TypedDict `TenantCustomConfigDict` does not have key `feature2` [bad-typed-dict-key]
+   --> tests/unit_tests/models/test_account_models.py:737:23
+ERROR Argument `dict[str, bool | str]` is not assignable to parameter `value` with type `TenantCustomConfigDict` in function `models.account.Tenant.custom_config_dict` [bad-argument-type]
+   --> tests/unit_tests/models/test_account_models.py:758:37
 ERROR `None` is not subscriptable [unsupported-operation]
     --> tests/unit_tests/models/test_app_models.py:1293:20
 ERROR `None` is not subscriptable [unsupported-operation]

@asukaminato0721 asukaminato0721 added this pull request to the merge queue Apr 7, 2026
Merged via the queue into langgenius:main with commit 485fc2c Apr 7, 2026
27 checks passed
@YB0y YB0y deleted the refactor/typed-dict-models-file-and-tools branch April 8, 2026 13:35
HanqingZ pushed a commit to HanqingZ/dify that referenced this pull request Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer refactor size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants