codemie-sdk-python 0.1.697__tar.gz → 0.1.699__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/PKG-INFO +16 -10
  2. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/README.md +5 -6
  3. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/pyproject.toml +8 -5
  4. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/__init__.py +6 -1
  5. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/assistant.py +109 -1
  6. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/conversation.py +3 -3
  7. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/assistant.py +183 -0
  8. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/conversation.py +2 -2
  9. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/customer_config_service.py +1 -1
  10. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/auth/__init__.py +0 -0
  11. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/auth/credentials.py +0 -0
  12. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/builders/__init__.py +0 -0
  13. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/builders/workflow/__init__.py +0 -0
  14. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/builders/workflow/builder.py +0 -0
  15. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/builders/workflow/definition.py +0 -0
  16. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/builders/workflow/publish.py +0 -0
  17. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/client/__init__.py +0 -0
  18. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/client/client.py +0 -0
  19. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/exceptions.py +0 -0
  20. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/__init__.py +0 -0
  21. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/a2a.py +0 -0
  22. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/activity_event.py +0 -0
  23. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/admin.py +0 -0
  24. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/analytics.py +0 -0
  25. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/categories.py +0 -0
  26. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/common.py +0 -0
  27. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/cost_center.py +0 -0
  28. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/datasource.py +0 -0
  29. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/errors.py +0 -0
  30. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/file_operation.py +0 -0
  31. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/guardrails.py +0 -0
  32. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/integration.py +0 -0
  33. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/llm.py +0 -0
  34. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/mcp_config.py +0 -0
  35. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/mermaid.py +0 -0
  36. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/project.py +0 -0
  37. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/skill.py +0 -0
  38. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/task.py +0 -0
  39. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/user.py +0 -0
  40. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/vendor_assistant.py +0 -0
  41. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/vendor_guardrail.py +0 -0
  42. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/vendor_knowledgebase.py +0 -0
  43. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/vendor_runtime.py +0 -0
  44. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/vendor_workflow.py +0 -0
  45. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/workflow.py +0 -0
  46. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/workflow_execution_payload.py +0 -0
  47. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/workflow_state.py +0 -0
  48. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/workflow_thoughts.py +0 -0
  49. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/workflow_transition.py +0 -0
  50. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/models/workspace.py +0 -0
  51. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/a2a.py +0 -0
  52. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/activity_event.py +0 -0
  53. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/admin.py +0 -0
  54. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/analytics.py +0 -0
  55. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/categories.py +0 -0
  56. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/codemie_guardrails.py +0 -0
  57. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/cost_center.py +0 -0
  58. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/datasource.py +0 -0
  59. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/dynamic_config.py +0 -0
  60. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/files.py +0 -0
  61. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/integration.py +0 -0
  62. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/llm.py +0 -0
  63. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/mcp_configs.py +0 -0
  64. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/mermaid.py +0 -0
  65. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/project.py +0 -0
  66. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/project_budget_groups.py +0 -0
  67. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/skill.py +0 -0
  68. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/task.py +0 -0
  69. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/user.py +0 -0
  70. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/vendor_assistant.py +0 -0
  71. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/vendor_guardrail.py +0 -0
  72. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/vendor_knowledgebase.py +0 -0
  73. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/vendor_runtime.py +0 -0
  74. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/vendor_workflow.py +0 -0
  75. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/webhook.py +0 -0
  76. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/workflow.py +0 -0
  77. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/workflow_execution.py +0 -0
  78. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/workflow_execution_state.py +0 -0
  79. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/services/workspace.py +0 -0
  80. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/utils/__init__.py +0 -0
  81. {codemie_sdk_python-0.1.697 → codemie_sdk_python-0.1.699}/src/codemie_sdk/utils/http.py +0 -0
@@ -1,15 +1,22 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: codemie-sdk-python
3
- Version: 0.1.697
3
+ Version: 0.1.699
4
4
  Summary: CodeMie SDK for Python
5
- Author: Vadym Vlasenko
6
- Author-email: vadym_vlasenko@epam.com
5
+ License: Apache-2.0
6
+ Author: CodeMie
7
7
  Requires-Python: >=3.12,<4.0
8
+ Classifier: License :: OSI Approved :: Apache Software License
8
9
  Classifier: Programming Language :: Python :: 3
9
10
  Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Classifier: Programming Language :: Python :: 3.15
