oagi-core 0.10.0__py3-none-any.whl → 0.10.2__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.
- oagi/agent/default.py +7 -0
- oagi/agent/factories.py +6 -0
- oagi/agent/observer/exporters.py +142 -251
- oagi/agent/observer/report_template.html +455 -0
- oagi/agent/tasker/__init__.py +0 -2
- oagi/agent/tasker/memory.py +3 -27
- oagi/agent/tasker/models.py +0 -7
- oagi/agent/tasker/planner.py +2 -11
- oagi/agent/tasker/taskee_agent.py +8 -0
- oagi/agent/tasker/tasker_agent.py +7 -17
- oagi/cli/agent.py +108 -1
- oagi/client/async_.py +0 -3
- oagi/client/base.py +0 -4
- oagi/client/sync.py +0 -3
- oagi/handler/pyautogui_action_handler.py +20 -24
- oagi/server/socketio_server.py +20 -19
- oagi/types/__init__.py +12 -1
- oagi/types/models/__init__.py +10 -1
- oagi/types/models/action.py +51 -0
- oagi/types/models/client.py +7 -3
- {oagi_core-0.10.0.dist-info → oagi_core-0.10.2.dist-info}/METADATA +2 -1
- {oagi_core-0.10.0.dist-info → oagi_core-0.10.2.dist-info}/RECORD +25 -24
- {oagi_core-0.10.0.dist-info → oagi_core-0.10.2.dist-info}/WHEEL +0 -0
- {oagi_core-0.10.0.dist-info → oagi_core-0.10.2.dist-info}/entry_points.txt +0 -0
- {oagi_core-0.10.0.dist-info → oagi_core-0.10.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Agent Execution Report</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
10
|
+
max-width: 1200px;
|
|
11
|
+
margin: 0 auto;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
background: #f5f5f5;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
h1 {
|
|
17
|
+
color: #333;
|
|
18
|
+
border-bottom: 2px solid #007bff;
|
|
19
|
+
padding-bottom: 10px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.step, .plan {
|
|
23
|
+
background: white;
|
|
24
|
+
border-radius: 8px;
|
|
25
|
+
padding: 20px;
|
|
26
|
+
margin: 20px 0;
|
|
27
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.step h2 {
|
|
31
|
+
margin-top: 0;
|
|
32
|
+
color: #007bff;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.plan {
|
|
36
|
+
background: #e7f3ff;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.plan h3 {
|
|
40
|
+
margin-top: 0;
|
|
41
|
+
color: #0056b3;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.timestamp {
|
|
45
|
+
color: #666;
|
|
46
|
+
font-size: 0.9em;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.screenshot-container {
|
|
50
|
+
position: relative;
|
|
51
|
+
display: inline-block;
|
|
52
|
+
margin: 10px 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.screenshot {
|
|
56
|
+
max-width: 100%;
|
|
57
|
+
border: 1px solid #ddd;
|
|
58
|
+
border-radius: 4px;
|
|
59
|
+
display: block;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.reasoning {
|
|
63
|
+
background: #f8f9fa;
|
|
64
|
+
padding: 10px;
|
|
65
|
+
border-left: 3px solid #007bff;
|
|
66
|
+
margin: 10px 0;
|
|
67
|
+
white-space: pre-wrap;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.actions {
|
|
71
|
+
margin: 10px 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.actions ul {
|
|
75
|
+
margin: 5px 0;
|
|
76
|
+
padding-left: 20px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.actions code {
|
|
80
|
+
background: #e9ecef;
|
|
81
|
+
padding: 2px 6px;
|
|
82
|
+
border-radius: 3px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.complete {
|
|
86
|
+
background: #d4edda;
|
|
87
|
+
color: #155724;
|
|
88
|
+
padding: 10px;
|
|
89
|
+
border-radius: 4px;
|
|
90
|
+
margin-top: 10px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.action-result {
|
|
94
|
+
padding: 10px;
|
|
95
|
+
margin: 5px 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.success {
|
|
99
|
+
color: #155724;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.error {
|
|
103
|
+
color: #721c24;
|
|
104
|
+
background: #f8d7da;
|
|
105
|
+
padding: 10px;
|
|
106
|
+
border-radius: 4px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.log {
|
|
110
|
+
background: #fff3cd;
|
|
111
|
+
padding: 10px;
|
|
112
|
+
margin: 10px 0;
|
|
113
|
+
border-radius: 4px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.split {
|
|
117
|
+
text-align: center;
|
|
118
|
+
margin: 30px 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.split h3 {
|
|
122
|
+
color: #666;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.split-line {
|
|
126
|
+
border: none;
|
|
127
|
+
border-top: 2px dashed #ccc;
|
|
128
|
+
margin: 30px 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.url {
|
|
132
|
+
word-break: break-all;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.plan-result {
|
|
136
|
+
background: #d1ecf1;
|
|
137
|
+
color: #0c5460;
|
|
138
|
+
padding: 10px;
|
|
139
|
+
border-radius: 4px;
|
|
140
|
+
margin-top: 10px;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* Cursor indicators */
|
|
144
|
+
.click-indicator {
|
|
145
|
+
position: absolute;
|
|
146
|
+
width: 20px;
|
|
147
|
+
height: 20px;
|
|
148
|
+
border-radius: 50%;
|
|
149
|
+
background: rgba(255, 0, 0, 0.8);
|
|
150
|
+
border: 2px solid #fff;
|
|
151
|
+
box-shadow: 0 0 10px rgba(255, 0, 0, 0.6);
|
|
152
|
+
transform: translate(-50%, -50%);
|
|
153
|
+
pointer-events: none;
|
|
154
|
+
z-index: 10;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.drag-indicator {
|
|
158
|
+
position: absolute;
|
|
159
|
+
width: 20px;
|
|
160
|
+
height: 20px;
|
|
161
|
+
border-radius: 50%;
|
|
162
|
+
border: 2px solid #fff;
|
|
163
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
|
164
|
+
transform: translate(-50%, -50%);
|
|
165
|
+
pointer-events: none;
|
|
166
|
+
z-index: 10;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.drag-start {
|
|
170
|
+
background: rgba(0, 255, 0, 0.8);
|
|
171
|
+
box-shadow: 0 0 10px rgba(0, 255, 0, 0.6);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.drag-end {
|
|
175
|
+
background: rgba(255, 0, 0, 0.8);
|
|
176
|
+
box-shadow: 0 0 10px rgba(255, 0, 0, 0.6);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.drag-line {
|
|
180
|
+
position: absolute;
|
|
181
|
+
background: rgba(255, 255, 0, 0.8);
|
|
182
|
+
height: 3px;
|
|
183
|
+
border-radius: 2px;
|
|
184
|
+
box-shadow: 0 0 5px rgba(255, 255, 0, 0.4);
|
|
185
|
+
pointer-events: none;
|
|
186
|
+
z-index: 9;
|
|
187
|
+
transform-origin: left center;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.scroll-indicator {
|
|
191
|
+
position: absolute;
|
|
192
|
+
width: 40px;
|
|
193
|
+
height: 40px;
|
|
194
|
+
border-radius: 50%;
|
|
195
|
+
background: rgba(138, 43, 226, 0.9);
|
|
196
|
+
border: 2px solid #fff;
|
|
197
|
+
box-shadow: 0 0 15px rgba(138, 43, 226, 0.6);
|
|
198
|
+
transform: translate(-50%, -50%);
|
|
199
|
+
pointer-events: none;
|
|
200
|
+
z-index: 10;
|
|
201
|
+
display: flex;
|
|
202
|
+
align-items: center;
|
|
203
|
+
justify-content: center;
|
|
204
|
+
font-size: 20px;
|
|
205
|
+
color: white;
|
|
206
|
+
font-weight: bold;
|
|
207
|
+
}
|
|
208
|
+
</style>
|
|
209
|
+
</head>
|
|
210
|
+
<body>
|
|
211
|
+
<h1>Agent Execution Report</h1>
|
|
212
|
+
<div id="content"></div>
|
|
213
|
+
|
|
214
|
+
<script>
|
|
215
|
+
const eventsData = {EVENTS_DATA};
|
|
216
|
+
|
|
217
|
+
function escapeHtml(text) {
|
|
218
|
+
const div = document.createElement('div');
|
|
219
|
+
div.textContent = text;
|
|
220
|
+
return div.innerHTML;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function removeIndicators(container) {
|
|
224
|
+
container.querySelectorAll('.click-indicator, .drag-indicator, .drag-line, .scroll-indicator')
|
|
225
|
+
.forEach(el => el.remove());
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function addIndicators(container) {
|
|
229
|
+
const img = container.querySelector('.screenshot');
|
|
230
|
+
const actionsAttr = container.getAttribute('data-actions');
|
|
231
|
+
if (!actionsAttr || !img) return;
|
|
232
|
+
|
|
233
|
+
// Remove existing indicators before adding new ones
|
|
234
|
+
removeIndicators(container);
|
|
235
|
+
|
|
236
|
+
const actions = JSON.parse(actionsAttr);
|
|
237
|
+
const imgWidth = img.offsetWidth;
|
|
238
|
+
const imgHeight = img.offsetHeight;
|
|
239
|
+
|
|
240
|
+
actions.forEach(action => {
|
|
241
|
+
switch (action.type) {
|
|
242
|
+
case 'click':
|
|
243
|
+
addClickIndicator(container, action, imgWidth, imgHeight);
|
|
244
|
+
break;
|
|
245
|
+
case 'drag':
|
|
246
|
+
addDragIndicator(container, action, imgWidth, imgHeight);
|
|
247
|
+
break;
|
|
248
|
+
case 'scroll':
|
|
249
|
+
addScrollIndicator(container, action, imgWidth, imgHeight);
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Recalculate indicator positions on window resize
|
|
256
|
+
let resizeTimeout;
|
|
257
|
+
window.addEventListener('resize', function () {
|
|
258
|
+
clearTimeout(resizeTimeout);
|
|
259
|
+
resizeTimeout = setTimeout(function () {
|
|
260
|
+
document.querySelectorAll('.screenshot-container').forEach(container => {
|
|
261
|
+
addIndicators(container);
|
|
262
|
+
});
|
|
263
|
+
}, 100);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
function addClickIndicator(container, action, imgWidth, imgHeight) {
|
|
267
|
+
const x = (action.x / 1000) * imgWidth;
|
|
268
|
+
const y = (action.y / 1000) * imgHeight;
|
|
269
|
+
|
|
270
|
+
const indicator = document.createElement('div');
|
|
271
|
+
indicator.className = 'click-indicator';
|
|
272
|
+
indicator.style.left = x + 'px';
|
|
273
|
+
indicator.style.top = y + 'px';
|
|
274
|
+
container.appendChild(indicator);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function addDragIndicator(container, action, imgWidth, imgHeight) {
|
|
278
|
+
const x1 = (action.x1 / 1000) * imgWidth;
|
|
279
|
+
const y1 = (action.y1 / 1000) * imgHeight;
|
|
280
|
+
const x2 = (action.x2 / 1000) * imgWidth;
|
|
281
|
+
const y2 = (action.y2 / 1000) * imgHeight;
|
|
282
|
+
|
|
283
|
+
const startIndicator = document.createElement('div');
|
|
284
|
+
startIndicator.className = 'drag-indicator drag-start';
|
|
285
|
+
startIndicator.style.left = x1 + 'px';
|
|
286
|
+
startIndicator.style.top = y1 + 'px';
|
|
287
|
+
container.appendChild(startIndicator);
|
|
288
|
+
|
|
289
|
+
const endIndicator = document.createElement('div');
|
|
290
|
+
endIndicator.className = 'drag-indicator drag-end';
|
|
291
|
+
endIndicator.style.left = x2 + 'px';
|
|
292
|
+
endIndicator.style.top = y2 + 'px';
|
|
293
|
+
container.appendChild(endIndicator);
|
|
294
|
+
|
|
295
|
+
const line = document.createElement('div');
|
|
296
|
+
line.className = 'drag-line';
|
|
297
|
+
const deltaX = x2 - x1;
|
|
298
|
+
const deltaY = y2 - y1;
|
|
299
|
+
const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
300
|
+
const angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
|
|
301
|
+
line.style.left = x1 + 'px';
|
|
302
|
+
line.style.top = y1 + 'px';
|
|
303
|
+
line.style.width = length + 'px';
|
|
304
|
+
line.style.transform = 'rotate(' + angle + 'deg)';
|
|
305
|
+
container.appendChild(line);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function addScrollIndicator(container, action, imgWidth, imgHeight) {
|
|
309
|
+
const x = (action.x / 1000) * imgWidth;
|
|
310
|
+
const y = (action.y / 1000) * imgHeight;
|
|
311
|
+
|
|
312
|
+
const indicator = document.createElement('div');
|
|
313
|
+
indicator.className = 'scroll-indicator';
|
|
314
|
+
indicator.style.left = x + 'px';
|
|
315
|
+
indicator.style.top = y + 'px';
|
|
316
|
+
|
|
317
|
+
if (action.direction === 'up') {
|
|
318
|
+
indicator.innerHTML = '↑';
|
|
319
|
+
indicator.title = 'Scroll Up';
|
|
320
|
+
} else if (action.direction === 'down') {
|
|
321
|
+
indicator.innerHTML = '↓';
|
|
322
|
+
indicator.title = 'Scroll Down';
|
|
323
|
+
} else {
|
|
324
|
+
indicator.innerHTML = '↕';
|
|
325
|
+
indicator.title = 'Scroll';
|
|
326
|
+
}
|
|
327
|
+
container.appendChild(indicator);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function renderEvents() {
|
|
331
|
+
const content = document.getElementById('content');
|
|
332
|
+
let html = '';
|
|
333
|
+
|
|
334
|
+
eventsData.forEach(event => {
|
|
335
|
+
const timestamp = event.timestamp;
|
|
336
|
+
|
|
337
|
+
switch (event.event_type) {
|
|
338
|
+
case 'step':
|
|
339
|
+
html += '<div class="step">';
|
|
340
|
+
html += `<h2>Step ${event.step_num}</h2>`;
|
|
341
|
+
html += `<span class="timestamp">${timestamp}</span>`;
|
|
342
|
+
|
|
343
|
+
if (event.image) {
|
|
344
|
+
const actionsJson = JSON.stringify(event.action_coords || []).replace(/"/g, '"');
|
|
345
|
+
html += `<div class="screenshot-container" data-actions="${actionsJson}">`;
|
|
346
|
+
if (event.image.startsWith('data:') || event.image.startsWith('http')) {
|
|
347
|
+
html += `<img src="${event.image}" alt="Step ${event.step_num}" class="screenshot"/>`;
|
|
348
|
+
} else {
|
|
349
|
+
html += `<img src="data:image/png;base64,${event.image}" alt="Step ${event.step_num}" class="screenshot"/>`;
|
|
350
|
+
}
|
|
351
|
+
html += '</div>';
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (event.reason) {
|
|
355
|
+
html += '<div class="reasoning">';
|
|
356
|
+
html += `<strong>Reasoning:</strong><p>${escapeHtml(event.reason)}</p>`;
|
|
357
|
+
html += '</div>';
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (event.actions && event.actions.length > 0) {
|
|
361
|
+
html += '<div class="actions"><strong>Planned Actions:</strong><ul>';
|
|
362
|
+
event.actions.forEach(action => {
|
|
363
|
+
const countStr = action.count > 1 ? ` (x${action.count})` : '';
|
|
364
|
+
html += `<li><code>${action.type}</code>: ${escapeHtml(action.argument)}${countStr}</li>`;
|
|
365
|
+
});
|
|
366
|
+
html += '</ul></div>';
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (event.stop) {
|
|
370
|
+
html += '<div class="complete">Task Complete</div>';
|
|
371
|
+
}
|
|
372
|
+
html += '</div>';
|
|
373
|
+
break;
|
|
374
|
+
|
|
375
|
+
case 'action':
|
|
376
|
+
html += '<div class="action-result">';
|
|
377
|
+
html += `<span class="timestamp">${timestamp}</span>`;
|
|
378
|
+
if (event.error) {
|
|
379
|
+
html += `<div class="error">Error: ${escapeHtml(event.error)}</div>`;
|
|
380
|
+
} else {
|
|
381
|
+
html += '<div class="success">Actions executed successfully</div>';
|
|
382
|
+
}
|
|
383
|
+
html += '</div>';
|
|
384
|
+
break;
|
|
385
|
+
|
|
386
|
+
case 'log':
|
|
387
|
+
html += '<div class="log">';
|
|
388
|
+
html += `<span class="timestamp">${timestamp}</span>`;
|
|
389
|
+
html += `<p>${escapeHtml(event.message)}</p>`;
|
|
390
|
+
html += '</div>';
|
|
391
|
+
break;
|
|
392
|
+
|
|
393
|
+
case 'split':
|
|
394
|
+
if (event.label) {
|
|
395
|
+
html += `<div class="split"><h3>${escapeHtml(event.label)}</h3></div>`;
|
|
396
|
+
} else {
|
|
397
|
+
html += '<hr class="split-line"/>';
|
|
398
|
+
}
|
|
399
|
+
break;
|
|
400
|
+
|
|
401
|
+
case 'plan':
|
|
402
|
+
const phaseTitles = {
|
|
403
|
+
'initial': 'Initial Planning',
|
|
404
|
+
'reflection': 'Reflection',
|
|
405
|
+
'summary': 'Summary'
|
|
406
|
+
};
|
|
407
|
+
const phaseTitle = phaseTitles[event.phase] || event.phase;
|
|
408
|
+
|
|
409
|
+
html += '<div class="plan">';
|
|
410
|
+
html += `<h3>${phaseTitle}</h3>`;
|
|
411
|
+
html += `<span class="timestamp">${timestamp}</span>`;
|
|
412
|
+
|
|
413
|
+
if (event.image) {
|
|
414
|
+
html += '<div class="screenshot-container">';
|
|
415
|
+
if (event.image.startsWith('data:') || event.image.startsWith('http')) {
|
|
416
|
+
html += `<img src="${event.image}" alt="${phaseTitle}" class="screenshot"/>`;
|
|
417
|
+
} else {
|
|
418
|
+
html += `<img src="data:image/png;base64,${event.image}" alt="${phaseTitle}" class="screenshot"/>`;
|
|
419
|
+
}
|
|
420
|
+
html += '</div>';
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (event.reasoning) {
|
|
424
|
+
html += '<div class="reasoning">';
|
|
425
|
+
html += `<strong>Reasoning:</strong><p>${escapeHtml(event.reasoning)}</p>`;
|
|
426
|
+
html += '</div>';
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (event.result) {
|
|
430
|
+
html += `<div class="plan-result"><strong>Result:</strong> ${escapeHtml(event.result)}</div>`;
|
|
431
|
+
}
|
|
432
|
+
html += '</div>';
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
content.innerHTML = html;
|
|
438
|
+
|
|
439
|
+
// Add cursor indicators after images load
|
|
440
|
+
document.querySelectorAll('.screenshot-container').forEach(container => {
|
|
441
|
+
const img = container.querySelector('.screenshot');
|
|
442
|
+
if (img) {
|
|
443
|
+
if (img.complete) {
|
|
444
|
+
addIndicators(container);
|
|
445
|
+
} else {
|
|
446
|
+
img.onload = () => addIndicators(container);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
document.addEventListener('DOMContentLoaded', renderEvents);
|
|
453
|
+
</script>
|
|
454
|
+
</body>
|
|
455
|
+
</html>
|
oagi/agent/tasker/__init__.py
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
from .memory import PlannerMemory
|
|
10
10
|
from .models import (
|
|
11
11
|
Action,
|
|
12
|
-
Deliverable,
|
|
13
12
|
PlannerOutput,
|
|
14
13
|
ReflectionOutput,
|
|
15
14
|
Todo,
|
|
@@ -27,7 +26,6 @@ __all__ = [
|
|
|
27
26
|
"Planner",
|
|
28
27
|
"Todo",
|
|
29
28
|
"TodoStatus",
|
|
30
|
-
"Deliverable",
|
|
31
29
|
"Action",
|
|
32
30
|
"TodoHistory",
|
|
33
31
|
"PlannerOutput",
|
oagi/agent/tasker/memory.py
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
|
-
from .models import Action,
|
|
11
|
+
from .models import Action, Todo, TodoHistory, TodoStatus
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class PlannerMemory:
|
|
@@ -16,7 +16,7 @@ class PlannerMemory:
|
|
|
16
16
|
|
|
17
17
|
This class manages the hierarchical task execution state for TaskerAgent.
|
|
18
18
|
It provides methods for:
|
|
19
|
-
- Task/todo
|
|
19
|
+
- Task/todo management
|
|
20
20
|
- Execution history tracking
|
|
21
21
|
- Memory state serialization
|
|
22
22
|
|
|
@@ -27,7 +27,6 @@ class PlannerMemory:
|
|
|
27
27
|
"""Initialize empty memory."""
|
|
28
28
|
self.task_description: str = ""
|
|
29
29
|
self.todos: list[Todo] = []
|
|
30
|
-
self.deliverables: list[Deliverable] = []
|
|
31
30
|
self.history: list[TodoHistory] = []
|
|
32
31
|
self.task_execution_summary: str = ""
|
|
33
32
|
self.todo_execution_summaries: dict[int, str] = {}
|
|
@@ -36,14 +35,12 @@ class PlannerMemory:
|
|
|
36
35
|
self,
|
|
37
36
|
task_description: str,
|
|
38
37
|
todos: list[str] | list[Todo],
|
|
39
|
-
deliverables: list[str] | list[Deliverable] | None = None,
|
|
40
38
|
) -> None:
|
|
41
|
-
"""Set the task
|
|
39
|
+
"""Set the task and todos.
|
|
42
40
|
|
|
43
41
|
Args:
|
|
44
42
|
task_description: Overall task description
|
|
45
43
|
todos: List of todo items (strings or Todo objects)
|
|
46
|
-
deliverables: Optional list of deliverables (strings or Deliverable objects)
|
|
47
44
|
"""
|
|
48
45
|
self.task_description = task_description
|
|
49
46
|
|
|
@@ -55,15 +52,6 @@ class PlannerMemory:
|
|
|
55
52
|
else:
|
|
56
53
|
self.todos.append(todo)
|
|
57
54
|
|
|
58
|
-
# Convert deliverables
|
|
59
|
-
self.deliverables = []
|
|
60
|
-
if deliverables:
|
|
61
|
-
for deliverable in deliverables:
|
|
62
|
-
if isinstance(deliverable, str):
|
|
63
|
-
self.deliverables.append(Deliverable(description=deliverable))
|
|
64
|
-
else:
|
|
65
|
-
self.deliverables.append(deliverable)
|
|
66
|
-
|
|
67
55
|
def get_current_todo(self) -> tuple[Todo | None, int]:
|
|
68
56
|
"""Get the next pending or in-progress todo.
|
|
69
57
|
|
|
@@ -133,10 +121,6 @@ class PlannerMemory:
|
|
|
133
121
|
{"index": i, "description": t.description, "status": t.status}
|
|
134
122
|
for i, t in enumerate(self.todos)
|
|
135
123
|
],
|
|
136
|
-
"deliverables": [
|
|
137
|
-
{"description": d.description, "achieved": d.achieved}
|
|
138
|
-
for d in self.deliverables
|
|
139
|
-
],
|
|
140
124
|
"history": [
|
|
141
125
|
{
|
|
142
126
|
"todo_index": h.todo_index,
|
|
@@ -174,11 +158,3 @@ class PlannerMemory:
|
|
|
174
158
|
description: Description of the new todo
|
|
175
159
|
"""
|
|
176
160
|
self.todos.append(Todo(description=description))
|
|
177
|
-
|
|
178
|
-
def append_deliverable(self, description: str) -> None:
|
|
179
|
-
"""Append a new deliverable to the list.
|
|
180
|
-
|
|
181
|
-
Args:
|
|
182
|
-
description: Description of the new deliverable
|
|
183
|
-
"""
|
|
184
|
-
self.deliverables.append(Deliverable(description=description))
|
oagi/agent/tasker/models.py
CHANGED
|
@@ -28,13 +28,6 @@ class Todo(BaseModel):
|
|
|
28
28
|
status: TodoStatus = TodoStatus.PENDING
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
class Deliverable(BaseModel):
|
|
32
|
-
"""A deliverable or goal to be achieved."""
|
|
33
|
-
|
|
34
|
-
description: str
|
|
35
|
-
achieved: bool = False
|
|
36
|
-
|
|
37
|
-
|
|
38
31
|
class Action(BaseModel):
|
|
39
32
|
"""An action taken during execution."""
|
|
40
33
|
|
oagi/agent/tasker/planner.py
CHANGED
|
@@ -62,7 +62,7 @@ class Planner:
|
|
|
62
62
|
memory: PlannerMemory | None,
|
|
63
63
|
context: dict[str, Any],
|
|
64
64
|
todo_index: int | None = None,
|
|
65
|
-
) -> tuple[str, list, list,
|
|
65
|
+
) -> tuple[str, list, list, str | None, str]:
|
|
66
66
|
"""Extract memory data for API calls.
|
|
67
67
|
|
|
68
68
|
Args:
|
|
@@ -71,7 +71,7 @@ class Planner:
|
|
|
71
71
|
todo_index: Optional todo index for extracting overall_todo
|
|
72
72
|
|
|
73
73
|
Returns:
|
|
74
|
-
Tuple of (task_description, todos,
|
|
74
|
+
Tuple of (task_description, todos, history,
|
|
75
75
|
task_execution_summary, overall_todo)
|
|
76
76
|
"""
|
|
77
77
|
if memory and todo_index is not None:
|
|
@@ -86,7 +86,6 @@ class Planner:
|
|
|
86
86
|
}
|
|
87
87
|
for i, t in enumerate(memory.todos)
|
|
88
88
|
]
|
|
89
|
-
deliverables = [d.model_dump() for d in memory.deliverables]
|
|
90
89
|
history = [
|
|
91
90
|
{
|
|
92
91
|
"todo_index": h.todo_index,
|
|
@@ -103,7 +102,6 @@ class Planner:
|
|
|
103
102
|
# Fallback to basic context
|
|
104
103
|
task_description = context.get("task_description", "")
|
|
105
104
|
todos = context.get("todos", [])
|
|
106
|
-
deliverables = context.get("deliverables", [])
|
|
107
105
|
history = context.get("history", [])
|
|
108
106
|
task_execution_summary = None
|
|
109
107
|
overall_todo = context.get("current_todo", "")
|
|
@@ -111,7 +109,6 @@ class Planner:
|
|
|
111
109
|
return (
|
|
112
110
|
task_description,
|
|
113
111
|
todos,
|
|
114
|
-
deliverables,
|
|
115
112
|
history,
|
|
116
113
|
task_execution_summary,
|
|
117
114
|
overall_todo,
|
|
@@ -150,7 +147,6 @@ class Planner:
|
|
|
150
147
|
(
|
|
151
148
|
task_description,
|
|
152
149
|
todos,
|
|
153
|
-
deliverables,
|
|
154
150
|
history,
|
|
155
151
|
task_execution_summary,
|
|
156
152
|
_, # overall_todo not needed here, we use the `todo` parameter
|
|
@@ -162,7 +158,6 @@ class Planner:
|
|
|
162
158
|
overall_todo=todo,
|
|
163
159
|
task_description=task_description,
|
|
164
160
|
todos=todos,
|
|
165
|
-
deliverables=deliverables,
|
|
166
161
|
history=history,
|
|
167
162
|
current_todo_index=todo_index,
|
|
168
163
|
task_execution_summary=task_execution_summary,
|
|
@@ -209,7 +204,6 @@ class Planner:
|
|
|
209
204
|
(
|
|
210
205
|
task_description,
|
|
211
206
|
todos,
|
|
212
|
-
deliverables,
|
|
213
207
|
history,
|
|
214
208
|
task_execution_summary,
|
|
215
209
|
overall_todo,
|
|
@@ -245,7 +239,6 @@ class Planner:
|
|
|
245
239
|
overall_todo=overall_todo,
|
|
246
240
|
task_description=task_description,
|
|
247
241
|
todos=todos,
|
|
248
|
-
deliverables=deliverables,
|
|
249
242
|
history=history,
|
|
250
243
|
current_todo_index=todo_index,
|
|
251
244
|
task_execution_summary=task_execution_summary,
|
|
@@ -284,7 +277,6 @@ class Planner:
|
|
|
284
277
|
(
|
|
285
278
|
task_description,
|
|
286
279
|
todos,
|
|
287
|
-
deliverables,
|
|
288
280
|
history,
|
|
289
281
|
task_execution_summary,
|
|
290
282
|
overall_todo,
|
|
@@ -302,7 +294,6 @@ class Planner:
|
|
|
302
294
|
overall_todo=overall_todo,
|
|
303
295
|
task_description=task_description,
|
|
304
296
|
todos=todos,
|
|
305
|
-
deliverables=deliverables,
|
|
306
297
|
history=history,
|
|
307
298
|
current_todo_index=todo_index,
|
|
308
299
|
task_execution_summary=task_execution_summary,
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
# Licensed under the MIT License.
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
|
|
9
|
+
import asyncio
|
|
9
10
|
import logging
|
|
10
11
|
from datetime import datetime
|
|
11
12
|
from typing import Any
|
|
@@ -59,6 +60,7 @@ class TaskeeAgent(AsyncAgent):
|
|
|
59
60
|
external_memory: PlannerMemory | None = None,
|
|
60
61
|
todo_index: int | None = None,
|
|
61
62
|
step_observer: AsyncObserver | None = None,
|
|
63
|
+
step_delay: float = 0.3,
|
|
62
64
|
):
|
|
63
65
|
"""Initialize the taskee agent.
|
|
64
66
|
|
|
@@ -73,6 +75,7 @@ class TaskeeAgent(AsyncAgent):
|
|
|
73
75
|
external_memory: External memory from parent agent
|
|
74
76
|
todo_index: Index of the todo being executed
|
|
75
77
|
step_observer: Optional observer for step tracking
|
|
78
|
+
step_delay: Delay in seconds after actions before next screenshot
|
|
76
79
|
"""
|
|
77
80
|
self.api_key = api_key
|
|
78
81
|
self.base_url = base_url
|
|
@@ -84,6 +87,7 @@ class TaskeeAgent(AsyncAgent):
|
|
|
84
87
|
self.external_memory = external_memory
|
|
85
88
|
self.todo_index = todo_index
|
|
86
89
|
self.step_observer = step_observer
|
|
90
|
+
self.step_delay = step_delay
|
|
87
91
|
|
|
88
92
|
# Internal state
|
|
89
93
|
self.actor: AsyncActor | None = None
|
|
@@ -327,6 +331,10 @@ class TaskeeAgent(AsyncAgent):
|
|
|
327
331
|
self.total_actions += len(step.actions)
|
|
328
332
|
self.since_reflection += len(step.actions)
|
|
329
333
|
|
|
334
|
+
# Wait after actions before next screenshot
|
|
335
|
+
if self.step_delay > 0:
|
|
336
|
+
await asyncio.sleep(self.step_delay)
|
|
337
|
+
|
|
330
338
|
steps_taken += 1
|
|
331
339
|
|
|
332
340
|
# Check if task is complete
|