pyxecm 3.0.1__py3-none-any.whl → 3.1.1__py3-none-any.whl
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.
Potentially problematic release.
This version of pyxecm might be problematic. Click here for more details.
- pyxecm/avts.py +4 -4
- pyxecm/coreshare.py +14 -15
- pyxecm/helper/data.py +2 -1
- pyxecm/helper/web.py +11 -11
- pyxecm/helper/xml.py +41 -10
- pyxecm/otac.py +1 -1
- pyxecm/otawp.py +19 -19
- pyxecm/otca.py +878 -70
- pyxecm/otcs.py +1716 -349
- pyxecm/otds.py +332 -153
- pyxecm/otkd.py +4 -4
- pyxecm/otmm.py +1 -1
- pyxecm/otpd.py +246 -30
- {pyxecm-3.0.1.dist-info → pyxecm-3.1.1.dist-info}/METADATA +2 -1
- pyxecm-3.1.1.dist-info/RECORD +82 -0
- pyxecm_api/app.py +45 -35
- pyxecm_api/auth/functions.py +2 -2
- pyxecm_api/auth/router.py +2 -3
- pyxecm_api/common/functions.py +67 -12
- pyxecm_api/settings.py +0 -8
- pyxecm_api/terminal/router.py +1 -1
- pyxecm_api/v1_csai/router.py +33 -18
- pyxecm_customizer/browser_automation.py +161 -79
- pyxecm_customizer/customizer.py +43 -25
- pyxecm_customizer/guidewire.py +422 -8
- pyxecm_customizer/k8s.py +23 -27
- pyxecm_customizer/knowledge_graph.py +498 -20
- pyxecm_customizer/m365.py +45 -44
- pyxecm_customizer/payload.py +1723 -1188
- pyxecm_customizer/payload_list.py +3 -0
- pyxecm_customizer/salesforce.py +122 -79
- pyxecm_customizer/servicenow.py +27 -7
- pyxecm_customizer/settings.py +3 -1
- pyxecm_customizer/successfactors.py +2 -2
- pyxecm_customizer/translate.py +1 -1
- pyxecm-3.0.1.dist-info/RECORD +0 -96
- pyxecm_api/agents/__init__.py +0 -7
- pyxecm_api/agents/app.py +0 -13
- pyxecm_api/agents/functions.py +0 -119
- pyxecm_api/agents/models.py +0 -10
- pyxecm_api/agents/otcm_knowledgegraph/__init__.py +0 -1
- pyxecm_api/agents/otcm_knowledgegraph/functions.py +0 -85
- pyxecm_api/agents/otcm_knowledgegraph/models.py +0 -61
- pyxecm_api/agents/otcm_knowledgegraph/router.py +0 -74
- pyxecm_api/agents/otcm_user_agent/__init__.py +0 -1
- pyxecm_api/agents/otcm_user_agent/models.py +0 -20
- pyxecm_api/agents/otcm_user_agent/router.py +0 -65
- pyxecm_api/agents/otcm_workspace_agent/__init__.py +0 -1
- pyxecm_api/agents/otcm_workspace_agent/models.py +0 -40
- pyxecm_api/agents/otcm_workspace_agent/router.py +0 -200
- {pyxecm-3.0.1.dist-info → pyxecm-3.1.1.dist-info}/WHEEL +0 -0
- {pyxecm-3.0.1.dist-info → pyxecm-3.1.1.dist-info}/entry_points.txt +0 -0
pyxecm_api/agents/__init__.py
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"""init Module."""
|
|
2
|
-
|
|
3
|
-
from .otcm_knowledgegraph.router import router as otcm_knowledgegraph_router
|
|
4
|
-
from .otcm_user_agent.router import router as otcm_user_agent_router
|
|
5
|
-
from .otcm_workspace_agent.router import router as otcm_workspace_agent_router
|
|
6
|
-
|
|
7
|
-
__all__ = ["otcm_knowledgegraph_router", "otcm_user_agent_router", "otcm_workspace_agent_router"]
|
pyxecm_api/agents/app.py
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"""List of all routers for the csai agents."""
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
|
-
from fastapi import APIRouter
|
|
6
|
-
|
|
7
|
-
from . import otcm_knowledgegraph_router, otcm_user_agent_router, otcm_workspace_agent_router
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger("pyxecm_api.agents")
|
|
10
|
-
|
|
11
|
-
router = APIRouter(tags=["csai agents"])
|
|
12
|
-
|
|
13
|
-
agent_routers = [router, otcm_workspace_agent_router, otcm_user_agent_router, otcm_knowledgegraph_router]
|
pyxecm_api/agents/functions.py
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
"""List of all routers for the csai agents."""
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
from importlib.metadata import version
|
|
5
|
-
from threading import Thread
|
|
6
|
-
|
|
7
|
-
from fastapi.openapi.utils import get_openapi
|
|
8
|
-
from fastapi.routing import APIRoute
|
|
9
|
-
from pyxecm import OTCA, OTCS
|
|
10
|
-
from pyxecm_customizer.settings import Settings
|
|
11
|
-
|
|
12
|
-
from pyxecm_api.common.functions import get_k8s_object, get_otcs_object
|
|
13
|
-
|
|
14
|
-
logger = logging.getLogger("pyxecm_api.agents")
|
|
15
|
-
|
|
16
|
-
SETTINGS = Settings()
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def get_otca_object(otcs_object: OTCS | None = None) -> OTCA:
|
|
20
|
-
"""Get the OTCA object."""
|
|
21
|
-
|
|
22
|
-
k8s_object = get_k8s_object()
|
|
23
|
-
content_system = {}
|
|
24
|
-
for service in ["chat", "embed"]:
|
|
25
|
-
cm = k8s_object.get_config_map(f"csai-{service}-svc")
|
|
26
|
-
if cm:
|
|
27
|
-
content_system[service] = cm.data.get("CONTENT_SYSTEM", "none")
|
|
28
|
-
|
|
29
|
-
otca = OTCA(
|
|
30
|
-
chat_url=str(SETTINGS.aviator.chat_svc_url),
|
|
31
|
-
embed_url=str(SETTINGS.aviator.embed_svc_url),
|
|
32
|
-
studio_url=str(SETTINGS.aviator.studio_url),
|
|
33
|
-
otds_url=str(SETTINGS.otds.url_internal),
|
|
34
|
-
client_id=SETTINGS.aviator.oauth_client,
|
|
35
|
-
client_secret=SETTINGS.aviator.oauth_secret,
|
|
36
|
-
otcs_object=otcs_object,
|
|
37
|
-
content_system=content_system,
|
|
38
|
-
logger=logger.getChild("otca"),
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
return otca
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
# end function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def register_tool_body(route: APIRoute, agents: list[str] | None = None) -> dict:
|
|
48
|
-
"""Generate the request body for the CSAI Studio integration.
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
route (APIRoute):
|
|
52
|
-
The API routes.
|
|
53
|
-
agents (list[str] | None, optional):
|
|
54
|
-
A list of agents this tool is associated with.
|
|
55
|
-
Defaults to ["retrieverAgent"].
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
dict:
|
|
59
|
-
The body for the REST API call to register a tool in Content Aviator.
|
|
60
|
-
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
if agents is None:
|
|
64
|
-
agents = ["retrieverAgent"]
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
"name": route.name,
|
|
68
|
-
"description": route.description,
|
|
69
|
-
"APISchema": get_openapi(
|
|
70
|
-
title=route.name,
|
|
71
|
-
openapi_version="3.0.0",
|
|
72
|
-
version=version("pyxecm"),
|
|
73
|
-
servers=[{"url": "http://customizer:8000"}],
|
|
74
|
-
routes=[route],
|
|
75
|
-
),
|
|
76
|
-
"requestTemplate": {
|
|
77
|
-
"data": {"context": {"where": "memory.input.where", "query": "memory.input.query"}},
|
|
78
|
-
},
|
|
79
|
-
"responseTemplate": {}, # Optional response template used to filter the response from the API.
|
|
80
|
-
"agents": agents,
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
# end function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def register_all() -> None:
|
|
88
|
-
"""Register all tools."""
|
|
89
|
-
|
|
90
|
-
def register_all_routes() -> None:
|
|
91
|
-
otca = get_otca_object(otcs_object=get_otcs_object())
|
|
92
|
-
response = otca.do_request(
|
|
93
|
-
method="POST",
|
|
94
|
-
url=str(SETTINGS.aviator.studio_url) + "studio/v1/import",
|
|
95
|
-
show_error=False,
|
|
96
|
-
parse_request_response=False,
|
|
97
|
-
)
|
|
98
|
-
if not response or response.text != "Accepted":
|
|
99
|
-
logger.error("Failed to import tools!")
|
|
100
|
-
return
|
|
101
|
-
get_k8s_object().restart_deployment(deployment_name="csai-chat-svc")
|
|
102
|
-
|
|
103
|
-
for route in routes:
|
|
104
|
-
logger.info("Registering Content Aviator tool -> '%s'...", route.name)
|
|
105
|
-
request_body = register_tool_body(route=route)
|
|
106
|
-
result = otca.register_tool(request_body=request_body)
|
|
107
|
-
if result:
|
|
108
|
-
logger.info("Tool got registered successfully -> %s", route.name)
|
|
109
|
-
logger.debug("%s", result)
|
|
110
|
-
|
|
111
|
-
from pyxecm_api.app import app
|
|
112
|
-
|
|
113
|
-
# Get all FastAPI routes and register them as tools:
|
|
114
|
-
routes: list[APIRoute] = [route for route in app.routes if route.path.startswith("/agents")]
|
|
115
|
-
|
|
116
|
-
Thread(target=register_all_routes, name="RegisterTools").start()
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# end function
|
pyxecm_api/agents/models.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""init module."""
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
"""Function to build a knowledge graph from the OTCS object."""
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
import time
|
|
5
|
-
from datetime import UTC, datetime
|
|
6
|
-
|
|
7
|
-
from pyxecm_customizer.knowledge_graph import KnowledgeGraph
|
|
8
|
-
|
|
9
|
-
from pyxecm_api.common.functions import get_otcs_object
|
|
10
|
-
|
|
11
|
-
logger = logging.getLogger("pyxecm_api.agent.otcm_knowledge_graph")
|
|
12
|
-
|
|
13
|
-
KNOWLEDGEGRAPH_OBJECT: KnowledgeGraph = None
|
|
14
|
-
KNOWLEDGEGRAPH_ONTOLOGY = {
|
|
15
|
-
("Vendor", "Material", "child"): ["offers", "supplies", "provides"],
|
|
16
|
-
("Vendor", "Purchase Order", "child"): ["supplies", "provides"],
|
|
17
|
-
("Vendor", "Purchase Contract", "child"): ["signs", "owns"],
|
|
18
|
-
("Material", "Vendor", "parent"): ["is supplied by"],
|
|
19
|
-
("Purchase Order", "Material", "child"): ["includes", "is part of"],
|
|
20
|
-
("Customer", "Sales Order", "child"): ["has ordered"],
|
|
21
|
-
("Customer", "Sales Contract", "child"): ["signs", "owns"],
|
|
22
|
-
("Sales Order", "Customer", "parent"): ["belongs to", "is initiated by"],
|
|
23
|
-
("Sales Order", "Material", "child"): ["includes", "consists of"],
|
|
24
|
-
("Sales Order", "Delivery", "child"): ["triggers", "is followed by"],
|
|
25
|
-
("Sales Order", "Production Order", "child"): ["triggers", "is followed by"],
|
|
26
|
-
("Sales Contract", "Material", "child"): ["includes", "consists of"],
|
|
27
|
-
("Production Order", "Material", "child"): ["includes", "consists of"],
|
|
28
|
-
("Production Order", "Delivery", "child"): ["triggers", "is followed by"],
|
|
29
|
-
("Production Order", "Goods Movement", "child"): ["triggers", "is followed by"],
|
|
30
|
-
("Delivery", "Goods Movement", "child"): ["triggers", "is followed by"],
|
|
31
|
-
("Delivery", "Material", "child"): ["triggers", "is followed by"],
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def build_graph() -> None:
|
|
36
|
-
"""Build the knowledgeGraph. And keep it updated every hour."""
|
|
37
|
-
|
|
38
|
-
def build() -> None:
|
|
39
|
-
knowledge_graph = KnowledgeGraph(otcs_object=get_otcs_object(), ontology=KNOWLEDGEGRAPH_ONTOLOGY)
|
|
40
|
-
|
|
41
|
-
start_time = datetime.now(UTC)
|
|
42
|
-
result = knowledge_graph.build_graph(
|
|
43
|
-
workspace_type_exclusions=None,
|
|
44
|
-
workspace_type_inclusions=[
|
|
45
|
-
"Vendor",
|
|
46
|
-
"Purchase Contract",
|
|
47
|
-
"Purchase Order",
|
|
48
|
-
"Material",
|
|
49
|
-
"Customer",
|
|
50
|
-
"Sales Order",
|
|
51
|
-
"Sales Contract",
|
|
52
|
-
"Delivery",
|
|
53
|
-
"Goods Movement",
|
|
54
|
-
],
|
|
55
|
-
workers=20,
|
|
56
|
-
filter_at_traversal=True, # also filter for workspace types if following relationships
|
|
57
|
-
relationship_types=["child"], # only go from parent to child
|
|
58
|
-
strategy="BFS",
|
|
59
|
-
metadata=False,
|
|
60
|
-
)
|
|
61
|
-
end_time = datetime.now(UTC)
|
|
62
|
-
logger.info(
|
|
63
|
-
"Knowledge Graph completed in %s. Processed %d workspace nodes and traversed %d workspace relationships.",
|
|
64
|
-
str(end_time - start_time),
|
|
65
|
-
result["processed"],
|
|
66
|
-
result["traversed"],
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
global KNOWLEDGEGRAPH_OBJECT # noqa: PLW0603
|
|
70
|
-
KNOWLEDGEGRAPH_OBJECT = knowledge_graph
|
|
71
|
-
|
|
72
|
-
while True:
|
|
73
|
-
logger.info("Building knowledge graph...")
|
|
74
|
-
build()
|
|
75
|
-
logger.info("Knowledge graph build complete. Waiting for 1 hour before rebuilding...")
|
|
76
|
-
time.sleep(3600)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
###
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def get_knowledgegraph_object() -> KnowledgeGraph:
|
|
83
|
-
"""Get the OTCA object."""
|
|
84
|
-
|
|
85
|
-
return KNOWLEDGEGRAPH_OBJECT
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"""Define Models for KnowledgeGraph."""
|
|
2
|
-
|
|
3
|
-
from typing import Annotated, Literal
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel, Field
|
|
6
|
-
|
|
7
|
-
from pyxecm_api.agents.models import Context
|
|
8
|
-
from pyxecm_api.agents.otcm_workspace_agent.models import WorkspaceModel
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class KnowledgeGraphQueryModel(BaseModel):
|
|
12
|
-
"""Defines Model for describing workspaces in OTCM (Opentext Content Management).
|
|
13
|
-
|
|
14
|
-
To display an instance of this model, please display the link.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
source_type: Annotated[
|
|
18
|
-
str,
|
|
19
|
-
Field(
|
|
20
|
-
description="Source workspace type name provided in the user query. This provides the start point of the query in the Knowledge Graph."
|
|
21
|
-
),
|
|
22
|
-
]
|
|
23
|
-
source_value: Annotated[
|
|
24
|
-
str,
|
|
25
|
-
Field(
|
|
26
|
-
description="Name of the source workspace instance (of the type provided by source_type). This is NOT optional. If it is missing then you need to switch source and target. The source always needs to have a specific value!"
|
|
27
|
-
),
|
|
28
|
-
]
|
|
29
|
-
target_type: Annotated[
|
|
30
|
-
str,
|
|
31
|
-
Field(
|
|
32
|
-
description="Target workspace type name provided in the user query. This defines the result workspace types of the Knolwedge Graph query."
|
|
33
|
-
),
|
|
34
|
-
] = None
|
|
35
|
-
target_value: Annotated[
|
|
36
|
-
str,
|
|
37
|
-
Field(
|
|
38
|
-
description="Name of the target workspace instance (of the type provided by the target_type). This value is optionalis an additional / optional selection criteria."
|
|
39
|
-
),
|
|
40
|
-
] = None
|
|
41
|
-
intermediate_types: Annotated[
|
|
42
|
-
list[str],
|
|
43
|
-
Field(
|
|
44
|
-
description="List of workspace types (entities) that are on the path between the source workspace type and target workspace type. These are typically additional relational conditions the user is giving in the query. The start type and target types should never be in intermediate types!"
|
|
45
|
-
),
|
|
46
|
-
] = None
|
|
47
|
-
direction: Annotated[
|
|
48
|
-
Literal["child", "parent"],
|
|
49
|
-
Field(
|
|
50
|
-
description="The direction the graph should be traversed in. This is either 'child' (the default) or 'parent'. 'child' is typically used if traversing from main entities to related sub-entities thus following a '1 -> many' relationship (top-down). 'parent' is typically used if traversing bottom-up. This should reflect the relationship between the source type of the workspace and the requested target type. A 'child' relationship is e.g. 'Customer' -> 'Sales Order'. A 'parent' relationship is e.g. 'Material' -> 'Sales Order'."
|
|
51
|
-
),
|
|
52
|
-
] = None
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class KnowledgeGraphResponseModel(BaseModel):
|
|
56
|
-
"""Response of the Knowledge Graph tool."""
|
|
57
|
-
|
|
58
|
-
results: Annotated[list[WorkspaceModel], Field(description="A list of workspaces matching the query.")]
|
|
59
|
-
context_update: Annotated[
|
|
60
|
-
Context, Field(description="An update for the LLM context. Update the graph state with this information!")
|
|
61
|
-
]
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
"""Define router for workspace endpoints."""
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
from typing import Annotated
|
|
5
|
-
|
|
6
|
-
from fastapi import APIRouter, Body, Depends, HTTPException
|
|
7
|
-
from pyxecm_customizer.knowledge_graph import KnowledgeGraph
|
|
8
|
-
|
|
9
|
-
from pyxecm_api.agents.models import Context
|
|
10
|
-
from pyxecm_api.agents.otcm_workspace_agent.models import WorkspaceModel
|
|
11
|
-
|
|
12
|
-
from .functions import (
|
|
13
|
-
KNOWLEDGEGRAPH_ONTOLOGY,
|
|
14
|
-
get_knowledgegraph_object,
|
|
15
|
-
)
|
|
16
|
-
from .models import (
|
|
17
|
-
KnowledgeGraphQueryModel,
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
router = APIRouter(prefix="/otcm_knowledgegraph_agent", tags=["csai agents"])
|
|
21
|
-
|
|
22
|
-
logger = logging.getLogger("pyxecm_api.agents.otcm_knowledgegraph_agent")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@router.post(
|
|
26
|
-
path="/query",
|
|
27
|
-
summary="Query the knowledge graph for a list of workspaces matching the user query.",
|
|
28
|
-
description=f"Use the following ontology to understand the relationship between workspace types and the direction of the relationships (either 'parent' or 'child'): {KNOWLEDGEGRAPH_ONTOLOGY}",
|
|
29
|
-
responses={
|
|
30
|
-
200: {"description": "Workspaces found"},
|
|
31
|
-
403: {"description": "Invalid credentials"},
|
|
32
|
-
404: {"description": "No matching workspaces found"},
|
|
33
|
-
500: {"description": "Knowledge Graph is not available"},
|
|
34
|
-
},
|
|
35
|
-
# response_model=ToolResponse,
|
|
36
|
-
# response_model=list[WorkspaceModel],
|
|
37
|
-
response_description="List of workspaces that match the query. Best presented as a list with hyperlinks to the workspace.",
|
|
38
|
-
)
|
|
39
|
-
def otcm_knowledgegraph_query(
|
|
40
|
-
context: Context,
|
|
41
|
-
knowledge_graph: Annotated[KnowledgeGraph, Depends(get_knowledgegraph_object)],
|
|
42
|
-
knowledge_graph_query: Annotated[KnowledgeGraphQueryModel, Body()],
|
|
43
|
-
) -> dict | None: # ToolResponse | None: # list[WorkspaceModel] | None:
|
|
44
|
-
# ) -> list[WorkspaceModel] | None:
|
|
45
|
-
"""Query the knowledge graph for a list of workspaces matching the user query. Workspaces are entities and workspace types are entitiy types."""
|
|
46
|
-
|
|
47
|
-
if not knowledge_graph:
|
|
48
|
-
raise HTTPException(status_code=500, detail="Knowledge Graph is not available")
|
|
49
|
-
|
|
50
|
-
logger.info("Got context -> %s", context)
|
|
51
|
-
results = knowledge_graph.graph_query(
|
|
52
|
-
source_type=knowledge_graph_query.source_type,
|
|
53
|
-
source_value=knowledge_graph_query.source_value,
|
|
54
|
-
intermediate_types=knowledge_graph_query.intermediate_types,
|
|
55
|
-
target_type=knowledge_graph_query.target_type,
|
|
56
|
-
target_value=knowledge_graph_query.target_value,
|
|
57
|
-
direction=knowledge_graph_query.direction,
|
|
58
|
-
max_hops=4,
|
|
59
|
-
)
|
|
60
|
-
if not results:
|
|
61
|
-
raise HTTPException(status_code=404, detail="No result found")
|
|
62
|
-
|
|
63
|
-
where_clause = [{"workspaceID": str(workspace[1])} for workspace in results]
|
|
64
|
-
context_update = Context(where=where_clause, query=context.query)
|
|
65
|
-
logger.info("Return context -> %s", context_update)
|
|
66
|
-
|
|
67
|
-
results = [WorkspaceModel(name=n, id=i, type=knowledge_graph_query.target_type) for n, i in results]
|
|
68
|
-
|
|
69
|
-
return {"where": where_clause}
|
|
70
|
-
|
|
71
|
-
# return results
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# return ToolResponse(results=results, context_update=context_update)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""init module."""
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"""Define Models for users."""
|
|
2
|
-
|
|
3
|
-
from typing import Annotated
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel, Field
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class UserModel(BaseModel):
|
|
9
|
-
"""Defines Model for describing users in OTCS.
|
|
10
|
-
|
|
11
|
-
To display the user data as a markdown table, use the `UserModel` class.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
user_id: Annotated[int, Field(description="ID of the user")] = None
|
|
15
|
-
login: Annotated[str, Field(description="Login name of the user")] = None
|
|
16
|
-
first_name: Annotated[str, Field(description="First name of the user")] = None
|
|
17
|
-
last_name: Annotated[str, Field(description="Last name of the user")] = None
|
|
18
|
-
email: Annotated[str, Field(description="Email address of the user")] = None
|
|
19
|
-
department: Annotated[str, Field(description="Department of the user")] = None
|
|
20
|
-
business_phone: Annotated[str, Field(description="Business phone number of the user")] = None
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"""Define router for User endpoints."""
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
from typing import Annotated
|
|
5
|
-
|
|
6
|
-
from fastapi import APIRouter, Body, Depends, HTTPException, status
|
|
7
|
-
from pyxecm.otcs import OTCS
|
|
8
|
-
|
|
9
|
-
from pyxecm_api.common.functions import get_otcs_object_from_otcsticket
|
|
10
|
-
|
|
11
|
-
from .models import UserModel
|
|
12
|
-
|
|
13
|
-
router = APIRouter(prefix="/otcm_user_agent", tags=["csai agents"])
|
|
14
|
-
|
|
15
|
-
logger = logging.getLogger("pyxecm_api.agents.otcm_user_agent")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@router.post(
|
|
19
|
-
"/user",
|
|
20
|
-
summary="Find a user by name or user attributes",
|
|
21
|
-
responses={
|
|
22
|
-
200: {"description": "User found"},
|
|
23
|
-
403: {"description": "Invalid credentials"},
|
|
24
|
-
400: {"description": "User not found"},
|
|
25
|
-
},
|
|
26
|
-
response_model=UserModel,
|
|
27
|
-
response_description="Details about a user. Best presented as a table with each user property in a row.",
|
|
28
|
-
)
|
|
29
|
-
def otcm_user_agent_find_user(
|
|
30
|
-
otcs: Annotated[OTCS, Depends(get_otcs_object_from_otcsticket)],
|
|
31
|
-
user: Annotated[UserModel, Body()],
|
|
32
|
-
) -> UserModel | None:
|
|
33
|
-
"""Find a user by by its name or other attributes.
|
|
34
|
-
|
|
35
|
-
The user ID, the user name (login), user first name, user last name and user email will be returned.
|
|
36
|
-
When a user is returned, display the user data as a markdown table.
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
response = otcs.get_users(
|
|
40
|
-
where_name=user.login,
|
|
41
|
-
where_first_name=user.first_name,
|
|
42
|
-
where_last_name=user.last_name,
|
|
43
|
-
where_business_email=user.email,
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
if not response or not response["results"]:
|
|
47
|
-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
|
|
48
|
-
|
|
49
|
-
try:
|
|
50
|
-
department_id = otcs.get_result_value(response=response, key="group_id")
|
|
51
|
-
department = otcs.get_group(group_id=department_id) if department_id else None
|
|
52
|
-
department_name = otcs.get_result_value(response=department, key="name") if department else None
|
|
53
|
-
return UserModel(
|
|
54
|
-
user_id=otcs.get_result_value(response=response, key="id"),
|
|
55
|
-
login=otcs.get_result_value(response=response, key="name"),
|
|
56
|
-
first_name=otcs.get_result_value(response=response, key="first_name"),
|
|
57
|
-
last_name=otcs.get_result_value(response=response, key="last_name"),
|
|
58
|
-
email=otcs.get_result_value(response=response, key="business_email"),
|
|
59
|
-
department=department_name,
|
|
60
|
-
)
|
|
61
|
-
except Exception as e:
|
|
62
|
-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found") from e
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
# end function definition
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""init module."""
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"""Define Models for workspaces."""
|
|
2
|
-
|
|
3
|
-
from typing import Annotated, Any
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel, Field
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class WorkspaceAttributeModel(BaseModel):
|
|
9
|
-
"""Model for a workspace attribute."""
|
|
10
|
-
|
|
11
|
-
category: Annotated[str, Field(description="Category for the workspace attributes")]
|
|
12
|
-
attribute: Annotated[str, Field(description="Name of the attribute")]
|
|
13
|
-
value: Annotated[str, Field(description="Value of the attribute")]
|
|
14
|
-
set: Annotated[str, Field(description="Optional attribute group or set name")]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class WorkspaceModel(BaseModel):
|
|
18
|
-
"""Defines Model for describing workspaces in OTCM (Opentext Content Management).
|
|
19
|
-
|
|
20
|
-
To display an instance of this model, please display the link.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
id: Annotated[int, Field(description="ID of the workspace")] = None
|
|
24
|
-
name: Annotated[str, Field(description="Name of the workspace")] = None
|
|
25
|
-
type: Annotated[str, Field(description="Name of the workspace type")] = None
|
|
26
|
-
description: Annotated[str, Field(description="Description of the workspace")] = None
|
|
27
|
-
|
|
28
|
-
link: Annotated[str, Field(description="Link to the workspace, should be used when the instance is displayed")] = (
|
|
29
|
-
None
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
# attributes: Annotated[
|
|
33
|
-
# list[WorkspaceAttributeModel] | None,
|
|
34
|
-
# Body(description="List of custom attributes associated with the workspace"),
|
|
35
|
-
# ] = None
|
|
36
|
-
|
|
37
|
-
def model_post_init(self, context: Any) -> None: # noqa: ARG002, ANN401
|
|
38
|
-
"""Post model initialization."""
|
|
39
|
-
# this could also be done with `default_factory`:
|
|
40
|
-
self.link = f"[{self.name}](/cs/cs/app/nodes/{self.id})"
|