Skip to content

Commit 52ed165

Browse files
authored
Merge pull request #495 from microsoft/macae-v3-fr-dev-92
Macae v3 fr dev 92
2 parents 9ee5d1a + 0e41183 commit 52ed165

File tree

7 files changed

+103
-37
lines changed

7 files changed

+103
-37
lines changed

src/backend/common/models/messages_kernel.py

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from datetime import datetime, timezone
33
from enum import Enum
44
from typing import Any, Dict, List, Literal, Optional
5-
from pydantic import BaseModel
5+
66
from semantic_kernel.kernel_pydantic import Field, KernelBaseModel
77

88
class DataType(str, Enum):
@@ -111,21 +111,7 @@ class UserCurrentTeam(BaseDataModel):
111111
user_id: str
112112
team_id: str
113113

114-
class MStep(BaseModel):
115-
"""model of a step in a plan"""
116-
agent: str = ""
117-
action: str = ""
118-
class MPlan(BaseModel):
119-
"""model of a plan"""
120-
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
121-
user_id: str = ""
122-
team_id: str = ""
123-
plan_id: str = ""
124-
overall_status: PlanStatus = PlanStatus.created
125-
user_request: str = ""
126-
team: List[str] = []
127-
facts: str = ""
128-
steps: List[MStep] = []
114+
129115
class Plan(BaseDataModel):
130116
"""Represents a plan containing multiple steps."""
131117

@@ -136,7 +122,7 @@ class Plan(BaseDataModel):
136122
overall_status: PlanStatus = PlanStatus.in_progress
137123
approved: bool = False
138124
source: str = AgentType.PLANNER.value
139-
m_plan: Optional[MPlan] = None
125+
m_plan: Optional[Dict[str, Any]] = None
140126
summary: Optional[str] = None
141127
team_id: Optional[str] = None
142128
human_clarification_request: Optional[str] = None

src/backend/v3/api/router.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,9 +1127,9 @@ async def select_team(selection: TeamSelectionRequest, request: Request):
11271127
)
11281128

11291129
# save to in-memory config for current user
1130-
# team_config.set_current_team(
1131-
# user_id=user_id, team_configuration=team_configuration
1132-
# )
1130+
team_config.set_current_team(
1131+
user_id=user_id, team_configuration=team_configuration
1132+
)
11331133

