@botcord/daemon 0.2.60 → 0.2.62
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/acp-logs.d.ts +39 -0
- package/dist/acp-logs.js +333 -0
- package/dist/diagnostics.js +58 -1
- package/dist/gateway/channels/botcord.d.ts +7 -0
- package/dist/gateway/channels/botcord.js +3 -1
- package/dist/gateway/dispatcher.js +35 -7
- package/dist/gateway/runtimes/acp-stream.js +114 -3
- package/dist/gateway/runtimes/openclaw-acp.js +77 -0
- package/dist/gateway/types.d.ts +1 -0
- package/dist/index.js +30 -24
- package/dist/openclaw-discovery.js +13 -5
- package/dist/provision.js +29 -0
- package/package.json +1 -1
- package/src/__tests__/acp-logs.test.ts +88 -0
- package/src/__tests__/openclaw-acp.test.ts +39 -0
- package/src/__tests__/openclaw-discovery.test.ts +1 -0
- package/src/acp-logs.ts +382 -0
- package/src/diagnostics.ts +60 -0
- package/src/gateway/__tests__/botcord-channel.test.ts +77 -0
- package/src/gateway/__tests__/dispatcher.test.ts +30 -0
- package/src/gateway/__tests__/hermes-agent-adapter.test.ts +27 -0
- package/src/gateway/channels/botcord.ts +10 -1
- package/src/gateway/dispatcher.ts +34 -8
- package/src/gateway/runtimes/acp-stream.ts +112 -1
- package/src/gateway/runtimes/openclaw-acp.ts +76 -0
- package/src/gateway/types.ts +1 -0
- package/src/index.ts +31 -23
- package/src/openclaw-discovery.ts +16 -5
- package/src/provision.ts +32 -1
|
@@ -346,6 +346,7 @@ export function mergeOpenclawGateways(
|
|
|
346
346
|
|
|
347
347
|
function discoverFromConfigDir(root: string): DiscoveredOpenclawGateway[] {
|
|
348
348
|
const dir = expandHome(root);
|
|
349
|
+
const rootIsQclaw = path.basename(dir) === ".qclaw";
|
|
349
350
|
let names: string[];
|
|
350
351
|
try {
|
|
351
352
|
names = readdirSync(dir);
|
|
@@ -362,8 +363,9 @@ function discoverFromConfigDir(root: string): DiscoveredOpenclawGateway[] {
|
|
|
362
363
|
const raw = readFileSync(file, "utf8");
|
|
363
364
|
const parsed = name.endsWith(".json") ? parseJsonConfig(raw) : parseTomlConfig(raw);
|
|
364
365
|
if (!parsed?.url) continue;
|
|
366
|
+
const namePrefix = rootIsQclaw || name.toLowerCase() === "qclaw.json" ? "qclaw" : "openclaw";
|
|
365
367
|
const item: DiscoveredOpenclawGateway = {
|
|
366
|
-
name: nameFromUrl(parsed.url),
|
|
368
|
+
name: nameFromUrl(parsed.url, namePrefix),
|
|
367
369
|
url: parsed.url,
|
|
368
370
|
source: "config-file",
|
|
369
371
|
};
|
|
@@ -487,25 +489,34 @@ function dedupeDiscovered(items: DiscoveredOpenclawGateway[]): DiscoveredOpencla
|
|
|
487
489
|
for (const item of items) {
|
|
488
490
|
const key = normalizeUrlKey(item.url);
|
|
489
491
|
const prev = byUrl.get(key);
|
|
490
|
-
if (
|
|
492
|
+
if (
|
|
493
|
+
!prev ||
|
|
494
|
+
priority[item.source] > priority[prev.source] ||
|
|
495
|
+
hasMoreAuth(item, prev) ||
|
|
496
|
+
prefersQclawName(item, prev)
|
|
497
|
+
) {
|
|
491
498
|
byUrl.set(key, item);
|
|
492
499
|
}
|
|
493
500
|
}
|
|
494
501
|
return [...byUrl.values()];
|
|
495
502
|
}
|
|
496
503
|
|
|
504
|
+
function prefersQclawName(a: DiscoveredOpenclawGateway, b: DiscoveredOpenclawGateway): boolean {
|
|
505
|
+
return a.name.startsWith("qclaw-") && !b.name.startsWith("qclaw-");
|
|
506
|
+
}
|
|
507
|
+
|
|
497
508
|
function hasMoreAuth(a: DiscoveredOpenclawGateway, b: DiscoveredOpenclawGateway): boolean {
|
|
498
509
|
const score = (x: DiscoveredOpenclawGateway): number => (x.token ? 2 : x.tokenFile ? 1 : 0);
|
|
499
510
|
return score(a) > score(b);
|
|
500
511
|
}
|
|
501
512
|
|
|
502
|
-
function nameFromUrl(raw: string): string {
|
|
513
|
+
function nameFromUrl(raw: string, prefix = "openclaw"): string {
|
|
503
514
|
try {
|
|
504
515
|
const u = new URL(raw);
|
|
505
516
|
const base = `${u.hostname}-${u.port || (u.protocol === "wss:" ? "443" : "80")}`;
|
|
506
|
-
return
|
|
517
|
+
return `${prefix}-${base.replace(/[^A-Za-z0-9_-]+/g, "-")}`;
|
|
507
518
|
} catch {
|
|
508
|
-
return
|
|
519
|
+
return `${prefix}-local`;
|
|
509
520
|
}
|
|
510
521
|
}
|
|
511
522
|
|
package/src/provision.ts
CHANGED
|
@@ -48,6 +48,11 @@ import {
|
|
|
48
48
|
buildManagedRoutes,
|
|
49
49
|
prepareGatewayProfile,
|
|
50
50
|
} from "./daemon-config-map.js";
|
|
51
|
+
import {
|
|
52
|
+
discoverLocalOpenclawGateways,
|
|
53
|
+
mergeOpenclawGateways,
|
|
54
|
+
openclawDiscoveryConfigEnabled,
|
|
55
|
+
} from "./openclaw-discovery.js";
|
|
51
56
|
import {
|
|
52
57
|
agentHomeDir,
|
|
53
58
|
agentStateDir,
|
|
@@ -324,9 +329,10 @@ export function createProvisioner(opts: ProvisionerOptions): (
|
|
|
324
329
|
case CONTROL_FRAME_TYPES.LIST_RUNTIMES: {
|
|
325
330
|
// Async path so the openclaw-acp endpoints get probed inline; gateway
|
|
326
331
|
// / WS errors are swallowed inside `collectRuntimeSnapshotAsync`.
|
|
327
|
-
let cfgForProbe:
|
|
332
|
+
let cfgForProbe: DaemonConfig | undefined;
|
|
328
333
|
try {
|
|
329
334
|
cfgForProbe = loadConfig();
|
|
335
|
+
cfgForProbe = await refreshDiscoveredOpenclawGateways(cfgForProbe);
|
|
330
336
|
} catch {
|
|
331
337
|
cfgForProbe = undefined;
|
|
332
338
|
}
|
|
@@ -428,6 +434,31 @@ export function createProvisioner(opts: ProvisionerOptions): (
|
|
|
428
434
|
};
|
|
429
435
|
}
|
|
430
436
|
|
|
437
|
+
async function refreshDiscoveredOpenclawGateways(cfg: DaemonConfig): Promise<DaemonConfig> {
|
|
438
|
+
if (!openclawDiscoveryConfigEnabled(cfg)) return cfg;
|
|
439
|
+
try {
|
|
440
|
+
const found = await discoverLocalOpenclawGateways({
|
|
441
|
+
searchPaths: cfg.openclawDiscovery?.searchPaths,
|
|
442
|
+
defaultPorts: cfg.openclawDiscovery?.defaultPorts,
|
|
443
|
+
timeoutMs: 500,
|
|
444
|
+
});
|
|
445
|
+
const merged = mergeOpenclawGateways(cfg, found);
|
|
446
|
+
if (!merged.changed) return cfg;
|
|
447
|
+
saveConfig(merged.cfg);
|
|
448
|
+
daemonLog.info("openclaw discovery: gateways merged", {
|
|
449
|
+
source: "list_runtimes",
|
|
450
|
+
added: merged.added.map((g) => ({ name: g.name, url: g.url })),
|
|
451
|
+
});
|
|
452
|
+
return merged.cfg;
|
|
453
|
+
} catch (err) {
|
|
454
|
+
daemonLog.warn("openclaw discovery failed; continuing", {
|
|
455
|
+
source: "list_runtimes",
|
|
456
|
+
error: err instanceof Error ? err.message : String(err),
|
|
457
|
+
});
|
|
458
|
+
return cfg;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
431
462
|
interface WakeAgentParams {
|
|
432
463
|
agent_id?: string;
|
|
433
464
|
agentId?: string;
|