cua-agent 0.4.22__py3-none-any.whl → 0.7.16__py3-none-any.whl
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.
Potentially problematic release.
This version of cua-agent might be problematic. Click here for more details.
- agent/__init__.py +4 -10
- agent/__main__.py +2 -1
- agent/adapters/__init__.py +4 -0
- agent/adapters/azure_ml_adapter.py +283 -0
- agent/adapters/cua_adapter.py +161 -0
- agent/adapters/huggingfacelocal_adapter.py +67 -125
- agent/adapters/human_adapter.py +116 -114
- agent/adapters/mlxvlm_adapter.py +110 -99
- agent/adapters/models/__init__.py +41 -0
- agent/adapters/models/generic.py +78 -0
- agent/adapters/models/internvl.py +290 -0
- agent/adapters/models/opencua.py +115 -0
- agent/adapters/models/qwen2_5_vl.py +78 -0
- agent/agent.py +337 -185
- agent/callbacks/__init__.py +9 -4
- agent/callbacks/base.py +45 -31
- agent/callbacks/budget_manager.py +22 -10
- agent/callbacks/image_retention.py +54 -98
- agent/callbacks/logging.py +55 -42
- agent/callbacks/operator_validator.py +35 -33
- agent/callbacks/otel.py +291 -0
- agent/callbacks/pii_anonymization.py +19 -16
- agent/callbacks/prompt_instructions.py +47 -0
- agent/callbacks/telemetry.py +99 -61
- agent/callbacks/trajectory_saver.py +95 -69
- agent/cli.py +269 -119
- agent/computers/__init__.py +14 -9
- agent/computers/base.py +32 -19
- agent/computers/cua.py +52 -25
- agent/computers/custom.py +78 -71
- agent/decorators.py +23 -14
- agent/human_tool/__init__.py +2 -7
- agent/human_tool/__main__.py +6 -2
- agent/human_tool/server.py +48 -37
- agent/human_tool/ui.py +359 -235
- agent/integrations/hud/__init__.py +38 -99
- agent/integrations/hud/agent.py +369 -0
- agent/integrations/hud/proxy.py +166 -52
- agent/loops/__init__.py +44 -14
- agent/loops/anthropic.py +579 -492
- agent/loops/base.py +19 -15
- agent/loops/composed_grounded.py +136 -150
- agent/loops/fara/__init__.py +8 -0
- agent/loops/fara/config.py +506 -0
- agent/loops/fara/helpers.py +357 -0
- agent/loops/fara/schema.py +143 -0
- agent/loops/gelato.py +183 -0
- agent/loops/gemini.py +935 -0
- agent/loops/generic_vlm.py +601 -0
- agent/loops/glm45v.py +140 -135
- agent/loops/gta1.py +48 -51
- agent/loops/holo.py +218 -0
- agent/loops/internvl.py +180 -0
- agent/loops/moondream3.py +493 -0
- agent/loops/omniparser.py +326 -226
- agent/loops/openai.py +50 -51
- agent/loops/opencua.py +134 -0
- agent/loops/uiins.py +175 -0
- agent/loops/uitars.py +247 -206
- agent/loops/uitars2.py +951 -0
- agent/playground/__init__.py +5 -0
- agent/playground/server.py +301 -0
- agent/proxy/examples.py +61 -57
- agent/proxy/handlers.py +46 -39
- agent/responses.py +447 -347
- agent/tools/__init__.py +24 -0
- agent/tools/base.py +253 -0
- agent/tools/browser_tool.py +423 -0
- agent/types.py +11 -5
- agent/ui/__init__.py +1 -1
- agent/ui/__main__.py +1 -1
- agent/ui/gradio/app.py +25 -22
- agent/ui/gradio/ui_components.py +314 -167
- cua_agent-0.7.16.dist-info/METADATA +85 -0
- cua_agent-0.7.16.dist-info/RECORD +79 -0
- {cua_agent-0.4.22.dist-info → cua_agent-0.7.16.dist-info}/WHEEL +1 -1
- cua_agent-0.4.22.dist-info/METADATA +0 -436
- cua_agent-0.4.22.dist-info/RECORD +0 -51
- {cua_agent-0.4.22.dist-info → cua_agent-0.7.16.dist-info}/entry_points.txt +0 -0
agent/human_tool/server.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import uuid
|
|
3
|
+
from dataclasses import asdict, dataclass
|
|
3
4
|
from datetime import datetime
|
|
4
|
-
from typing import Dict, List, Any, Optional
|
|
5
|
-
from dataclasses import dataclass, asdict
|
|
6
5
|
from enum import Enum
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
7
|
|
|
8
8
|
from fastapi import FastAPI, HTTPException
|
|
9
9
|
from pydantic import BaseModel
|
|
@@ -49,7 +49,7 @@ class CompletionQueue:
|
|
|
49
49
|
self._queue: Dict[str, CompletionCall] = {}
|
|
50
50
|
self._pending_order: List[str] = []
|
|
51
51
|
self._lock = asyncio.Lock()
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
async def add_completion(self, messages: List[Dict[str, Any]], model: str) -> str:
|
|
54
54
|
"""Add a completion call to the queue."""
|
|
55
55
|
async with self._lock:
|
|
@@ -59,42 +59,47 @@ class CompletionQueue:
|
|
|
59
59
|
messages=messages,
|
|
60
60
|
model=model,
|
|
61
61
|
status=CompletionStatus.PENDING,
|
|
62
|
-
created_at=datetime.now()
|
|
62
|
+
created_at=datetime.now(),
|
|
63
63
|
)
|
|
64
64
|
self._queue[call_id] = completion_call
|
|
65
65
|
self._pending_order.append(call_id)
|
|
66
66
|
return call_id
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
async def get_pending_calls(self) -> List[Dict[str, Any]]:
|
|
69
69
|
"""Get all pending completion calls."""
|
|
70
70
|
async with self._lock:
|
|
71
71
|
pending_calls = []
|
|
72
72
|
for call_id in self._pending_order:
|
|
73
|
-
if
|
|
73
|
+
if (
|
|
74
|
+
call_id in self._queue
|
|
75
|
+
and self._queue[call_id].status == CompletionStatus.PENDING
|
|
76
|
+
):
|
|
74
77
|
call = self._queue[call_id]
|
|
75
|
-
pending_calls.append(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
pending_calls.append(
|
|
79
|
+
{
|
|
80
|
+
"id": call.id,
|
|
81
|
+
"model": call.model,
|
|
82
|
+
"created_at": call.created_at.isoformat(),
|
|
83
|
+
"messages": call.messages,
|
|
84
|
+
}
|
|
85
|
+
)
|
|
81
86
|
return pending_calls
|
|
82
|
-
|
|
87
|
+
|
|
83
88
|
async def get_call_status(self, call_id: str) -> Optional[Dict[str, Any]]:
|
|
84
89
|
"""Get the status of a specific completion call."""
|
|
85
90
|
async with self._lock:
|
|
86
91
|
if call_id not in self._queue:
|
|
87
92
|
return None
|
|
88
|
-
|
|
93
|
+
|
|
89
94
|
call = self._queue[call_id]
|
|
90
95
|
result = {
|
|
91
96
|
"id": call.id,
|
|
92
97
|
"status": call.status.value,
|
|
93
98
|
"created_at": call.created_at.isoformat(),
|
|
94
99
|
"model": call.model,
|
|
95
|
-
"messages": call.messages
|
|
100
|
+
"messages": call.messages,
|
|
96
101
|
}
|
|
97
|
-
|
|
102
|
+
|
|
98
103
|
if call.completed_at:
|
|
99
104
|
result["completed_at"] = call.completed_at.isoformat()
|
|
100
105
|
if call.response:
|
|
@@ -103,69 +108,74 @@ class CompletionQueue:
|
|
|
103
108
|
result["tool_calls"] = call.tool_calls
|
|
104
109
|
if call.error:
|
|
105
110
|
result["error"] = call.error
|
|
106
|
-
|
|
111
|
+
|
|
107
112
|
return result
|
|
108
|
-
|
|
109
|
-
async def complete_call(
|
|
113
|
+
|
|
114
|
+
async def complete_call(
|
|
115
|
+
self,
|
|
116
|
+
call_id: str,
|
|
117
|
+
response: Optional[str] = None,
|
|
118
|
+
tool_calls: Optional[List[Dict[str, Any]]] = None,
|
|
119
|
+
) -> bool:
|
|
110
120
|
"""Mark a completion call as completed with a response or tool calls."""
|
|
111
121
|
async with self._lock:
|
|
112
122
|
if call_id not in self._queue:
|
|
113
123
|
return False
|
|
114
|
-
|
|
124
|
+
|
|
115
125
|
call = self._queue[call_id]
|
|
116
126
|
if call.status != CompletionStatus.PENDING:
|
|
117
127
|
return False
|
|
118
|
-
|
|
128
|
+
|
|
119
129
|
call.status = CompletionStatus.COMPLETED
|
|
120
130
|
call.completed_at = datetime.now()
|
|
121
131
|
call.response = response
|
|
122
132
|
call.tool_calls = tool_calls
|
|
123
|
-
|
|
133
|
+
|
|
124
134
|
# Remove from pending order
|
|
125
135
|
if call_id in self._pending_order:
|
|
126
136
|
self._pending_order.remove(call_id)
|
|
127
|
-
|
|
137
|
+
|
|
128
138
|
return True
|
|
129
|
-
|
|
139
|
+
|
|
130
140
|
async def fail_call(self, call_id: str, error: str) -> bool:
|
|
131
141
|
"""Mark a completion call as failed with an error."""
|
|
132
142
|
async with self._lock:
|
|
133
143
|
if call_id not in self._queue:
|
|
134
144
|
return False
|
|
135
|
-
|
|
145
|
+
|
|
136
146
|
call = self._queue[call_id]
|
|
137
147
|
if call.status != CompletionStatus.PENDING:
|
|
138
148
|
return False
|
|
139
|
-
|
|
149
|
+
|
|
140
150
|
call.status = CompletionStatus.FAILED
|
|
141
151
|
call.completed_at = datetime.now()
|
|
142
152
|
call.error = error
|
|
143
|
-
|
|
153
|
+
|
|
144
154
|
# Remove from pending order
|
|
145
155
|
if call_id in self._pending_order:
|
|
146
156
|
self._pending_order.remove(call_id)
|
|
147
|
-
|
|
157
|
+
|
|
148
158
|
return True
|
|
149
|
-
|
|
159
|
+
|
|
150
160
|
async def wait_for_completion(self, call_id: str, timeout: float = 300.0) -> Optional[str]:
|
|
151
161
|
"""Wait for a completion call to be completed and return the response."""
|
|
152
162
|
start_time = asyncio.get_event_loop().time()
|
|
153
|
-
|
|
163
|
+
|
|
154
164
|
while True:
|
|
155
165
|
status = await self.get_call_status(call_id)
|
|
156
166
|
if not status:
|
|
157
167
|
return None
|
|
158
|
-
|
|
168
|
+
|
|
159
169
|
if status["status"] == CompletionStatus.COMPLETED.value:
|
|
160
170
|
return status.get("response")
|
|
161
171
|
elif status["status"] == CompletionStatus.FAILED.value:
|
|
162
172
|
raise Exception(f"Completion failed: {status.get('error', 'Unknown error')}")
|
|
163
|
-
|
|
173
|
+
|
|
164
174
|
# Check timeout
|
|
165
175
|
if asyncio.get_event_loop().time() - start_time > timeout:
|
|
166
176
|
await self.fail_call(call_id, "Timeout waiting for human response")
|
|
167
177
|
raise TimeoutError("Timeout waiting for human response")
|
|
168
|
-
|
|
178
|
+
|
|
169
179
|
# Wait a bit before checking again
|
|
170
180
|
await asyncio.sleep(0.5)
|
|
171
181
|
|
|
@@ -204,9 +214,7 @@ async def get_status(call_id: str):
|
|
|
204
214
|
async def complete_call(call_id: str, response: CompletionResponse):
|
|
205
215
|
"""Complete a call with a human response."""
|
|
206
216
|
success = await completion_queue.complete_call(
|
|
207
|
-
call_id,
|
|
208
|
-
response=response.response,
|
|
209
|
-
tool_calls=response.tool_calls
|
|
217
|
+
call_id, response=response.response, tool_calls=response.tool_calls
|
|
210
218
|
)
|
|
211
219
|
if success:
|
|
212
220
|
return {"status": "success", "message": "Call completed"}
|
|
@@ -219,7 +227,9 @@ async def fail_call(call_id: str, error: Dict[str, str]):
|
|
|
219
227
|
"""Mark a call as failed."""
|
|
220
228
|
success = await completion_queue.fail_call(call_id, error.get("error", "Unknown error"))
|
|
221
229
|
if not success:
|
|
222
|
-
raise HTTPException(
|
|
230
|
+
raise HTTPException(
|
|
231
|
+
status_code=404, detail="Completion call not found or already completed"
|
|
232
|
+
)
|
|
223
233
|
return {"status": "failed"}
|
|
224
234
|
|
|
225
235
|
|
|
@@ -231,4 +241,5 @@ async def root():
|
|
|
231
241
|
|
|
232
242
|
if __name__ == "__main__":
|
|
233
243
|
import uvicorn
|
|
244
|
+
|
|
234
245
|
uvicorn.run(app, host="0.0.0.0", port=8002)
|