ShoaibSSM commited on
Commit
ce159c0
·
verified ·
1 Parent(s): d2db789

Update tools/send_request.py

Browse files
Files changed (1) hide show
  1. tools/send_request.py +90 -123
tools/send_request.py CHANGED
@@ -1,144 +1,111 @@
1
- # from langchain_core.tools import tool
2
- # from shared_store import BASE64_STORE, url_time
3
- # import time
4
- # import os
5
- # import requests
6
- # import json
7
- # from collections import defaultdict
8
- # from typing import Any, Dict, Optional
9
-
10
- # cache = defaultdict(int)
11
- # retry_limit = 4
12
- # @tool
13
- # def post_request(url: str, payload: Dict[str, Any], headers: Optional[Dict[str, str]] = None) -> Any:
14
- # """
15
- # Send an HTTP POST request to the given URL with the provided payload.
16
-
17
- # This function is designed for LangGraph applications, where it can be wrapped
18
- # as a Tool or used inside a Runnable to call external APIs, webhooks, or backend
19
- # services during graph execution.
20
- # REMEMBER: This a blocking function so it may take a while to return. Wait for the response.
21
- # Args:
22
- # url (str): The endpoint to send the POST request to.
23
- # payload (Dict[str, Any]): The JSON-serializable request body.
24
- # headers (Optional[Dict[str, str]]): Optional HTTP headers to include
25
- # in the request. If omitted, a default JSON header is applied.
26
-
27
- # Returns:
28
- # Any: The response body. If the server returns JSON, a parsed dict is
29
- # returned. Otherwise, the raw text response is returned.
30
-
31
- # Raises:
32
- # requests.HTTPError: If the server responds with an unsuccessful status.
33
- # requests.RequestException: For network-related errors.
34
- # """
35
- # # Handling if the answer is a BASE64
36
- # ans = payload.get("answer")
37
-
38
- # if isinstance(ans, str) and ans.startswith("BASE64_KEY:"):
39
- # key = ans.split(":", 1)[1]
40
- # payload["answer"] = BASE64_STORE[key]
41
- # headers = headers or {"Content-Type": "application/json"}
42
- # try:
43
- # cur_url = os.getenv("url")
44
- # cache[cur_url] += 1
45
- # sending = payload
46
- # if isinstance(payload.get("answer"), str):
47
- # sending = {
48
- # "answer": payload.get("answer", "")[:100],
49
- # "email": payload.get("email", ""),
50
- # "url": payload.get("url", "")
51
- # }
52
- # print(f"\nSending Answer \n{json.dumps(sending, indent=4)}\n to url: {url}")
53
- # response = requests.post(url, json=payload, headers=headers)
54
-
55
- # # Raise on 4xx/5xx
56
- # response.raise_for_status()
57
-
58
- # # Try to return JSON, fallback to raw text
59
- # data = response.json()
60
- # print("Got the response: \n", json.dumps(data, indent=4), '\n')
61
- # if "message" in data:
62
- # del data["message"]
63
-
64
- # delay = data.get("delay", 0)
65
- # delay = delay if isinstance(delay, (int, float)) else 0
66
-
67
- # next_url = data.get("url")
68
- # if next_url not in url_time:
69
- # url_time[next_url] = time.time()
70
-
71
- # correct = data.get("correct")
72
- # if not correct:
73
- # cur_time = time.time()
74
- # prev = url_time[next_url]
75
- # if cache[cur_url] >= retry_limit or delay >= 180 or (prev != "0" and (cur_time - float(prev)) > 90): # Shouldn't retry
76
- # data = {"url": data.get("url", "")}
77
- # else: # Retry
78
- # os.environ["offset"] = str(url_time[next_url])
79
- # data["url"] = cur_url
80
- # data["message"] = "Retry Again!"
81
- # print("Formatted: '\n", json.dumps(data, indent=4), '\n')
82
- # forward_url = data.get("url", "")
83
- # os.environ["url"] = forward_url
84
- # if forward_url == next_url:
85
- # os.environ["offset"] = "0"
86
-
87
- # return data
88
- # except requests.HTTPError as e:
89
- # # Extract server’s error response
90
- # err_resp = e.response
91
-
92
- # try:
93
- # err_data = err_resp.json()
94
- # except ValueError:
95
- # err_data = err_resp.text
96
-
97
- # print("HTTP Error Response:\n", err_data)
98
- # return err_data
99
-
100
- # except Exception as e:
101
- # print("Unexpected error:", e)
102
- # return str(e)
103
-
104
-
105
  from langchain_core.tools import tool
 
 
 
106
  import requests
107
  import json
108
- import os
 
 
 
 
109
 
110
  @tool
111
- def post_request(url: str, payload: dict, headers: dict = None):
112
  """
113
- Clean and correct POST request tool.
114
- - NEVER rewrites URLs
115
- - NEVER loops back to previous URL
116
- - NEVER modifies payload secretly
117
- - Updates os.environ["url"] ONLY if new URL provided
118
  """
 
 
 
 
 
 
 