10
14
  Requires-Dist: pydantic (>=2.12.2,<3.0.0)
11
15
  Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
12
16
  Requires-Dist: requests (>=2.31.0,<3.0.0)
17
+ Project-URL: Homepage, https://github.com/codemie-ai/codemie-sdk
18
+ Project-URL: Issues, https://github.com/codemie-ai/codemie-sdk/issues
19
+ Project-URL: Repository, https://github.com/codemie-ai/codemie-sdk
13
20
  Description-Content-Type: text/markdown
14
21
 
15
22
  # CodeMie Python SDK
@@ -87,11 +94,11 @@ from codemie_sdk import CodeMieClient
87
94
 
88
95
  # Initialize client with authentication parameters
89
96
  client = CodeMieClient(
90
- auth_server_url="https://keycloak.eks-core.aws.main.edp.projects.epam.com/auth",
97
+ auth_server_url="https://your-keycloak-host.example.com/auth",
91
98
  auth_client_id="your-client-id",
92
99
  auth_client_secret="your-client-secret",
93
100
  auth_realm_name="your-realm",
94
- codemie_api_domain="https://codemie.lab.epam.com/code-assistant-api"
101
+ codemie_api_domain="https://your-codemie-host.example.com/code-assistant-api"
95
102
  )
96
103
  ```
97
104
 
@@ -1662,7 +1669,7 @@ client = CodeMieClient(
1662
1669
 
1663
1670
  ## Support
1664
1671
 
1665
- For providing credentials please contact AI/Run CodeMie Team: Vadym_Vlasenko@epam.com or Nikita_Levyankov@epam.com
1672
+ For questions and bug reports, open an issue via GitHub Issues. To report a security vulnerability, follow the policy in [SECURITY.md](../../SECURITY.md).
1666
1673
 
1667
1674
  ## Development
1668
1675
 
@@ -1693,7 +1700,6 @@ poetry run ruff format
1693
1700
  # Build package
1694
1701
  poetry build
1695
1702
  # Or make build
1696
-
1697
- # Publish to PyPI
1698
- make publish
1699
1703
  ```
1704
+
1705
+ Maintainers publish releases through the release workflow. See [RELEASING.md](../../docs/RELEASING.md).
@@ -73,11 +73,11 @@ from codemie_sdk import CodeMieClient
73
73
 
74
74
  # Initialize client with authentication parameters
75
75
  client = CodeMieClient(
76
- auth_server_url="https://keycloak.eks-core.aws.main.edp.projects.epam.com/auth",
76
+ auth_server_url="https://your-keycloak-host.example.com/auth",
77
77
  auth_client_id="your-client-id",
78
78
  auth_client_secret="your-client-secret",
79
79
  auth_realm_name="your-realm",
80
- codemie_api_domain="https://codemie.lab.epam.com/code-assistant-api"
80
+ codemie_api_domain="https://your-codemie-host.example.com/code-assistant-api"
81
81
  )
82
82
  ```
83
83
 
@@ -1648,7 +1648,7 @@ client = CodeMieClient(
1648
1648
 
1649
1649
  ## Support
1650
1650
 
1651
- For providing credentials please contact AI/Run CodeMie Team: Vadym_Vlasenko@epam.com or Nikita_Levyankov@epam.com
1651
+ For questions and bug reports, open an issue via GitHub Issues. To report a security vulnerability, follow the policy in [SECURITY.md](../../SECURITY.md).
1652
1652
 
1653
1653
  ## Development
1654
1654
 
@@ -1679,7 +1679,6 @@ poetry run ruff format
1679
1679
  # Build package
1680
1680
  poetry build
1681
1681
  # Or make build
1682
+ ```
1682
1683
 
