@openagents-org/agent-launcher 0.2.98 → 0.2.100

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.98",
3
+ "version": "0.2.100",
4
4
  "description": "OpenAgents Launcher — install, configure, and run AI coding agents from your terminal",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -33,9 +33,10 @@ class CodexAdapter extends BaseAdapter {
33
33
  this._codexThreadId = null;
34
34
 
35
35
  // Direct LLM API mode
36
- this._directApiKey = process.env.OPENAI_API_KEY || '';
37
- this._directBaseUrl = (process.env.OPENAI_BASE_URL || '').replace(/\/+$/, '');
38
- this._directModel = process.env.CODEX_MODEL || process.env.OPENCLAW_MODEL || '';
36
+ const env = this.agentEnv || process.env;
37
+ this._directApiKey = env.OPENAI_API_KEY || '';
38
+ this._directBaseUrl = (env.OPENAI_BASE_URL || '').replace(/\/+$/, '');
39
+ this._directModel = env.CODEX_MODEL || env.OPENCLAW_MODEL || '';
39
40
  this._directMode = !!(this._directApiKey && this._directBaseUrl);
40
41
 
41
42
  if (this._directMode) {
@@ -134,7 +135,9 @@ class CodexAdapter extends BaseAdapter {
134
135
  }
135
136
 
136
137
  let fullText = '';
138
+ let toolCallText = '';
137
139
  let buffer = '';
140
+ let chunkCount = 0;
138
141
  res.on('data', (chunk) => {
139
142
  buffer += chunk.toString('utf-8');
140
143
  const lines = buffer.split('\n');
@@ -150,11 +153,33 @@ class CodexAdapter extends BaseAdapter {
150
153
  if (choices.length > 0) {
151
154
  const delta = choices[0].delta || {};
152
155
  if (delta.content) fullText += delta.content;
156
+ // Capture tool call arguments as fallback text
157
+ if (delta.tool_calls) {
158
+ for (const tc of delta.tool_calls) {
159
+ if (tc.function && tc.function.arguments) {
160
+ toolCallText += tc.function.arguments;
161
+ }
162
+ }
163
+ }
153
164
  }
165
+ chunkCount++;
154
166
  } catch {}
155
167
  }
156
168
  });
157
- res.on('end', () => resolve(fullText.trim()));
169
+ res.on('end', () => {
170
+ this._log(`API response: ${chunkCount} chunks, content=${fullText.length}chars, toolCalls=${toolCallText.length}chars`);
171
+ // If model tried tool calls instead of text, extract the message
172
+ if (!fullText && toolCallText) {
173
+ try {
174
+ const args = JSON.parse(toolCallText);
175
+ fullText = args.command || args.input || args.content || args.text || toolCallText;
176
+ } catch {
177
+ fullText = toolCallText;
178
+ }
179
+ this._log(`Extracted from tool_calls: ${fullText.slice(0, 100)}`);
180
+ }
181
+ resolve(fullText.trim());
182
+ });
158
183
  });
159
184
 
160
185
  req.on('error', reject);
package/src/daemon.js CHANGED
@@ -25,6 +25,7 @@ class Daemon {
25
25
 
26
26
  // State
27
27
  this._processes = {}; // agentName → { proc, state, restarts, startedAt, lastError }
28
+ this._adapters = {}; // agentName → adapter instance
28
29
  this._stoppedAgents = new Set();
29
30
  this._shuttingDown = false;
30
31
  this._statusInterval = null;
@@ -273,6 +274,12 @@ class Daemon {
273
274
  const name = agentCfg.name;
274
275
  const type = agentCfg.type || 'openclaw';
275
276
 
277
+ // Prevent duplicate launches — if an adapter is already running, skip
278
+ if (this._adapters && this._adapters[name]) {
279
+ this._log(`${name} already running, skipping duplicate launch`);
280
+ return;
281
+ }
282
+
276
283
  this._stoppedAgents.delete(name);
277
284
 
278
285
  const info = {
@@ -418,8 +425,7 @@ class Daemon {
418
425
  return;
419
426
  }
420
427
 
421
- // Store adapter reference for stop
422
- this._adapters = this._adapters || {};
428
+ // Store adapter reference for stop and duplicate detection
423
429
  this._adapters[name] = adapter;
424
430
 
425
431
  info.state = 'running';