diff --git a/assistants/codespace-assistant/.vscode/launch.json b/assistants/codespace-assistant/.vscode/launch.json index 6b7a81a3..6b34f89b 100644 --- a/assistants/codespace-assistant/.vscode/launch.json +++ b/assistants/codespace-assistant/.vscode/launch.json @@ -10,5 +10,18 @@ "consoleTitle": "${workspaceFolderBasename}" //"justMyCode": false, // Set to false to debug external libraries } + ], + "compounds": [ + { + "name": "assistants: codespace-assistant (for dev)", + "configurations": [ + "assistants: codespace-assistant", + "app: semantic-workbench-app", + "service: semantic-workbench-service", + "mcp-servers: mcp-server-bing-search", + "mcp-servers: mcp-server-giphy", + "mcp-servers: mcp-server-open-deep-research" + ] + } ] } diff --git a/assistants/codespace-assistant/assistant/extensions/tools/__mcp_server_utils.py b/assistants/codespace-assistant/assistant/extensions/tools/__mcp_server_utils.py index b9a64c74..31cc19f1 100644 --- a/assistants/codespace-assistant/assistant/extensions/tools/__mcp_server_utils.py +++ b/assistants/codespace-assistant/assistant/extensions/tools/__mcp_server_utils.py @@ -81,7 +81,7 @@ async def establish_mcp_sessions(tools_config: ToolsConfigModel, stack: AsyncExi client_session: ClientSession | None = await stack.enter_async_context(connect_to_mcp_server(server_config)) if client_session: # Create an MCP session with the client session - mcp_session = MCPSession(name=server_config.key, client_session=client_session) + mcp_session = MCPSession(config=server_config, client_session=client_session) # Initialize the session to load tools, resources, etc. await mcp_session.initialize() # Add the session to the list of established sessions diff --git a/assistants/codespace-assistant/assistant/extensions/tools/__mcp_tool_utils.py b/assistants/codespace-assistant/assistant/extensions/tools/__mcp_tool_utils.py index e9a76139..0b0454af 100644 --- a/assistants/codespace-assistant/assistant/extensions/tools/__mcp_tool_utils.py +++ b/assistants/codespace-assistant/assistant/extensions/tools/__mcp_tool_utils.py @@ -1,6 +1,7 @@ # utils/tool_utils.py import logging -from typing import List +from textwrap import dedent +from typing import AsyncGenerator, List import deepmerge from mcp import Tool @@ -23,47 +24,27 @@ def retrieve_tools_from_sessions(mcp_sessions: List[MCPSession], tools_config: T ] -async def handle_tool_call( +def get_mcp_session_and_tool_by_tool_name( mcp_sessions: List[MCPSession], - tool_call: ToolCall, - method_metadata_key: str, -) -> ToolCallResult: + tool_name: str, +) -> tuple[MCPSession | None, Tool | None]: """ - Handle the tool call by invoking the appropriate tool and returning a ToolCallResult. + Retrieve the MCP session and tool by tool name. """ - - # Initialize metadata - metadata = {} - - # Find the tool and session from the full collection of sessions - mcp_session, tool = next( - ( - (mcp_session, tool) - for mcp_session in mcp_sessions - for tool in mcp_session.tools - if tool.name == tool_call.name - ), + return next( + ((mcp_session, tool) for mcp_session in mcp_sessions for tool in mcp_session.tools if tool.name == tool_name), (None, None), ) - if not mcp_session or not tool: - return ToolCallResult( - id=tool_call.id, - content=f"Tool '{tool_call.name}' not found in any of the sessions.", - message_type=ToolMessageType.notice, - metadata={}, - ) - # Update metadata with tool call details - deepmerge.always_merger.merge( - metadata, - { - "debug": { - method_metadata_key: { - "tool_call": tool_call.to_json(), - }, - }, - }, - ) + +async def execute_tool_call( + mcp_session: MCPSession, + tool_call: ToolCall, + method_metadata_key: str, +) -> ToolCallResult: + + # Initialize metadata + metadata = {} # Initialize tool_result tool_result = None @@ -72,7 +53,7 @@ async def handle_tool_call( # Invoke the tool try: - logger.debug(f"Invoking '{mcp_session.name}.{tool_call.name}' with arguments: {tool_call.arguments}") + logger.debug(f"Invoking '{mcp_session.config.key}.{tool_call.name}' with arguments: {tool_call.arguments}") tool_result = await mcp_session.client_session.call_tool(tool_call.name, tool_call.arguments) tool_output = tool_result.content except Exception as e: @@ -106,3 +87,63 @@ async def handle_tool_call( message_type=ToolMessageType.tool_result, metadata=metadata, ) + +async def handle_tool_call( + mcp_sessions: List[MCPSession], + tool_call: ToolCall, + method_metadata_key: str, +) -> ToolCallResult: + """ + Handle the tool call by invoking the appropriate tool and returning a ToolCallResult. + """ + + # Find the tool and session from the full collection of sessions + mcp_session, tool = get_mcp_session_and_tool_by_tool_name(mcp_sessions, tool_call.name) + + if not mcp_session or not tool: + return ToolCallResult( + id=tool_call.id, + content=f"Tool '{tool_call.name}' not found in any of the sessions.", + message_type=ToolMessageType.notice, + metadata={}, + ) + + return await execute_tool_call(mcp_session, tool_call, method_metadata_key) + + +async def handle_long_running_tool_call( + mcp_sessions: List[MCPSession], + tool_call: ToolCall, + method_metadata_key: str, +) -> AsyncGenerator[ToolCallResult, None]: + """ + Handle the streaming tool call by invoking the appropriate tool and returning a ToolCallResult. + """ + + # Find the tool and session from the full collection of sessions + mcp_session, tool = get_mcp_session_and_tool_by_tool_name(mcp_sessions, tool_call.name) + + if not mcp_session or not tool: + yield ToolCallResult( + id=tool_call.id, + content=f"Tool '{tool_call.name}' not found in any of the sessions.", + message_type=ToolMessageType.notice, + metadata={}, + ) + return + + # For now, let's just hack to return an immediate response to indicate that the tool call was received + # and is being processed and that the results will be sent in a separate message. + yield ToolCallResult( + id=tool_call.id, + content=dedent(f""" + Processing tool call '{tool_call.name}'. + Estimated time to completion: {mcp_session.config.task_completion_estimate} + """).strip(), + message_type=ToolMessageType.tool_result, + metadata={}, + ) + + # Perform the tool call + tool_call_result = await execute_tool_call(mcp_session, tool_call, method_metadata_key) + yield tool_call_result diff --git a/assistants/codespace-assistant/assistant/extensions/tools/__model.py b/assistants/codespace-assistant/assistant/extensions/tools/__model.py index 5c93a8b3..f47a0ba0 100644 --- a/assistants/codespace-assistant/assistant/extensions/tools/__model.py +++ b/assistants/codespace-assistant/assistant/extensions/tools/__model.py @@ -12,52 +12,6 @@ logger = logging.getLogger(__name__) -class MCPSession: - name: str - client_session: ClientSession - tools: List[Tool] = [] - - def __init__(self, name: str, client_session: ClientSession) -> None: - self.name = name - self.client_session = client_session - - async def initialize(self) -> None: - # Load all tools from the session, later we can do the same for resources, prompts, etc. - tools_result = await self.client_session.list_tools() - self.tools = tools_result.tools - logger.debug(f"Loaded {len(tools_result.tools)} tools from session '{self.name}'") - - -@dataclass -class ToolCall: - id: str - name: str - arguments: dict[str, Any] - - def to_dict(self) -> dict[str, Any]: - return { - "id": self.id, - "name": self.name, - "arguments": self.arguments, - } - - def to_json(self, **kwargs) -> str: - return json.dumps(self, default=lambda o: o.__dict__, **kwargs) - - -class ToolMessageType(StrEnum): - notice = "notice" - tool_result = "tool_result" - - -@dataclass -class ToolCallResult: - id: str - content: str - message_type: ToolMessageType - metadata: dict[str, Any] - - class MCPServerEnvConfig(BaseModel): key: Annotated[str, Field(title="Key", description="Environment variable key.")] value: Annotated[str, Field(title="Value", description="Environment variable value.")] @@ -69,11 +23,7 @@ class MCPServerConfig(BaseModel): key: Annotated[str, Field(title="Key", description="Unique key for the server configuration.")] command: Annotated[ - str, - Field( - title="Command", - description="Command to run the server, use url if using SSE transport." - ) + str, Field(title="Command", description="Command to run the server, use url if using SSE transport.") ] args: Annotated[List[str], Field(title="Arguments", description="Arguments to pass to the server.")] @@ -89,6 +39,19 @@ class MCPServerConfig(BaseModel): UISchema(widget="textarea"), ] = "" + long_running: Annotated[ + bool, + Field(title="Long Running", description="Does this server run long running tasks?"), + ] = False + + task_completion_estimate: Annotated[ + int, + Field( + title="Long Running Task Completion Time Estimate", + description="Estimated time to complete an average long running task (in seconds).", + ), + ] = 30 + class ToolsConfigModel(BaseModel): enabled: Annotated[ @@ -150,6 +113,30 @@ class ToolsConfigModel(BaseModel): command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "/workspaces/semanticworkbench"], ), + MCPServerConfig( + key="vscode", + command="http://127.0.0.1:6010/sse", + args=[], + enabled=False, + ), + MCPServerConfig( + key="bing-search", + command="http://127.0.0.1:6030/sse", + args=[], + enabled=False, + ), + MCPServerConfig( + key="open-deep-research", + command="http://127.0.0.1:6020/sse", + args=[], + enabled=False, + ), + MCPServerConfig( + key="giphy", + command="http://http://127.0.0.1:6000/sse", + args=[], + enabled=False, + ), MCPServerConfig( key="memory", command="npx", @@ -178,24 +165,6 @@ class ToolsConfigModel(BaseModel): """).strip(), enabled=False, ), - MCPServerConfig( - key="open-deep-research", - command="http://127.0.0.1:6020/sse", - args=[], - enabled=False, - ), - MCPServerConfig( - key="vscode", - command="http://127.0.0.1:6010/sse", - args=[], - enabled=False, - ), - MCPServerConfig( - key="giphy", - command="http://http://127.0.0.1:6000/sse", - args=[], - enabled=False, - ), MCPServerConfig( key="sequential-thinking", command="npx", @@ -214,3 +183,49 @@ class ToolsConfigModel(BaseModel): """).strip(), ), ] = ["directory_tree"] + + +class MCPSession: + config: MCPServerConfig + client_session: ClientSession + tools: List[Tool] = [] + + def __init__(self, config: MCPServerConfig, client_session: ClientSession) -> None: + self.config = config + self.client_session = client_session + + async def initialize(self) -> None: + # Load all tools from the session, later we can do the same for resources, prompts, etc. + tools_result = await self.client_session.list_tools() + self.tools = tools_result.tools + logger.debug(f"Loaded {len(tools_result.tools)} tools from session '{self.config.key}'") + + +@dataclass +class ToolCall: + id: str + name: str + arguments: dict[str, Any] + + def to_dict(self) -> dict[str, Any]: + return { + "id": self.id, + "name": self.name, + "arguments": self.arguments, + } + + def to_json(self, **kwargs) -> str: + return json.dumps(self, default=lambda o: o.__dict__, **kwargs) + + +class ToolMessageType(StrEnum): + notice = "notice" + tool_result = "tool_result" + + +@dataclass +class ToolCallResult: + id: str + content: str + message_type: ToolMessageType + metadata: dict[str, Any] diff --git a/assistants/codespace-assistant/assistant/response/completion_handler.py b/assistants/codespace-assistant/assistant/response/completion_handler.py index e9f3df63..8e0fe576 100644 --- a/assistants/codespace-assistant/assistant/response/completion_handler.py +++ b/assistants/codespace-assistant/assistant/response/completion_handler.py @@ -61,10 +61,10 @@ async def handle_error(error_message: str) -> StepResult: # get the total tokens used for the completion total_tokens = completion.usage.total_tokens if completion.usage else 0 - response_content: list[str] = [] + content: str | None = None if (completion.choices[0].message.content is not None) and (completion.choices[0].message.content.strip() != ""): - response_content.append(completion.choices[0].message.content) + content = completion.choices[0].message.content # check if the completion has tool calls tool_calls: list[ToolCall] = [] @@ -79,14 +79,14 @@ async def handle_error(error_message: str) -> StepResult: ) for tool_call in completion.choices[0].message.tool_calls ]) - if ai_context is not None and ai_context.strip() != "": - response_content.append(ai_context) - else: - response_content.append( - f"[Assistant is calling tools: {', '.join([tool_call.name for tool_call in tool_calls])}]" - ) - - content = "\n\n".join(response_content) + if content is None: + if ai_context is not None and ai_context.strip() != "": + content = ai_context + # else: + # content = f"[Assistant is calling tools: {', '.join([tool_call.name for tool_call in tool_calls])}]" + + if content is None: + content = "[no response from openai]" # update the metadata with debug information deepmerge.always_merger.merge( diff --git a/assistants/codespace-assistant/assistant/text_includes/instruction_prompt.txt b/assistants/codespace-assistant/assistant/text_includes/instruction_prompt.txt index 80a7f5f7..34a24163 100644 --- a/assistants/codespace-assistant/assistant/text_includes/instruction_prompt.txt +++ b/assistants/codespace-assistant/assistant/text_includes/instruction_prompt.txt @@ -50,6 +50,11 @@ When assisting with coding projects, follow these guidelines to ensure clarity a - **File Formatting:** Ensure every file ends with a newline. +- **Verify Files:** + Before creating a new file, verify that there is not already a file with the same name and location. + Always assume that files may be updated from outside of this conversation and re-read them if they + are needed in the current turn and have not been read yet this turn. + ### B. **Dependency Management** - **Installation Instructions:** @@ -90,18 +95,3 @@ When assisting with coding projects, follow these guidelines to ensure clarity a - **Updated Documentation:** Ensure that code comments and documentation always reflect the latest project information. - -## Visual Overview of Content Types - -For an improved communication through visuals, consider the following mermaid diagram as an example: - -```mermaid -flowchart TD - U[User Request] --> A[Process Input] - A --> T[Generate Text & Markdown] - A --> C[Produce Code Snippets] - A --> M[Render Mermaid Diagrams] - A --> B[Output ABC Music Markdown] -``` - -This diagram illustrates how your different response types are generated based on the user's needs. diff --git a/assistants/skill-assistant/uv.lock b/assistants/skill-assistant/uv.lock index 8c453319..f633b762 100644 --- a/assistants/skill-assistant/uv.lock +++ b/assistants/skill-assistant/uv.lock @@ -506,7 +506,7 @@ name = "click" version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ @@ -883,7 +883,7 @@ name = "ipykernel" version = "6.29.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "appnope", marker = "platform_system == 'Darwin'" }, + { name = "appnope", marker = "sys_platform == 'darwin'" }, { name = "comm" }, { name = "debugpy" }, { name = "ipython" }, @@ -1003,6 +1003,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/91/61/c80ef80ed8a0a21158e289ef70dac01e351d929a1c30cb0f49be60772547/jiter-0.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566", size = 202374 }, ] +[[package]] +name = "jsonschema" +version = "4.23.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/2e/03362ee4034a4c917f697890ccd4aec0800ccf9ded7f511971c75451deec/jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", size = 325778 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462 }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2024.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/db/58f950c996c793472e336ff3655b13fbcf1e3b359dcf52dcf3ed3b52c352/jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", size = 15561 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/0f/8910b19ac0670a0f80ce1008e5e751c4a57e14d2c4c13a482aa6079fa9d6/jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf", size = 18459 }, +] + [[package]] name = "jupyter-client" version = "8.6.3" @@ -1398,7 +1425,7 @@ name = "portalocker" version = "2.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pywin32", marker = "platform_system == 'Windows'" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ed/d3/c6c64067759e87af98cc668c1cc75171347d0f1577fab7ca3749134e3cd4/portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f", size = 40891 } wheels = [ @@ -1851,6 +1878,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/d6/32fd69744afb53995619bc5effa2a405ae0d343cd3e747d0fbc43fe894ee/pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0", size = 1392485 }, ] +[[package]] +name = "referencing" +version = "0.36.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775 }, +] + [[package]] name = "regex" version = "2024.11.6" @@ -1958,6 +1999,66 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/3c/3b66696fc8a6c980674851108d7d57fbcbfedbefb3d8b61a64166dc9b18e/rich_toolkit-0.12.0-py3-none-any.whl", hash = "sha256:a2da4416384410ae871e890db7edf8623e1f5e983341dbbc8cc03603ce24f0ab", size = 13012 }, ] +[[package]] +name = "rpds-py" +version = "0.22.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/80/cce854d0921ff2f0a9fa831ba3ad3c65cee3a46711addf39a2af52df2cfd/rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d", size = 26771 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/ad/8d1ddf78f2805a71253fcd388017e7b4a0615c22c762b6d35301fef20106/rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f", size = 359773 }, + { url = "https://files.pythonhosted.org/packages/c8/75/68c15732293a8485d79fe4ebe9045525502a067865fa4278f178851b2d87/rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a", size = 349214 }, + { url = "https://files.pythonhosted.org/packages/3c/4c/7ce50f3070083c2e1b2bbd0fb7046f3da55f510d19e283222f8f33d7d5f4/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5", size = 380477 }, + { url = "https://files.pythonhosted.org/packages/9a/e9/835196a69cb229d5c31c13b8ae603bd2da9a6695f35fe4270d398e1db44c/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb", size = 386171 }, + { url = "https://files.pythonhosted.org/packages/f9/8e/33fc4eba6683db71e91e6d594a2cf3a8fbceb5316629f0477f7ece5e3f75/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2", size = 422676 }, + { url = "https://files.pythonhosted.org/packages/37/47/2e82d58f8046a98bb9497a8319604c92b827b94d558df30877c4b3c6ccb3/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0", size = 446152 }, + { url = "https://files.pythonhosted.org/packages/e1/78/79c128c3e71abbc8e9739ac27af11dc0f91840a86fce67ff83c65d1ba195/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1", size = 381300 }, + { url = "https://files.pythonhosted.org/packages/c9/5b/2e193be0e8b228c1207f31fa3ea79de64dadb4f6a4833111af8145a6bc33/rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d", size = 409636 }, + { url = "https://files.pythonhosted.org/packages/c2/3f/687c7100b762d62186a1c1100ffdf99825f6fa5ea94556844bbbd2d0f3a9/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648", size = 556708 }, + { url = "https://files.pythonhosted.org/packages/8c/a2/c00cbc4b857e8b3d5e7f7fc4c81e23afd8c138b930f4f3ccf9a41a23e9e4/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74", size = 583554 }, + { url = "https://files.pythonhosted.org/packages/d0/08/696c9872cf56effdad9ed617ac072f6774a898d46b8b8964eab39ec562d2/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a", size = 552105 }, + { url = "https://files.pythonhosted.org/packages/18/1f/4df560be1e994f5adf56cabd6c117e02de7c88ee238bb4ce03ed50da9d56/rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64", size = 220199 }, + { url = "https://files.pythonhosted.org/packages/b8/1b/c29b570bc5db8237553002788dc734d6bd71443a2ceac2a58202ec06ef12/rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c", size = 231775 }, + { url = "https://files.pythonhosted.org/packages/75/47/3383ee3bd787a2a5e65a9b9edc37ccf8505c0a00170e3a5e6ea5fbcd97f7/rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e", size = 352334 }, + { url = "https://files.pythonhosted.org/packages/40/14/aa6400fa8158b90a5a250a77f2077c0d0cd8a76fce31d9f2b289f04c6dec/rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56", size = 342111 }, + { url = "https://files.pythonhosted.org/packages/7d/06/395a13bfaa8a28b302fb433fb285a67ce0ea2004959a027aea8f9c52bad4/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45", size = 384286 }, + { url = "https://files.pythonhosted.org/packages/43/52/d8eeaffab047e6b7b7ef7f00d5ead074a07973968ffa2d5820fa131d7852/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e", size = 391739 }, + { url = "https://files.pythonhosted.org/packages/83/31/52dc4bde85c60b63719610ed6f6d61877effdb5113a72007679b786377b8/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d", size = 427306 }, + { url = "https://files.pythonhosted.org/packages/70/d5/1bab8e389c2261dba1764e9e793ed6830a63f830fdbec581a242c7c46bda/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38", size = 442717 }, + { url = "https://files.pythonhosted.org/packages/82/a1/a45f3e30835b553379b3a56ea6c4eb622cf11e72008229af840e4596a8ea/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15", size = 385721 }, + { url = "https://files.pythonhosted.org/packages/a6/27/780c942de3120bdd4d0e69583f9c96e179dfff082f6ecbb46b8d6488841f/rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059", size = 415824 }, + { url = "https://files.pythonhosted.org/packages/94/0b/aa0542ca88ad20ea719b06520f925bae348ea5c1fdf201b7e7202d20871d/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e", size = 561227 }, + { url = "https://files.pythonhosted.org/packages/0d/92/3ed77d215f82c8f844d7f98929d56cc321bb0bcfaf8f166559b8ec56e5f1/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61", size = 587424 }, + { url = "https://files.pythonhosted.org/packages/09/42/cacaeb047a22cab6241f107644f230e2935d4efecf6488859a7dd82fc47d/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7", size = 555953 }, + { url = "https://files.pythonhosted.org/packages/e6/52/c921dc6d5f5d45b212a456c1f5b17df1a471127e8037eb0972379e39dff4/rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627", size = 221339 }, + { url = "https://files.pythonhosted.org/packages/f2/c7/f82b5be1e8456600395366f86104d1bd8d0faed3802ad511ef6d60c30d98/rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4", size = 235786 }, + { url = "https://files.pythonhosted.org/packages/d0/bf/36d5cc1f2c609ae6e8bf0fc35949355ca9d8790eceb66e6385680c951e60/rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84", size = 351657 }, + { url = "https://files.pythonhosted.org/packages/24/2a/f1e0fa124e300c26ea9382e59b2d582cba71cedd340f32d1447f4f29fa4e/rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25", size = 341829 }, + { url = "https://files.pythonhosted.org/packages/cf/c2/0da1231dd16953845bed60d1a586fcd6b15ceaeb965f4d35cdc71f70f606/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4", size = 384220 }, + { url = "https://files.pythonhosted.org/packages/c7/73/a4407f4e3a00a9d4b68c532bf2d873d6b562854a8eaff8faa6133b3588ec/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5", size = 391009 }, + { url = "https://files.pythonhosted.org/packages/a9/c3/04b7353477ab360fe2563f5f0b176d2105982f97cd9ae80a9c5a18f1ae0f/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc", size = 426989 }, + { url = "https://files.pythonhosted.org/packages/8d/e6/e4b85b722bcf11398e17d59c0f6049d19cd606d35363221951e6d625fcb0/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b", size = 441544 }, + { url = "https://files.pythonhosted.org/packages/27/fc/403e65e56f65fff25f2973216974976d3f0a5c3f30e53758589b6dc9b79b/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518", size = 385179 }, + { url = "https://files.pythonhosted.org/packages/57/9b/2be9ff9700d664d51fd96b33d6595791c496d2778cb0b2a634f048437a55/rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd", size = 415103 }, + { url = "https://files.pythonhosted.org/packages/bb/a5/03c2ad8ca10994fcf22dd2150dd1d653bc974fa82d9a590494c84c10c641/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2", size = 560916 }, + { url = "https://files.pythonhosted.org/packages/ba/2e/be4fdfc8b5b576e588782b56978c5b702c5a2307024120d8aeec1ab818f0/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16", size = 587062 }, + { url = "https://files.pythonhosted.org/packages/67/e0/2034c221937709bf9c542603d25ad43a68b4b0a9a0c0b06a742f2756eb66/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f", size = 555734 }, + { url = "https://files.pythonhosted.org/packages/ea/ce/240bae07b5401a22482b58e18cfbabaa392409b2797da60223cca10d7367/rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de", size = 220663 }, + { url = "https://files.pythonhosted.org/packages/cb/f0/d330d08f51126330467edae2fa4efa5cec8923c87551a79299380fdea30d/rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9", size = 235503 }, + { url = "https://files.pythonhosted.org/packages/f7/c4/dbe1cc03df013bf2feb5ad00615038050e7859f381e96fb5b7b4572cd814/rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b", size = 347698 }, + { url = "https://files.pythonhosted.org/packages/a4/3a/684f66dd6b0f37499cad24cd1c0e523541fd768576fa5ce2d0a8799c3cba/rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b", size = 337330 }, + { url = "https://files.pythonhosted.org/packages/82/eb/e022c08c2ce2e8f7683baa313476492c0e2c1ca97227fe8a75d9f0181e95/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1", size = 380022 }, + { url = "https://files.pythonhosted.org/packages/e4/21/5a80e653e4c86aeb28eb4fea4add1f72e1787a3299687a9187105c3ee966/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83", size = 390754 }, + { url = "https://files.pythonhosted.org/packages/37/a4/d320a04ae90f72d080b3d74597074e62be0a8ecad7d7321312dfe2dc5a6a/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd", size = 423840 }, + { url = "https://files.pythonhosted.org/packages/87/70/674dc47d93db30a6624279284e5631be4c3a12a0340e8e4f349153546728/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1", size = 438970 }, + { url = "https://files.pythonhosted.org/packages/3f/64/9500f4d66601d55cadd21e90784cfd5d5f4560e129d72e4339823129171c/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3", size = 383146 }, + { url = "https://files.pythonhosted.org/packages/4d/45/630327addb1d17173adcf4af01336fd0ee030c04798027dfcb50106001e0/rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130", size = 408294 }, + { url = "https://files.pythonhosted.org/packages/5f/ef/8efb3373cee54ea9d9980b772e5690a0c9e9214045a4e7fa35046e399fee/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c", size = 556345 }, + { url = "https://files.pythonhosted.org/packages/54/01/151d3b9ef4925fc8f15bfb131086c12ec3c3d6dd4a4f7589c335bf8e85ba/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b", size = 582292 }, + { url = "https://files.pythonhosted.org/packages/30/89/35fc7a6cdf3477d441c7aca5e9bbf5a14e0f25152aed7f63f4e0b141045d/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333", size = 553855 }, + { url = "https://files.pythonhosted.org/packages/8f/e0/830c02b2457c4bd20a8c5bb394d31d81f57fbefce2dbdd2e31feff4f7003/rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730", size = 219100 }, + { url = "https://files.pythonhosted.org/packages/f8/30/7ac943f69855c2db77407ae363484b915d861702dbba1aa82d68d57f42be/rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf", size = 233794 }, +] + [[package]] name = "semantic-workbench-api-model" version = "0.1.0" @@ -2037,7 +2138,9 @@ source = { editable = "../../libraries/python/skills/skill-library" } dependencies = [ { name = "assistant-drive" }, { name = "assistant-extensions", extra = ["attachments"] }, + { name = "bs4" }, { name = "events" }, + { name = "jsonschema" }, { name = "openai" }, { name = "openai-client" }, { name = "pydantic" }, @@ -2052,7 +2155,9 @@ dependencies = [ requires-dist = [ { name = "assistant-drive", editable = "../../libraries/python/assistant-drive" }, { name = "assistant-extensions", extras = ["attachments"], editable = "../../libraries/python/assistant-extensions" }, + { name = "bs4", specifier = ">=0.0.2" }, { name = "events", editable = "../../libraries/python/events" }, + { name = "jsonschema", specifier = ">=4.23.0" }, { name = "openai", specifier = ">=1.16.1" }, { name = "openai-client", editable = "../../libraries/python/openai-client" }, { name = "pydantic", specifier = ">=2.6.1" }, @@ -2168,7 +2273,7 @@ name = "tqdm" version = "4.67.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 } wheels = [ diff --git a/libraries/python/skills/skill-library/.vscode/settings.json b/libraries/python/skills/skill-library/.vscode/settings.json index 07ab0453..f29e404c 100644 --- a/libraries/python/skills/skill-library/.vscode/settings.json +++ b/libraries/python/skills/skill-library/.vscode/settings.json @@ -58,8 +58,10 @@ "asyncio", "dotenv", "httpx", + "jsonschema", "levelname", "metadrive", + "norecursedirs", "openai", "pydantic", "pypdf", diff --git a/libraries/python/skills/skill-library/pyproject.toml b/libraries/python/skills/skill-library/pyproject.toml index 2b5e80d3..ae4a6b8c 100644 --- a/libraries/python/skills/skill-library/pyproject.toml +++ b/libraries/python/skills/skill-library/pyproject.toml @@ -17,6 +17,8 @@ dependencies = [ "python-liquid>=1.12.1", "requests>=2.32.0", "tiktoken>=0.8.0", + "jsonschema>=4.23.0", + "bs4>=0.0.2", ] [dependency-groups] @@ -46,4 +48,4 @@ log_cli_format = "%(asctime)s | %(levelname)-7s | %(name)s | %(message)s" testpaths = ["tests"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" -norecursedirs = ["skill_library/skills/guided_conversation"] \ No newline at end of file +norecursedirs = ["skill_library/skills/guided_conversation"] diff --git a/libraries/python/skills/skill-library/uv.lock b/libraries/python/skills/skill-library/uv.lock index 830dbb50..402425d4 100644 --- a/libraries/python/skills/skill-library/uv.lock +++ b/libraries/python/skills/skill-library/uv.lock @@ -301,6 +301,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8", size = 15148 }, ] +[[package]] +name = "beautifulsoup4" +version = "4.13.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f0/3c/adaf39ce1fb4afdd21b611e3d530b183bb7759c9b673d60db0e347fd4439/beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b", size = 619516 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/49/6abb616eb3cbab6a7cca303dc02fdf3836de2e0b834bf966a7f5271a34d8/beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16", size = 186015 }, +] + +[[package]] +name = "bs4" +version = "0.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/aa/4acaf814ff901145da37332e05bb510452ebed97bc9602695059dd46ef39/bs4-0.0.2.tar.gz", hash = "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925", size = 698 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/bb/bf7aab772a159614954d84aa832c129624ba6c32faa559dfb200a534e50b/bs4-0.0.2-py2.py3-none-any.whl", hash = "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc", size = 1189 }, +] + [[package]] name = "certifi" version = "2024.8.30" @@ -414,7 +439,7 @@ name = "click" version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ @@ -774,6 +799,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ca/96/58b3d260e212add0087563672931b1176e70bef1225839a4470ec66157a5/jiter-0.7.0-cp313-none-win_amd64.whl", hash = "sha256:7417c2b928062c496f381fb0cb50412eee5ad1d8b53dbc0e011ce45bb2de522c", size = 199305 }, ] +[[package]] +name = "jsonschema" +version = "4.23.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/2e/03362ee4034a4c917f697890ccd4aec0800ccf9ded7f511971c75451deec/jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", size = 325778 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462 }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2024.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/db/58f950c996c793472e336ff3655b13fbcf1e3b359dcf52dcf3ed3b52c352/jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", size = 15561 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/0f/8910b19ac0670a0f80ce1008e5e751c4a57e14d2c4c13a482aa6079fa9d6/jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf", size = 18459 }, +] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -1088,7 +1140,7 @@ name = "portalocker" version = "2.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pywin32", marker = "platform_system == 'Windows'" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ed/d3/c6c64067759e87af98cc668c1cc75171347d0f1577fab7ca3749134e3cd4/portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f", size = 40891 } wheels = [ @@ -1434,6 +1486,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, ] +[[package]] +name = "referencing" +version = "0.36.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775 }, +] + [[package]] name = "regex" version = "2024.11.6" @@ -1527,6 +1593,66 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, ] +[[package]] +name = "rpds-py" +version = "0.22.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/80/cce854d0921ff2f0a9fa831ba3ad3c65cee3a46711addf39a2af52df2cfd/rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d", size = 26771 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/ad/8d1ddf78f2805a71253fcd388017e7b4a0615c22c762b6d35301fef20106/rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f", size = 359773 }, + { url = "https://files.pythonhosted.org/packages/c8/75/68c15732293a8485d79fe4ebe9045525502a067865fa4278f178851b2d87/rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a", size = 349214 }, + { url = "https://files.pythonhosted.org/packages/3c/4c/7ce50f3070083c2e1b2bbd0fb7046f3da55f510d19e283222f8f33d7d5f4/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5", size = 380477 }, + { url = "https://files.pythonhosted.org/packages/9a/e9/835196a69cb229d5c31c13b8ae603bd2da9a6695f35fe4270d398e1db44c/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb", size = 386171 }, + { url = "https://files.pythonhosted.org/packages/f9/8e/33fc4eba6683db71e91e6d594a2cf3a8fbceb5316629f0477f7ece5e3f75/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2", size = 422676 }, + { url = "https://files.pythonhosted.org/packages/37/47/2e82d58f8046a98bb9497a8319604c92b827b94d558df30877c4b3c6ccb3/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0", size = 446152 }, + { url = "https://files.pythonhosted.org/packages/e1/78/79c128c3e71abbc8e9739ac27af11dc0f91840a86fce67ff83c65d1ba195/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1", size = 381300 }, + { url = "https://files.pythonhosted.org/packages/c9/5b/2e193be0e8b228c1207f31fa3ea79de64dadb4f6a4833111af8145a6bc33/rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d", size = 409636 }, + { url = "https://files.pythonhosted.org/packages/c2/3f/687c7100b762d62186a1c1100ffdf99825f6fa5ea94556844bbbd2d0f3a9/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648", size = 556708 }, + { url = "https://files.pythonhosted.org/packages/8c/a2/c00cbc4b857e8b3d5e7f7fc4c81e23afd8c138b930f4f3ccf9a41a23e9e4/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74", size = 583554 }, + { url = "https://files.pythonhosted.org/packages/d0/08/696c9872cf56effdad9ed617ac072f6774a898d46b8b8964eab39ec562d2/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a", size = 552105 }, + { url = "https://files.pythonhosted.org/packages/18/1f/4df560be1e994f5adf56cabd6c117e02de7c88ee238bb4ce03ed50da9d56/rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64", size = 220199 }, + { url = "https://files.pythonhosted.org/packages/b8/1b/c29b570bc5db8237553002788dc734d6bd71443a2ceac2a58202ec06ef12/rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c", size = 231775 }, + { url = "https://files.pythonhosted.org/packages/75/47/3383ee3bd787a2a5e65a9b9edc37ccf8505c0a00170e3a5e6ea5fbcd97f7/rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e", size = 352334 }, + { url = "https://files.pythonhosted.org/packages/40/14/aa6400fa8158b90a5a250a77f2077c0d0cd8a76fce31d9f2b289f04c6dec/rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56", size = 342111 }, + { url = "https://files.pythonhosted.org/packages/7d/06/395a13bfaa8a28b302fb433fb285a67ce0ea2004959a027aea8f9c52bad4/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45", size = 384286 }, + { url = "https://files.pythonhosted.org/packages/43/52/d8eeaffab047e6b7b7ef7f00d5ead074a07973968ffa2d5820fa131d7852/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e", size = 391739 }, + { url = "https://files.pythonhosted.org/packages/83/31/52dc4bde85c60b63719610ed6f6d61877effdb5113a72007679b786377b8/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d", size = 427306 }, + { url = "https://files.pythonhosted.org/packages/70/d5/1bab8e389c2261dba1764e9e793ed6830a63f830fdbec581a242c7c46bda/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38", size = 442717 }, + { url = "https://files.pythonhosted.org/packages/82/a1/a45f3e30835b553379b3a56ea6c4eb622cf11e72008229af840e4596a8ea/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15", size = 385721 }, + { url = "https://files.pythonhosted.org/packages/a6/27/780c942de3120bdd4d0e69583f9c96e179dfff082f6ecbb46b8d6488841f/rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059", size = 415824 }, + { url = "https://files.pythonhosted.org/packages/94/0b/aa0542ca88ad20ea719b06520f925bae348ea5c1fdf201b7e7202d20871d/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e", size = 561227 }, + { url = "https://files.pythonhosted.org/packages/0d/92/3ed77d215f82c8f844d7f98929d56cc321bb0bcfaf8f166559b8ec56e5f1/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61", size = 587424 }, + { url = "https://files.pythonhosted.org/packages/09/42/cacaeb047a22cab6241f107644f230e2935d4efecf6488859a7dd82fc47d/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7", size = 555953 }, + { url = "https://files.pythonhosted.org/packages/e6/52/c921dc6d5f5d45b212a456c1f5b17df1a471127e8037eb0972379e39dff4/rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627", size = 221339 }, + { url = "https://files.pythonhosted.org/packages/f2/c7/f82b5be1e8456600395366f86104d1bd8d0faed3802ad511ef6d60c30d98/rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4", size = 235786 }, + { url = "https://files.pythonhosted.org/packages/d0/bf/36d5cc1f2c609ae6e8bf0fc35949355ca9d8790eceb66e6385680c951e60/rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84", size = 351657 }, + { url = "https://files.pythonhosted.org/packages/24/2a/f1e0fa124e300c26ea9382e59b2d582cba71cedd340f32d1447f4f29fa4e/rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25", size = 341829 }, + { url = "https://files.pythonhosted.org/packages/cf/c2/0da1231dd16953845bed60d1a586fcd6b15ceaeb965f4d35cdc71f70f606/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4", size = 384220 }, + { url = "https://files.pythonhosted.org/packages/c7/73/a4407f4e3a00a9d4b68c532bf2d873d6b562854a8eaff8faa6133b3588ec/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5", size = 391009 }, + { url = "https://files.pythonhosted.org/packages/a9/c3/04b7353477ab360fe2563f5f0b176d2105982f97cd9ae80a9c5a18f1ae0f/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc", size = 426989 }, + { url = "https://files.pythonhosted.org/packages/8d/e6/e4b85b722bcf11398e17d59c0f6049d19cd606d35363221951e6d625fcb0/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b", size = 441544 }, + { url = "https://files.pythonhosted.org/packages/27/fc/403e65e56f65fff25f2973216974976d3f0a5c3f30e53758589b6dc9b79b/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518", size = 385179 }, + { url = "https://files.pythonhosted.org/packages/57/9b/2be9ff9700d664d51fd96b33d6595791c496d2778cb0b2a634f048437a55/rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd", size = 415103 }, + { url = "https://files.pythonhosted.org/packages/bb/a5/03c2ad8ca10994fcf22dd2150dd1d653bc974fa82d9a590494c84c10c641/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2", size = 560916 }, + { url = "https://files.pythonhosted.org/packages/ba/2e/be4fdfc8b5b576e588782b56978c5b702c5a2307024120d8aeec1ab818f0/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16", size = 587062 }, + { url = "https://files.pythonhosted.org/packages/67/e0/2034c221937709bf9c542603d25ad43a68b4b0a9a0c0b06a742f2756eb66/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f", size = 555734 }, + { url = "https://files.pythonhosted.org/packages/ea/ce/240bae07b5401a22482b58e18cfbabaa392409b2797da60223cca10d7367/rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de", size = 220663 }, + { url = "https://files.pythonhosted.org/packages/cb/f0/d330d08f51126330467edae2fa4efa5cec8923c87551a79299380fdea30d/rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9", size = 235503 }, + { url = "https://files.pythonhosted.org/packages/f7/c4/dbe1cc03df013bf2feb5ad00615038050e7859f381e96fb5b7b4572cd814/rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b", size = 347698 }, + { url = "https://files.pythonhosted.org/packages/a4/3a/684f66dd6b0f37499cad24cd1c0e523541fd768576fa5ce2d0a8799c3cba/rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b", size = 337330 }, + { url = "https://files.pythonhosted.org/packages/82/eb/e022c08c2ce2e8f7683baa313476492c0e2c1ca97227fe8a75d9f0181e95/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1", size = 380022 }, + { url = "https://files.pythonhosted.org/packages/e4/21/5a80e653e4c86aeb28eb4fea4add1f72e1787a3299687a9187105c3ee966/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83", size = 390754 }, + { url = "https://files.pythonhosted.org/packages/37/a4/d320a04ae90f72d080b3d74597074e62be0a8ecad7d7321312dfe2dc5a6a/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd", size = 423840 }, + { url = "https://files.pythonhosted.org/packages/87/70/674dc47d93db30a6624279284e5631be4c3a12a0340e8e4f349153546728/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1", size = 438970 }, + { url = "https://files.pythonhosted.org/packages/3f/64/9500f4d66601d55cadd21e90784cfd5d5f4560e129d72e4339823129171c/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3", size = 383146 }, + { url = "https://files.pythonhosted.org/packages/4d/45/630327addb1d17173adcf4af01336fd0ee030c04798027dfcb50106001e0/rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130", size = 408294 }, + { url = "https://files.pythonhosted.org/packages/5f/ef/8efb3373cee54ea9d9980b772e5690a0c9e9214045a4e7fa35046e399fee/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c", size = 556345 }, + { url = "https://files.pythonhosted.org/packages/54/01/151d3b9ef4925fc8f15bfb131086c12ec3c3d6dd4a4f7589c335bf8e85ba/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b", size = 582292 }, + { url = "https://files.pythonhosted.org/packages/30/89/35fc7a6cdf3477d441c7aca5e9bbf5a14e0f25152aed7f63f4e0b141045d/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333", size = 553855 }, + { url = "https://files.pythonhosted.org/packages/8f/e0/830c02b2457c4bd20a8c5bb394d31d81f57fbefce2dbdd2e31feff4f7003/rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730", size = 219100 }, + { url = "https://files.pythonhosted.org/packages/f8/30/7ac943f69855c2db77407ae363484b915d861702dbba1aa82d68d57f42be/rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf", size = 233794 }, +] + [[package]] name = "semantic-workbench-api-model" version = "0.1.0" @@ -1606,7 +1732,9 @@ source = { editable = "." } dependencies = [ { name = "assistant-drive" }, { name = "assistant-extensions", extra = ["attachments"] }, + { name = "bs4" }, { name = "events" }, + { name = "jsonschema" }, { name = "openai" }, { name = "openai-client" }, { name = "pydantic" }, @@ -1629,7 +1757,9 @@ dev = [ requires-dist = [ { name = "assistant-drive", editable = "../../assistant-drive" }, { name = "assistant-extensions", extras = ["attachments"], editable = "../../assistant-extensions" }, + { name = "bs4", specifier = ">=0.0.2" }, { name = "events", editable = "../../events" }, + { name = "jsonschema", specifier = ">=4.23.0" }, { name = "openai", specifier = ">=1.16.1" }, { name = "openai-client", editable = "../../openai-client" }, { name = "pydantic", specifier = ">=2.6.1" }, @@ -1657,6 +1787,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, ] +[[package]] +name = "soupsieve" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 }, +] + [[package]] name = "starlette" version = "0.41.2" @@ -1704,7 +1843,7 @@ name = "tqdm" version = "4.67.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e8/4f/0153c21dc5779a49a0598c445b1978126b1344bab9ee71e53e44877e14e0/tqdm-4.67.0.tar.gz", hash = "sha256:fe5a6f95e6fe0b9755e9469b77b9c3cf850048224ecaa8293d7d2d31f97d869a", size = 169739 } wheels = [ diff --git a/workbench-app/docs/MESSAGE_METADATA.md b/workbench-app/docs/MESSAGE_METADATA.md index c17b93fa..3f669641 100644 --- a/workbench-app/docs/MESSAGE_METADATA.md +++ b/workbench-app/docs/MESSAGE_METADATA.md @@ -51,4 +51,94 @@ Example: } ``` +## Tools in UX via Metadata + +There is experimental support for rendering tools calls and their results in the UX via metadata. This is not yet fully implemented, but the intent is to allow assistants to send messages that include both the list of tools they are going to call and then individual messages for each tool result. + +To invoke this behavior, include the following metadata properties in messages that contain `tools calls`: + +- Metadata properties: + + - `tool_calls`: A list of tool calls that the assistant is going to make. Each tool call + - `id: string` - The ID of the tool call. + - `name: string` - The name of the tool call. + - `arguments: Record` - The arguments for the tool call. + +- Include an commentary from the assistant regarding the intended use of the tool(s) in the `content` of the message. +- Message container will be based upon the `message_type` of the message. Suggestion is to use `chat`. + +Example: + +```json +{ + ... ConversationMessageProps, + "content": "I will now read the README files...", + "metadata": { + "tool_calls": [ + { + "id": "tool_call_1", + "name": "Tool 1", + "arguments": { + ... + } + }, + { + "id": "tool_call_2", + "name": "Tool 2", + "arguments": { + ... + } + } + ] + } +} +``` + +Then, for each tool result, send a message with the following metadata properties: + +- Metadata properties: + + - `tool_calls`: Same list of tool calls as above, it will be used to retrieve the + tool call that corresponds to the tool result. + - `tool_result: Record`: A dictionary with the following property (others are ignored): + + - `tool_call_id`: The ID of the tool result. + +- The actual results of the tool call should be the `content` of the message. +- The `message_type` will be ignored as there is a separate renderer for tool results. + +Example: + +```json +{ + ... ConversationMessageProps, + "content": { + "README.md: ..." + }, + "metadata": { + "tool_calls": [ + { + "id": "tool_call_1", + "name": "Tool 1", + "arguments": { + ... + } + }, + { + "id": "tool_call_2", + "name": "Tool 2", + "arguments": { + ... + } + } + ], + "tool_result": { + "tool_call_id": "tool_result_1", + }, + } +} +``` + +--- + Additional metadata child properties can be added by the user, and the app will ignore them, but they will be available to other systems that have access to the message. diff --git a/workbench-app/pnpm-lock.yaml b/workbench-app/pnpm-lock.yaml index b70285b7..0c6fe981 100644 --- a/workbench-app/pnpm-lock.yaml +++ b/workbench-app/pnpm-lock.yaml @@ -974,6 +974,10 @@ packages: resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.26.9': + resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} + engines: {node: '>=6.9.0'} + '@babel/template@7.25.0': resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} engines: {node: '>=6.9.0'} @@ -1839,8 +1843,8 @@ packages: react: '>=16.14.0 <19.0.0' react-dom: '>=16.14.0 <19.0.0' - '@fluentui/react-portal-compat-context@9.0.12': - resolution: {integrity: sha512-5AVXWX9GnbvwnJZYUb4LSIF7BsI/N8oTI6+7Yn0w6B3yaWykA8Menlz757X5tgVBjouEj4Eom+AoVvA7u8gPDA==} + '@fluentui/react-portal-compat-context@9.0.13': + resolution: {integrity: sha512-N+c6Qs775jnr/4WIzsQuNaRu4v16fa+gGsOCzzU1bqxX0IR9BSjjO2oLGC6luaAOqlQP+JIwn/aumOIJICKXkA==} peerDependencies: '@types/react': '>=16.14.0 <19.0.0' react: '>=16.14.0 <19.0.0' @@ -2405,6 +2409,9 @@ packages: '@swc/helpers@0.5.13': resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@ts-morph/common@0.12.3': resolution: {integrity: sha512-4tUmeLyXJnJWvTFOKtcNJ1yh0a3SsTLi2MUoyj8iUNznFRN1ZquaNe7Oukqrnki2FzZkm0J9adCNLDZxUzvj+w==} @@ -4048,8 +4055,8 @@ packages: lexical@0.17.1: resolution: {integrity: sha512-72/MhR7jqmyqD10bmJw8gztlCm4KDDT+TPtU4elqXrEvHoO5XENi34YAEUD9gIkPfqSwyLa9mwAX1nKzIr5xEA==} - lib0@0.2.98: - resolution: {integrity: sha512-XteTiNO0qEXqqweWx+b21p/fBnNHUA1NwAtJNJek1oPrewEZs2uiT4gWivHKr9GqCjDPAhchz0UQO8NwU3bBNA==} + lib0@0.2.99: + resolution: {integrity: sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w==} engines: {node: '>=16'} hasBin: true @@ -4952,6 +4959,9 @@ packages: tslib@2.7.0: resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsutils@3.21.0: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -6193,6 +6203,10 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 + '@babel/runtime@7.26.9': + dependencies: + regenerator-runtime: 0.14.1 + '@babel/template@7.25.0': dependencies: '@babel/code-frame': 7.24.7 @@ -6795,7 +6809,7 @@ snapshots: '@fluentui/accessibility@0.66.5': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 lodash: 4.17.21 '@fluentui/dom-utilities@1.1.2': @@ -6910,7 +6924,7 @@ snapshots: '@fluentui/react-bindings@0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 '@fluentui/accessibility': 0.66.5 '@fluentui/dom-utilities': 1.1.2 '@fluentui/react-component-event-listener': 0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -7021,20 +7035,20 @@ snapshots: '@fluentui/react-component-event-listener@0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) '@fluentui/react-component-nesting-registry@0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 prop-types: 15.8.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) '@fluentui/react-component-ref@0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-is: 17.0.2 @@ -7196,7 +7210,7 @@ snapshots: '@fluentui/react-icons-northstar@0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 '@fluentui/accessibility': 0.66.5 '@fluentui/react-bindings': 0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/styles': 0.66.5 @@ -7405,7 +7419,7 @@ snapshots: '@fluentui/react-northstar-fela-renderer@0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 '@fluentui/react-northstar-styles-renderer': 0.66.5(react@18.3.1) '@fluentui/styles': 0.66.5 css-in-js-utils: 3.1.0 @@ -7425,13 +7439,13 @@ snapshots: '@fluentui/react-northstar-styles-renderer@0.66.5(react@18.3.1)': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 '@fluentui/styles': 0.66.5 react: 18.3.1 '@fluentui/react-northstar@0.66.5(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 '@fluentui/accessibility': 0.66.5 '@fluentui/dom-utilities': 1.1.2 '@fluentui/react-bindings': 0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) @@ -7440,7 +7454,7 @@ snapshots: '@fluentui/react-component-ref': 0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-icons-northstar': 0.66.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-northstar-styles-renderer': 0.66.5(react@18.3.1) - '@fluentui/react-portal-compat-context': 9.0.12(@types/react@18.3.10)(react@18.3.1) + '@fluentui/react-portal-compat-context': 9.0.13(@types/react@18.3.10)(react@18.3.1) '@fluentui/react-proptypes': 0.66.5 '@fluentui/state': 0.66.5 '@fluentui/styles': 0.66.5 @@ -7512,9 +7526,9 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-portal-compat-context@9.0.12(@types/react@18.3.10)(react@18.3.1)': + '@fluentui/react-portal-compat-context@9.0.13(@types/react@18.3.10)(react@18.3.1)': dependencies: - '@swc/helpers': 0.5.13 + '@swc/helpers': 0.5.15 '@types/react': 18.3.10 react: 18.3.1 @@ -7563,7 +7577,7 @@ snapshots: '@fluentui/react-proptypes@0.66.5': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 lodash: 4.17.21 prop-types: 15.8.1 @@ -8027,7 +8041,7 @@ snapshots: '@fluentui/state@0.66.5': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 '@fluentui/style-utilities@8.11.0(@types/react@18.3.10)(react@18.3.1)': dependencies: @@ -8043,7 +8057,7 @@ snapshots: '@fluentui/styles@0.66.5': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 csstype: 3.1.3 lodash: 4.17.21 @@ -8465,6 +8479,10 @@ snapshots: dependencies: tslib: 2.7.0 + '@swc/helpers@0.5.15': + dependencies: + tslib: 2.8.1 + '@ts-morph/common@0.12.3': dependencies: fast-glob: 3.3.2 @@ -9432,7 +9450,7 @@ snapshots: downshift@5.0.5(react@18.3.1): dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.26.9 compute-scroll-into-view: 1.0.11 prop-types: 15.8.1 react: 18.3.1 @@ -10473,7 +10491,7 @@ snapshots: lexical@0.17.1: {} - lib0@0.2.98: + lib0@0.2.99: dependencies: isomorphic.js: 0.2.5 @@ -11757,6 +11775,8 @@ snapshots: tslib@2.7.0: {} + tslib@2.8.1: {} + tsutils@3.21.0(typescript@5.6.2): dependencies: tslib: 1.14.1 @@ -12042,7 +12062,7 @@ snapshots: yjs@13.6.19: dependencies: - lib0: 0.2.98 + lib0: 0.2.99 yocto-queue@0.1.0: {} diff --git a/workbench-app/src/Constants.ts b/workbench-app/src/Constants.ts index 60a623e8..4cbf8ae9 100644 --- a/workbench-app/src/Constants.ts +++ b/workbench-app/src/Constants.ts @@ -1,8 +1,9 @@ // Allow static build of React code to access env vars // SEE https://create-react-app.dev/docs/title-and-meta-tags/#injecting-data-from-the-server-into-the-page -const serviceUrl = (window.VITE_SEMANTIC_WORKBENCH_SERVICE_URL && window.VITE_SEMANTIC_WORKBENCH_SERVICE_URL.startsWith('https://')) - ? window.VITE_SEMANTIC_WORKBENCH_SERVICE_URL - : (import.meta.env.VITE_SEMANTIC_WORKBENCH_SERVICE_URL) +const serviceUrl = + window.VITE_SEMANTIC_WORKBENCH_SERVICE_URL && window.VITE_SEMANTIC_WORKBENCH_SERVICE_URL.startsWith('https://') + ? window.VITE_SEMANTIC_WORKBENCH_SERVICE_URL + : import.meta.env.VITE_SEMANTIC_WORKBENCH_SERVICE_URL ? import.meta.env.VITE_SEMANTIC_WORKBENCH_SERVICE_URL : 'http://127.0.0.1:3000'; diff --git a/workbench-app/src/components/App/CodeLabel.tsx b/workbench-app/src/components/App/CodeLabel.tsx new file mode 100644 index 00000000..12451e6c --- /dev/null +++ b/workbench-app/src/components/App/CodeLabel.tsx @@ -0,0 +1,22 @@ +import { makeStyles, shorthands, tokens } from '@fluentui/react-components'; +import React from 'react'; + +const useClasses = makeStyles({ + root: { + ...shorthands.border(tokens.strokeWidthThin, 'solid', tokens.colorNeutralStroke2), + borderRadius: tokens.borderRadiusMedium, + backgroundColor: tokens.colorNeutralBackground3, + ...shorthands.padding(tokens.spacingVerticalXXS, tokens.spacingHorizontalS), + }, +}); + +interface CodeLabelProps { + children?: React.ReactNode; +} + +export const CodeLabel: React.FC = (props) => { + const { children } = props; + const classes = useClasses(); + + return {children}; +}; diff --git a/workbench-app/src/components/App/CommandButton.tsx b/workbench-app/src/components/App/CommandButton.tsx index 2bcc7eef..0460ad1c 100644 --- a/workbench-app/src/components/App/CommandButton.tsx +++ b/workbench-app/src/components/App/CommandButton.tsx @@ -1,16 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. -import { - Button, - ButtonProps, - makeStyles, - mergeClasses, - tokens, - ToolbarButton, - Tooltip, -} from '@fluentui/react-components'; +import { Button, ButtonProps, makeStyles, mergeClasses, tokens, ToolbarButton } from '@fluentui/react-components'; import React from 'react'; import { DialogControl, DialogControlContent } from './DialogControl'; +import { TooltipWrapper } from './TooltipWrapper'; const useClasses = makeStyles({ menuItem: { @@ -56,11 +49,7 @@ export const CommandButton: React.FC = (props) => { if (dialogContent?.trigger) { if (description) { - commandButton = ( - - {dialogContent.trigger} - - ); + commandButton = {dialogContent.trigger}; } else { commandButton = dialogContent.trigger; } @@ -81,7 +70,7 @@ export const CommandButton: React.FC = (props) => { } else if (iconOnly) { if (description) { commandButton = ( - + ); if (description) { - commandButton = ( - - {commandButton} - - ); + commandButton = {commandButton}; } } diff --git a/workbench-app/src/components/App/CopyButton.tsx b/workbench-app/src/components/App/CopyButton.tsx index 99f49f96..51284037 100644 --- a/workbench-app/src/components/App/CopyButton.tsx +++ b/workbench-app/src/components/App/CopyButton.tsx @@ -1,8 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. -import { Button, Slot, Tooltip, makeStyles, tokens } from '@fluentui/react-components'; +import { Button, Slot, makeStyles, tokens } from '@fluentui/react-components'; import { Checkmark24Regular, CopyRegular } from '@fluentui/react-icons'; import React from 'react'; +import { TooltipWrapper } from './TooltipWrapper'; const useClasses = makeStyles({ root: { @@ -48,13 +49,7 @@ export const CopyButton: React.FC = (props) => { - + )} {hasMoveUp && ( - + - + )} {hasMoveDown && ( - + - + )} )} diff --git a/workbench-app/src/components/App/LabelWithDescription.tsx b/workbench-app/src/components/App/LabelWithDescription.tsx index 3a6edd82..bebc27b0 100644 --- a/workbench-app/src/components/App/LabelWithDescription.tsx +++ b/workbench-app/src/components/App/LabelWithDescription.tsx @@ -1,8 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. -import { Text, Tooltip } from '@fluentui/react-components'; +import { Text } from '@fluentui/react-components'; import { QuestionCircle16Regular } from '@fluentui/react-icons'; import React from 'react'; +import { TooltipWrapper } from './TooltipWrapper'; interface LabelWithDescriptionProps { label: string; @@ -16,9 +17,9 @@ export const LabelWithDescription: React.FC = (props)
{label} {description && ( - + - + )}
); diff --git a/workbench-app/src/components/App/MenuItemControl.tsx b/workbench-app/src/components/App/MenuItemControl.tsx index f69de88a..f9a942bf 100644 --- a/workbench-app/src/components/App/MenuItemControl.tsx +++ b/workbench-app/src/components/App/MenuItemControl.tsx @@ -1,7 +1,8 @@ // Copyright (c) Microsoft. All rights reserved. -import { ButtonProps, MenuItem, Tooltip } from '@fluentui/react-components'; +import { ButtonProps, MenuItem } from '@fluentui/react-components'; import React from 'react'; +import { TooltipWrapper } from './TooltipWrapper'; type MenuItemControlProps = ButtonProps & { label?: string; @@ -18,9 +19,9 @@ export const MenuItemControl: React.FC = (props) => { if (iconOnly) { if (description) { menuItem = ( - + - + ); } else { menuItem = ; @@ -32,11 +33,7 @@ export const MenuItemControl: React.FC = (props) => { ); if (description) { - menuItem = ( - - {menuItem} - - ); + menuItem = {menuItem}; } } return menuItem; diff --git a/workbench-app/src/components/App/MiniControl.tsx b/workbench-app/src/components/App/MiniControl.tsx index cd8aa849..f5addd00 100644 --- a/workbench-app/src/components/App/MiniControl.tsx +++ b/workbench-app/src/components/App/MiniControl.tsx @@ -1,8 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. -import { Card, Label, Tooltip, makeStyles, shorthands, tokens } from '@fluentui/react-components'; +import { Card, Label, makeStyles, shorthands, tokens } from '@fluentui/react-components'; import React from 'react'; import { Link } from 'react-router-dom'; +import { TooltipWrapper } from './TooltipWrapper'; const useClasses = makeStyles({ header: { @@ -54,13 +55,7 @@ export const MiniControl: React.FC = (props) => { return (
- {tooltip ? ( - - {link} - - ) : ( - link - )} + {tooltip ? {link} : link}
{actions}
diff --git a/workbench-app/src/components/App/TooltipWrapper.tsx b/workbench-app/src/components/App/TooltipWrapper.tsx new file mode 100644 index 00000000..f26fe239 --- /dev/null +++ b/workbench-app/src/components/App/TooltipWrapper.tsx @@ -0,0 +1,32 @@ +import { Tooltip } from '@fluentui/react-components'; +import React from 'react'; + +interface TooltipWrapperProps { + content: string; + children: React.ReactElement; +} + +// Use forwardRef to allow it to still be used within a DialogTrigger +export const TooltipWrapper = React.forwardRef((props: TooltipWrapperProps, forwardedRef) => { + const { content, children, ...rest } = props; + + // rest will include any props passed by DialogTrigger, + // e.g. onClick, aria-expanded, data-dialog-trigger, etc. + + const onlyChild = React.Children.only(children); + + // Merge and forward everything onto the actual child (button, link, etc.) + const childWithAllProps = React.cloneElement(onlyChild, { + ...onlyChild.props, + ...rest, + ref: forwardedRef, + }); + + return ( + + {childWithAllProps} + + ); +}); + +TooltipWrapper.displayName = 'TooltipWrapper'; diff --git a/workbench-app/src/components/Conversations/ContentRenderers/MermaidContentRenderer.tsx b/workbench-app/src/components/Conversations/ContentRenderers/MermaidContentRenderer.tsx index cdb8f8ef..9720a677 100644 --- a/workbench-app/src/components/Conversations/ContentRenderers/MermaidContentRenderer.tsx +++ b/workbench-app/src/components/Conversations/ContentRenderers/MermaidContentRenderer.tsx @@ -14,6 +14,7 @@ import { import { ErrorCircle20Regular, Info20Regular, ZoomFit24Regular } from '@fluentui/react-icons'; import mermaid from 'mermaid'; import React from 'react'; +import { TooltipWrapper } from '../../App/TooltipWrapper'; import { DebugInspector } from '../DebugInspector'; mermaid.initialize({ @@ -141,9 +142,9 @@ export const MermaidContentRenderer: React.FC = (prop
{content.trim()}
- +