119
  headers = headers or {"Content-Type": "application/json"}
120
 
121
- print(f"\nSending Answer:\n{json.dumps(payload, indent=4)}\nTo URL: {url}\n")
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  try:
124
- r = requests.post(url, json=payload, headers=headers)
 
125
  except Exception as e:
126
- print("Network error:", str(e))
127
  return {"error": str(e)}
128
 
129
  try:
130
- data = r.json()
131
  except:
132
- print("Non-JSON response:", r.text)
133
- return {"error": r.text}
 
 
 
 
 
 
134
 
135
- print("Received Response:\n", json.dumps(data, indent=4))
 
136
 
137
- # update environment URL if server gives next link
138
  next_url = data.get("url")
139
- if next_url:
140
- os.environ["url"] = next_url
141
- else:
142
- os.environ["url"] = "" # marks completion
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
  return data
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from langchain_core.tools import tool
2
+ from shared_store import BASE64_STORE, url_time
3
+ import time
4
+ import os
5
  import requests
6
  import json
7
+ from collections import defaultdict
8
+ from typing import Any, Dict, Optional
9
+
10
+ cache = defaultdict(int)
11
+ retry_limit = 4
12
 
13
  @tool
14
+ def post_request(url: str, payload: Dict[str, Any], headers: Optional[Dict[str, str]] = None) -> Any:
15
  """
16
+ Fully patched old version with:
17
+ - no KeyError
18
+ - no infinite retry loops
19
+ - correct retry timing
20
+ - correct routing
21
  """
22
+ ans = payload.get("answer")
23
+
24
+ # handle BASE64 keys
25
+ if isinstance(ans, str) and ans.startswith("BASE64_KEY:"):
26
+ key = ans.split(":", 1)[1]
27
+ payload["answer"] = BASE64_STORE[key]
28
+
29
  headers = headers or {"Content-Type": "application/json"}
30
 
31
+ # FIX 1 ensure cur_url always valid
32
+ cur_url = os.getenv("url") or url
33
+ cache[cur_url] += 1
34
+
35
+ sending = payload
36
+ if isinstance(payload.get("answer"), str):
37
+ sending = {
38
+ "answer": payload.get("answer", "")[:100],
39
+ "email": payload.get("email", ""),
40
+ "url": payload.get("url", "")
41
+ }
42
+
43
+ print(f"\nSending Answer \n{json.dumps(sending, indent=4)}\n to url: {url}")
44
 
45
  try:
46
+ response = requests.post(url, json=payload, headers=headers)
47
+ response.raise_for_status()
48
  except Exception as e:
49
+ print("HTTP Error:", str(e))
50
  return {"error": str(e)}
51
 
52
  try:
53
+ data = response.json()
54
  except:
55
+ print("Non JSON response:", response.text)
56
+ return {"error": response.text}
57
+
58
+ print("Got the response: \n", json.dumps(data, indent=4), '\n')
59
+
60
+ # remove message for safety
61
+ if "message" in data:
62
+ del data["message"]
63
 
64
+ delay = data.get("delay", 0)
65
+ delay = delay if isinstance(delay, (int, float)) else 0
66
 
 
67
  next_url = data.get("url")
68
+ correct = data.get("correct")
69
+
70
+ # FIX 2 — initialize url_time properly
71
+ if next_url and next_url not in url_time:
72
+ url_time[next_url] = time.time()
73
+
74
+ # incorrect answer handling
75
+ if not correct:
76
+ cur_time = time.time()
77
+ prev = url_time.get(next_url, 0) # FIX 3 no KeyError
78
+ prev = float(prev)
79
+
80
+ # should NOT retry?
81
+ if cache[cur_url] >= retry_limit or delay >= 180 or (cur_time - prev) > 90:
82
+ # FIX 4 — preserve routing fields
83
+ fixed = {
84
+ "url": next_url,
85
+ "correct": False
86
+ }
87
+ print("Formatted: '\n", json.dumps(fixed, indent=4), '\n')
88
+ os.environ["url"] = next_url
89
+ os.environ["offset"] = "0"
90
+ return fixed
91
+
92
+ # retry same page
93
+ os.environ["offset"] = str(prev)
94
+ if os.environ["offset"] in ["None", None, ""]:
95
+ os.environ["offset"] = "0"
96
+
97
+ retry_data = {
98
+ "url": cur_url,
99
+ "correct": False,
100
+ "message": "Retry Again!"
101
+ }
102
+ print("Formatted: '\n", json.dumps(retry_data, indent=4), '\n')
103
+ os.environ["url"] = cur_url
104
+ return retry_data
105
+
106
+ # success path
107
+ print("Formatted: '\n", json.dumps(data, indent=4), '\n')
108
+ os.environ["url"] = next_url
109
+ os.environ["offset"] = "0"
110
 
111
  return data