@syengup/friday-channel-next 0.0.43 → 0.0.45
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/src/agent/node-pairing-bridge.js +30 -24
- package/install.js +82 -93
- package/package.json +1 -1
- package/src/agent/node-pairing-bridge.ts +27 -21
|
@@ -1,29 +1,20 @@
|
|
|
1
1
|
import { readdirSync } from "node:fs";
|
|
2
|
-
import { join
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { join } from "node:path";
|
|
4
3
|
let cache = null;
|
|
5
4
|
function resolveOpenClawDist() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"/opt/homebrew/lib/node_modules/openclaw/dist",
|
|
16
|
-
"/home/linuxbrew/.linuxbrew/lib/node_modules/openclaw/dist",
|
|
17
|
-
"/usr/local/lib/node_modules/openclaw/dist",
|
|
18
|
-
]) {
|
|
19
|
-
try {
|
|
20
|
-
readdirSync(root);
|
|
21
|
-
return root;
|
|
22
|
-
}
|
|
23
|
-
catch { }
|
|
5
|
+
for (const root of [
|
|
6
|
+
join(process.env.APPDATA ?? "", "npm/node_modules/openclaw/dist"),
|
|
7
|
+
"/opt/homebrew/lib/node_modules/openclaw/dist",
|
|
8
|
+
"/home/linuxbrew/.linuxbrew/lib/node_modules/openclaw/dist",
|
|
9
|
+
"/usr/local/lib/node_modules/openclaw/dist",
|
|
10
|
+
]) {
|
|
11
|
+
try {
|
|
12
|
+
readdirSync(root);
|
|
13
|
+
return root;
|
|
24
14
|
}
|
|
25
|
-
|
|
15
|
+
catch { }
|
|
26
16
|
}
|
|
17
|
+
throw new Error("OpenClaw dist directory not found");
|
|
27
18
|
}
|
|
28
19
|
export async function loadNodePairingModule() {
|
|
29
20
|
if (cache)
|
|
@@ -32,9 +23,24 @@ export async function loadNodePairingModule() {
|
|
|
32
23
|
const file = readdirSync(dist).find((f) => f.startsWith("node-pairing-") && f.endsWith(".js") && !f.includes("authz"));
|
|
33
24
|
if (!file)
|
|
34
25
|
throw new Error("node-pairing module not found in OpenClaw dist");
|
|
35
|
-
// ESM import()
|
|
36
|
-
//
|
|
37
|
-
|
|
26
|
+
// ESM import() returns the minified export names (r, t, …) because the
|
|
27
|
+
// bundled module uses `export { listNodePairing as r, … }`. Resolve the
|
|
28
|
+
// correct functions by Function.name, which preserves the original name.
|
|
29
|
+
const mod = await import(join(dist, file));
|
|
30
|
+
let listNodePairing;
|
|
31
|
+
let approveNodePairing;
|
|
32
|
+
for (const value of Object.values(mod)) {
|
|
33
|
+
if (typeof value === "function") {
|
|
34
|
+
if (value.name === "listNodePairing")
|
|
35
|
+
listNodePairing = value;
|
|
36
|
+
else if (value.name === "approveNodePairing")
|
|
37
|
+
approveNodePairing = value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!listNodePairing || !approveNodePairing) {
|
|
41
|
+
throw new Error("node-pairing module did not export expected functions");
|
|
42
|
+
}
|
|
43
|
+
cache = { listNodePairing, approveNodePairing };
|
|
38
44
|
return cache;
|
|
39
45
|
}
|
|
40
46
|
/** Vitest-only: inject mock pairing functions. */
|
package/install.js
CHANGED
|
@@ -89,15 +89,14 @@ if (!hasOpenclaw()) {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
// --------------- install
|
|
92
|
+
// --------------- install plugin package ---------------
|
|
93
93
|
|
|
94
|
-
log("Installing Friday Next channel
|
|
94
|
+
log("Installing Friday Next channel plugin...");
|
|
95
95
|
let installed = false;
|
|
96
96
|
|
|
97
97
|
try {
|
|
98
|
-
// --dangerously-force-unsafe-install needed for child_process in device-approve / nodes-approve
|
|
99
98
|
const out = execSync(
|
|
100
|
-
`${openclawCmd} plugins install
|
|
99
|
+
`${openclawCmd} plugins install @syengup/friday-channel-next@latest`,
|
|
101
100
|
{ encoding: "utf8", stdio: "pipe", timeout: 120000 }
|
|
102
101
|
);
|
|
103
102
|
if (out.trim()) console.log(out.trim());
|
|
@@ -117,113 +116,104 @@ if (!installed) {
|
|
|
117
116
|
err("npm is required for manual install. Install Node.js first.");
|
|
118
117
|
process.exit(1);
|
|
119
118
|
}
|
|
119
|
+
warn("Manual install complete, but auto-upgrade is NOT available.");
|
|
120
|
+
warn("To enable auto-upgrade later, run: openclaw plugins install @syengup/friday-channel-next");
|
|
121
|
+
}
|
|
120
122
|
|
|
121
|
-
|
|
122
|
-
err(`OpenClaw config not found at ${OPENCLAW_CONFIG}`);
|
|
123
|
-
err("Run openclaw at least once before installing plugins.");
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Configure OpenClaw
|
|
128
|
-
log("Configuring OpenClaw...");
|
|
123
|
+
// --------------- configure OpenClaw ---------------
|
|
129
124
|
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
config = JSON.parse(readFileSync(OPENCLAW_CONFIG, "utf8"));
|
|
133
|
-
} catch {
|
|
134
|
-
err(`Failed to read ${OPENCLAW_CONFIG}.`);
|
|
135
|
-
process.exit(1);
|
|
136
|
-
}
|
|
125
|
+
log("Configuring OpenClaw...");
|
|
137
126
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
127
|
+
let config;
|
|
128
|
+
try {
|
|
129
|
+
config = JSON.parse(readFileSync(OPENCLAW_CONFIG, "utf8"));
|
|
130
|
+
} catch {
|
|
131
|
+
err(`Failed to read ${OPENCLAW_CONFIG}.`);
|
|
132
|
+
err("Make sure OpenClaw is installed and has been run at least once.");
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
144
135
|
|
|
145
|
-
|
|
146
|
-
if (!config.plugins.entries["friday-next"]) {
|
|
147
|
-
config.plugins.entries["friday-next"] = { enabled: true };
|
|
148
|
-
console.log(" + Added friday-next to plugins.entries (enabled)");
|
|
149
|
-
} else if (!config.plugins.entries["friday-next"].enabled) {
|
|
150
|
-
config.plugins.entries["friday-next"].enabled = true;
|
|
151
|
-
console.log(" + Enabled friday-next in plugins.entries");
|
|
152
|
-
}
|
|
136
|
+
let configChanged = false;
|
|
153
137
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
138
|
+
function setConfig(path, value) {
|
|
139
|
+
const keys = path.split(".");
|
|
140
|
+
let obj = config;
|
|
141
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
142
|
+
if (!obj[keys[i]] || typeof obj[keys[i]] !== "object" || Array.isArray(obj[keys[i]])) {
|
|
143
|
+
obj[keys[i]] = {};
|
|
144
|
+
}
|
|
145
|
+
obj = obj[keys[i]];
|
|
157
146
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
config.plugins.entries["canvas"].enabled = true;
|
|
163
|
-
console.log(" + Enabled canvas in plugins.entries");
|
|
147
|
+
const last = keys[keys.length - 1];
|
|
148
|
+
if (JSON.stringify(obj[last]) !== JSON.stringify(value)) {
|
|
149
|
+
obj[last] = value;
|
|
150
|
+
configChanged = true;
|
|
164
151
|
}
|
|
152
|
+
}
|
|
165
153
|
|
|
166
|
-
|
|
167
|
-
if (!
|
|
168
|
-
|
|
169
|
-
console.log(" + Added friday-next channel config");
|
|
170
|
-
} else {
|
|
171
|
-
if (!config.channels["friday-next"].enabled) {
|
|
172
|
-
config.channels["friday-next"].enabled = true;
|
|
173
|
-
console.log(" + Enabled friday-next channel");
|
|
174
|
-
}
|
|
175
|
-
if (!config.channels["friday-next"].transport) {
|
|
176
|
-
config.channels["friday-next"].transport = "http+sse";
|
|
177
|
-
console.log(" + Set friday-next transport to http+sse");
|
|
178
|
-
}
|
|
179
|
-
}
|
|
154
|
+
function ensureArrayContains(arr, item) {
|
|
155
|
+
if (!arr.includes(item)) { arr.push(item); configChanged = true; }
|
|
156
|
+
}
|
|
180
157
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
158
|
+
// Plugins
|
|
159
|
+
if (!config.plugins) config.plugins = {};
|
|
160
|
+
if (!Array.isArray(config.plugins.allow)) config.plugins.allow = [];
|
|
161
|
+
ensureArrayContains(config.plugins.allow, "friday-next");
|
|
162
|
+
ensureArrayContains(config.plugins.allow, "canvas");
|
|
163
|
+
|
|
164
|
+
if (!config.plugins.entries) config.plugins.entries = {};
|
|
165
|
+
for (const id of ["friday-next", "canvas"]) {
|
|
166
|
+
if (!config.plugins.entries[id]) { config.plugins.entries[id] = { enabled: true }; configChanged = true; }
|
|
167
|
+
else if (!config.plugins.entries[id].enabled) { config.plugins.entries[id].enabled = true; configChanged = true; }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Channel
|
|
171
|
+
if (!config.channels) config.channels = {};
|
|
172
|
+
if (!config.channels["friday-next"]) { config.channels["friday-next"] = { enabled: true, transport: "http+sse" }; configChanged = true; }
|
|
173
|
+
else {
|
|
174
|
+
if (!config.channels["friday-next"].enabled) { config.channels["friday-next"].enabled = true; configChanged = true; }
|
|
175
|
+
if (!config.channels["friday-next"].transport) { config.channels["friday-next"].transport = "http+sse"; configChanged = true; }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Gateway bind + nodes
|
|
179
|
+
if (!config.gateway) config.gateway = {};
|
|
180
|
+
if (config.gateway.bind !== "lan") { config.gateway.bind = "lan"; configChanged = true; }
|
|
181
|
+
if (!config.gateway.nodes) config.gateway.nodes = {};
|
|
182
|
+
if (!Array.isArray(config.gateway.nodes.allowCommands)) config.gateway.nodes.allowCommands = [];
|
|
183
|
+
for (const cmd of [
|
|
184
|
+
"canvas.navigate", "canvas.present", "canvas.hide", "canvas.eval",
|
|
185
|
+
"canvas.snapshot", "canvas.a2ui.push", "canvas.a2ui.reset", "canvas.a2ui.pushJSONL",
|
|
186
|
+
]) {
|
|
187
|
+
ensureArrayContains(config.gateway.nodes.allowCommands, cmd);
|
|
188
|
+
}
|
|
197
189
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
190
|
+
// Agent tools
|
|
191
|
+
if (!config.agents) config.agents = {};
|
|
192
|
+
if (!Array.isArray(config.agents.list)) config.agents.list = [];
|
|
193
|
+
let mainAgent = config.agents.list.find((a) => a.id === "main");
|
|
194
|
+
if (!mainAgent) { mainAgent = { id: "main" }; config.agents.list.push(mainAgent); configChanged = true; }
|
|
195
|
+
if (!mainAgent.tools) mainAgent.tools = {};
|
|
196
|
+
if (!Array.isArray(mainAgent.tools.alsoAllow)) mainAgent.tools.alsoAllow = [];
|
|
197
|
+
for (const tool of ["canvas", "nodes"]) {
|
|
198
|
+
ensureArrayContains(mainAgent.tools.alsoAllow, tool);
|
|
199
|
+
}
|
|
200
|
+
if (Array.isArray(mainAgent.tools.deny)) {
|
|
204
201
|
for (const tool of ["canvas", "nodes"]) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
console.log(" + Added " + tool + " to agent 'main' tools.alsoAllow");
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
if (Array.isArray(mainAgent.tools.deny)) {
|
|
211
|
-
for (const tool of ["canvas", "nodes"]) {
|
|
212
|
-
const idx = mainAgent.tools.deny.indexOf(tool);
|
|
213
|
-
if (idx !== -1) { mainAgent.tools.deny.splice(idx, 1); console.log(" - Removed " + tool + " from agent 'main' tools.deny"); }
|
|
214
|
-
}
|
|
202
|
+
const idx = mainAgent.tools.deny.indexOf(tool);
|
|
203
|
+
if (idx !== -1) { mainAgent.tools.deny.splice(idx, 1); configChanged = true; }
|
|
215
204
|
}
|
|
205
|
+
}
|
|
216
206
|
|
|
207
|
+
if (configChanged) {
|
|
217
208
|
try {
|
|
218
209
|
writeFileSync(OPENCLAW_CONFIG, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
219
|
-
|
|
210
|
+
log("openclaw.json updated.");
|
|
220
211
|
} catch {
|
|
221
212
|
err(`Failed to write ${OPENCLAW_CONFIG}.`);
|
|
222
213
|
process.exit(1);
|
|
223
214
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
warn("To enable auto-upgrade, run: openclaw plugins install --dangerously-force-unsafe-install @syengup/friday-channel-next");
|
|
215
|
+
} else {
|
|
216
|
+
log("openclaw.json already configured.");
|
|
227
217
|
}
|
|
228
218
|
|
|
229
219
|
// --------------- restart gateway ---------------
|
|
@@ -250,7 +240,6 @@ function getLanIp() {
|
|
|
250
240
|
return "127.0.0.1";
|
|
251
241
|
}
|
|
252
242
|
|
|
253
|
-
let config;
|
|
254
243
|
try { config = JSON.parse(readFileSync(OPENCLAW_CONFIG, "utf8")); } catch { config = {}; }
|
|
255
244
|
|
|
256
245
|
const gatewayPort = config.gateway?.port || 18789;
|
package/package.json
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
import { readdirSync } from "node:fs";
|
|
2
|
-
import { join
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { join } from "node:path";
|
|
4
3
|
|
|
5
4
|
let cache: { listNodePairing: Function; approveNodePairing: Function } | null = null;
|
|
6
5
|
|
|
7
6
|
function resolveOpenClawDist(): string {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
join(process.env.APPDATA ?? "", "npm/node_modules/openclaw/dist"),
|
|
16
|
-
"/opt/homebrew/lib/node_modules/openclaw/dist",
|
|
17
|
-
"/home/linuxbrew/.linuxbrew/lib/node_modules/openclaw/dist",
|
|
18
|
-
"/usr/local/lib/node_modules/openclaw/dist",
|
|
19
|
-
]) {
|
|
20
|
-
try { readdirSync(root); return root; } catch {}
|
|
21
|
-
}
|
|
22
|
-
throw new Error("OpenClaw dist directory not found");
|
|
7
|
+
for (const root of [
|
|
8
|
+
join(process.env.APPDATA ?? "", "npm/node_modules/openclaw/dist"),
|
|
9
|
+
"/opt/homebrew/lib/node_modules/openclaw/dist",
|
|
10
|
+
"/home/linuxbrew/.linuxbrew/lib/node_modules/openclaw/dist",
|
|
11
|
+
"/usr/local/lib/node_modules/openclaw/dist",
|
|
12
|
+
]) {
|
|
13
|
+
try { readdirSync(root); return root; } catch {}
|
|
23
14
|
}
|
|
15
|
+
throw new Error("OpenClaw dist directory not found");
|
|
24
16
|
}
|
|
25
17
|
|
|
26
18
|
export async function loadNodePairingModule(): Promise<{
|
|
@@ -33,10 +25,24 @@ export async function loadNodePairingModule(): Promise<{
|
|
|
33
25
|
(f) => f.startsWith("node-pairing-") && f.endsWith(".js") && !f.includes("authz"),
|
|
34
26
|
);
|
|
35
27
|
if (!file) throw new Error("node-pairing module not found in OpenClaw dist");
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
|
|
29
|
+
// ESM import() returns the minified export names (r, t, …) because the
|
|
30
|
+
// bundled module uses `export { listNodePairing as r, … }`. Resolve the
|
|
31
|
+
// correct functions by Function.name, which preserves the original name.
|
|
32
|
+
const mod = await import(join(dist, file));
|
|
33
|
+
let listNodePairing: Function | undefined;
|
|
34
|
+
let approveNodePairing: Function | undefined;
|
|
35
|
+
for (const value of Object.values(mod)) {
|
|
36
|
+
if (typeof value === "function") {
|
|
37
|
+
if (value.name === "listNodePairing") listNodePairing = value;
|
|
38
|
+
else if (value.name === "approveNodePairing") approveNodePairing = value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!listNodePairing || !approveNodePairing) {
|
|
42
|
+
throw new Error("node-pairing module did not export expected functions");
|
|
43
|
+
}
|
|
44
|
+
cache = { listNodePairing, approveNodePairing };
|
|
45
|
+
return cache;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
/** Vitest-only: inject mock pairing functions. */
|