0agent 1.0.57 → 1.0.59
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.
- package/bin/chat.js +109 -8
- package/package.json +1 -1
package/bin/chat.js
CHANGED
|
@@ -175,6 +175,89 @@ function renderMarkdown(text) {
|
|
|
175
175
|
return out.join('\n');
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
// ─── Human-readable active task summary ───────────────────────────────────────
|
|
179
|
+
// Translates raw AgentExecutor step labels into a plain-English 1-liner shown
|
|
180
|
+
// as the live "what is happening right now" status line.
|
|
181
|
+
function stepToHuman(step) {
|
|
182
|
+
// Tool invocations: "▶ tool_name(args...)"
|
|
183
|
+
const toolMatch = step.match(/^▶\s+(\w+)\((.{0,200})\)/);
|
|
184
|
+
if (toolMatch) {
|
|
185
|
+
const [, tool, args] = toolMatch;
|
|
186
|
+
// gui_automation — decode action
|
|
187
|
+
if (tool === 'gui_automation') {
|
|
188
|
+
const act = (args.match(/action[=:]\s*["']?(\w+)["']?/i) || [])[1] ?? '';
|
|
189
|
+
const txt = (args.match(/text[=:]\s*["']([^"']{0,40})["']/i) || [])[1] ?? '';
|
|
190
|
+
const url = (args.match(/url[=:]\s*["']([^"']{0,60})["']/i) || [])[1] ?? '';
|
|
191
|
+
const secs = (args.match(/seconds[=:]\s*([\d.]+)/i) || [])[1] ?? '';
|
|
192
|
+
const x = (args.match(/\bx[=:]\s*(\d+)/i) || [])[1] ?? '';
|
|
193
|
+
const y = (args.match(/\by[=:]\s*(\d+)/i) || [])[1] ?? '';
|
|
194
|
+
const map = {
|
|
195
|
+
screenshot: 'Taking screenshot of screen',
|
|
196
|
+
click: x ? `Clicking at (${x}, ${y})` : 'Clicking',
|
|
197
|
+
double_click: x ? `Double-clicking at (${x}, ${y})` : 'Double-clicking',
|
|
198
|
+
right_click: 'Right-clicking',
|
|
199
|
+
move: x ? `Moving cursor to (${x}, ${y})` : 'Moving cursor',
|
|
200
|
+
type: txt ? `Typing: "${txt.slice(0,30)}"` : 'Typing text',
|
|
201
|
+
hotkey: txt ? `Pressing ${txt}` : 'Pressing hotkey',
|
|
202
|
+
scroll: 'Scrolling',
|
|
203
|
+
drag: 'Dragging',
|
|
204
|
+
find_and_click: txt ? `Clicking "${txt}"` : 'Finding and clicking',
|
|
205
|
+
open_url: url ? `Opening ${url}` : 'Opening URL in browser',
|
|
206
|
+
open_app: txt ? `Opening ${txt}` : 'Opening app',
|
|
207
|
+
get_screen_size: 'Getting screen size',
|
|
208
|
+
get_cursor_pos: 'Getting cursor position',
|
|
209
|
+
wait: secs ? `Waiting ${secs}s for UI to load` : 'Waiting for UI',
|
|
210
|
+
};
|
|
211
|
+
return map[act] ?? `GUI: ${act}`;
|
|
212
|
+
}
|
|
213
|
+
// shell_exec
|
|
214
|
+
if (tool === 'shell_exec') {
|
|
215
|
+
const cmd = args.replace(/^["']|["']$/g, '').replace(/\\n/g, ' ').trim().slice(0, 60);
|
|
216
|
+
return `Running: ${cmd}`;
|
|
217
|
+
}
|
|
218
|
+
// web_search
|
|
219
|
+
if (tool === 'web_search') {
|
|
220
|
+
const q = (args.match(/["']([^"']{1,60})["']/) || [])[1] ?? args.slice(0,50);
|
|
221
|
+
return `Searching: ${q}`;
|
|
222
|
+
}
|
|
223
|
+
// file_op
|
|
224
|
+
if (tool === 'file_op') {
|
|
225
|
+
const op = (args.match(/op[=:]\s*["']?(\w+)["']?/i) || [])[1] ?? '';
|
|
226
|
+
const path = (args.match(/path[=:]\s*["']([^"']{1,50})["']/i) || [])[1] ?? '';
|
|
227
|
+
const opMap = { write: 'Writing', read: 'Reading', list: 'Listing', mkdir: 'Creating folder', delete: 'Deleting' };
|
|
228
|
+
return `${opMap[op] ?? op}: ${path}`;
|
|
229
|
+
}
|
|
230
|
+
// browser_open / scrape_url
|
|
231
|
+
if (tool === 'browser_open' || tool === 'scrape_url') {
|
|
232
|
+
const url = (args.match(/["']([^"']{1,60})["']/) || [])[1] ?? args.slice(0,50);
|
|
233
|
+
return `Reading page: ${url}`;
|
|
234
|
+
}
|
|
235
|
+
// memory_write
|
|
236
|
+
if (tool === 'memory_write') {
|
|
237
|
+
const label = (args.match(/label[=:]\s*["']([^"']{1,40})["']/i) || [])[1] ?? '';
|
|
238
|
+
return `Saving to memory: ${label}`;
|
|
239
|
+
}
|
|
240
|
+
// generic fallback
|
|
241
|
+
const cleanArgs = args.replace(/^["'](.*)["']$/, '$1').replace(/\\n/g, ' ').slice(0, 50);
|
|
242
|
+
return `${tool}: ${cleanArgs}`;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Result line: " ↳ text" — show briefly as status, not in history
|
|
246
|
+
if (/^\s*↳/.test(step)) {
|
|
247
|
+
return step.replace(/^\s*↳\s*/, '').slice(0, 80);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Thinking / Continuing
|
|
251
|
+
if (/^Thinking/.test(step)) return 'Thinking…';
|
|
252
|
+
if (/^Continuing/.test(step)) return 'Working on it…';
|
|
253
|
+
|
|
254
|
+
// Self-heal, skill, misc
|
|
255
|
+
if (/^↺/.test(step)) return step.slice(0, 80);
|
|
256
|
+
if (/^✓/.test(step)) return step.slice(0, 80);
|
|
257
|
+
|
|
258
|
+
return step.slice(0, 80);
|
|
259
|
+
}
|
|
260
|
+
|
|
178
261
|
// ─── Step formatter ───────────────────────────────────────────────────────────
|
|
179
262
|
// Converts raw step labels from AgentExecutor into icon + clean readable form.
|
|
180
263
|
function formatStep(step) {
|
|
@@ -370,12 +453,29 @@ function handleWsEvent(event) {
|
|
|
370
453
|
case 'session.step': {
|
|
371
454
|
spinner.stop();
|
|
372
455
|
if (streaming) { process.stdout.write('\n'); streaming = false; streamLineCount = 0; }
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
456
|
+
|
|
457
|
+
const step = event.step;
|
|
458
|
+
const isToolCall = /^▶\s+\w+\(/.test(step); // ▶ tool(args)
|
|
459
|
+
const isResult = /^\s*↳/.test(step); // ↳ result
|
|
460
|
+
const isThinking = /^(Thinking|Continuing)/.test(step);
|
|
461
|
+
const isSummary = /^(Done|Files|Commands|Matched|Fetching|Loaded|Selected|Extracting|Querying|↺|✓)/.test(step);
|
|
462
|
+
|
|
463
|
+
// Print tool invocations and summary milestones to scrolling history
|
|
464
|
+
if (isToolCall || isSummary) {
|
|
465
|
+
const formatted = formatStep(step);
|
|
466
|
+
if (formatted !== null) {
|
|
467
|
+
process.stdout.write('\r\x1b[2K');
|
|
468
|
+
console.log(formatted);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Always update the live 1-liner status (overwrites current line)
|
|
473
|
+
const human = stepToHuman(step);
|
|
474
|
+
if (human) {
|
|
475
|
+
const icon = isThinking ? fmt(C.dim, '⠋') : isResult ? fmt(C.dim, '↳') : fmt(C.cyan, '⚡');
|
|
476
|
+
process.stdout.write(`\r\x1b[2K ${icon} ${fmt(C.dim, human)}`);
|
|
377
477
|
}
|
|
378
|
-
|
|
478
|
+
|
|
379
479
|
rl.prompt(true);
|
|
380
480
|
break;
|
|
381
481
|
}
|
|
@@ -1181,9 +1281,11 @@ emitKeypressEvents(process.stdin, rl);
|
|
|
1181
1281
|
process.stdin.on('keypress', (_char, key) => {
|
|
1182
1282
|
if (!key || _paletteOpen) return;
|
|
1183
1283
|
if (key.name === 'escape' && pendingResolve) {
|
|
1184
|
-
// Cancel the running session cleanly
|
|
1185
|
-
process.stdout.write(`\r\x1b[2K\n ${fmt(C.yellow, '↩')} Cancelled\n`);
|
|
1186
1284
|
spinner.stop();
|
|
1285
|
+
process.stdout.write(`\r\x1b[2K`);
|
|
1286
|
+
process.stdout.write(`\n ${fmt(C.yellow, '⏹')} ${fmt(C.bold, 'Task stopped.')} All background processes killed.\n`);
|
|
1287
|
+
process.stdout.write(` ${fmt(C.dim, 'Send a new message to start fresh.')}\n\n`);
|
|
1288
|
+
|
|
1187
1289
|
if (sessionId) {
|
|
1188
1290
|
fetch(`${BASE_URL}/api/sessions/${sessionId}`, { method: 'DELETE' }).catch(() => {});
|
|
1189
1291
|
}
|
|
@@ -1195,7 +1297,6 @@ process.stdin.on('keypress', (_char, key) => {
|
|
|
1195
1297
|
messageQueue.length = 0;
|
|
1196
1298
|
|
|
1197
1299
|
// Kill any OS-level processes spawned by GUI/shell capabilities
|
|
1198
|
-
// (python3 GUI scripts, bash subprocesses) so nothing keeps running
|
|
1199
1300
|
import('node:child_process').then(({ execSync: _exec }) => {
|
|
1200
1301
|
try { _exec('pkill -f "0agent_gui_" 2>/dev/null; pkill -f "0agent-bg-" 2>/dev/null; true', { stdio: 'ignore' }); } catch {}
|
|
1201
1302
|
}).catch(() => {});
|