@openagents-org/agent-launcher 0.2.10 → 0.2.12
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 +1 -1
- package/src/adapters/openclaw.js +95 -3
package/package.json
CHANGED
package/src/adapters/openclaw.js
CHANGED
|
@@ -36,12 +36,23 @@ class OpenClawAdapter extends BaseAdapter {
|
|
|
36
36
|
this.openclawAgentId = opts.openclawAgentId || 'main';
|
|
37
37
|
this.disabledModules = opts.disabledModules || new Set();
|
|
38
38
|
|
|
39
|
+
// Direct API mode: call LLM via HTTP (no OpenClaw CLI needed).
|
|
40
|
+
// Activated when LLM_API_KEY + LLM_BASE_URL are in agent env.
|
|
41
|
+
const env = opts.agentEnv || {};
|
|
42
|
+
this._directApiKey = env.OPENAI_API_KEY || env.LLM_API_KEY || '';
|
|
43
|
+
this._directBaseUrl = (env.OPENAI_BASE_URL || env.LLM_BASE_URL || '').replace(/\/+$/, '');
|
|
44
|
+
this._directModel = env.OPENCLAW_MODEL || env.LLM_MODEL || 'gpt-4o';
|
|
45
|
+
this._directMode = !!(this._directApiKey && this._directBaseUrl);
|
|
46
|
+
|
|
39
47
|
// Find the openclaw binary
|
|
40
48
|
this._openclawBinary = this._findOpenclawBinary();
|
|
41
|
-
|
|
49
|
+
|
|
50
|
+
if (this._directMode) {
|
|
51
|
+
this._log(`Using direct LLM API mode (${this._directBaseUrl}, model=${this._directModel})`);
|
|
52
|
+
} else if (this._openclawBinary) {
|
|
42
53
|
this._log(`Using OpenClaw CLI mode (${this._openclawBinary})`);
|
|
43
54
|
} else {
|
|
44
|
-
this._log('OpenClaw binary not found — agent will not be able to process messages');
|
|
55
|
+
this._log('OpenClaw binary not found and no direct API config — agent will not be able to process messages');
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
// Install workspace skill
|
|
@@ -150,7 +161,12 @@ class OpenClawAdapter extends BaseAdapter {
|
|
|
150
161
|
await this.sendStatus(msgChannel, 'thinking...');
|
|
151
162
|
|
|
152
163
|
try {
|
|
153
|
-
|
|
164
|
+
let responseText;
|
|
165
|
+
if (this._directMode) {
|
|
166
|
+
responseText = await this._runDirectApi(content, msgChannel);
|
|
167
|
+
} else {
|
|
168
|
+
responseText = await this._runCliAgent(content, msgChannel);
|
|
169
|
+
}
|
|
154
170
|
|
|
155
171
|
if (responseText) {
|
|
156
172
|
await this.sendResponse(msgChannel, responseText);
|
|
@@ -255,6 +271,82 @@ class OpenClawAdapter extends BaseAdapter {
|
|
|
255
271
|
});
|
|
256
272
|
});
|
|
257
273
|
}
|
|
274
|
+
// ------------------------------------------------------------------
|
|
275
|
+
// Direct API mode (bypass OpenClaw CLI, call LLM directly)
|
|
276
|
+
// ------------------------------------------------------------------
|
|
277
|
+
|
|
278
|
+
async _runDirectApi(userMessage, channel) {
|
|
279
|
+
const https = require('https');
|
|
280
|
+
const http = require('http');
|
|
281
|
+
const url = new URL(this._directBaseUrl + '/chat/completions');
|
|
282
|
+
const transport = url.protocol === 'https:' ? https : http;
|
|
283
|
+
|
|
284
|
+
// Build system prompt
|
|
285
|
+
let systemPrompt;
|
|
286
|
+
try {
|
|
287
|
+
const { buildOpenclawSystemPrompt } = require('./workspace-prompt');
|
|
288
|
+
systemPrompt = buildOpenclawSystemPrompt({
|
|
289
|
+
agentName: this.agentName,
|
|
290
|
+
workspaceId: this.workspaceId,
|
|
291
|
+
channelName: channel,
|
|
292
|
+
endpoint: this.client?.endpoint || '',
|
|
293
|
+
token: this.token || '',
|
|
294
|
+
});
|
|
295
|
+
} catch (e) {
|
|
296
|
+
this._log(`System prompt build failed (using fallback): ${e.message}`);
|
|
297
|
+
}
|
|
298
|
+
if (!systemPrompt) {
|
|
299
|
+
systemPrompt = `You are a helpful AI assistant named ${this.agentName}. You are connected to an OpenAgents workspace. Answer questions concisely and helpfully.`;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Simple conversation (no history for now)
|
|
303
|
+
const messages = [
|
|
304
|
+
{ role: 'system', content: systemPrompt || 'You are a helpful assistant.' },
|
|
305
|
+
{ role: 'user', content: userMessage },
|
|
306
|
+
];
|
|
307
|
+
|
|
308
|
+
const body = JSON.stringify({
|
|
309
|
+
model: this._directModel,
|
|
310
|
+
messages,
|
|
311
|
+
stream: false,
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
this._log(`Direct API: ${url.hostname} model=${this._directModel} msg=${userMessage.slice(0, 50)}...`);
|
|
315
|
+
|
|
316
|
+
return new Promise((resolve, reject) => {
|
|
317
|
+
const req = transport.request(url, {
|
|
318
|
+
method: 'POST',
|
|
319
|
+
headers: {
|
|
320
|
+
'Content-Type': 'application/json',
|
|
321
|
+
'Authorization': `Bearer ${this._directApiKey}`,
|
|
322
|
+
'Content-Length': Buffer.byteLength(body),
|
|
323
|
+
},
|
|
324
|
+
timeout: 120000,
|
|
325
|
+
}, (res) => {
|
|
326
|
+
let data = '';
|
|
327
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
328
|
+
res.on('end', () => {
|
|
329
|
+
try {
|
|
330
|
+
if (res.statusCode !== 200) {
|
|
331
|
+
reject(new Error(`${res.statusCode} ${data.slice(0, 200)}`));
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const result = JSON.parse(data);
|
|
335
|
+
const text = result.choices?.[0]?.message?.content || '';
|
|
336
|
+
this._log(`Direct API response: ${text.slice(0, 80)}...`);
|
|
337
|
+
resolve(text);
|
|
338
|
+
} catch (e) {
|
|
339
|
+
reject(new Error(`Parse error: ${e.message}`));
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
req.on('error', reject);
|
|
344
|
+
req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout')); });
|
|
345
|
+
req.write(body);
|
|
346
|
+
req.end();
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
258
350
|
// ------------------------------------------------------------------
|
|
259
351
|
// Static: configure OpenClaw's native auth from LLM env vars
|
|
260
352
|
// ------------------------------------------------------------------
|