@badgerclaw/connect 1.4.14 → 1.4.15
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/index.ts +72 -1
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -65,6 +65,9 @@ async function startPairWatcher(logger: { info?: (msg: string) => void; warn?: (
|
|
|
65
65
|
|
|
66
66
|
// Write to config via openclaw config set — triggers hot-reload, bot starts immediately
|
|
67
67
|
const { execSync } = await import("child_process");
|
|
68
|
+
const path = await import("path");
|
|
69
|
+
const os = await import("os");
|
|
70
|
+
const fs = await import("fs");
|
|
68
71
|
const localpart = bot.user_id.split(":")[0].replace("@", "").replace(/_bot$/, "");
|
|
69
72
|
const base = `channels.badgerclaw.accounts.${localpart}`;
|
|
70
73
|
const opts = { encoding: "utf-8" as const, timeout: 10000, stdio: "pipe" as const };
|
|
@@ -74,6 +77,9 @@ async function startPairWatcher(logger: { info?: (msg: string) => void; warn?: (
|
|
|
74
77
|
execSync(`openclaw config set ${base}.encryption true`, opts);
|
|
75
78
|
if (bot.device_id) execSync(`openclaw config set ${base}.deviceId "${bot.device_id}"`, opts);
|
|
76
79
|
|
|
80
|
+
// Auto-provision agent with separate context for this bot
|
|
81
|
+
provisionBotAgent({ localpart, botName: bot.bot_name, fs, path, os, execSync, opts });
|
|
82
|
+
|
|
77
83
|
// Mark claimed
|
|
78
84
|
await fetch(`${API_BASE}/api/v1/openclaw/pending-pairs/${data.pair_code}/claim`, {
|
|
79
85
|
method: "POST",
|
|
@@ -94,6 +100,62 @@ async function startPairWatcher(logger: { info?: (msg: string) => void; warn?: (
|
|
|
94
100
|
connect();
|
|
95
101
|
}
|
|
96
102
|
|
|
103
|
+
function provisionBotAgent(params: {
|
|
104
|
+
localpart: string;
|
|
105
|
+
botName: string;
|
|
106
|
+
fs: any;
|
|
107
|
+
path: any;
|
|
108
|
+
os: any;
|
|
109
|
+
execSync: any;
|
|
110
|
+
opts: any;
|
|
111
|
+
}): void {
|
|
112
|
+
const { localpart, botName, fs, path, os, execSync, opts } = params;
|
|
113
|
+
try {
|
|
114
|
+
// 1. Create agent workspace dir with SOUL.md
|
|
115
|
+
const agentDir = path.join(os.homedir(), ".openclaw", "agents", localpart);
|
|
116
|
+
fs.mkdirSync(agentDir, { recursive: true });
|
|
117
|
+
const soulPath = path.join(agentDir, "SOUL.md");
|
|
118
|
+
if (!fs.existsSync(soulPath)) {
|
|
119
|
+
fs.writeFileSync(soulPath, `# SOUL.md — ${botName}\n\nI am ${botName}, a helpful AI assistant on BadgerClaw. I respond directly and helpfully. My name is ${botName}.\n`);
|
|
120
|
+
}
|
|
121
|
+
const agentsPath = path.join(agentDir, "AGENTS.md");
|
|
122
|
+
if (!fs.existsSync(agentsPath)) {
|
|
123
|
+
fs.writeFileSync(agentsPath, `# AGENTS.md\n## Session Startup\nRead SOUL.md\n`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 2. Add agent to agents.list
|
|
127
|
+
const cfgPath = path.join(os.homedir(), ".openclaw", "openclaw.json");
|
|
128
|
+
const cfg = JSON.parse(fs.readFileSync(cfgPath, "utf-8"));
|
|
129
|
+
const agentsList: any[] = cfg.agents?.list ?? [];
|
|
130
|
+
if (!agentsList.find((a: any) => a.id === localpart)) {
|
|
131
|
+
agentsList.push({
|
|
132
|
+
id: localpart,
|
|
133
|
+
name: botName,
|
|
134
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
135
|
+
workspace: agentDir,
|
|
136
|
+
agentDir: path.join(agentDir, "agent"),
|
|
137
|
+
identity: { name: botName, emoji: "🤖" },
|
|
138
|
+
});
|
|
139
|
+
cfg.agents = cfg.agents ?? {};
|
|
140
|
+
cfg.agents.list = agentsList;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 3. Add binding: badgerclaw.<localpart> → agent:<localpart>
|
|
144
|
+
const bindings: any[] = cfg.bindings ?? [];
|
|
145
|
+
if (!bindings.find((b: any) => b.match?.channel === "badgerclaw" && b.match?.accountId === localpart)) {
|
|
146
|
+
bindings.push({ type: "route", agentId: localpart, match: { channel: "badgerclaw", accountId: localpart } });
|
|
147
|
+
cfg.bindings = bindings;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
|
|
151
|
+
|
|
152
|
+
// Trigger hot-reload via a harmless config set touch
|
|
153
|
+
try { execSync(`openclaw config set channels.badgerclaw.accounts.${localpart}.agentId "${localpart}"`, opts); } catch {}
|
|
154
|
+
} catch (e: any) {
|
|
155
|
+
console.log(`[badgerclaw] agent provision warning for ${localpart}: ${e.message}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
97
159
|
async function checkPluginUpdate(log: (msg: string) => void): Promise<void> {
|
|
98
160
|
try {
|
|
99
161
|
const CURRENT = "1.4.4";
|
|
@@ -159,11 +221,20 @@ const plugin = {
|
|
|
159
221
|
};
|
|
160
222
|
await writeConfigFile(snapshot.path, cfg);
|
|
161
223
|
|
|
224
|
+
// Auto-provision separate agent with its own context
|
|
225
|
+
const { execSync } = await import("child_process");
|
|
226
|
+
const pathMod = await import("path");
|
|
227
|
+
const osMod = await import("os");
|
|
228
|
+
const fsMod = await import("fs");
|
|
229
|
+
const opts = { encoding: "utf-8" as const, timeout: 10000, stdio: "pipe" as const };
|
|
230
|
+
provisionBotAgent({ localpart, botName: result.bot_name, fs: fsMod, path: pathMod, os: osMod, execSync, opts });
|
|
231
|
+
|
|
162
232
|
console.log("\n✅ Connected to BadgerClaw bot!");
|
|
163
233
|
console.log(" Bot name: " + result.bot_name);
|
|
164
234
|
console.log(" Bot user: " + result.user_id);
|
|
165
235
|
console.log(" Account: " + localpart);
|
|
166
|
-
console.log("
|
|
236
|
+
console.log(" Agent: agent:" + localpart + " (separate context)");
|
|
237
|
+
console.log("\n⚡ Bot account + agent written to OpenClaw config — hot-reloading...");
|
|
167
238
|
} catch (err: any) {
|
|
168
239
|
console.error("\n❌ Failed to connect: " + (err.message || err));
|
|
169
240
|
process.exit(1);
|