Skip to content

Commit 0be1150

Browse files
committed
feat(chat): add keys to bridge
1 parent 40de0d3 commit 0be1150

2 files changed

Lines changed: 39 additions & 6 deletions

File tree

src/uipath/_cli/_chat/_bridge.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
import os
77
import uuid
88
from typing import Any
9-
from urllib.parse import urlparse
9+
from urllib.parse import urlencode, urlparse
1010

11+
from uipath._utils.constants import (
12+
ENV_FOLDER_KEY,
13+
ENV_JOB_KEY,
14+
)
1115
from uipath.core.chat import (
1216
UiPathConversationEvent,
1317
UiPathConversationExchangeEndEvent,
@@ -389,7 +393,6 @@ def get_chat_bridge(
389393
assert context.conversation_id is not None, "conversation_id must be set in context"
390394
assert context.exchange_id is not None, "exchange_id must be set in context"
391395

392-
# Extract host from UIPATH_URL
393396
base_url = os.environ.get("UIPATH_URL")
394397
if not base_url:
395398
raise RuntimeError(
@@ -401,9 +404,20 @@ def get_chat_bridge(
401404
raise RuntimeError(f"Invalid UIPATH_URL format: {base_url}")
402405

403406
host = parsed.netloc
407+
conversation_id = context.conversation_id
408+
folder_key = os.environ.get(ENV_FOLDER_KEY)
409+
job_key = os.environ.get(ENV_JOB_KEY)
410+
411+
# Build query params for CAS for use verifying the requesting agent should have access when runAsMe=False
412+
query_params: dict[str, str] = {
413+
"conversationId": conversation_id,
414+
"folderKey": folder_key or "",
415+
"jobKey": job_key or "",
416+
}
417+
query_params = {k: v for k, v in query_params.items() if v}
418+
query_string = urlencode(query_params)
404419

405-
# Construct WebSocket URL for CAS
406-
websocket_url = f"wss://{host}?conversationId={context.conversation_id}"
420+
websocket_url = f"wss://{host}?{query_string}"
407421
websocket_path = "autopilotforeveryone_/websocket_/socket.io"
408422

409423
if os.environ.get("CAS_WEBSOCKET_HOST"):
@@ -420,13 +434,13 @@ def get_chat_bridge(
420434
or os.environ.get("UIPATH_TENANT_ID", ""),
421435
"X-UiPath-Internal-AccountId": f"{context.org_id}"
422436
or os.environ.get("UIPATH_ORGANIZATION_ID", ""),
423-
"X-UiPath-ConversationId": context.conversation_id,
437+
"X-UiPath-ConversationId": conversation_id,
424438
}
425439

426440
return SocketIOChatBridge(
427441
websocket_url=websocket_url,
428442
websocket_path=websocket_path,
429-
conversation_id=context.conversation_id,
443+
conversation_id=conversation_id,
430444
exchange_id=context.exchange_id,
431445
headers=headers,
432446
)

tests/cli/chat/test_bridge.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,25 @@ def test_get_chat_bridge_includes_conversation_id_in_url(
165165

166166
assert "conversationId=my-conversation-id" in bridge.websocket_url
167167

168+
def test_get_chat_bridge_includes_folder_key_job_key_when_set(
169+
self, monkeypatch: pytest.MonkeyPatch
170+
) -> None:
171+
"""folderKey and jobKey are included in URL when env vars are set (CAS contract)."""
172+
monkeypatch.setenv("UIPATH_URL", "https://cloud.uipath.com/org/tenant")
173+
monkeypatch.setenv("UIPATH_ACCESS_TOKEN", "test-token")
174+
monkeypatch.setenv("UIPATH_FOLDER_KEY", "folder-guid-456")
175+
monkeypatch.setenv("UIPATH_JOB_KEY", "job-guid-789")
176+
monkeypatch.delenv("CAS_WEBSOCKET_HOST", raising=False)
177+
178+
context = MockRuntimeContext(conversation_id="conv-id")
179+
180+
bridge = cast(SocketIOChatBridge, get_chat_bridge(cast(Any, context)))
181+
182+
assert "conversationId=conv-id" in bridge.websocket_url
183+
assert "folderKey=folder-guid-456" in bridge.websocket_url
184+
assert "jobKey=job-guid-789" in bridge.websocket_url
185+
assert "robotKey" not in bridge.websocket_url
186+
168187

169188
class TestGetChatBridge:
170189
"""Tests for get_chat_bridge factory function."""

0 commit comments

Comments
 (0)