Skip to content

Commit fd2de4c

Browse files
committed
Merge remote-tracking branch 'template/main'
2 parents 38e1fcc + 85b64b3 commit fd2de4c

1 file changed

Lines changed: 50 additions & 22 deletions

File tree

src/agent/context.py

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional, Dict, Any
1+
from typing import Optional, Dict, Any, Tuple
22

33

44
def parse_json_to_prompt(context: dict, task_progress: dict) -> str:
@@ -11,7 +11,7 @@ def parse_json_to_prompt(context: dict, task_progress: dict) -> str:
1111
set_data = context.get("set", {})
1212
current_part = task_progress.get("currentPart", {}) if task_progress else {}
1313
current_part_position = current_part.get("position")
14-
submissions = current_part.get("responseAreas", [])
14+
student_work_index = _build_student_work_index(task_progress)
1515

1616
sections = []
1717

@@ -63,7 +63,7 @@ def parse_json_to_prompt(context: dict, task_progress: dict) -> str:
6363
part_position = part.get("position", i + 1)
6464
is_current = current_part_position == part_position
6565
time_on_part = current_part.get("timeSpentOnPart") if is_current else None
66-
sections.append(_format_part(part, part_position, is_current, time_on_part, submissions))
66+
sections.append(_format_part(part, part_position, is_current, time_on_part, student_work_index))
6767

6868
# Combine
6969
valid_sections = [s.strip() for s in sections if s and s.strip()]
@@ -72,11 +72,34 @@ def parse_json_to_prompt(context: dict, task_progress: dict) -> str:
7272
return "\n".join(line for line in content.split("\n") if line.strip() or not line).strip()
7373

7474

75+
def _build_student_work_index(task_progress: dict) -> Dict[Tuple[int, int], dict]:
76+
"""Index the reported progress by (part position, response area position)."""
77+
if not task_progress:
78+
return {}
79+
80+
reported_parts = []
81+
current_part = task_progress.get("currentPart")
82+
if current_part:
83+
reported_parts.append(current_part)
84+
reported_parts.extend(task_progress.get("parts") or [])
85+
86+
index: Dict[Tuple[int, int], dict] = {}
87+
for reported_part in reported_parts:
88+
part_position = reported_part.get("position")
89+
for j, ra in enumerate(reported_part.get("responseAreas") or []):
90+
ra_part_position = ra.get("partPosition", part_position)
91+
ra_position = ra.get("position", j + 1)
92+
if ra_part_position is None or ra_position is None:
93+
continue
94+
index[(ra_part_position, ra_position)] = ra
95+
return index
96+
97+
7598
def _part_letter(position: int) -> str:
7699
"""Map a 1-indexed part position to its letter (1 -> 'a', 2 -> 'b', ...)."""
77100
return chr(96 + position)
78101

79-
def _format_part(part: dict, part_position: int, is_current: bool, time_on_part: Optional[str], submissions: list) -> str:
102+
def _format_part(part: dict, part_position: int, is_current: bool, time_on_part: Optional[str], student_work_index: Dict[Tuple[int, int], dict]) -> str:
80103
letter = _part_letter(part_position)
81104
status_text = " [CURRENTLY WORKING ON]" if is_current else ""
82105
header = f"## Part ({letter}){status_text}"
@@ -89,7 +112,7 @@ def _format_part(part: dict, part_position: int, is_current: bool, time_on_part:
89112
response_areas = []
90113
for j, ra in enumerate(part.get("responseAreas", [])):
91114
ra_position = ra.get("position", j + 1)
92-
student_work = _get_student_work(ra_position, submissions)
115+
student_work = _get_student_work(part_position, ra_position, student_work_index)
93116
response_areas.append(_format_response_area(ra_position, ra.get("preResponseText"), ra.get("answer"), student_work))
94117
ra_block = f"\n### Response Areas\n\n{''.join(response_areas)}" if response_areas else ""
95118

@@ -110,24 +133,29 @@ def _format_part(part: dict, part_position: int, is_current: bool, time_on_part:
110133

111134
return "\n".join([header, content, ra_block, answer_block, solutions_block, tutorials_block]) + "\n---\n"
112135

113-
def _get_student_work(ra_position: int, submissions: list) -> Dict[str, Any]:
114-
"""Look up the student's submission for a 1-indexed response area position."""
115-
if 1 <= ra_position <= len(submissions):
116-
s = submissions[ra_position - 1]
117-
latest = s.get("latestSubmission") or {}
118-
if latest:
119-
return {
120-
"has_submissions": True,
121-
"latest_response": latest.get("submission"),
122-
"latest_feedback": latest.get("feedback"),
123-
"total_submissions": s.get("totalSubmissions"),
124-
"total_wrong": s.get("wrongSubmissions"),
125-
}
126-
return {"has_submissions": False}
127-
128-
def _format_response_area(position: int, task_description: Optional[str], expected_answer: Any, student_work: Dict[str, Any]) -> str:
136+
def _get_student_work(part_position: int, ra_position: int, student_work_index: Dict[Tuple[int, int], dict]) -> Optional[Dict[str, Any]]:
137+
"""Look up the student's progress on a 1-indexed part/response area position."""
138+
reported = student_work_index.get((part_position, ra_position))
139+
if reported is None:
140+
return None
141+
142+
latest = reported.get("latestSubmission") or {}
143+
if not latest:
144+
return {"has_submissions": False}
145+
146+
return {
147+
"has_submissions": True,
148+
"latest_response": latest.get("submission"),
149+
"latest_feedback": latest.get("feedback"),
150+
"total_submissions": reported.get("totalSubmissions"),
151+
"total_wrong": reported.get("wrongSubmissions"),
152+
}
153+
154+
def _format_response_area(position: int, task_description: Optional[str], expected_answer: Any, student_work: Optional[Dict[str, Any]]) -> str:
129155
task_text = f"- Task: {task_description}" if task_description else "- Task: Not specified"
130-
if not student_work.get("has_submissions"):
156+
if student_work is None:
157+
submission_text = "- Student's work on this response area: Not reported"
158+
elif not student_work.get("has_submissions"):
131159
submission_text = "- Student's work on this response area: No response submitted yet"
132160
else:
133161
submission_text = (

0 commit comments

Comments
 (0)