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.
Files changed (2) hide show
  1. package/bin/chat.js +109 -8
  2. 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
- const formatted = formatStep(event.step);
374
- if (formatted !== null) {
375
- process.stdout.write('\r\x1b[2K');
376
- console.log(formatted);
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
- spinner.startSession(event.step.slice(0, 50));
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(() => {});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0agent",
3
- "version": "1.0.57",
3
+ "version": "1.0.59",
4
4
  "description": "A persistent, learning AI agent that runs on your machine. An agent that learns.",
5
5
  "private": false,
6
6
  "license": "Apache-2.0",