computer-use-ootb-internal 0.0.95.post2__tar.gz → 0.0.96__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/PKG-INFO +1 -1
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/pyproject.toml +1 -1
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/app_teachmode.py +420 -387
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/.gitignore +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/README.md +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/app_teachmode_gradio.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/animation/click_animation.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/animation/icons8-select-cursor-transparent-96.gif +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/executor/teachmode_executor.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/__init__.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/gui_capture.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/gui_parser.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/icon_detection/icon_detection.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/panel_recognition/llm_panel_recognize.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/test_capture.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/uia_parser.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/utils.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/uia_tools/__init__.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/uia_tools/screenshot_cli.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/uia_tools/screenshot_service.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/llm_utils/llm_utils.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/llm_utils/oai.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/llm_utils/run_litellm.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/llm_utils/run_llm.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/vlm_utils/__init__.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/gui_agent/vlm_utils/run_vlm.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/__init__.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/aws_request.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/base.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/bash.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/collection.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/colorful_text.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/computer.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/computer_marbot.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/edit.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/run.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/computer_use_demo/tools/screen_capture.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/dependency_check.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/example_websocket_js.html +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/requirements-lite.txt +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/run_teachmode_ootb_args.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/service_teachmode.py +0 -0
- {computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/src/computer_use_ootb_internal/service_teachmode_test.py +0 -0
{computer_use_ootb_internal-0.0.95.post2 → computer_use_ootb_internal-0.0.96}/pyproject.toml
RENAMED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "computer-use-ootb-internal"
|
7
|
-
version = "0.0.
|
7
|
+
version = "0.0.96"
|
8
8
|
description = "Computer Use OOTB"
|
9
9
|
authors = [{ name = "Siyuan Hu", email = "siyuan.hu.sg@gmail.com" }]
|
10
10
|
requires-python = ">=3.11"
|
@@ -1,387 +1,420 @@
|
|
1
|
-
import argparse
|
2
|
-
import time
|
3
|
-
import json
|
4
|
-
import
|
5
|
-
|
6
|
-
|
7
|
-
from fastapi
|
8
|
-
from
|
9
|
-
from
|
10
|
-
from
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
self.
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
self.
|
68
|
-
|
69
|
-
self.
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
shared_state.
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
#
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
)
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
if
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
#
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
)
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
shared_state.
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
if
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
1
|
+
import argparse
|
2
|
+
import time
|
3
|
+
import json
|
4
|
+
from datetime import datetime
|
5
|
+
import threading
|
6
|
+
import requests
|
7
|
+
from fastapi import FastAPI, Request
|
8
|
+
from fastapi.responses import JSONResponse
|
9
|
+
from fastapi.middleware.cors import CORSMiddleware
|
10
|
+
from screeninfo import get_monitors
|
11
|
+
from computer_use_ootb_internal.computer_use_demo.tools.computer import get_screen_details
|
12
|
+
from computer_use_ootb_internal.run_teachmode_ootb_args import simple_teachmode_sampling_loop
|
13
|
+
|
14
|
+
app = FastAPI()
|
15
|
+
|
16
|
+
# Add CORS middleware to allow requests from the frontend
|
17
|
+
app.add_middleware(
|
18
|
+
CORSMiddleware,
|
19
|
+
allow_origins=["*"],
|
20
|
+
allow_credentials=True,
|
21
|
+
allow_methods=["*"],
|
22
|
+
allow_headers=["*"],
|
23
|
+
)
|
24
|
+
|
25
|
+
# Rate limiter for API endpoints
|
26
|
+
class RateLimiter:
|
27
|
+
def __init__(self, interval_seconds=2):
|
28
|
+
self.interval = interval_seconds
|
29
|
+
self.last_request_time = {}
|
30
|
+
self.lock = threading.Lock()
|
31
|
+
|
32
|
+
def allow_request(self, endpoint):
|
33
|
+
with self.lock:
|
34
|
+
current_time = time.time()
|
35
|
+
# Priority endpoints always allowed
|
36
|
+
if endpoint in ["/update_params", "/update_message"]:
|
37
|
+
return True
|
38
|
+
|
39
|
+
# For other endpoints, apply rate limiting
|
40
|
+
if endpoint not in self.last_request_time:
|
41
|
+
self.last_request_time[endpoint] = current_time
|
42
|
+
return True
|
43
|
+
|
44
|
+
elapsed = current_time - self.last_request_time[endpoint]
|
45
|
+
if elapsed < self.interval:
|
46
|
+
return False
|
47
|
+
|
48
|
+
self.last_request_time[endpoint] = current_time
|
49
|
+
return True
|
50
|
+
|
51
|
+
|
52
|
+
def log_ootb_request(server_url, ootb_request_type, data):
|
53
|
+
logging_data = {
|
54
|
+
"type": ootb_request_type,
|
55
|
+
"data": data,
|
56
|
+
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
57
|
+
}
|
58
|
+
if not server_url.endswith("/update_ootb_logging"):
|
59
|
+
server_logging_url = server_url + "/update_ootb_logging"
|
60
|
+
else:
|
61
|
+
server_logging_url = server_url
|
62
|
+
requests.post(server_logging_url, json=logging_data)
|
63
|
+
|
64
|
+
|
65
|
+
class SharedState:
|
66
|
+
def __init__(self, args):
|
67
|
+
self.args = args
|
68
|
+
self.task_updated = False
|
69
|
+
self.chatbot_messages = []
|
70
|
+
# Store all state-related data here
|
71
|
+
self.model = args.model
|
72
|
+
self.task = getattr(args, 'task', "")
|
73
|
+
self.selected_screen = args.selected_screen
|
74
|
+
self.user_id = args.user_id
|
75
|
+
self.trace_id = args.trace_id
|
76
|
+
self.api_keys = args.api_keys
|
77
|
+
self.server_url = args.server_url
|
78
|
+
self.message_queue = []
|
79
|
+
self.is_processing = False
|
80
|
+
self.should_stop = False
|
81
|
+
self.is_paused = False
|
82
|
+
# Add a new event to better control stopping
|
83
|
+
self.stop_event = threading.Event()
|
84
|
+
# Add a reference to the processing thread
|
85
|
+
self.processing_thread = None
|
86
|
+
|
87
|
+
shared_state = None
|
88
|
+
rate_limiter = RateLimiter(interval_seconds=2)
|
89
|
+
|
90
|
+
@app.post("/update_params")
|
91
|
+
async def update_parameters(request: Request):
|
92
|
+
data = await request.json()
|
93
|
+
|
94
|
+
if 'task' not in data:
|
95
|
+
return JSONResponse(
|
96
|
+
content={"status": "error", "message": "Missing required field: task"},
|
97
|
+
status_code=400
|
98
|
+
)
|
99
|
+
|
100
|
+
shared_state.args = argparse.Namespace(**data)
|
101
|
+
shared_state.task_updated = True
|
102
|
+
|
103
|
+
# Update shared state when parameters change
|
104
|
+
shared_state.model = getattr(shared_state.args, 'model', "teach-mode-gpt-4o")
|
105
|
+
shared_state.task = getattr(shared_state.args, 'task', "Create a claim on the SAP system, using Receipt.pdf as attachment.")
|
106
|
+
shared_state.selected_screen = getattr(shared_state.args, 'selected_screen', 0)
|
107
|
+
shared_state.user_id = getattr(shared_state.args, 'user_id', "a_test")
|
108
|
+
shared_state.trace_id = getattr(shared_state.args, 'trace_id', "jess_4")
|
109
|
+
shared_state.api_keys = getattr(shared_state.args, 'api_keys', "sk-proj-1234567890")
|
110
|
+
shared_state.server_url = getattr(shared_state.args, 'server_url', "http://ec2-44-234-43-86.us-west-2.compute.amazonaws.com")
|
111
|
+
|
112
|
+
log_ootb_request(shared_state.server_url, "update_params", data)
|
113
|
+
|
114
|
+
return JSONResponse(
|
115
|
+
content={"status": "success", "message": "Parameters updated", "new_args": vars(shared_state.args)},
|
116
|
+
status_code=200
|
117
|
+
)
|
118
|
+
|
119
|
+
@app.post("/update_message")
|
120
|
+
async def update_message(request: Request):
|
121
|
+
data = await request.json()
|
122
|
+
|
123
|
+
if 'message' not in data:
|
124
|
+
return JSONResponse(
|
125
|
+
content={"status": "error", "message": "Missing required field: message"},
|
126
|
+
status_code=400
|
127
|
+
)
|
128
|
+
|
129
|
+
log_ootb_request(shared_state.server_url, "update_message", data)
|
130
|
+
|
131
|
+
message = data['message']
|
132
|
+
shared_state.chatbot_messages.append({"role": "user", "content": message})
|
133
|
+
shared_state.task = message
|
134
|
+
shared_state.args.task = message
|
135
|
+
|
136
|
+
# Reset stop event before starting
|
137
|
+
shared_state.stop_event.clear()
|
138
|
+
|
139
|
+
# Start processing if not already running
|
140
|
+
if not shared_state.is_processing:
|
141
|
+
# Create and store the thread
|
142
|
+
shared_state.processing_thread = threading.Thread(target=process_input, daemon=True)
|
143
|
+
shared_state.processing_thread.start()
|
144
|
+
|
145
|
+
return JSONResponse(
|
146
|
+
content={"status": "success", "message": "Message received", "task": shared_state.task},
|
147
|
+
status_code=200
|
148
|
+
)
|
149
|
+
|
150
|
+
@app.get("/get_messages")
|
151
|
+
async def get_messages(request: Request):
|
152
|
+
# Apply rate limiting
|
153
|
+
if not rate_limiter.allow_request(request.url.path):
|
154
|
+
return JSONResponse(
|
155
|
+
content={"status": "error", "message": "Rate limit exceeded. Try again after 2 seconds."},
|
156
|
+
status_code=429
|
157
|
+
)
|
158
|
+
|
159
|
+
log_ootb_request(shared_state.server_url, "get_messages", {})
|
160
|
+
|
161
|
+
# Return all messages in the queue and clear it
|
162
|
+
messages = shared_state.message_queue.copy()
|
163
|
+
shared_state.message_queue = []
|
164
|
+
|
165
|
+
return JSONResponse(
|
166
|
+
content={"status": "success", "messages": messages},
|
167
|
+
status_code=200
|
168
|
+
)
|
169
|
+
|
170
|
+
@app.get("/get_screens")
|
171
|
+
async def get_screens(request: Request):
|
172
|
+
# Apply rate limiting
|
173
|
+
if not rate_limiter.allow_request(request.url.path):
|
174
|
+
return JSONResponse(
|
175
|
+
content={"status": "error", "message": "Rate limit exceeded. Try again after 2 seconds."},
|
176
|
+
status_code=429
|
177
|
+
)
|
178
|
+
|
179
|
+
log_ootb_request(shared_state.server_url, "get_screens", {})
|
180
|
+
|
181
|
+
screen_options, primary_index = get_screen_details()
|
182
|
+
|
183
|
+
return JSONResponse(
|
184
|
+
content={"status": "success", "screens": screen_options, "primary_index": primary_index},
|
185
|
+
status_code=200
|
186
|
+
)
|
187
|
+
|
188
|
+
@app.post("/stop_processing")
|
189
|
+
async def stop_processing(request: Request):
|
190
|
+
# Apply rate limiting
|
191
|
+
if not rate_limiter.allow_request(request.url.path):
|
192
|
+
return JSONResponse(
|
193
|
+
content={"status": "error", "message": "Rate limit exceeded. Try again after 2 seconds."},
|
194
|
+
status_code=429
|
195
|
+
)
|
196
|
+
|
197
|
+
log_ootb_request(shared_state.server_url, "stop_processing", {})
|
198
|
+
|
199
|
+
if shared_state.is_processing:
|
200
|
+
# Set both flags to ensure stopping the current task
|
201
|
+
shared_state.should_stop = True
|
202
|
+
shared_state.stop_event.set()
|
203
|
+
|
204
|
+
# Send an immediate message to the queue to inform the user
|
205
|
+
stop_initiated_msg = {"role": "assistant", "content": f"Stopping task '{shared_state.task}'..."}
|
206
|
+
shared_state.message_queue.append(stop_initiated_msg)
|
207
|
+
|
208
|
+
return JSONResponse(
|
209
|
+
content={"status": "success", "message": "Task is being stopped, server will remain available for new tasks"},
|
210
|
+
status_code=200
|
211
|
+
)
|
212
|
+
else:
|
213
|
+
return JSONResponse(
|
214
|
+
content={"status": "error", "message": "No active processing to stop"},
|
215
|
+
status_code=400
|
216
|
+
)
|
217
|
+
|
218
|
+
@app.post("/toggle_pause")
|
219
|
+
async def toggle_pause(request: Request):
|
220
|
+
# Apply rate limiting
|
221
|
+
if not rate_limiter.allow_request(request.url.path):
|
222
|
+
return JSONResponse(
|
223
|
+
content={"status": "error", "message": "Rate limit exceeded. Try again after 2 seconds."},
|
224
|
+
status_code=429
|
225
|
+
)
|
226
|
+
|
227
|
+
log_ootb_request(shared_state.server_url, "toggle_pause", {})
|
228
|
+
|
229
|
+
if not shared_state.is_processing:
|
230
|
+
return JSONResponse(
|
231
|
+
content={"status": "error", "message": "No active processing to pause/resume"},
|
232
|
+
status_code=400
|
233
|
+
)
|
234
|
+
|
235
|
+
# Toggle the pause state
|
236
|
+
shared_state.is_paused = not shared_state.is_paused
|
237
|
+
current_state = shared_state.is_paused
|
238
|
+
|
239
|
+
print(f"Toggled pause state to: {current_state}")
|
240
|
+
|
241
|
+
status_message = "paused" if current_state else "resumed"
|
242
|
+
|
243
|
+
# Add a message to the queue to inform the user
|
244
|
+
if current_state:
|
245
|
+
message = {"role": "assistant", "content": f"Task '{shared_state.task}' has been paused. Click Continue to resume."}
|
246
|
+
else:
|
247
|
+
message = {"role": "assistant", "content": f"Task '{shared_state.task}' has been resumed."}
|
248
|
+
|
249
|
+
shared_state.chatbot_messages.append(message)
|
250
|
+
shared_state.message_queue.append(message)
|
251
|
+
|
252
|
+
return JSONResponse(
|
253
|
+
content={
|
254
|
+
"status": "success",
|
255
|
+
"message": f"Processing {status_message}",
|
256
|
+
"is_paused": current_state
|
257
|
+
},
|
258
|
+
status_code=200
|
259
|
+
)
|
260
|
+
|
261
|
+
@app.get("/status")
|
262
|
+
async def get_status(request: Request):
|
263
|
+
# Apply rate limiting
|
264
|
+
if not rate_limiter.allow_request(request.url.path):
|
265
|
+
return JSONResponse(
|
266
|
+
content={"status": "error", "message": "Rate limit exceeded. Try again after 2 seconds."},
|
267
|
+
status_code=429
|
268
|
+
)
|
269
|
+
|
270
|
+
log_ootb_request(shared_state.server_url, "get_status", {})
|
271
|
+
|
272
|
+
print(f"Status check - Processing: {shared_state.is_processing}, Paused: {shared_state.is_paused}")
|
273
|
+
return JSONResponse(
|
274
|
+
content={
|
275
|
+
"status": "success",
|
276
|
+
"is_processing": shared_state.is_processing,
|
277
|
+
"is_paused": shared_state.is_paused
|
278
|
+
},
|
279
|
+
status_code=200
|
280
|
+
)
|
281
|
+
|
282
|
+
def process_input():
|
283
|
+
shared_state.is_processing = True
|
284
|
+
shared_state.should_stop = False
|
285
|
+
shared_state.is_paused = False
|
286
|
+
shared_state.stop_event.clear() # Ensure stop event is cleared at the start
|
287
|
+
|
288
|
+
print(f"start sampling loop: {shared_state.chatbot_messages}")
|
289
|
+
print(f"shared_state.args before sampling loop: {shared_state.args}")
|
290
|
+
|
291
|
+
|
292
|
+
try:
|
293
|
+
# Get the generator for the sampling loop
|
294
|
+
sampling_loop = simple_teachmode_sampling_loop(
|
295
|
+
model=shared_state.model,
|
296
|
+
task=shared_state.task,
|
297
|
+
selected_screen=shared_state.selected_screen,
|
298
|
+
user_id=shared_state.user_id,
|
299
|
+
trace_id=shared_state.trace_id,
|
300
|
+
api_keys=shared_state.api_keys,
|
301
|
+
server_url=shared_state.server_url,
|
302
|
+
)
|
303
|
+
|
304
|
+
# Process messages from the sampling loop
|
305
|
+
for loop_msg in sampling_loop:
|
306
|
+
# Check stop condition more frequently
|
307
|
+
if shared_state.should_stop or shared_state.stop_event.is_set():
|
308
|
+
print("Processing stopped by user")
|
309
|
+
break
|
310
|
+
|
311
|
+
# Check if paused and wait while paused
|
312
|
+
while shared_state.is_paused and not shared_state.should_stop and not shared_state.stop_event.is_set():
|
313
|
+
print(f"Processing paused at: {time.strftime('%H:%M:%S')}")
|
314
|
+
# Wait a short time and check stop condition regularly
|
315
|
+
for _ in range(5): # Check 5 times per second
|
316
|
+
if shared_state.should_stop or shared_state.stop_event.is_set():
|
317
|
+
break
|
318
|
+
time.sleep(0.2)
|
319
|
+
|
320
|
+
# Check again after pause loop
|
321
|
+
if shared_state.should_stop or shared_state.stop_event.is_set():
|
322
|
+
print("Processing stopped while paused or resuming")
|
323
|
+
break
|
324
|
+
|
325
|
+
# Process the message
|
326
|
+
if loop_msg.startswith('<img'):
|
327
|
+
message = {"role": "user", "content": loop_msg}
|
328
|
+
else:
|
329
|
+
message = {"role": "assistant", "content": loop_msg}
|
330
|
+
|
331
|
+
shared_state.chatbot_messages.append(message)
|
332
|
+
shared_state.message_queue.append(message)
|
333
|
+
|
334
|
+
# Short sleep to allow stop signals to be processed
|
335
|
+
for _ in range(5): # Check 5 times per second
|
336
|
+
if shared_state.should_stop or shared_state.stop_event.is_set():
|
337
|
+
print("Processing stopped during sleep")
|
338
|
+
break
|
339
|
+
time.sleep(0.1)
|
340
|
+
|
341
|
+
if shared_state.should_stop or shared_state.stop_event.is_set():
|
342
|
+
break
|
343
|
+
|
344
|
+
except Exception as e:
|
345
|
+
# Handle any exceptions in the processing loop
|
346
|
+
error_msg = f"Error during task processing: {str(e)}"
|
347
|
+
print(error_msg)
|
348
|
+
error_message = {"role": "assistant", "content": error_msg}
|
349
|
+
shared_state.message_queue.append(error_message)
|
350
|
+
|
351
|
+
finally:
|
352
|
+
# Handle completion or interruption
|
353
|
+
if shared_state.should_stop or shared_state.stop_event.is_set():
|
354
|
+
stop_msg = f"Task '{shared_state.task}' was stopped. Ready for new tasks."
|
355
|
+
final_message = {"role": "assistant", "content": stop_msg}
|
356
|
+
else:
|
357
|
+
complete_msg = f"Task '{shared_state.task}' completed. Thanks for using Teachmode-OOTB."
|
358
|
+
final_message = {"role": "assistant", "content": complete_msg}
|
359
|
+
|
360
|
+
shared_state.chatbot_messages.append(final_message)
|
361
|
+
shared_state.message_queue.append(final_message)
|
362
|
+
|
363
|
+
# Reset all state flags to allow for new tasks
|
364
|
+
shared_state.is_processing = False
|
365
|
+
shared_state.should_stop = False
|
366
|
+
shared_state.is_paused = False
|
367
|
+
shared_state.stop_event.clear()
|
368
|
+
print("Processing completed, ready for new tasks")
|
369
|
+
|
370
|
+
def main():
|
371
|
+
global app, shared_state, rate_limiter
|
372
|
+
|
373
|
+
parser = argparse.ArgumentParser(
|
374
|
+
description="Run a synchronous sampling loop for assistant/tool interactions in teach-mode."
|
375
|
+
)
|
376
|
+
parser.add_argument("--model", default="teach-mode-gpt-4o")
|
377
|
+
parser.add_argument("--task", default="Create a claim on the SAP system, using Receipt.pdf as attachment.")
|
378
|
+
parser.add_argument("--selected_screen", type=int, default=0)
|
379
|
+
parser.add_argument("--user_id", default="star_rail_dev")
|
380
|
+
parser.add_argument("--trace_id", default="scroll")
|
381
|
+
parser.add_argument("--api_key_file", default="api_key.json")
|
382
|
+
parser.add_argument("--api_keys", default="")
|
383
|
+
parser.add_argument(
|
384
|
+
"--server_url",
|
385
|
+
default="http://ec2-44-234-43-86.us-west-2.compute.amazonaws.com",
|
386
|
+
help="Server URL for the session"
|
387
|
+
)
|
388
|
+
|
389
|
+
args = parser.parse_args()
|
390
|
+
shared_state = SharedState(args)
|
391
|
+
rate_limiter = RateLimiter(interval_seconds=2)
|
392
|
+
|
393
|
+
import uvicorn
|
394
|
+
import platform
|
395
|
+
import os
|
396
|
+
|
397
|
+
# Default port
|
398
|
+
port = 7888
|
399
|
+
|
400
|
+
# Determine port based on Windows username
|
401
|
+
if platform.system() == "Windows":
|
402
|
+
username = os.environ["USERNAME"].lower()
|
403
|
+
if username == "altair":
|
404
|
+
port = 14000
|
405
|
+
elif username.startswith("guest") and username[5:].isdigit():
|
406
|
+
num = int(username[5:])
|
407
|
+
if 1 <= num <= 10:
|
408
|
+
port = 14000 + num
|
409
|
+
else:
|
410
|
+
port = 7888
|
411
|
+
else:
|
412
|
+
port = 7888
|
413
|
+
|
414
|
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
415
|
+
|
416
|
+
if __name__ == "__main__":
|
417
|
+
# main()
|
418
|
+
|
419
|
+
# Test log_ootb_request
|
420
|
+
log_ootb_request("http://ec2-44-234-43-86.us-west-2.compute.amazonaws.com", "test_request", {"message": "Test message"})
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|