1683
- # Publish to PyPI
1684
- make publish
1685
- ```
1684
+ Maintainers publish releases through the release workflow. See [RELEASING.md](../../docs/RELEASING.md).
@@ -1,15 +1,19 @@
1
1
  [tool.poetry]
2
2
  name = "codemie-sdk-python"
3
- version = "0.1.697"
3
+ version = "0.1.699"
4
4
  description = "CodeMie SDK for Python"
5
- authors = [
6
- "Vadym Vlasenko <vadym_vlasenko@epam.com>",
7
- ]
5
+ authors = ["CodeMie"]
6
+ license = "Apache-2.0"
7
+ homepage = "https://github.com/codemie-ai/codemie-sdk"
8
+ repository = "https://github.com/codemie-ai/codemie-sdk"
8
9
  readme = "README.md"
9
10
  packages = [
10
11
  { include = "codemie_sdk", from="src"}
11
12
  ]
12
13
 
14
+ [tool.poetry.urls]
15
+ Issues = "https://github.com/codemie-ai/codemie-sdk/issues"
16
+
13
17
  [tool.poetry.dependencies]
14
18
  python = "^3.12"
15
19
  requests = "^2.31.0"
@@ -29,7 +33,6 @@ python-gitlab = "^5.6.0"
29
33
  boto3 = "^1.39.8"
30
34
  aws-assume-role-lib = "^2.10.0"
31
35
  codemie-plugins = "^0.1.123"
32
- pytest-reportportal = "^5.5.2"
33
36
  pytest-playwright = "^0.7.0"
34
37
  tzlocal = "^5.3.1"
35
38
 
@@ -17,6 +17,8 @@ Basic usage:
17
17
  >>> assistants = client.assistants.list()
18
18
  """
19
19
 
20
+ from importlib.metadata import PackageNotFoundError, version as _pkg_version
21
+
20
22
  from .client.client import CodeMieClient
21
23
  from .models.vendor_assistant import (
22
24
  VendorType,
@@ -174,7 +176,10 @@ from .models.a2a import (
174
176
  )
175
177
  from .services.a2a import A2AService
176
178
 
177
- __version__ = "0.2.12"
179
+ try:
180
+ __version__ = _pkg_version("codemie-sdk-python")
181
+ except PackageNotFoundError: # running from a source tree that is not installed
182
+ __version__ = "0+unknown"
178
183
  __all__ = [
179
184
  "CodeMieClient",
180
185
  "VendorType",
@@ -456,7 +456,7 @@ class ToolConfig(BaseModel):
456
456
  At least one of these fields must be specified for the tool configuration
457
457
  to be valid. This ensures that the tool has a way to obtain credentials.
458
458
  """
459
- if not self.tool_creds and not self.integration_id:
459
+ if not self.tool_creds and self.integration_id is None:
460
460
  raise ValueError("Either tool_creds or integration_id must be provided")
461
461
  if self.tool_creds and self.integration_id:
462
462
  raise ValueError(
@@ -652,3 +652,111 @@ class ReactionRequest(BaseModel):
652
652
  model_config = ConfigDict(extra="ignore", use_enum_values=True)
653
653
 
654
654
  reaction: ReactionType = Field(description="Reaction type: 'like' or 'dislike'")
655
+
656
+
657
+ class AssistantProjectFeature(str, Enum):
658
+ """Feature discriminator for assistant/project mappings (e.g. Teams bot).
659
+
660
+ This enum is expected to grow over time on the backend; treat unrecognized
661
+ wire values defensively rather than assuming this is the complete set.
662
+ """
663
+
664
+ TEAMS = "teams"
665
+
666
+
667
+ class AssistantProjectMappingRequest(BaseModel):
668
+ """Request body for POST /v1/assistants/{assistant_id}/projects/mapping."""
669
+
670
+ model_config = ConfigDict(extra="ignore", use_enum_values=True)
671
+
672
+ project_name: str = Field(description="Project (application) name")
673
+ feature: AssistantProjectFeature = Field(
674
+ description="Feature discriminator this mapping is for, e.g. 'teams'"
675
+ )
676
+
677
+
678
+ class AssistantProjectMappingPagination(BaseModel):
679
+ """Pagination metadata returned by GET /v1/assistants/projects/mapping."""
680
+
681
+ model_config = ConfigDict(extra="ignore")
682
+
683
+ page: int = Field(description="Current page, 0-indexed")
684
+ per_page: int = Field(description="Items per page")
685
+ total: int = Field(description="Total matching assistants across all pages")
686
+
687
+
688
+ class AssistantProjectMappingListResponse(BaseModel):
689
+ """Response for GET /v1/assistants/projects/mapping.
690
+
691
+ List items are intentionally typed as ``dict[str, Any]`` rather than
692
+ ``Assistant``/``AssistantBase``. The backend contract documents this
693
+ endpoint as returning "the same shape as GET /v1/assistants", but that
694
+ endpoint's own shape is parameterized by a ``minimal_response`` flag that
695
+ this new endpoint does not expose, and the exact per-item fields returned
696
+ here are not otherwise confirmed. Rather than guess the wire format,
697
+ callers get the raw dict and can assert on whichever fields they need
698
+ (e.g. ``item["id"]``).
699
+ """
700
+
701
+ model_config = ConfigDict(extra="ignore")
702
+
703
+ data: list[dict[str, Any]] = Field(default_factory=list)
704
+ pagination: AssistantProjectMappingPagination
705
+
706
+
707
+ class UserMappingSlotConfig(BaseModel):
708
+ """Configuration for a single integration slot in user mapping."""
709
+
710
+ model_config = ConfigDict(extra="ignore")
711
+
712
+ name: str = Field(description="Integration slot name (tool name, e.g. 'Git')")
713
+ integration_id: Optional[str] = Field(
714
+ default=None,
715
+ description="Integration ID. None = auto-lookup; empty string = explicit 'no integration'",
716
+ )
717
+ auto_lookup: Optional[bool] = Field(
718
+ default=None,
719
+ description="Whether auto-credentials lookup is enabled for this slot",
720
+ )
721
+ explicit_none: Optional[bool] = Field(
722
+ default=None,
723
+ description="User explicitly chose no integration, blocking auto-lookup override",
724
+ )
725
+
726
+
727
+ class UserMappingSaveRequest(BaseModel):
728
+ """Request body for POST /v1/assistants/{assistant_id}/users/mapping."""
729
+
730
+ model_config = ConfigDict(extra="ignore")
731
+
732
+ tools_config: List[UserMappingSlotConfig] = Field(
733
+ default_factory=list,
734
+ description="Slot configurations to save",
735
+ )
736
+ workflow_id: Optional[str] = Field(
737
+ default=None,
738
+ description="Workflow scope reference. None = assistant scope",
739
+ )
740
+ apply_to_assistant_scope: bool = Field(
741
+ default=False,
742
+ description="When True, saves at assistant scope and removes workflow-scoped override",
743
+ )
744
+
745
+
746
+ class UserMappingResponse(BaseModel):
747
+ """Response body for GET /v1/assistants/{assistant_id}/users/mapping."""
748
+
749
+ model_config = ConfigDict(extra="ignore")
750
+
751
+ tools_config: List[UserMappingSlotConfig] = Field(
752
+ default_factory=list,
753
+ description="Current effective slot configurations",
754
+ )
755
+ has_assistant_scope_selection: bool = Field(
756
+ default=False,
757
+ description="Whether an assistant-scoped mapping row exists for this user",
758
+ )
759
+ workflow_id: Optional[str] = Field(
760
+ default=None,
761
+ description="Workflow scope the response is effective for",
762
+ )
@@ -92,7 +92,7 @@ class HistoryItem(BaseModel):
92
92
  thoughts: list[Thought] | None = Field(default_factory=list)
93
93
  workflowExecutionRef: str | bool | None = None
94
94
  executionId: str | None = None
95
- # WorkflowExecutionStatusEnum value, e.g. "In Progress" (EPMCDME-14075)
95
+ # WorkflowExecutionStatusEnum value, e.g. "In Progress"
96
96
  executionStatus: str | None = None
97
97
 
98
98
 
@@ -322,7 +322,7 @@ class AdminConversationListResponse(BaseModel):
322
322
  pagination: ConversationPagination
323
323
 
324
324
 
325
- # Feedback on assistant messages (EPMCDME-14625)
325
+ # Feedback on assistant messages
326
326
 
327
327
 
328
328
  class FeedbackMark(str, Enum):
@@ -345,7 +345,7 @@ class FeedbackCreateRequest(BaseModel):
345
345
 
346
346
  ``response`` is required by the backend even though the client already has
347
347
  the text elsewhere: omitting it returns a 422 ``response: Field required``
348
- error. This was the root cause of EPMCDME-14625, where the frontend built
348
+ error. This was the root cause of an earlier bug, where the frontend built
349
349
  the payload without it and negative feedback could never be submitted.
350
350
  Callers must always populate ``response`` -- an empty string is a valid
351
351
  value for incomplete, failed, or technical-error assistant responses.
@@ -29,8 +29,12 @@ from ..models.assistant import (
29
29
  AssistantEvaluationRequest,
30
30
  ReactionRequest,
31
31
  ToolCallResumeRequest,
32
+ AssistantProjectFeature,
33
+ AssistantProjectMappingListResponse,
34
+ AssistantProjectMappingRequest,
32
35
  )
33
36
  from ..models.common import PaginationParams
37
+ from ..models.conversation import BaseResponse
34
38
  from ..utils import ApiRequestHandler, TokenSource
35
39
 
36
40
 
@@ -644,3 +648,182 @@ class AssistantService:
644
648
  Response from the API
645
649
  """
646
650
  return self._api.delete(f"/v1/assistants/{assistant_id}/reactions", dict)
651
+
652
+ def list_project_mapping(
653
+ self,
654
+ project_name: str,
655
+ feature: AssistantProjectFeature = AssistantProjectFeature.TEAMS,
656
+ page: int = 0,
657
+ per_page: int = 12,
658
+ ) -> AssistantProjectMappingListResponse:
659
+ """List assistants enabled for a project feature (e.g. Teams bot).
660
+
661
+ Accessible to any member of ``project_name``, not just project admins.
662
+
663
+ Args:
664
+ project_name: Project (application) name to list mappings for
665
+ feature: Feature discriminator, currently only "teams"
666
+ page: Page number, 0-indexed
667
+ per_page: Items per page (default 12, max 10000)
668
+
669
+ Returns:
670
+ Paginated list of assistants enabled for the project feature
671
+ """
672
+ feature_value = (
673
+ feature.value if isinstance(feature, AssistantProjectFeature) else feature
674
+ )
675
+ params = PaginationParams(page=page, per_page=per_page).to_dict()
676
+ params["feature"] = feature_value
677
+ params["project"] = project_name
678
+ return self._api.get(
679
+ "/v1/assistants/projects/mapping",
680
+ AssistantProjectMappingListResponse,
681
+ params=params,
682
+ wrap_response=False,
683
+ )
684
+
685
+ def enable_for_project(
686
+ self,
687
+ assistant_id: str,
688
+ project_name: str,
689
+ feature: AssistantProjectFeature = AssistantProjectFeature.TEAMS,
690
+ ) -> BaseResponse:
691
+ """Enable an assistant for a project feature (e.g. Teams bot).
692
+
693
+ Idempotent — calling this when the mapping already exists returns 200
694
+ with no error. Requires the caller to be a project admin/maintainer
695
+ (or application admin) for ``project_name``.
696
+
697
+ Args:
698
+ assistant_id: ID of the assistant to enable
699
+ project_name: Project (application) name to enable the mapping for
700
+ feature: Feature discriminator, currently only "teams"
701
+
702
+ Returns:
703
+ Response confirming the assistant was enabled
704
+ """
705
+ request = AssistantProjectMappingRequest(
706
+ project_name=project_name, feature=feature
707
+ )
708
+ return self._api.post(
709
+ f"/v1/assistants/{assistant_id}/projects/mapping",
710
+ BaseResponse,
711
+ json_data=request.model_dump(exclude_none=True),
712
+ )
713
+
714
+ def disable_for_project(
715
+ self,
716
+ assistant_id: str,
717
+ project_name: str,
718
+ feature: AssistantProjectFeature = AssistantProjectFeature.TEAMS,
719
+ ) -> BaseResponse:
720
+ """Disable an assistant for a project feature (e.g. Teams bot).
721
+
722
+ Raises an HTTP error (404) if the mapping does not exist. Requires the
723
+ caller to be a project admin/maintainer (or application admin) for
724
+ ``project_name``.
725
+
726
+ Args:
727
+ assistant_id: ID of the assistant to disable
728
+ project_name: Project (application) name to disable the mapping for
729
+ feature: Feature discriminator, currently only "teams"
730
+
731
+ Returns:
732
+ Response confirming the assistant was disabled
733
+ """
734
+ feature_value = (
735
+ feature.value if isinstance(feature, AssistantProjectFeature) else feature
736
+ )
737
+ params = {"project": project_name, "feature": feature_value}
738
+ return self._api.delete(
739
+ f"/v1/assistants/{assistant_id}/projects/mapping",
740
+ BaseResponse,
741
+ params=params,
742
+ )
743
+
744
+ def get_user_mapping(
745
+ self,
746
+ assistant_id: str,
747
+ workflow_id: Optional[str] = None,
748
+ ) -> dict:
749
+ """Get the effective personal integration mapping for an assistant.
750
+
751
+ Returns the merged per-slot view following the resolution order:
752
+ workflow-scoped → assistant-scoped → auto-lookup → none.
753
+
754
+ Args:
755
+ assistant_id: ID of the assistant
756
+ workflow_id: Optional workflow scope. When provided, returns the effective
757
+ selection for that workflow; when omitted, returns assistant-scoped only.
758
+
759
+ Returns:
760
+ Mapping response dict with ``tools_config`` list and
761
+ ``has_assistant_scope_selection`` boolean.
762
+ """
763
+ params: dict = {}
764
+ if workflow_id is not None:
765
+ params["workflow_id"] = workflow_id
766
+ return self._api.get(
767
+ f"/v1/assistants/{assistant_id}/users/mapping",
768
+ dict,
769
+ params=params or None,
770
+ )
771
+
772
+ def save_user_mapping(
773
+ self,
774
+ assistant_id: str,
775
+ tools_config: list,
776
+ workflow_id: Optional[str] = None,
777
+ apply_to_assistant_scope: bool = False,
778
+ ) -> dict:
779
+ """Save personal integration mapping for an assistant.
780
+
781
+ When ``workflow_id`` is supplied and ``apply_to_assistant_scope`` is False,
782
+ a workflow-scoped record is created/updated (the new default on workflow screens).
783
+ When ``apply_to_assistant_scope`` is True, the mapping is promoted to assistant
784
+ scope and any existing workflow-scoped override is removed atomically.
785
+
786
+ Args:
787
+ assistant_id: ID of the assistant
788
+ tools_config: List of slot configuration dicts (each with ``slot_id``
789
+ and optionally ``integration_id``)
790
+ workflow_id: Optional workflow scope reference
791
+ apply_to_assistant_scope: When True, saves at assistant scope
792
+
793
+ Returns:
794
+ Saved mapping response dict
795
+ """
796
+ payload: dict = {"tools_config": tools_config}
797
+ if workflow_id is not None:
798
+ payload["workflow_id"] = workflow_id
799
+ if apply_to_assistant_scope:
800
+ payload["apply_to_assistant_scope"] = True
801
+ return self._api.post(
802
+ f"/v1/assistants/{assistant_id}/users/mapping",
803
+ dict,
804
+ json_data=payload,
805
+ )
806
+
807
+ def delete_user_mapping(
808
+ self,
809
+ assistant_id: str,
810
+ workflow_id: Optional[str] = None,
811
+ ) -> dict:
812
+ """Delete personal integration mapping for an assistant.
813
+
814
+ Args:
815
+ assistant_id: ID of the assistant
816
+ workflow_id: When provided, deletes the workflow-scoped record only.
817
+ When omitted, deletes the assistant-scoped record.
818
+
819
+ Returns:
820
+ Response from the API
821
+ """
822
+ params: dict = {}
823
+ if workflow_id is not None:
824
+ params["workflow_id"] = workflow_id
825
+ return self._api.delete(
826
+ f"/v1/assistants/{assistant_id}/users/mapping",
827
+ dict,
828
+ params=params or None,
829
+ )
@@ -352,7 +352,7 @@ class ConversationService:
352
352
  SharedConversationResponse,
353
353
  )
354
354
 
355
- # Feedback management methods (EPMCDME-14625)
355
+ # Feedback management methods
356
356
 
357
357
  def create_feedback(self, request: FeedbackCreateRequest) -> FeedbackCreateResponse:
358
358
  """Submit like/dislike feedback on an assistant message.
@@ -385,7 +385,7 @@ class ConversationService:
385
385
  json_data=request.model_dump(by_alias=True, exclude_none=True),
386
386
  )
387
387
 
388
- # Conversation finishing (EPMCDME-11067)
388
+ # Conversation finishing
389
389
 
390
390
  def finish(self, conversation_id: str) -> ConversationFinishResponse:
391
391
  """Mark a conversation as finished (owner-only).
@@ -1,6 +1,6 @@
1
1
  """Customer config service implementation.
2
2
 
3
- Wraps four endpoints introduced in EPMCDME-13983:
3
+ Wraps four customer-config endpoints:
4
4
  GET /v1/config/declarations — list dynamic-config declarations (admin/maintainer)
5
5
  PUT /v1/config/declarations/{id} — save override settings for a component
6
6
  DELETE /v1/config/declarations/{id} — reset component to YAML default (idempotent)