11341134
# Track the team selection event
11351135
track_event_if_configured(
@@ -1340,12 +1340,13 @@ async def get_plan_by_id(request: Request, plan_id: Optional[str] = Query(None)
13401340

13411341
team = await memory_store.get_team_by_id(team_id=plan.team_id)
13421342
agent_messages = await memory_store.get_agent_messages(plan_id=plan.plan_id)
1343-
1343+
mplan = plan.m_plan if plan.m_plan else None
1344+
plan.m_plan = None # remove m_plan from plan object for response
13441345
return {
13451346
"plan": plan,
13461347
"team": team if team else None,
13471348
"messages": agent_messages,
1348-
"m_plan": plan.m_plan,
1349+
"m_plan": mplan,
13491350
}
13501351
else:
13511352
track_event_if_configured(

src/backend/v3/common/services/plan_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ async def handle_plan_approval(
158158
orchestration_config.plans[human_feedback.m_plan_id] = mplan
159159
if plan:
160160
plan.overall_status = PlanStatus.approved
161-
plan.m_plan = mplan
161+
plan.m_plan = mplan.model_dump()
162162
await memory_store.update_plan(plan)
163163
track_event_if_configured(
164164
"PlanApproved",

src/backend/v3/models/models.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import uuid
22
from datetime import datetime, timezone
33
from enum import Enum
4-
from typing import List, Literal, Optional
4+
from typing import Any, Dict, List, Literal, Optional
55

6-
from pydantic import BaseModel, Field
6+
from dataclasses import asdict, dataclass, field
77

8-
from common.models.messages_kernel import DataType
8+
from pydantic import BaseModel, Field
99

1010

1111
class PlanStatus(str, Enum):
@@ -16,11 +16,13 @@ class PlanStatus(str, Enum):
1616
FAILED = "failed"
1717
CANCELLED = "cancelled"
1818

19+
1920
class MStep(BaseModel):
2021
"""model of a step in a plan"""
2122
agent: str = ""
2223
action: str = ""
2324

25+
2426
class MPlan(BaseModel):
2527
"""model of a plan"""
2628
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
@@ -31,4 +33,5 @@ class MPlan(BaseModel):
3133
user_request: str = ""
3234
team: List[str] = []
3335
facts: str = ""
34-
steps: List[MStep] = []
36+
steps: List[MStep] = []
37+

src/frontend/src/models/plan.tsx

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,50 @@ export interface MStepBE {
127127
/** Action to be performed */
128128
action: string;
129129
}
130+
/**
131+
* Represents a user request item within the user_request object
132+
*/
133+
export interface UserRequestItem {
134+
/** AI model identifier */
135+
ai_model_id?: string | null;
136+
/** Metadata */
137+
metadata?: Record<string, any>;
138+
/** Content type */
139+
content_type?: string;
140+
/** Text content */
141+
text?: string;
142+
/** Encoding */
143+
encoding?: string | null;
144+
}
130145

131-
export interface MPlanBE extends BaseModel {
132-
/** The type of data model */
133-
data_type: "m_plan";
146+
/**
147+
* Represents the user_request object structure from the database
148+
*/
149+
export interface UserRequestObject {
150+
/** AI model identifier */
151+
ai_model_id?: string | null;
152+
/** Metadata */
153+
metadata?: Record<string, any>;
154+
/** Content type */
155+
content_type?: string;
156+
/** Role */
157+
role?: string;
158+
/** Name */
159+
name?: string | null;
160+
/** Items array containing the actual request text */
161+
items?: UserRequestItem[];
162+
/** Encoding */
163+
encoding?: string | null;
164+
/** Finish reason */
165+
finish_reason?: string | null;
166+
/** Status */
167+
status?: string | null;
168+
}
169+
170+
export interface MPlanBE {
171+
172+
/** Unique identifier */
173+
id: string;
134174
/** User identifier */
135175
user_id: string;
136176
/** Team identifier */
@@ -139,8 +179,8 @@ export interface MPlanBE extends BaseModel {
139179
plan_id: string;
140180
/** Overall status of the plan */
141181
overall_status: PlanStatus;
142-
/** User's original request */
143-
user_request: string;
182+
/** User's original request - can be string or complex object */
183+
user_request: string | UserRequestObject;
144184
/** List of team member names */
145185
team: string[];
146186
/** Facts or context for the plan */

src/frontend/src/pages/PlanPage.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const PlanPage: React.FC = () => {
4747
const [waitingForPlan, setWaitingForPlan] = useState<boolean>(true);
4848
const [showProcessingPlanSpinner, setShowProcessingPlanSpinner] = useState<boolean>(false);
4949
const [showApprovalButtons, setShowApprovalButtons] = useState<boolean>(true);
50-
const [continueWithWebsocketFlow, setContinueWithWebsocketFlow] = useState<boolean>(true);
50+
const [continueWithWebsocketFlow, setContinueWithWebsocketFlow] = useState<boolean>(false);
5151
// WebSocket connection state
5252
const [wsConnected, setWsConnected] = useState<boolean>(false);
5353
const [streamingMessages, setStreamingMessages] = useState<StreamingPlanUpdate[]>([]);
@@ -279,7 +279,7 @@ const PlanPage: React.FC = () => {
279279
// WebSocket connection with proper error handling and v3 backend compatibility
280280
useEffect(() => {
281281
if (planId && continueWithWebsocketFlow) {
282-
console.log('🔌 Connecting WebSocket:', { planId });
282+
console.log('🔌 Connecting WebSocket:', { planId, continueWithWebsocketFlow });
283283

284284
const connectWebSocket = async () => {
285285
try {
@@ -355,6 +355,7 @@ const PlanPage: React.FC = () => {
355355
setShowApprovalButtons(true);
356356

357357
} else {
358+
setShowApprovalButtons(false);
358359
setWaitingForPlan(false);
359360
}
360361
if (planResult?.plan?.overall_status !== PlanStatus.COMPLETED) {

src/frontend/src/services/PlanDataService.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import {
2020
MStepBE,
2121
AgentMessageResponse,
2222
FinalMessage,
23-
StreamingMessage
23+
StreamingMessage,
24+
UserRequestObject
2425
} from "@/models";
2526
import { apiService } from "@/api";
2627

@@ -122,6 +123,37 @@ export class PlanDataService {
122123
}))
123124
};
124125
}
126+
/**
127+
* Extracts the actual text from a user_request object or string
128+
* @param userRequest - Either a string or UserRequestObject
129+
* @returns The extracted text string
130+
*/
131+
static extractUserRequestText(userRequest: string | UserRequestObject): string {
132+
if (typeof userRequest === 'string') {
133+
return userRequest;
134+
}
135+
136+
if (userRequest && typeof userRequest === 'object') {
137+
// Look for text in the items array
138+
if (Array.isArray(userRequest.items)) {
139+
const textItem = userRequest.items.find(item => item.text);
140+
if (textItem?.text) {
141+
return textItem.text;
142+
}
143+
}
144+
145+
// Fallback: try to find any text content
146+
if (userRequest.content_type === 'text' && 'text' in userRequest) {
147+
return (userRequest as any).text || '';
148+
}
149+
150+
// Last resort: stringify the object
151+
return JSON.stringify(userRequest);
152+
}
153+
154+
return '';
155+
}
156+
125157
/**
126158
* Converts MPlanBE to MPlanData
127159
* @param mplanBE - MPlanBE from backend
@@ -132,6 +164,9 @@ export class PlanDataService {
132164
return null;
133165
}
134166

167+
// Extract the actual user request text
168+
const userRequestText = this.extractUserRequestText(mplanBE.user_request);
169+
135170
// Convert MStepBE[] to the MPlanData steps format
136171
const steps = mplanBE.steps.map((stepBE: MStepBE, index: number) => ({
137172
id: index + 1, // MPlanData expects numeric id starting from 1
@@ -151,12 +186,12 @@ export class PlanDataService {
151186
return {
152187
id: mplanBE.id,
153188
status: mplanBE.overall_status.toString().toUpperCase(),
154-
user_request: mplanBE.user_request,
189+
user_request: userRequestText,
155190
team: mplanBE.team,
156191
facts: mplanBE.facts,
157192
steps: steps,
158193
context: {
159-
task: mplanBE.user_request,
194+
task: userRequestText,
160195
participant_descriptions: {} // Default empty object since it's not in MPlanBE
161196
},
162197
// Additional fields from m_plan

0 commit comments

Comments
 (0)