@agentbean/daemon 0.1.28 → 0.1.31
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/dist/adapters/claude-code.js +5 -1
- package/dist/adapters/codex.js +17 -2
- package/dist/device-daemon.js +66 -4
- package/dist/scanner.js +3 -3
- package/package.json +1 -1
|
@@ -11,6 +11,10 @@ function buildPrompt(input, systemPrompt) {
|
|
|
11
11
|
parts.push(input.prompt);
|
|
12
12
|
return parts.join('\n\n---\n\n');
|
|
13
13
|
}
|
|
14
|
+
function normalizeClaudeArgs(args) {
|
|
15
|
+
const filtered = (args ?? []).filter((arg) => arg !== '--bare');
|
|
16
|
+
return ['-p', ...filtered];
|
|
17
|
+
}
|
|
14
18
|
export class ClaudeCodeAdapter {
|
|
15
19
|
opts;
|
|
16
20
|
kind = 'claude-code';
|
|
@@ -21,7 +25,7 @@ export class ClaudeCodeAdapter {
|
|
|
21
25
|
return new Promise((resolve, reject) => {
|
|
22
26
|
const prompt = buildPrompt(input, this.opts.systemPrompt ?? input.systemPrompt);
|
|
23
27
|
const cwd = input.workspace ?? this.opts.cwd ?? process.cwd();
|
|
24
|
-
const baseArgs =
|
|
28
|
+
const baseArgs = normalizeClaudeArgs(this.opts.args);
|
|
25
29
|
if (input.workspace)
|
|
26
30
|
baseArgs.push('--add-dir', input.workspace);
|
|
27
31
|
baseArgs.push('--add-dir', join(homedir(), '.codex', 'generated_images'));
|
package/dist/adapters/codex.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { spawn } from 'node-pty';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
2
4
|
function renderPayload(input, systemPrompt) {
|
|
3
5
|
const parts = [];
|
|
4
6
|
if (systemPrompt)
|
|
@@ -52,6 +54,19 @@ function adapterTimeoutMs() {
|
|
|
52
54
|
const fromEnv = Number.parseInt(process.env.AGENTBEAN_CODEX_TIMEOUT_MS ?? '', 10);
|
|
53
55
|
return Number.isFinite(fromEnv) && fromEnv > 0 ? fromEnv : 900_000;
|
|
54
56
|
}
|
|
57
|
+
function buildRuntimeEnv(extra) {
|
|
58
|
+
const pathEntries = [
|
|
59
|
+
process.env.PATH,
|
|
60
|
+
'/opt/homebrew/bin',
|
|
61
|
+
'/usr/local/bin',
|
|
62
|
+
join(homedir(), '.local/bin'),
|
|
63
|
+
join(homedir(), '.bun/bin'),
|
|
64
|
+
join(homedir(), '.npm-global/bin'),
|
|
65
|
+
join(homedir(), '.asdf/shims'),
|
|
66
|
+
join(homedir(), '.local/share/mise/shims'),
|
|
67
|
+
].filter(Boolean).join(':');
|
|
68
|
+
return { ...process.env, PATH: pathEntries, ...(extra ?? {}) };
|
|
69
|
+
}
|
|
55
70
|
export class CodexAdapter {
|
|
56
71
|
opts;
|
|
57
72
|
kind = 'codex';
|
|
@@ -74,7 +89,7 @@ export class CodexAdapter {
|
|
|
74
89
|
cols: 80,
|
|
75
90
|
rows: 30,
|
|
76
91
|
cwd,
|
|
77
|
-
env:
|
|
92
|
+
env: buildRuntimeEnv(input.env),
|
|
78
93
|
});
|
|
79
94
|
const chunks = [];
|
|
80
95
|
let finished = false;
|
|
@@ -128,7 +143,7 @@ export class CodexAdapter {
|
|
|
128
143
|
const pty = spawn('bash', ['-c', 'codex --version'], {
|
|
129
144
|
name: 'xterm-color', cols: 80, rows: 30,
|
|
130
145
|
cwd: this.opts.cwd ?? process.cwd(),
|
|
131
|
-
env:
|
|
146
|
+
env: buildRuntimeEnv(),
|
|
132
147
|
});
|
|
133
148
|
pty.onExit(({ exitCode }) => resolve({ ok: exitCode === 0, detail: exitCode === 0 ? undefined : `exit ${exitCode}` }));
|
|
134
149
|
}
|
package/dist/device-daemon.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { io } from 'socket.io-client';
|
|
2
2
|
import { execFile } from 'node:child_process';
|
|
3
3
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
4
|
-
import { join } from 'node:path';
|
|
4
|
+
import { basename, isAbsolute, join } from 'node:path';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { promisify } from 'node:util';
|
|
7
7
|
import { logger } from './log.js';
|
|
@@ -29,6 +29,58 @@ function agentSlug(name) {
|
|
|
29
29
|
function scannedAgentId(deviceId, name) {
|
|
30
30
|
return `scan-${deviceId}-${agentSlug(name)}`;
|
|
31
31
|
}
|
|
32
|
+
function normalizeAdapterKind(kind) {
|
|
33
|
+
const normalized = (kind ?? '').trim().toLowerCase().replace(/[_\s]+/g, '-');
|
|
34
|
+
if (normalized === 'claude' || normalized === 'claude-code')
|
|
35
|
+
return 'claude-code';
|
|
36
|
+
if (normalized === 'codex' || normalized === 'codex-cli')
|
|
37
|
+
return 'codex';
|
|
38
|
+
if (normalized === 'kimi' || normalized === 'kimi-cli')
|
|
39
|
+
return 'kimi-cli';
|
|
40
|
+
return normalized;
|
|
41
|
+
}
|
|
42
|
+
function runtimeScoreForCustomAgent(runtime, custom) {
|
|
43
|
+
if (!runtime.installed || !runtime.command?.trim())
|
|
44
|
+
return 0;
|
|
45
|
+
const runtimeCommand = runtime.command.trim();
|
|
46
|
+
const customCommand = custom.command?.trim() ?? '';
|
|
47
|
+
if (runtimeCommand && customCommand && runtimeCommand === customCommand)
|
|
48
|
+
return 100;
|
|
49
|
+
const runtimeBase = basename(runtimeCommand).toLowerCase();
|
|
50
|
+
const customBase = customCommand ? basename(customCommand).toLowerCase() : '';
|
|
51
|
+
if (runtimeBase && customBase && runtimeBase === customBase)
|
|
52
|
+
return 90;
|
|
53
|
+
const runtimeKind = normalizeAdapterKind(runtime.adapterKind);
|
|
54
|
+
const customKind = normalizeAdapterKind(custom.adapterKind);
|
|
55
|
+
if (runtimeKind === 'kimi-cli' && customKind === 'codex' && customCommand.toLowerCase().includes('kimi'))
|
|
56
|
+
return 85;
|
|
57
|
+
if (runtimeKind && customKind && runtimeKind === customKind)
|
|
58
|
+
return 70;
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
export function resolveCustomAgentRuntime(custom, runtimes) {
|
|
62
|
+
const configured = custom.command?.trim() ?? '';
|
|
63
|
+
const configuredAbsoluteExists = configured && isAbsolute(configured) && existsSync(configured);
|
|
64
|
+
const bestRuntime = [...runtimes]
|
|
65
|
+
.map((runtime) => ({ runtime, score: runtimeScoreForCustomAgent(runtime, custom) }))
|
|
66
|
+
.filter((candidate) => candidate.score > 0)
|
|
67
|
+
.sort((a, b) => b.score - a.score)[0]?.runtime;
|
|
68
|
+
if (configuredAbsoluteExists) {
|
|
69
|
+
return { command: configured, runtime: bestRuntime };
|
|
70
|
+
}
|
|
71
|
+
if (bestRuntime?.command?.trim()) {
|
|
72
|
+
return { command: bestRuntime.command.trim(), runtime: bestRuntime };
|
|
73
|
+
}
|
|
74
|
+
if (configured && isAbsolute(configured) && !configuredAbsoluteExists) {
|
|
75
|
+
const fallback = basename(configured).trim();
|
|
76
|
+
if (fallback)
|
|
77
|
+
return { command: fallback };
|
|
78
|
+
}
|
|
79
|
+
if (!configured && normalizeAdapterKind(custom.adapterKind) === 'codex') {
|
|
80
|
+
return { command: 'codex' };
|
|
81
|
+
}
|
|
82
|
+
return { command: configured };
|
|
83
|
+
}
|
|
32
84
|
export function nativeDirectoryPickerCommands(platform = process.platform) {
|
|
33
85
|
if (platform === 'darwin') {
|
|
34
86
|
return [{ command: 'osascript', args: ['-e', 'POSIX path of (choose folder with prompt "选择项目目录")'] }];
|
|
@@ -184,10 +236,12 @@ export function createDeviceDaemon(cfg, agents) {
|
|
|
184
236
|
const httpBase = cfg.server.url.replace(/\/agent$/, '');
|
|
185
237
|
let firstConnect = true;
|
|
186
238
|
const systemInfo = collectSystemInfo();
|
|
239
|
+
let latestRuntimes = [];
|
|
187
240
|
const publicAgents = Array.from(agents.values())
|
|
188
241
|
.filter((a) => a.visibility === 'public')
|
|
189
242
|
.map((a) => a.publicMeta);
|
|
190
243
|
function emitRegister(sock, payload) {
|
|
244
|
+
latestRuntimes = payload.runtimes.filter((runtime) => runtime.installed);
|
|
191
245
|
if (payload.runtimes.length > 0) {
|
|
192
246
|
sock.emit('device:register-runtimes', { runtimes: payload.runtimes }, (ack) => {
|
|
193
247
|
if (!ack?.ok)
|
|
@@ -323,8 +377,9 @@ export function createDeviceDaemon(cfg, agents) {
|
|
|
323
377
|
});
|
|
324
378
|
socket.on('dispatch', (req) => {
|
|
325
379
|
let agent = agents.get(req.agentId);
|
|
326
|
-
if (
|
|
380
|
+
if (req.customAgent) {
|
|
327
381
|
const custom = req.customAgent;
|
|
382
|
+
const resolvedRuntime = resolveCustomAgentRuntime(custom, latestRuntimes);
|
|
328
383
|
const entry = {
|
|
329
384
|
id: custom.id,
|
|
330
385
|
name: custom.name,
|
|
@@ -332,7 +387,7 @@ export function createDeviceDaemon(cfg, agents) {
|
|
|
332
387
|
category: 'executor-hosted',
|
|
333
388
|
adapter: {
|
|
334
389
|
kind: custom.adapterKind,
|
|
335
|
-
command:
|
|
390
|
+
command: resolvedRuntime.command,
|
|
336
391
|
args: custom.args ?? [],
|
|
337
392
|
cwd: custom.cwd ?? undefined,
|
|
338
393
|
workspace: custom.cwd ?? undefined,
|
|
@@ -343,7 +398,14 @@ export function createDeviceDaemon(cfg, agents) {
|
|
|
343
398
|
try {
|
|
344
399
|
agent = new AgentInstance(entry, pickAdapter(entry.adapter));
|
|
345
400
|
agents.set(req.agentId, agent);
|
|
346
|
-
logger.info({
|
|
401
|
+
logger.info({
|
|
402
|
+
agentId: req.agentId,
|
|
403
|
+
kind: entry.adapter.kind,
|
|
404
|
+
command: entry.adapter.command,
|
|
405
|
+
configuredCommand: custom.command,
|
|
406
|
+
runtimeCommand: resolvedRuntime.runtime?.command,
|
|
407
|
+
cwd: entry.adapter.cwd,
|
|
408
|
+
}, 'custom agent instance created for dispatch');
|
|
347
409
|
}
|
|
348
410
|
catch (err) {
|
|
349
411
|
logger.warn({ agentId: req.agentId, err: errorMessage(err) }, 'failed to create custom dispatch agent');
|
package/dist/scanner.js
CHANGED
|
@@ -285,14 +285,14 @@ async function checkOpenClawGateway() {
|
|
|
285
285
|
return null;
|
|
286
286
|
const status = await run(path, ["gateway", "status"]);
|
|
287
287
|
const running = status.includes("running") || status.includes("✓");
|
|
288
|
-
|
|
289
|
-
|
|
288
|
+
const agentId = parseOpenClawAgentId(await run(path, ["agents", "list", "--json"]));
|
|
289
|
+
if (running || agentId) {
|
|
290
290
|
return {
|
|
291
291
|
category: "agentos-hosted",
|
|
292
292
|
name: "OpenClaw-Agent",
|
|
293
293
|
adapterKind: "openclaw",
|
|
294
294
|
command: path,
|
|
295
|
-
args: ["agent", "--agent", agentId],
|
|
295
|
+
args: ["agent", "--agent", agentId ?? "main"],
|
|
296
296
|
source: "gateway",
|
|
297
297
|
};
|
|
298
298
|
}
|