ohmyapi commited on
Commit
5fc7bc7
·
1 Parent(s): ad25dd6

fix: prevent response truncation for complex multi-step queries

Browse files
Files changed (1) hide show
  1. emergent2api/backends/jobs.py +47 -10
emergent2api/backends/jobs.py CHANGED
@@ -65,7 +65,10 @@ class JobsBackend(EmergentBackend):
65
  has_received_anything = False
66
  job_completed = False
67
  last_change_time = 0.0
68
- max_wait_cycles = 900
 
 
 
69
  start_time = time.time()
70
 
71
  await asyncio.sleep(3.0)
@@ -84,6 +87,23 @@ class JobsBackend(EmergentBackend):
84
  if status in ("completed", "done", "finished"):
85
  job_completed = True
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  current_full_text = ""
88
  current_thinking = ""
89
  for item in data_items:
@@ -108,6 +128,7 @@ class JobsBackend(EmergentBackend):
108
  confirmed_end = False
109
  has_received_anything = True
110
  last_change_time = time.time()
 
111
  if stream and delta:
112
  yield {"type": "text", "content": delta}
113
  else:
@@ -117,22 +138,38 @@ class JobsBackend(EmergentBackend):
117
  logger.info("Stream completed (job status=completed)")
118
  break
119
 
120
- stable_secs = time.time() - last_change_time if last_change_time else 0
 
 
 
 
 
 
 
 
 
 
 
 
121
  text_len = len(full_text)
122
  if text_len < 50:
123
- stable_limit = 15.0
124
  elif text_len < 500:
125
- stable_limit = 25.0
126
  else:
127
- stable_limit = 45.0
128
- if has_received_anything and full_text and stable_secs >= stable_limit:
 
 
 
 
 
129
  if not confirmed_end:
130
- logger.debug(f"Content stable for {stable_secs:.0f}s (len={text_len}), confirming...")
131
  confirmed_end = True
132
- confirm_wait = 5.0 if text_len < 200 else 10.0
133
- await asyncio.sleep(confirm_wait)
134
  continue
135
- logger.info(f"Stream completed (stable {stable_secs:.0f}s, {text_len} chars)")
136
  break
137
 
138
  await self._dynamic_sleep(consecutive_unchanged, has_received_anything)
 
65
  has_received_anything = False
66
  job_completed = False
67
  last_change_time = 0.0
68
+ last_activity_time = 0.0
69
+ prev_item_count = 0
70
+ prev_max_step = -1
71
+ max_wait_cycles = 1200
72
  start_time = time.time()
73
 
74
  await asyncio.sleep(3.0)
 
87
  if status in ("completed", "done", "finished"):
88
  job_completed = True
89
 
90
+ cur_item_count = len(data_items)
91
+ cur_max_step = -1
92
+ for item in data_items:
93
+ payload = item.get("traj_payload") or {}
94
+ step = payload.get("step_num", -1)
95
+ if isinstance(step, (int, float)) and step > cur_max_step:
96
+ cur_max_step = int(step)
97
+
98
+ activity_changed = (
99
+ cur_item_count > prev_item_count
100
+ or cur_max_step > prev_max_step
101
+ )
102
+ if activity_changed:
103
+ last_activity_time = time.time()
104
+ prev_item_count = cur_item_count
105
+ prev_max_step = cur_max_step
106
+
107
  current_full_text = ""
108
  current_thinking = ""
109
  for item in data_items:
 
128
  confirmed_end = False
129
  has_received_anything = True
130
  last_change_time = time.time()
131
+ last_activity_time = time.time()
132
  if stream and delta:
133
  yield {"type": "text", "content": delta}
134
  else:
 
138
  logger.info("Stream completed (job status=completed)")
139
  break
140
 
141
+ now = time.time()
142
+ text_stable_secs = now - last_change_time if last_change_time else 0
143
+ activity_idle_secs = now - last_activity_time if last_activity_time else 0
144
+
145
+ if has_received_anything and full_text and activity_idle_secs >= 90.0:
146
+ if not confirmed_end:
147
+ logger.debug(f"No activity for {activity_idle_secs:.0f}s, confirming end...")
148
+ confirmed_end = True
149
+ await asyncio.sleep(10.0)
150
+ continue
151
+ logger.info(f"Stream completed (idle {activity_idle_secs:.0f}s, {len(full_text)} chars)")
152
+ break
153
+
154
  text_len = len(full_text)
155
  if text_len < 50:
156
+ stable_limit = 20.0
157
  elif text_len < 500:
158
+ stable_limit = 40.0
159
  else:
160
+ stable_limit = 90.0
161
+
162
+ if has_received_anything and full_text and text_stable_secs >= stable_limit:
163
+ if activity_idle_secs < 60.0:
164
+ logger.debug(f"Text stable {text_stable_secs:.0f}s but agent still active (idle {activity_idle_secs:.0f}s), waiting...")
165
+ await asyncio.sleep(3.0)
166
+ continue
167
  if not confirmed_end:
168
+ logger.debug(f"Text stable {text_stable_secs:.0f}s + agent idle {activity_idle_secs:.0f}s, confirming...")
169
  confirmed_end = True
170
+ await asyncio.sleep(10.0)
 
171
  continue
172
+ logger.info(f"Stream completed (stable {text_stable_secs:.0f}s, {text_len} chars)")
173
  break
174
 
175
  await self._dynamic_sleep(consecutive_unchanged, has_received_anything)