Neural Arun commited on
Commit
7762197
·
1 Parent(s): 28980f2

fixed tool error

Browse files
Files changed (3) hide show
  1. core/agent.py +146 -59
  2. core/api.py +24 -37
  3. core/bot.py +19 -19
core/agent.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import hashlib
2
  import html
3
  import json
@@ -48,6 +49,7 @@ TELEGRAM_MESSAGE_CHAR_LIMIT = 3500
48
  _GLOBAL_VECTORSTORE = None
49
  _GLOBAL_BM25 = None
50
  _GLOBAL_COMPRESSOR = None
 
51
 
52
  _RECENT_ALERTS: Dict[str, float] = {}
53
 
@@ -213,6 +215,37 @@ def send_debug_event(
213
  return "SUCCESS: debug event sent."
214
 
215
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  def _build_notification_metadata(
217
  reason: str,
218
  user_metadata: Optional[Dict[str, Any]] = None,
@@ -649,6 +682,25 @@ def _tool_map(tools):
649
  return {tool_obj.name: tool_obj for tool_obj in tools}
650
 
651
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652
  def _tool_was_used(scratchpad: List[Any], tool_name: str) -> bool:
653
  for item in scratchpad:
654
  if isinstance(item, dict) and item.get("name") == tool_name:
@@ -659,10 +711,6 @@ def _tool_was_used(scratchpad: List[Any], tool_name: str) -> bool:
659
  if tool_call.get("name") == tool_name:
660
  return True
661
 
662
- if isinstance(item, ToolMessage) and tool_name == "notify_arun":
663
- if str(getattr(item, "tool_call_id", "")).startswith("pre_notify_"):
664
- return True
665
-
666
  return False
667
 
668
 
@@ -671,38 +719,60 @@ def _run_pre_escalation(
671
  user_input: str,
672
  tool_map: Dict[str, Any],
673
  user_metadata: Optional[Dict[str, Any]] = None,
674
- ) -> List[ToolMessage]:
675
- messages: List[ToolMessage] = []
676
- if route.get("needs_notify"):
677
- category = route.get("notify_category") or "UNKNOWN_QUESTION"
678
- result = tool_map["notify_arun"].invoke(
679
- {
680
- "category": category,
681
- "user_input": user_input,
682
- "user_metadata_json": json.dumps(
683
- _build_notification_metadata(
684
- reason=route.get("reason", "unknown"),
685
- user_metadata=user_metadata,
686
- )
687
- ),
688
- }
689
- )
690
- messages.append(
691
- ToolMessage(
692
- content=str(result),
693
- tool_call_id=f"pre_notify_{int(time.time())}",
694
- )
695
- )
696
- return messages
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
697
 
698
 
699
  def run_pre_escalation(
700
  user_input: str,
701
  tool_map: Dict[str, Any],
702
  user_metadata: Optional[Dict[str, Any]] = None,
703
- ) -> List[ToolMessage]:
 
704
  route = _route_user_input(user_input)
705
- return _run_pre_escalation(route, user_input, tool_map, user_metadata=user_metadata)
 
 
 
 
 
 
706
 
707
 
708
  def maybe_notify_arun(
@@ -711,6 +781,7 @@ def maybe_notify_arun(
711
  scratchpad: List[Any],
712
  tool_map: Dict[str, Any],
713
  user_metadata: Optional[Dict[str, Any]] = None,
 
714
  ) -> Optional[str]:
715
  """
716
  Deterministic safety-net escalation used by API / bot flows.
@@ -718,7 +789,7 @@ def maybe_notify_arun(
718
  remembering to call `notify_arun` on its own.
719
  """
720
  route = _route_user_input(user_input)
721
- used_notify_tool = _tool_was_used(scratchpad, "notify_arun")
722
 
723
  should_notify = route.get("needs_notify", False)
724
  category = route.get("notify_category") or "UNKNOWN_QUESTION"
@@ -736,19 +807,45 @@ def maybe_notify_arun(
736
  if not tool_func:
737
  return "SKIPPED: notify_arun tool unavailable."
738
 
739
- metadata = _build_notification_metadata(
 
 
740
  reason=reason,
741
  user_metadata=user_metadata,
742
  assistant_output=final_response,
743
  )
744
 
745
- return tool_func.invoke(
746
- {
747
- "category": category,
748
- "user_input": user_input,
749
- "user_metadata_json": json.dumps(metadata),
750
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
751
  )
 
 
 
752
 
753
 
754
  def chat_interface():
@@ -775,10 +872,11 @@ def chat_interface():
775
 
776
  route = _route_user_input(user_input)
777
  scratchpad: List[Any] = []
778
- scratchpad.extend(_run_pre_escalation(route, user_input, tool_map))
 
 
779
 
780
  final_response: Optional[str] = None
781
- used_tools = set()
782
 
783
  for _ in range(MAX_TOOL_ROUNDS):
784
  messages = prompt.format_messages(
@@ -794,7 +892,6 @@ def chat_interface():
794
  scratchpad.append(ai_msg)
795
  for tc in ai_msg.tool_calls:
796
  tool_name = tc.get("name")
797
- used_tools.add(tool_name)
798
  print(f"[SYSTEM] Tool call: {tool_name}({tc.get('args')})")
799
 
800
  tool_func = tool_map.get(tool_name)
@@ -820,25 +917,15 @@ def chat_interface():
820
  if not final_response:
821
  final_response = "I do not have enough information to answer that."
822
 
823
- # Safety net: if the model sounds uncertain and did not notify Arun, escalate.
824
- if _contains_uncertainty(final_response) and "notify_arun" not in used_tools:
825
- try:
826
- notify_result = tool_map["notify_arun"].invoke(
827
- {
828
- "category": "UNKNOWN_QUESTION",
829
- "user_input": user_input,
830
- "user_metadata_json": json.dumps(
831
- {
832
- "reason": "uncertainty_detected_after_answer",
833
- "assistant_output": _safe_truncate(final_response, 300),
834
- "timestamp": _utc_now(),
835
- }
836
- ),
837
- }
838
- )
839
- print(f"[SYSTEM] {notify_result}")
840
- except Exception as e:
841
- print(f"[SYSTEM] Failed to auto-notify Arun: {e}")
842
 
843
  print(f"\nArunCore: {final_response}\n")
844
  print("-" * 60)
 
1
+ from concurrent.futures import ThreadPoolExecutor
2
  import hashlib
3
  import html
4
  import json
 
49
  _GLOBAL_VECTORSTORE = None
50
  _GLOBAL_BM25 = None
51
  _GLOBAL_COMPRESSOR = None
52
+ _BACKGROUND_EXECUTOR = ThreadPoolExecutor(max_workers=4, thread_name_prefix="aruncore-bg")
53
 
54
  _RECENT_ALERTS: Dict[str, float] = {}
55
 
 
215
  return "SUCCESS: debug event sent."
216
 
217
 
218
+ def _run_background_task(task_name: str, func, *args, **kwargs):
219
+ try:
220
+ return func(*args, **kwargs)
221
+ except Exception as e:
222
+ print(f"[BACKGROUND ERROR] {task_name}: {e}")
223
+ return None
224
+
225
+
226
+ def _submit_background_task(task_name: str, func, *args, **kwargs) -> bool:
227
+ try:
228
+ _BACKGROUND_EXECUTOR.submit(_run_background_task, task_name, func, *args, **kwargs)
229
+ return True
230
+ except RuntimeError as e:
231
+ print(f"[BACKGROUND ERROR] Failed to submit {task_name}: {e}")
232
+ return False
233
+
234
+
235
+ def queue_debug_event(
236
+ event_type: str,
237
+ content: str,
238
+ metadata: Optional[Dict[str, Any]] = None,
239
+ ) -> str:
240
+ if not _telegram_debug_enabled():
241
+ return "SKIPPED: debug stream disabled."
242
+
243
+ if _submit_background_task("debug_event", send_debug_event, event_type, content, metadata):
244
+ return "QUEUED: debug event scheduled."
245
+
246
+ return "FAILED: could not queue debug event."
247
+
248
+
249
  def _build_notification_metadata(
250
  reason: str,
251
  user_metadata: Optional[Dict[str, Any]] = None,
 
682
  return {tool_obj.name: tool_obj for tool_obj in tools}
683
 
684
 
685
+ def _build_notify_payload(
686
+ category: str,
687
+ user_input: str,
688
+ reason: str,
689
+ user_metadata: Optional[Dict[str, Any]] = None,
690
+ assistant_output: Optional[str] = None,
691
+ ) -> Dict[str, str]:
692
+ metadata = _build_notification_metadata(
693
+ reason=reason,
694
+ user_metadata=user_metadata,
695
+ assistant_output=assistant_output,
696
+ )
697
+ return {
698
+ "category": category,
699
+ "user_input": user_input,
700
+ "user_metadata_json": json.dumps(metadata),
701
+ }
702
+
703
+
704
  def _tool_was_used(scratchpad: List[Any], tool_name: str) -> bool:
705
  for item in scratchpad:
706
  if isinstance(item, dict) and item.get("name") == tool_name:
 
711
  if tool_call.get("name") == tool_name:
712
  return True
713
 
 
 
 
 
714
  return False
715
 
716
 
 
719
  user_input: str,
720
  tool_map: Dict[str, Any],
721
  user_metadata: Optional[Dict[str, Any]] = None,
722
+ background: bool = False,
723
+ ) -> Optional[Dict[str, Any]]:
724
+ if not route.get("needs_notify"):
725
+ return None
726
+
727
+ category = route.get("notify_category") or "UNKNOWN_QUESTION"
728
+ reason = route.get("reason", "unknown")
729
+ payload = _build_notify_payload(
730
+ category=category,
731
+ user_input=user_input,
732
+ reason=reason,
733
+ user_metadata=user_metadata,
734
+ )
735
+ tool_func = tool_map.get("notify_arun")
736
+ if not tool_func:
737
+ return {
738
+ "handled": False,
739
+ "category": category,
740
+ "reason": reason,
741
+ "result": "SKIPPED: notify_arun tool unavailable.",
742
+ }
743
+
744
+ if background:
745
+ submitted = _submit_background_task("pre_escalation_notify", tool_func.invoke, payload)
746
+ return {
747
+ "handled": submitted,
748
+ "category": category,
749
+ "reason": reason,
750
+ "result": "QUEUED: pre-escalation notification scheduled." if submitted else "FAILED: could not queue pre-escalation notification.",
751
+ }
752
+
753
+ result = str(tool_func.invoke(payload))
754
+ return {
755
+ "handled": result.startswith("SUCCESS") or result.startswith("SKIPPED"),
756
+ "category": category,
757
+ "reason": reason,
758
+ "result": result,
759
+ }
760
 
761
 
762
  def run_pre_escalation(
763
  user_input: str,
764
  tool_map: Dict[str, Any],
765
  user_metadata: Optional[Dict[str, Any]] = None,
766
+ background: bool = False,
767
+ ) -> Optional[Dict[str, Any]]:
768
  route = _route_user_input(user_input)
769
+ return _run_pre_escalation(
770
+ route,
771
+ user_input,
772
+ tool_map,
773
+ user_metadata=user_metadata,
774
+ background=background,
775
+ )
776
 
777
 
778
  def maybe_notify_arun(
 
781
  scratchpad: List[Any],
782
  tool_map: Dict[str, Any],
783
  user_metadata: Optional[Dict[str, Any]] = None,
784
+ pre_notified: bool = False,
785
  ) -> Optional[str]:
786
  """
787
  Deterministic safety-net escalation used by API / bot flows.
 
789
  remembering to call `notify_arun` on its own.
790
  """
791
  route = _route_user_input(user_input)
792
+ used_notify_tool = pre_notified or _tool_was_used(scratchpad, "notify_arun")
793
 
794
  should_notify = route.get("needs_notify", False)
795
  category = route.get("notify_category") or "UNKNOWN_QUESTION"
 
807
  if not tool_func:
808
  return "SKIPPED: notify_arun tool unavailable."
809
 
810
+ payload = _build_notify_payload(
811
+ category=category,
812
+ user_input=user_input,
813
  reason=reason,
814
  user_metadata=user_metadata,
815
  assistant_output=final_response,
816
  )
817
 
818
+ return tool_func.invoke(payload)
819
+
820
+
821
+ def queue_maybe_notify_arun(
822
+ user_input: str,
823
+ final_response: str,
824
+ scratchpad: List[Any],
825
+ tool_map: Dict[str, Any],
826
+ user_metadata: Optional[Dict[str, Any]] = None,
827
+ pre_notified: bool = False,
828
+ ) -> str:
829
+ def _background_notify():
830
+ result = maybe_notify_arun(
831
+ user_input=user_input,
832
+ final_response=final_response,
833
+ scratchpad=scratchpad,
834
+ tool_map=tool_map,
835
+ user_metadata=user_metadata,
836
+ pre_notified=pre_notified,
837
+ )
838
+ if result:
839
+ send_debug_event("auto_escalation", str(result), user_metadata)
840
+ return result
841
+
842
+ submitted = _submit_background_task(
843
+ "maybe_notify_arun",
844
+ _background_notify,
845
  )
846
+ if submitted:
847
+ return "QUEUED: maybe_notify_arun scheduled."
848
+ return "FAILED: could not queue maybe_notify_arun."
849
 
850
 
851
  def chat_interface():
 
872
 
873
  route = _route_user_input(user_input)
874
  scratchpad: List[Any] = []
875
+ pre_escalation = _run_pre_escalation(route, user_input, tool_map, background=True)
876
+ if pre_escalation:
877
+ print(f"[SYSTEM] {pre_escalation['result']}")
878
 
879
  final_response: Optional[str] = None
 
880
 
881
  for _ in range(MAX_TOOL_ROUNDS):
882
  messages = prompt.format_messages(
 
892
  scratchpad.append(ai_msg)
893
  for tc in ai_msg.tool_calls:
894
  tool_name = tc.get("name")
 
895
  print(f"[SYSTEM] Tool call: {tool_name}({tc.get('args')})")
896
 
897
  tool_func = tool_map.get(tool_name)
 
917
  if not final_response:
918
  final_response = "I do not have enough information to answer that."
919
 
920
+ notify_result = maybe_notify_arun(
921
+ user_input=user_input,
922
+ final_response=final_response,
923
+ scratchpad=scratchpad,
924
+ tool_map=tool_map,
925
+ pre_notified=bool(pre_escalation and pre_escalation.get("handled")),
926
+ )
927
+ if notify_result:
928
+ print(f"[SYSTEM] {notify_result}")
 
 
 
 
 
 
 
 
 
 
929
 
930
  print(f"\nArunCore: {final_response}\n")
931
  print("-" * 60)
core/api.py CHANGED
@@ -9,7 +9,7 @@ from typing import Dict
9
  from dotenv import load_dotenv
10
 
11
  # Import the core engine components
12
- from core.agent import init_agent, RollingMemory, maybe_notify_arun, run_pre_escalation, send_debug_event
13
  from langchain_openai import ChatOpenAI
14
 
15
  load_dotenv()
@@ -68,28 +68,31 @@ async def chat_endpoint(req: ChatRequest):
68
  final_response = None
69
 
70
  try:
71
- await asyncio.to_thread(
72
- send_debug_event,
73
  "user_message",
74
  req.message,
75
  {"channel": "api", "session_id": req.session_id},
76
  )
77
 
78
- pre_escalation_messages = await asyncio.to_thread(
79
  run_pre_escalation,
80
  req.message,
81
  global_tool_map,
82
  {"channel": "api", "session_id": req.session_id},
 
83
  )
84
- if pre_escalation_messages:
85
- scratchpad.extend(pre_escalation_messages)
86
  yield json.dumps({"type": "status", "content": "Sending notification to Arun..."}) + "\n"
87
  thoughts.append("Sending notification to Arun...")
88
- await asyncio.to_thread(
89
- send_debug_event,
90
  "pre_escalation",
91
- "\n\n".join(str(message.content) for message in pre_escalation_messages),
92
- {"channel": "api", "session_id": req.session_id},
 
 
 
 
 
93
  )
94
 
95
  while iterations < max_iterations:
@@ -117,8 +120,7 @@ async def chat_endpoint(req: ChatRequest):
117
 
118
  yield json.dumps({"type": "status", "content": status_msg}) + "\n"
119
  thoughts.append(status_msg)
120
- await asyncio.to_thread(
121
- send_debug_event,
122
  "tool_call",
123
  json.dumps(tool_args, ensure_ascii=False, indent=2, default=str),
124
  {
@@ -143,8 +145,7 @@ async def chat_endpoint(req: ChatRequest):
143
  "tool_call_id": tc["id"],
144
  "content": str(tool_result)[:2000],
145
  })
146
- await asyncio.to_thread(
147
- send_debug_event,
148
  "tool_result",
149
  str(tool_result),
150
  {
@@ -161,33 +162,20 @@ async def chat_endpoint(req: ChatRequest):
161
  if not final_response:
162
  final_response = "I encountered a processing limit. How else can I help?"
163
 
164
- await asyncio.to_thread(
165
- send_debug_event,
166
  "assistant_reply",
167
  final_response,
168
  {"channel": "api", "session_id": req.session_id},
169
  )
170
 
171
- escalation_result = await asyncio.to_thread(
172
- maybe_notify_arun,
173
- req.message,
174
- final_response,
175
- scratchpad,
176
- global_tool_map,
177
- {"channel": "api", "session_id": req.session_id},
178
  )
179
- if escalation_result:
180
- if isinstance(escalation_result, dict):
181
- escalation_category = escalation_result.get("category", "UNKNOWN")
182
- else:
183
- escalation_category = "UNKNOWN_QUESTION"
184
- thoughts.append(f"Auto-escalation triggered: {escalation_category}")
185
- await asyncio.to_thread(
186
- send_debug_event,
187
- "auto_escalation",
188
- str(escalation_result),
189
- {"channel": "api", "session_id": req.session_id},
190
- )
191
 
192
  memory.add_interaction(req.message, final_response)
193
 
@@ -199,8 +187,7 @@ async def chat_endpoint(req: ChatRequest):
199
  }) + "\n"
200
 
201
  except Exception as e:
202
- await asyncio.to_thread(
203
- send_debug_event,
204
  "error",
205
  str(e),
206
  {"channel": "api", "session_id": req.session_id},
 
9
  from dotenv import load_dotenv
10
 
11
  # Import the core engine components
12
+ from core.agent import init_agent, RollingMemory, queue_debug_event, queue_maybe_notify_arun, run_pre_escalation
13
  from langchain_openai import ChatOpenAI
14
 
15
  load_dotenv()
 
68
  final_response = None
69
 
70
  try:
71
+ queue_debug_event(
 
72
  "user_message",
73
  req.message,
74
  {"channel": "api", "session_id": req.session_id},
75
  )
76
 
77
+ pre_escalation = await asyncio.to_thread(
78
  run_pre_escalation,
79
  req.message,
80
  global_tool_map,
81
  {"channel": "api", "session_id": req.session_id},
82
+ True,
83
  )
84
+ if pre_escalation:
 
85
  yield json.dumps({"type": "status", "content": "Sending notification to Arun..."}) + "\n"
86
  thoughts.append("Sending notification to Arun...")
87
+ queue_debug_event(
 
88
  "pre_escalation",
89
+ pre_escalation.get("result", ""),
90
+ {
91
+ "channel": "api",
92
+ "session_id": req.session_id,
93
+ "category": pre_escalation.get("category"),
94
+ "reason": pre_escalation.get("reason"),
95
+ },
96
  )
97
 
98
  while iterations < max_iterations:
 
120
 
121
  yield json.dumps({"type": "status", "content": status_msg}) + "\n"
122
  thoughts.append(status_msg)
123
+ queue_debug_event(
 
124
  "tool_call",
125
  json.dumps(tool_args, ensure_ascii=False, indent=2, default=str),
126
  {
 
145
  "tool_call_id": tc["id"],
146
  "content": str(tool_result)[:2000],
147
  })
148
+ queue_debug_event(
 
149
  "tool_result",
150
  str(tool_result),
151
  {
 
162
  if not final_response:
163
  final_response = "I encountered a processing limit. How else can I help?"
164
 
165
+ queue_debug_event(
 
166
  "assistant_reply",
167
  final_response,
168
  {"channel": "api", "session_id": req.session_id},
169
  )
170
 
171
+ queue_maybe_notify_arun(
172
+ user_input=req.message,
173
+ final_response=final_response,
174
+ scratchpad=scratchpad,
175
+ tool_map=global_tool_map,
176
+ user_metadata={"channel": "api", "session_id": req.session_id},
177
+ pre_notified=bool(pre_escalation and pre_escalation.get("handled")),
178
  )
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
  memory.add_interaction(req.message, final_response)
181
 
 
187
  }) + "\n"
188
 
189
  except Exception as e:
190
+ queue_debug_event(
 
191
  "error",
192
  str(e),
193
  {"channel": "api", "session_id": req.session_id},
core/bot.py CHANGED
@@ -8,7 +8,7 @@ from telegram import Update
8
  from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
9
 
10
  # Import the core ArunCore engine
11
- from core.agent import init_agent, RollingMemory, maybe_notify_arun, run_pre_escalation, send_debug_event
12
 
13
  load_dotenv()
14
 
@@ -40,23 +40,28 @@ def run_agent(chat_id: int, user_message: str) -> str:
40
  scratchpad = []
41
 
42
  try:
43
- send_debug_event(
44
  "user_message",
45
  user_message,
46
  {"channel": "telegram", "chat_id": chat_id},
47
  )
48
 
49
- pre_escalation_messages = run_pre_escalation(
50
  user_message,
51
  tool_map,
52
  {"channel": "telegram", "chat_id": chat_id},
 
53
  )
54
- scratchpad.extend(pre_escalation_messages)
55
- if pre_escalation_messages:
56
- send_debug_event(
57
  "pre_escalation",
58
- "\n\n".join(str(message.content) for message in pre_escalation_messages),
59
- {"channel": "telegram", "chat_id": chat_id},
 
 
 
 
 
60
  )
61
 
62
  final_response = None
@@ -76,7 +81,7 @@ def run_agent(chat_id: int, user_message: str) -> str:
76
  for tc in ai_msg.tool_calls:
77
  tool_name = tc["name"]
78
  tool_args = tc.get("args", {})
79
- send_debug_event(
80
  "tool_call",
81
  json.dumps(tool_args, ensure_ascii=False, indent=2, default=str),
82
  {
@@ -98,7 +103,7 @@ def run_agent(chat_id: int, user_message: str) -> str:
98
  "tool_call_id": tc["id"],
99
  "content": str(result)[:2000],
100
  })
101
- send_debug_event(
102
  "tool_result",
103
  str(result),
104
  {
@@ -114,30 +119,25 @@ def run_agent(chat_id: int, user_message: str) -> str:
114
  if not final_response:
115
  final_response = "I ran into an issue internally. Please try again."
116
 
117
- send_debug_event(
118
  "assistant_reply",
119
  final_response,
120
  {"channel": "telegram", "chat_id": chat_id},
121
  )
122
 
123
- escalation_result = maybe_notify_arun(
124
  user_input=user_message,
125
  final_response=final_response,
126
  scratchpad=scratchpad,
127
  tool_map=tool_map,
128
  user_metadata={"channel": "telegram", "chat_id": chat_id},
 
129
  )
130
- if escalation_result:
131
- send_debug_event(
132
- "auto_escalation",
133
- str(escalation_result),
134
- {"channel": "telegram", "chat_id": chat_id},
135
- )
136
 
137
  memory.add_interaction(user_message, final_response)
138
  return final_response
139
  except Exception as e:
140
- send_debug_event(
141
  "error",
142
  str(e),
143
  {"channel": "telegram", "chat_id": chat_id},
 
8
  from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
9
 
10
  # Import the core ArunCore engine
11
+ from core.agent import init_agent, RollingMemory, queue_debug_event, queue_maybe_notify_arun, run_pre_escalation
12
 
13
  load_dotenv()
14
 
 
40
  scratchpad = []
41
 
42
  try:
43
+ queue_debug_event(
44
  "user_message",
45
  user_message,
46
  {"channel": "telegram", "chat_id": chat_id},
47
  )
48
 
49
+ pre_escalation = run_pre_escalation(
50
  user_message,
51
  tool_map,
52
  {"channel": "telegram", "chat_id": chat_id},
53
+ True,
54
  )
55
+ if pre_escalation:
56
+ queue_debug_event(
 
57
  "pre_escalation",
58
+ pre_escalation.get("result", ""),
59
+ {
60
+ "channel": "telegram",
61
+ "chat_id": chat_id,
62
+ "category": pre_escalation.get("category"),
63
+ "reason": pre_escalation.get("reason"),
64
+ },
65
  )
66
 
67
  final_response = None
 
81
  for tc in ai_msg.tool_calls:
82
  tool_name = tc["name"]
83
  tool_args = tc.get("args", {})
84
+ queue_debug_event(
85
  "tool_call",
86
  json.dumps(tool_args, ensure_ascii=False, indent=2, default=str),
87
  {
 
103
  "tool_call_id": tc["id"],
104
  "content": str(result)[:2000],
105
  })
106
+ queue_debug_event(
107
  "tool_result",
108
  str(result),
109
  {
 
119
  if not final_response:
120
  final_response = "I ran into an issue internally. Please try again."
121
 
122
+ queue_debug_event(
123
  "assistant_reply",
124
  final_response,
125
  {"channel": "telegram", "chat_id": chat_id},
126
  )
127
 
128
+ queue_maybe_notify_arun(
129
  user_input=user_message,
130
  final_response=final_response,
131
  scratchpad=scratchpad,
132
  tool_map=tool_map,
133
  user_metadata={"channel": "telegram", "chat_id": chat_id},
134
+ pre_notified=bool(pre_escalation and pre_escalation.get("handled")),
135
  )
 
 
 
 
 
 
136
 
137
  memory.add_interaction(user_message, final_response)
138
  return final_response
139
  except Exception as e:
140
+ queue_debug_event(
141
  "error",
142
  str(e),
143
  {"channel": "telegram", "chat_id": chat_id},