@openagents-org/agent-launcher 0.2.29 → 0.2.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openagents-org/agent-launcher",
3
- "version": "0.2.29",
3
+ "version": "0.2.30",
4
4
  "description": "OpenAgents Launcher — install, configure, and run AI coding agents from your terminal",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -286,21 +286,26 @@ class OpenClawAdapter extends BaseAdapter {
286
286
  clearInterval(pollInterval);
287
287
  clearTimeout(killTimeout);
288
288
  fs.closeSync(stderrFd);
289
- // Read any remaining stderr
289
+ // Read full stderr content (contains JSON output + trace lines)
290
+ let stderrContent = '';
290
291
  try {
291
- const remaining = fs.readFileSync(stderrFile, 'utf-8').slice(stderrOffset);
292
+ stderrContent = fs.readFileSync(stderrFile, 'utf-8');
293
+ // Process any remaining lines for tool events
294
+ const remaining = stderrContent.slice(stderrOffset);
292
295
  if (remaining) {
293
- output += remaining;
294
296
  for (const line of remaining.split('\n')) processLine(line);
295
297
  }
296
298
  } catch {}
297
299
  try { fs.unlinkSync(stderrFile); } catch {}
298
300
 
301
+ // OpenClaw --json writes JSON to stderr, so combine stdout + stderr
302
+ const allOutput = output + '\n' + stderrContent;
303
+
299
304
  if (code !== 0) {
300
- reject(new Error(`CLI exited ${code}: ${output.slice(-300)}`));
305
+ reject(new Error(`CLI exited ${code}: ${allOutput.slice(-300)}`));
301
306
  return;
302
307
  }
303
- this._parseCliOutput(output, resolve);
308
+ this._parseCliOutput(allOutput, resolve);
304
309
  });
305
310
  });
306
311
  }
@@ -308,19 +313,65 @@ class OpenClawAdapter extends BaseAdapter {
308
313
  _parseCliOutput(output, resolve) {
309
314
  const text = output.trim();
310
315
  if (!text) { resolve(''); return; }
311
- const jsonStart = text.indexOf('{');
312
- if (jsonStart < 0) { resolve(text); return; }
313
- try {
314
- const data = JSON.parse(text.slice(jsonStart));
315
- const payloads = data.payloads || [];
316
- if (payloads.length > 0) {
317
- resolve(payloads.filter(p => p.text).map(p => p.text).join('\n\n'));
318
- } else {
319
- resolve('');
316
+
317
+ // OpenClaw --json outputs a JSON blob with {"payloads":[...]} structure.
318
+ // With --log-level trace, stderr also contains diagnostic lines.
319
+ // Find the JSON by looking for '{"payloads"' or the last complete JSON object.
320
+ let jsonStr = null;
321
+
322
+ // Strategy 1: find {"payloads" directly
323
+ const payloadsIdx = text.indexOf('{"payloads"');
324
+ if (payloadsIdx >= 0) {
325
+ // Find the matching closing brace by counting braces
326
+ let depth = 0;
327
+ for (let i = payloadsIdx; i < text.length; i++) {
328
+ if (text[i] === '{') depth++;
329
+ else if (text[i] === '}') { depth--; if (depth === 0) { jsonStr = text.slice(payloadsIdx, i + 1); break; } }
330
+ }
331
+ }
332
+
333
+ // Strategy 2: find last '{' that starts a valid JSON with "payloads"
334
+ if (!jsonStr) {
335
+ for (let i = text.length - 1; i >= 0; i--) {
336
+ if (text[i] === '{') {
337
+ const candidate = text.slice(i);
338
+ try {
339
+ const d = JSON.parse(candidate);
340
+ if (d.payloads) { jsonStr = candidate; break; }
341
+ } catch {}
342
+ }
320
343
  }
321
- } catch {
322
- resolve(text);
323
344
  }
345
+
346
+ // Strategy 3: try each line that starts with '{'
347
+ if (!jsonStr) {
348
+ for (const line of text.split('\n')) {
349
+ const trimmed = line.trim();
350
+ if (trimmed.startsWith('{')) {
351
+ try {
352
+ const d = JSON.parse(trimmed);
353
+ if (d.payloads) { jsonStr = trimmed; break; }
354
+ } catch {}
355
+ }
356
+ }
357
+ }
358
+
359
+ if (jsonStr) {
360
+ try {
361
+ const data = JSON.parse(jsonStr);
362
+ const payloads = data.payloads || [];
363
+ if (payloads.length > 0) {
364
+ resolve(payloads.filter(p => p.text).map(p => p.text).join('\n\n'));
365
+ return;
366
+ }
367
+ } catch {}
368
+ }
369
+
370
+ // Fallback: return non-diagnostic text
371
+ const cleanLines = text.split('\n').filter(l =>
372
+ !l.includes('[diagnostic]') && !l.includes('[agent/embedded]') && !l.includes('Registered plugin')
373
+ ).map(l => l.trim()).filter(Boolean);
374
+ resolve(cleanLines.join('\n') || '');
324
375
  }
325
376
  // ------------------------------------------------------------------
326
377
  // Static: configure OpenClaw's native auth from LLM env vars