+
Loading plan data...
@@ -674,6 +746,14 @@ const PlanPage: React.FC = () => {
planApprovalRequest={planApprovalRequest}
/>
+
+ {/* Plan Cancellation Confirmation Dialog */}
+
);
};
diff --git a/src/frontend/src/services/PlanDataService.tsx b/src/frontend/src/services/PlanDataService.tsx
index 18770a114..e2c2b9e02 100644
--- a/src/frontend/src/services/PlanDataService.tsx
+++ b/src/frontend/src/services/PlanDataService.tsx
@@ -383,7 +383,7 @@ export class PlanDataService {
const facts =
body
- .match(/facts="([^"]*(?:\\.[^"]*)*)"/)?.[1]
+ .match(/facts="((?:[^"\\]|\\.)*)"/)?.[1]
?.replace(/\\n/g, '\n')
.replace(/\\"/g, '"') || '';
@@ -792,7 +792,7 @@ export class PlanDataService {
if (!source) return null;
// question=( "...") OR ('...')
- const questionRegex = /question=(?:"((?:\\.|[^"])*)"|'((?:\\.|[^'])*)')/;
+ const questionRegex = /question=(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')/;
const qMatch = source.match(questionRegex);
if (!qMatch) return null;
diff --git a/src/frontend/src/styles/Panel.css b/src/frontend/src/styles/Panel.css
new file mode 100644
index 000000000..9c56a0418
--- /dev/null
+++ b/src/frontend/src/styles/Panel.css
@@ -0,0 +1,74 @@
+/* Panel Toolbar Styles */
+.panel-toolbar {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 16px;
+ box-sizing: border-box;
+ height: 56px;
+}
+
+.panel-title {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ flex-shrink: 1;
+ overflow: hidden;
+ min-width: 0;
+}
+
+.panel-title-text {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.panel-title-clickable {
+ text-decoration: none;
+ color: inherit;
+ display: flex;
+ align-items: center;
+ min-width: 0;
+ flex-shrink: 1;
+ cursor: pointer;
+}
+
+.panel-title-icon {
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+}
+
+.panel-tools {
+ display: flex;
+ align-items: center;
+ flex-grow: 1;
+ justify-content: flex-end;
+ min-width: 0;
+}
+
+/* Plan Cancellation Dialog Styles */
+.plan-cancellation-dialog-title {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.plan-cancellation-warning-icon {
+ color: var(--colorPaletteYellowForeground1);
+}
+
+/* Button styles for consistency */
+.clickable-element {
+ cursor: pointer;
+ transition: background-color 0.2s ease-in-out;
+}
+
+.clickable-element:hover {
+ background-color: var(--colorSubtleBackgroundHover);
+}
+
+.clickable-element:focus-visible {
+ outline: 2px solid var(--colorStrokeFocus2);
+ outline-offset: 2px;
+}
\ No newline at end of file
diff --git a/src/frontend/src/styles/PlanPage.css b/src/frontend/src/styles/PlanPage.css
index 0739eb742..4c465c5ca 100644
--- a/src/frontend/src/styles/PlanPage.css
+++ b/src/frontend/src/styles/PlanPage.css
@@ -53,6 +53,20 @@
min-height: 200px;
}
+.plan-loading-spinner {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ justify-content: center;
+ padding: 20px;
+}
+
+.plan-error-message {
+ text-align: center;
+ padding: 40px 20px;
+ color: var(--colorNeutralForeground2);
+}
+
.loadingWrapper {
height: 100%;
display: flex;
diff --git a/src/frontend/src/styles/PlanPanelLeft.css b/src/frontend/src/styles/PlanPanelLeft.css
index 5a8831b44..ad8d3ea6f 100644
--- a/src/frontend/src/styles/PlanPanelLeft.css
+++ b/src/frontend/src/styles/PlanPanelLeft.css
@@ -39,6 +39,25 @@ background: radial-gradient(circle, rgba(238, 174, 221, 1) 0%, rgba(117, 121, 23
color: #2F2F4A; */
}
+/* Panel Layout Styles */
+.panel-left-container {
+ flex-shrink: 0;
+ display: flex;
+ overflow: hidden;
+}
+
+.team-selector-container {
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+
+.panel-footer-content {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ width: 100%;
+}
+
/* TASKLIST */
.task-tab {
@@ -87,4 +106,4 @@ color: #2F2F4A; */
.task-tab:hover .task-menu-button {
opacity: 1;
-}
+}
\ No newline at end of file
diff --git a/src/frontend/src/styles/TeamSelector.module.css b/src/frontend/src/styles/TeamSelector.module.css
index 987e3be7a..c13fa12df 100644
--- a/src/frontend/src/styles/TeamSelector.module.css
+++ b/src/frontend/src/styles/TeamSelector.module.css
@@ -407,7 +407,23 @@
background-color: var(--colorNeutralBackground3) !important;
color: var(--colorNeutralForeground1) !important;
}
+.moreButtonDisabled {
+ color: var(--colorNeutralForeground4) !important;
+ background-color: transparent !important;
+ cursor: not-allowed !important;
+ opacity: 0.6 !important;
+}
+
+.moreButtonDisabled:hover {
+ background-color: transparent !important;
+ color: var(--colorNeutralForeground4) !important;
+ opacity: 0.6 !important;
+}
+/* Ensure tooltips appear above other dialog content */
+:global(.fui-Tooltip) {
+ z-index: 9999 !important;
+}
/* Team Selector Button */
.teamSelectorButton {
width: 100%;
diff --git a/src/mcp_server/pyproject.toml b/src/mcp_server/pyproject.toml
index 4b9dc385b..4171f90f0 100644
--- a/src/mcp_server/pyproject.toml
+++ b/src/mcp_server/pyproject.toml
@@ -17,11 +17,11 @@ dynamic = ["version"]
dependencies = [
"fastmcp==2.11.3",
"uvicorn[standard]==0.32.1",
- "python-dotenv>=1.1.0",
+ "python-dotenv==1.1.1",
"azure-identity==1.19.0",
"pydantic==2.11.7",
"pydantic-settings==2.6.1",
- "python-multipart==0.0.17",
+ "python-multipart==0.0.18",
"httpx==0.28.1",
]
diff --git a/src/tests/agents/test_foundry_integration.py b/src/tests/agents/test_foundry_integration.py
index b35661d6a..d1febec71 100644
--- a/src/tests/agents/test_foundry_integration.py
+++ b/src/tests/agents/test_foundry_integration.py
@@ -14,8 +14,8 @@
sys.path.insert(0, str(backend_path))
# Now import from the v3 package
-from v3.magentic_agents.foundry_agent import FoundryAgentTemplate
-from v3.magentic_agents.models.agent_models import (BingConfig, MCPConfig,
+from src.backend.v3.magentic_agents.foundry_agent import FoundryAgentTemplate
+from src.backend.v3.magentic_agents.models.agent_models import (BingConfig, MCPConfig,
SearchConfig)
@@ -274,4 +274,4 @@ async def test_multiple_capabilities_together(self):
if __name__ == "__main__":
"""Run the tests directly for debugging."""
- pytest.main([__file__, "-v", "-s"])
\ No newline at end of file
+ pytest.main([__file__, "-v", "-s"])
diff --git a/src/tests/mcp_server/test_factory.py b/src/tests/mcp_server/test_factory.py
index a1e0b1c81..ca1172149 100644
--- a/src/tests/mcp_server/test_factory.py
+++ b/src/tests/mcp_server/test_factory.py
@@ -3,7 +3,7 @@
"""
import pytest
-from core.factory import MCPToolFactory, Domain, MCPToolBase
+from src.mcp_server.core.factory import MCPToolFactory, Domain, MCPToolBase
class TestMCPToolFactory:
diff --git a/src/tests/mcp_server/test_hr_service.py b/src/tests/mcp_server/test_hr_service.py
index 17b8d0dd6..c0323d0d8 100644
--- a/src/tests/mcp_server/test_hr_service.py
+++ b/src/tests/mcp_server/test_hr_service.py
@@ -3,8 +3,8 @@
"""
import pytest
-from services.hr_service import HRService
-from core.factory import Domain
+from src.mcp_server.services.hr_service import HRService
+from src.mcp_server.core.factory import Domain
class TestHRService:
diff --git a/src/tests/mcp_server/test_utils.py b/src/tests/mcp_server/test_utils.py
index a49e07712..f4925f889 100644
--- a/src/tests/mcp_server/test_utils.py
+++ b/src/tests/mcp_server/test_utils.py
@@ -4,12 +4,12 @@
import pytest
from datetime import datetime
-from utils.date_utils import (
+from src.mcp_server.utils.date_utils import (
format_date_for_user,
get_current_timestamp,
format_timestamp_for_display,
)
-from utils.formatters import (
+from src.mcp_server.utils.formatters import (
format_mcp_response,
format_error_response,
format_success_response,