too-many-claw 1.0.21 → 1.0.23
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/cli.js +152 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +28 -0
- package/dist/index.js +152 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1475,6 +1475,25 @@ var ConfigManager = class {
|
|
|
1475
1475
|
getOpenClawConfigPath() {
|
|
1476
1476
|
return this.openclawConfigPath;
|
|
1477
1477
|
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Get the OpenClaw Gateway authentication token
|
|
1480
|
+
* First checks environment variable OPENCLAW_GATEWAY_TOKEN,
|
|
1481
|
+
* then falls back to openclaw.json gateway.token or gateway.password
|
|
1482
|
+
*/
|
|
1483
|
+
getGatewayToken() {
|
|
1484
|
+
const envToken = process.env.OPENCLAW_GATEWAY_TOKEN;
|
|
1485
|
+
if (envToken) {
|
|
1486
|
+
return envToken;
|
|
1487
|
+
}
|
|
1488
|
+
const config = this.readOpenClawConfig();
|
|
1489
|
+
if (config?.gateway?.token) {
|
|
1490
|
+
return config.gateway.token;
|
|
1491
|
+
}
|
|
1492
|
+
if (config?.gateway?.password) {
|
|
1493
|
+
return config.gateway.password;
|
|
1494
|
+
}
|
|
1495
|
+
return void 0;
|
|
1496
|
+
}
|
|
1478
1497
|
// ============================================
|
|
1479
1498
|
// Validation & Repair
|
|
1480
1499
|
// ============================================
|
|
@@ -2330,6 +2349,7 @@ import WebSocket from "ws";
|
|
|
2330
2349
|
import { EventEmitter } from "events";
|
|
2331
2350
|
var DEFAULT_CONFIG2 = {
|
|
2332
2351
|
url: "ws://127.0.0.1:18789",
|
|
2352
|
+
gatewayToken: "",
|
|
2333
2353
|
reconnect: {
|
|
2334
2354
|
enabled: true,
|
|
2335
2355
|
maxAttempts: 10,
|
|
@@ -2337,7 +2357,8 @@ var DEFAULT_CONFIG2 = {
|
|
|
2337
2357
|
maxDelay: 3e4
|
|
2338
2358
|
},
|
|
2339
2359
|
heartbeatInterval: 3e4,
|
|
2340
|
-
connectionTimeout: 1e4
|
|
2360
|
+
connectionTimeout: 1e4,
|
|
2361
|
+
verbose: false
|
|
2341
2362
|
};
|
|
2342
2363
|
function extractTextContent(content) {
|
|
2343
2364
|
if (!content) {
|
|
@@ -2503,6 +2524,10 @@ var GatewayClient = class extends EventEmitter {
|
|
|
2503
2524
|
return;
|
|
2504
2525
|
}
|
|
2505
2526
|
this.emit("message", message);
|
|
2527
|
+
if (message.type === "event" && message.event === "connect.challenge") {
|
|
2528
|
+
this.handleConnectChallenge(message);
|
|
2529
|
+
return;
|
|
2530
|
+
}
|
|
2506
2531
|
const roleBasedMessage = message;
|
|
2507
2532
|
if (roleBasedMessage.role) {
|
|
2508
2533
|
this.handleRoleBasedMessage(roleBasedMessage);
|
|
@@ -2701,6 +2726,43 @@ var GatewayClient = class extends EventEmitter {
|
|
|
2701
2726
|
this.heartbeatTimer = null;
|
|
2702
2727
|
}
|
|
2703
2728
|
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Handle OpenClaw Gateway connect.challenge event
|
|
2731
|
+
* Responds with authentication token to complete connection handshake
|
|
2732
|
+
*/
|
|
2733
|
+
handleConnectChallenge(message) {
|
|
2734
|
+
const payload = message.payload || {};
|
|
2735
|
+
const nonce = payload.nonce;
|
|
2736
|
+
const ts = payload.ts;
|
|
2737
|
+
this.log(`Received connect.challenge (nonce: ${nonce?.substring(0, 8)}...)`);
|
|
2738
|
+
if (!this.config.gatewayToken) {
|
|
2739
|
+
this.log("Warning: No gateway token configured, authentication may fail");
|
|
2740
|
+
}
|
|
2741
|
+
const connectResponse = {
|
|
2742
|
+
type: "connect",
|
|
2743
|
+
token: this.config.gatewayToken,
|
|
2744
|
+
nonce,
|
|
2745
|
+
ts,
|
|
2746
|
+
client: {
|
|
2747
|
+
name: "too-many-claw",
|
|
2748
|
+
version: "1.0.0"
|
|
2749
|
+
}
|
|
2750
|
+
};
|
|
2751
|
+
const sent = this.send(connectResponse);
|
|
2752
|
+
if (sent) {
|
|
2753
|
+
this.log("Sent connect response with authentication token");
|
|
2754
|
+
} else {
|
|
2755
|
+
this.log("Failed to send connect response");
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
/**
|
|
2759
|
+
* Log message if verbose mode is enabled
|
|
2760
|
+
*/
|
|
2761
|
+
log(message) {
|
|
2762
|
+
if (this.config.verbose) {
|
|
2763
|
+
console.log(`[GatewayClient] ${message}`);
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2704
2766
|
};
|
|
2705
2767
|
|
|
2706
2768
|
// src/discord/BotMessageMonitor.ts
|
|
@@ -2817,7 +2879,8 @@ var BotMessageMonitor = class extends EventEmitter2 {
|
|
|
2817
2879
|
agentId,
|
|
2818
2880
|
timestamp: Date.now()
|
|
2819
2881
|
});
|
|
2820
|
-
this.
|
|
2882
|
+
this.forceLog(`\u{1F4DD} Registered pending: ${agentId} \u2192 "${content.substring(0, 40)}..."`);
|
|
2883
|
+
this.log(` Hash: ${hash.substring(0, 50)}`);
|
|
2821
2884
|
this.cleanupPendingMessages();
|
|
2822
2885
|
}
|
|
2823
2886
|
/**
|
|
@@ -2851,9 +2914,12 @@ var BotMessageMonitor = class extends EventEmitter2 {
|
|
|
2851
2914
|
lookupPendingAgent(content) {
|
|
2852
2915
|
const hash = this.hashContent(content);
|
|
2853
2916
|
const pending = this.pendingMessages.get(hash);
|
|
2917
|
+
this.log(`Looking up agent for content: "${content.substring(0, 40)}..."`);
|
|
2918
|
+
this.log(` Generated hash: ${hash.substring(0, 50)}`);
|
|
2919
|
+
this.log(` Pending messages count: ${this.pendingMessages.size}`);
|
|
2854
2920
|
if (pending && Date.now() - pending.timestamp < this.PENDING_MESSAGE_TTL) {
|
|
2855
2921
|
this.pendingMessages.delete(hash);
|
|
2856
|
-
this.
|
|
2922
|
+
this.forceLog(`\u2713 Found pending agent ${pending.agentId} via exact hash match`);
|
|
2857
2923
|
return pending.agentId;
|
|
2858
2924
|
}
|
|
2859
2925
|
const normalizedContent = content.trim().toLowerCase();
|
|
@@ -2862,11 +2928,17 @@ var BotMessageMonitor = class extends EventEmitter2 {
|
|
|
2862
2928
|
if (normalizedContent.includes(pendingContent.substring(0, 100)) || pendingContent.includes(normalizedContent.substring(0, 100))) {
|
|
2863
2929
|
if (Date.now() - data.timestamp < this.PENDING_MESSAGE_TTL) {
|
|
2864
2930
|
this.pendingMessages.delete(pendingHash);
|
|
2865
|
-
this.
|
|
2931
|
+
this.forceLog(`\u2713 Found pending agent ${data.agentId} via partial match`);
|
|
2866
2932
|
return data.agentId;
|
|
2867
2933
|
}
|
|
2868
2934
|
}
|
|
2869
2935
|
}
|
|
2936
|
+
if (this.pendingMessages.size > 0) {
|
|
2937
|
+
this.log(`No match found. Current pending messages:`);
|
|
2938
|
+
for (const [pendingHash, data] of this.pendingMessages) {
|
|
2939
|
+
this.log(` - ${data.agentId}: ${pendingHash.substring(0, 50)}...`);
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2870
2942
|
return null;
|
|
2871
2943
|
}
|
|
2872
2944
|
/**
|
|
@@ -2928,12 +3000,12 @@ var BotMessageMonitor = class extends EventEmitter2 {
|
|
|
2928
3000
|
if (pendingAgentId) {
|
|
2929
3001
|
agent = this.agentMapper.resolve(pendingAgentId) || this.agentMapper.getDefaultAgent();
|
|
2930
3002
|
cleanContent = message.content;
|
|
2931
|
-
this.
|
|
3003
|
+
this.forceLog(`\u2192 Using agent ${agent.emoji} ${agent.name} from Gateway event`);
|
|
2932
3004
|
} else {
|
|
2933
3005
|
const extracted = this.extractAgentFromContent(message.content);
|
|
2934
3006
|
agent = extracted.agent;
|
|
2935
3007
|
cleanContent = extracted.cleanContent;
|
|
2936
|
-
this.
|
|
3008
|
+
this.forceLog(`\u2192 Using agent ${agent.emoji} ${agent.name} from content extraction (fallback)`);
|
|
2937
3009
|
}
|
|
2938
3010
|
this.emit("intercepted", message.id, message.channel.id, agent.id);
|
|
2939
3011
|
this.forceLog(`\u{1F980} Intercepted message \u2192 ${agent.emoji} ${agent.name}`);
|
|
@@ -3086,6 +3158,10 @@ var AgentMapper = class {
|
|
|
3086
3158
|
this.idMap.set(agent.id.toLowerCase(), agent);
|
|
3087
3159
|
const normalizedName = this.normalizeName(agent.name);
|
|
3088
3160
|
this.nameMap.set(normalizedName, agent);
|
|
3161
|
+
const openClawName = `${agent.emoji} ${agent.name}`.toLowerCase();
|
|
3162
|
+
this.nameMap.set(openClawName, agent);
|
|
3163
|
+
this.nameMap.set(this.normalizeName(openClawName), agent);
|
|
3164
|
+
this.aliasMap.set(agent.emoji, agent);
|
|
3089
3165
|
this.buildAliases(agent);
|
|
3090
3166
|
}
|
|
3091
3167
|
}
|
|
@@ -3136,9 +3212,18 @@ var AgentMapper = class {
|
|
|
3136
3212
|
if (!identifier) {
|
|
3137
3213
|
return this.getDefaultAgent();
|
|
3138
3214
|
}
|
|
3139
|
-
|
|
3215
|
+
let cleanIdentifier = identifier.trim();
|
|
3216
|
+
const emojiMatch = cleanIdentifier.match(/^([\p{Emoji}])\s*/u);
|
|
3217
|
+
if (emojiMatch) {
|
|
3218
|
+
const emoji = emojiMatch[1];
|
|
3219
|
+
const byEmoji = this.aliasMap.get(emoji);
|
|
3220
|
+
if (byEmoji) return byEmoji;
|
|
3221
|
+
}
|
|
3222
|
+
const normalized = cleanIdentifier.toLowerCase().trim();
|
|
3140
3223
|
const byId = this.idMap.get(normalized);
|
|
3141
3224
|
if (byId) return byId;
|
|
3225
|
+
const byOpenClawName = this.nameMap.get(normalized);
|
|
3226
|
+
if (byOpenClawName) return byOpenClawName;
|
|
3142
3227
|
const byName = this.nameMap.get(this.normalizeName(identifier));
|
|
3143
3228
|
if (byName) return byName;
|
|
3144
3229
|
const byAlias = this.aliasMap.get(normalized);
|
|
@@ -3223,8 +3308,14 @@ var OpenClawDaemon = class extends EventEmitter3 {
|
|
|
3223
3308
|
this.configManager = new ConfigManager();
|
|
3224
3309
|
this.webhookManager = new WebhookManager();
|
|
3225
3310
|
this.agentMapper = new AgentMapper();
|
|
3311
|
+
const gatewayToken = this.configManager.getGatewayToken();
|
|
3312
|
+
if (!gatewayToken) {
|
|
3313
|
+
this.forceLog("Warning: No gateway token found. Set OPENCLAW_GATEWAY_TOKEN env var or configure in openclaw.json");
|
|
3314
|
+
}
|
|
3226
3315
|
this.gatewayClient = new GatewayClient({
|
|
3227
3316
|
url: this.config.gatewayUrl,
|
|
3317
|
+
gatewayToken,
|
|
3318
|
+
verbose: this.config.verbose,
|
|
3228
3319
|
reconnect: {
|
|
3229
3320
|
enabled: true,
|
|
3230
3321
|
maxAttempts: -1,
|
|
@@ -3453,9 +3544,12 @@ var OpenClawDaemon = class extends EventEmitter3 {
|
|
|
3453
3544
|
*/
|
|
3454
3545
|
registerPendingMessageForMonitor(message) {
|
|
3455
3546
|
if (!this.botMessageMonitor) return;
|
|
3456
|
-
const agentIdentifier =
|
|
3547
|
+
const agentIdentifier = this.extractAgentIdentifier(message);
|
|
3457
3548
|
const agent = this.agentMapper.resolve(agentIdentifier);
|
|
3458
3549
|
const agentId = agent?.id || "base";
|
|
3550
|
+
if (this.config.verbose) {
|
|
3551
|
+
this.log(`registerPendingMessageForMonitor - identifier: ${agentIdentifier}, resolved to: ${agentId}`);
|
|
3552
|
+
}
|
|
3459
3553
|
let content = "";
|
|
3460
3554
|
if (typeof message.content === "string") {
|
|
3461
3555
|
content = message.content;
|
|
@@ -3487,6 +3581,15 @@ var OpenClawDaemon = class extends EventEmitter3 {
|
|
|
3487
3581
|
if (message.stream) {
|
|
3488
3582
|
this.log(` Stream: ${message.stream}`);
|
|
3489
3583
|
}
|
|
3584
|
+
if (message.agentId) {
|
|
3585
|
+
this.log(` AgentId: ${message.agentId}`);
|
|
3586
|
+
}
|
|
3587
|
+
if (message.runId) {
|
|
3588
|
+
this.log(` RunId: ${message.runId}`);
|
|
3589
|
+
}
|
|
3590
|
+
if (message.data) {
|
|
3591
|
+
this.log(` Data keys: ${Object.keys(message.data).join(", ")}`);
|
|
3592
|
+
}
|
|
3490
3593
|
}
|
|
3491
3594
|
}
|
|
3492
3595
|
/**
|
|
@@ -3495,7 +3598,10 @@ var OpenClawDaemon = class extends EventEmitter3 {
|
|
|
3495
3598
|
* because the message_sent event handler will intercept and resend via webhook.
|
|
3496
3599
|
*/
|
|
3497
3600
|
async handleAgentResponse(message) {
|
|
3498
|
-
const agentIdentifier =
|
|
3601
|
+
const agentIdentifier = this.extractAgentIdentifier(message);
|
|
3602
|
+
if (this.config.verbose) {
|
|
3603
|
+
this.log(`Agent response - extracted identifier: ${agentIdentifier}`);
|
|
3604
|
+
}
|
|
3499
3605
|
let content = "";
|
|
3500
3606
|
if (typeof message.content === "string") {
|
|
3501
3607
|
content = message.content;
|
|
@@ -3517,11 +3623,43 @@ var OpenClawDaemon = class extends EventEmitter3 {
|
|
|
3517
3623
|
}
|
|
3518
3624
|
await this.forwardToWebhook(agent, content);
|
|
3519
3625
|
}
|
|
3626
|
+
/**
|
|
3627
|
+
* Extract agent identifier from OpenClaw Gateway message
|
|
3628
|
+
* Checks multiple fields since OpenClaw may send agent info in different places
|
|
3629
|
+
*/
|
|
3630
|
+
extractAgentIdentifier(message) {
|
|
3631
|
+
if (message.agentId) return message.agentId;
|
|
3632
|
+
if (message.agentName) return message.agentName;
|
|
3633
|
+
if (message.agent) return message.agent;
|
|
3634
|
+
if (message.name) return message.name;
|
|
3635
|
+
const data = message.data;
|
|
3636
|
+
if (data) {
|
|
3637
|
+
if (data.agentId) return data.agentId;
|
|
3638
|
+
if (data.agentName) return data.agentName;
|
|
3639
|
+
if (data.agent) return data.agent;
|
|
3640
|
+
if (data.name) return data.name;
|
|
3641
|
+
}
|
|
3642
|
+
const runId = message.id || message.runId;
|
|
3643
|
+
if (runId && typeof runId === "string") {
|
|
3644
|
+
const runIdMatch = runId.match(/^([a-z][a-z0-9-]*)-[a-z0-9]+$/i);
|
|
3645
|
+
if (runIdMatch) {
|
|
3646
|
+
const potentialAgent = runIdMatch[1];
|
|
3647
|
+
if (this.agentMapper.resolve(potentialAgent)) {
|
|
3648
|
+
return potentialAgent;
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
if (this.config.verbose) {
|
|
3653
|
+
this.log(`Could not extract agent from message. Keys: ${Object.keys(message).join(", ")}`);
|
|
3654
|
+
this.log(` Full message: ${JSON.stringify(message).substring(0, 300)}`);
|
|
3655
|
+
}
|
|
3656
|
+
return "assistant";
|
|
3657
|
+
}
|
|
3520
3658
|
/**
|
|
3521
3659
|
* Handle streaming delta (partial response)
|
|
3522
3660
|
*/
|
|
3523
3661
|
handleAgentDelta(message) {
|
|
3524
|
-
const agentIdentifier =
|
|
3662
|
+
const agentIdentifier = this.extractAgentIdentifier(message);
|
|
3525
3663
|
let delta = "";
|
|
3526
3664
|
if (typeof message.delta === "string") {
|
|
3527
3665
|
delta = message.delta;
|
|
@@ -3573,7 +3711,10 @@ var OpenClawDaemon = class extends EventEmitter3 {
|
|
|
3573
3711
|
*/
|
|
3574
3712
|
async handleAgentEnd(message) {
|
|
3575
3713
|
const messageId = message.id || message.runId || message.agentId || message.agentName || "default";
|
|
3576
|
-
const agentIdentifier =
|
|
3714
|
+
const agentIdentifier = this.extractAgentIdentifier(message);
|
|
3715
|
+
if (this.config.verbose) {
|
|
3716
|
+
this.log(`Agent end - messageId: ${messageId}, extracted identifier: ${agentIdentifier}`);
|
|
3717
|
+
}
|
|
3577
3718
|
this.log(`Agent end event [${messageId}] from: ${agentIdentifier}`);
|
|
3578
3719
|
const skipWebhook = this.botMessageMonitor && this.botMessageMonitor.isEnabled();
|
|
3579
3720
|
const buffered = this.responseBuffers.get(messageId);
|