@syengup/friday-channel-next 0.0.19 → 0.0.21

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.
Files changed (3) hide show
  1. package/install.js +30 -2
  2. package/package.json +1 -2
  3. package/install.sh +0 -298
package/install.js CHANGED
@@ -219,6 +219,31 @@ if (config.gateway.bind !== "lan") {
219
219
  console.log(" + Set gateway.bind to lan");
220
220
  }
221
221
 
222
+ // Ensure canvas and nodes are in agent tools.alsoAllow
223
+ if (!config.agents) config.agents = {};
224
+ if (!Array.isArray(config.agents.list)) config.agents.list = [];
225
+ if (config.agents.list.length === 0) config.agents.list.push({ id: "main" });
226
+ for (const agent of config.agents.list) {
227
+ if (!agent.tools) agent.tools = {};
228
+ if (!Array.isArray(agent.tools.alsoAllow)) agent.tools.alsoAllow = [];
229
+ for (const tool of ["canvas", "nodes"]) {
230
+ if (!agent.tools.alsoAllow.includes(tool)) {
231
+ agent.tools.alsoAllow.push(tool);
232
+ console.log(" + Added " + tool + " to agent '" + (agent.id || "?") + "' tools.alsoAllow");
233
+ }
234
+ }
235
+ // Remove canvas and nodes from deny list if present
236
+ if (Array.isArray(agent.tools.deny)) {
237
+ for (const tool of ["canvas", "nodes"]) {
238
+ const idx = agent.tools.deny.indexOf(tool);
239
+ if (idx !== -1) {
240
+ agent.tools.deny.splice(idx, 1);
241
+ console.log(" - Removed " + tool + " from agent '" + (agent.id || "?") + "' tools.deny");
242
+ }
243
+ }
244
+ }
245
+ }
246
+
222
247
  try {
223
248
  writeFileSync(OPENCLAW_CONFIG, JSON.stringify(config, null, 2) + "\n", "utf8");
224
249
  } catch {
@@ -241,8 +266,11 @@ if (sudoUser) {
241
266
 
242
267
  log("Restarting OpenClaw gateway...");
243
268
  try {
244
- execSync(`${openclawCmd} gateway restart`, { stdio: "inherit" });
245
- } catch {
269
+ const out = execSync(`${openclawCmd} gateway restart`, { encoding: "utf8", stdio: "pipe" });
270
+ if (out.trim()) console.log(out.trim());
271
+ } catch (e) {
272
+ if (e.stdout?.trim()) console.log(e.stdout.trim());
273
+ if (e.stderr?.trim()) console.error(e.stderr.trim());
246
274
  warn("Gateway restart failed. The plugin files are installed but the gateway was not restarted.");
247
275
  warn("Check 'openclaw gateway status' and restart manually: openclaw gateway restart");
248
276
  }
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@syengup/friday-channel-next",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "description": "OpenClaw Friday Next Apple channel plugin",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "index.ts",
8
8
  "src/",
9
9
  "install.js",
10
- "install.sh",
11
10
  "tsconfig.json",
12
11
  "openclaw.plugin.json"
13
12
  ],
package/install.sh DELETED
@@ -1,298 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # Friday Next plugin installer — one-click setup for the friday-next channel
4
- # Usage:
5
- # ./install.sh [plugin-dir]
6
- # curl -fsSL https://raw.githubusercontent.com/SyengUp/openclaw-fridaynext-channel/main/install.sh | bash
7
-
8
- set -e
9
-
10
- PLUGIN_DIR="${1:-$HOME/.openclaw/extensions/friday-channel-next}"
11
- OPENCLAW_CONFIG="$HOME/.openclaw/openclaw.json"
12
-
13
- RED='\033[0;31m'
14
- GREEN='\033[0;32m'
15
- YELLOW='\033[1;33m'
16
- NC='\033[0m'
17
-
18
- log() { printf " %s\\n" "$1"; }
19
- warn() { printf " ${YELLOW}!${NC} %s\\n" "$1"; }
20
- err() { printf " ${RED}X${NC} %s\\n" "$1" >&2; }
21
-
22
- trap 'err "Install failed."' ERR
23
-
24
- # Check prerequisites
25
- for cmd in node git openclaw; do
26
- if ! command -v "$cmd" &>/dev/null; then
27
- err "$cmd is required but not found. Install it first."
28
- exit 1
29
- fi
30
- done
31
-
32
- # Auto-detect package manager (prefer pnpm, fall back to npm)
33
- if command -v pnpm &>/dev/null; then
34
- PKG="pnpm"
35
- elif command -v npm &>/dev/null; then
36
- PKG="npm"
37
- else
38
- err "pnpm or npm is required but not found. Install one first."
39
- exit 1
40
- fi
41
-
42
- # Auto-detect best registry (measure latency; fall back to npmmirror if slow/unreachable)
43
- TIME=$(curl -s -o /dev/null -w '%{time_total}' --connect-timeout 2 --max-time 4 https://registry.npmjs.org/ 2>/dev/null || echo "999")
44
- case "$TIME" in
45
- 0.*) ;; # under 1s — fast enough
46
- *)
47
- warn "Default registry slow/unreachable, using https://registry.npmmirror.com"
48
- REGISTRY="--registry=https://registry.npmmirror.com"
49
- ;;
50
- esac
51
-
52
- if [ ! -f "$OPENCLAW_CONFIG" ]; then
53
- err "OpenClaw config not found at $OPENCLAW_CONFIG"
54
- err "Make sure OpenClaw is installed and has been run at least once."
55
- exit 1
56
- fi
57
-
58
- # Step 1: Clone (if needed), install deps, and build
59
-
60
- if [ -d "$PLUGIN_DIR" ]; then
61
- log "Plugin directory found: $PLUGIN_DIR"
62
- else
63
- log "Cloning plugin to $PLUGIN_DIR ..."
64
- REPO_URL="${FRIDAY_NEXT_REPO:-https://github.com/SyengUp/openclaw-fridaynext-channel.git}"
65
- git clone "$REPO_URL" "$PLUGIN_DIR"
66
- fi
67
-
68
- cd "$PLUGIN_DIR"
69
-
70
- log "Installing dependencies..."
71
- $PKG install $REGISTRY
72
-
73
- log "Building TypeScript..."
74
- $PKG run build
75
-
76
- # Step 2: Configure OpenClaw
77
-
78
- log "Configuring OpenClaw..."
79
-
80
- node --input-type=module -e '
81
- import fs from "node:fs";
82
-
83
- const configPath = process.argv[1];
84
- const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
85
-
86
- if (!config.plugins) config.plugins = {};
87
- if (!Array.isArray(config.plugins.allow)) config.plugins.allow = [];
88
- if (!config.plugins.allow.includes("friday-next")) {
89
- config.plugins.allow.push("friday-next");
90
- console.log(" + Added friday-next to plugins.allow");
91
- }
92
-
93
- if (!config.plugins.entries) config.plugins.entries = {};
94
- if (!config.plugins.entries["friday-next"]) {
95
- config.plugins.entries["friday-next"] = { enabled: true };
96
- console.log(" + Added friday-next to plugins.entries (enabled)");
97
- } else if (!config.plugins.entries["friday-next"].enabled) {
98
- config.plugins.entries["friday-next"].enabled = true;
99
- console.log(" + Enabled friday-next in plugins.entries");
100
- }
101
-
102
- if (!config.channels) config.channels = {};
103
- if (!config.channels["friday-next"]) {
104
- config.channels["friday-next"] = { enabled: true, transport: "http+sse" };
105
- console.log(" + Added friday-next channel config (auth defaults to gateway token)");
106
- } else {
107
- if (!config.channels["friday-next"].enabled) {
108
- config.channels["friday-next"].enabled = true;
109
- console.log(" + Enabled friday-next channel");
110
- }
111
- if (!config.channels["friday-next"].transport) {
112
- config.channels["friday-next"].transport = "http+sse";
113
- console.log(" + Set friday-next transport to http+sse");
114
- }
115
- }
116
-
117
- if (!config.gateway) config.gateway = {};
118
- if (config.gateway.bind !== "lan") {
119
- config.gateway.bind = "lan";
120
- console.log(" + Set gateway.bind to lan");
121
- }
122
-
123
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
124
- console.log(" Config updated.");
125
- ' "$OPENCLAW_CONFIG"
126
-
127
- # Step 3: Restart gateway
128
-
129
- log "Restarting OpenClaw gateway..."
130
- openclaw gateway restart
131
-
132
- # Verify gateway is up
133
- log "Verifying gateway..."
134
- VERIFY_LOG=$(mktemp)
135
- node --input-type=module -e '
136
- import { readFileSync } from "node:fs";
137
- import { networkInterfaces } from "node:os";
138
- import http from "node:http";
139
-
140
- const config = JSON.parse(readFileSync(process.argv[1], "utf8"));
141
-
142
- function getLanIp() {
143
- const nets = networkInterfaces();
144
- for (const name of Object.keys(nets)) {
145
- for (const net of nets[name]) {
146
- if (net.family === "IPv4" && !net.internal) return net.address;
147
- }
148
- }
149
- return "127.0.0.1";
150
- }
151
-
152
- const port = config.gateway?.port || 18789;
153
- const token = config.gateway?.auth?.token || "";
154
- const bind = config.gateway?.bind || "localhost";
155
- const host = bind === "lan" ? getLanIp() : "127.0.0.1";
156
-
157
- let ok = false;
158
- async function verifyGateway() {
159
- for (let i = 1; i <= 6; i++) {
160
- await new Promise((r) => setTimeout(r, 1000));
161
- try {
162
- const res = await new Promise((resolve, reject) => {
163
- const req = http.request(
164
- { hostname: host, port, path: "/friday-next/status", method: "GET",
165
- headers: { authorization: "Bearer " + token }, timeout: 5000 },
166
- (res) => { let body = ""; res.on("data", (c) => body += c); res.on("end", () => resolve({ status: res.statusCode, body })); },
167
- );
168
- req.on("error", reject);
169
- req.on("timeout", () => { req.destroy(); reject(new Error("timeout")); });
170
- req.end();
171
- });
172
- if (res.status === 200) {
173
- try {
174
- const data = JSON.parse(res.body);
175
- if (data.ok) {
176
- console.log(" Gateway verified OK (friday-next " + data.version + ", " + data.connections + " connections).");
177
- ok = true;
178
- return;
179
- }
180
- console.log(" ! Plugin responded but ok=false — " + JSON.stringify(data));
181
- return;
182
- } catch {
183
- if (i < 3) {
184
- console.log(" ! Plugin routes not registered yet, retrying (" + i + "/6)...");
185
- } else if (i < 6) {
186
- console.log(" ! Gateway is up but plugin routes missing — may need config reload, retrying (" + i + "/6)...");
187
- } else {
188
- console.log(" ! Gateway is running but plugin routes were not loaded. Check plugin config in openclaw.json.");
189
- }
190
- continue;
191
- }
192
- }
193
- if (res.status === 401) {
194
- console.log(" ! Auth token mismatch — check gateway.auth.token in openclaw.json.");
195
- return;
196
- }
197
- if (res.status === 404) {
198
- console.log(" ! Route /friday-next/status not found — plugin may not be loaded.");
199
- return;
200
- }
201
- if (i < 6) console.log(" ! Gateway responded " + res.status + ", retrying (" + i + "/6)...");
202
- } catch {
203
- if (i < 6) console.log(" ! Gateway not reachable, retrying (" + i + "/6)...");
204
- }
205
- }
206
- console.log(" ! Gateway verification timed out — check '\''openclaw gateway status'\'' manually.");
207
- }
208
- await verifyGateway();
209
- console.log(ok ? "VERIFY_OK" : "VERIFY_FAIL");
210
- ' "$OPENCLAW_CONFIG" 2>&1 | tee "$VERIFY_LOG"
211
- if grep -q "VERIFY_OK" "$VERIFY_LOG"; then
212
- VERIFY_PASS=1
213
- else
214
- VERIFY_PASS=0
215
- fi
216
- rm -f "$VERIFY_LOG"
217
-
218
- # Show connection info
219
- node --input-type=module -e '
220
- import { readFileSync } from "node:fs";
221
- import { networkInterfaces } from "node:os";
222
-
223
- const config = JSON.parse(readFileSync(process.argv[1], "utf8"));
224
-
225
- function getLanIp() {
226
- const nets = networkInterfaces();
227
- for (const name of Object.keys(nets)) {
228
- for (const net of nets[name]) {
229
- if (net.family === "IPv4" && !net.internal) return net.address;
230
- }
231
- }
232
- return "127.0.0.1";
233
- }
234
-
235
- const port = config.gateway?.port || 18789;
236
- const token = config.gateway?.auth?.token || "(not set)";
237
- const bind = config.gateway?.bind || "localhost";
238
- const host = bind === "lan" ? getLanIp() : "127.0.0.1";
239
-
240
- const YB = "\x1b[1;33m", N = "\x1b[0m";
241
- const qrPayload = JSON.stringify({ url: "http://" + host + ":" + port, token: token });
242
- let qrShown = false;
243
- try {
244
- const { createRequire } = await import("node:module");
245
- const qrcode = createRequire(import.meta.url)("qrcode-terminal");
246
- console.log("");
247
- console.log(YB + "Scan below to auto-fill URL & Token in FridayNext app:" + N);
248
- console.log(YB + "扫描下方二维码自动填入 URL 和 Token:" + N);
249
- console.log("");
250
- qrcode.generate(qrPayload, { small: true });
251
- console.log("");
252
- console.log("If QR scan does not work, enter manually:");
253
- console.log("若二维码无法使用,请手动输入:");
254
- qrShown = true;
255
- } catch {}
256
- if (!qrShown) {
257
- console.log("");
258
- console.log(YB + "Input the URL and Token below into your FridayNext app to connect." + N);
259
- console.log(YB + "请将下方 URL 和 Token 输入至 FridayNext App 完成连接。" + N);
260
- }
261
- console.log("");
262
- console.log("Gateway URL: " + YB + "http://" + host + ":" + port + N);
263
- console.log("Bearer Token: " + YB + token + N);
264
- console.log("");
265
- function classifyIp(ip) {
266
- var p = ip.split(".").map(Number);
267
- if (p[0] === 100 && p[1] >= 64 && p[1] <= 127) return "tailscale";
268
- if (p[0] === 127) return "loopback";
269
- if (p[0] === 10) return "private";
270
- if (p[0] === 172 && p[1] >= 16 && p[1] <= 31) return "private";
271
- if (p[0] === 192 && p[1] === 168) return "private";
272
- if (p[0] === 169 && p[1] === 254) return "private";
273
- return "public";
274
- }
275
- if (classifyIp(host) === "tailscale") {
276
- console.log("This is a Tailscale network URL (" + host + ").");
277
- console.log("Accessible from your Tailnet devices.");
278
- } else if (classifyIp(host) === "private") {
279
- console.log("This is a LOCAL network URL (" + host + ", bind=" + bind + ").");
280
- console.log("If you need public access, configure HTTPS, Tailscale, or a reverse proxy.");
281
- } else if (classifyIp(host) === "loopback") {
282
- console.log("This is a LOOPBACK URL (" + host + ").");
283
- console.log("Only accessible from this machine.");
284
- } else {
285
- console.log("This URL appears to be publicly accessible (" + host + ").");
286
- }
287
- ' "$OPENCLAW_CONFIG"
288
-
289
- log "--------------------------------------------------"
290
- if [ "$VERIFY_PASS" = "1" ]; then
291
- log "Installation complete! Friday Next channel is now active."
292
- else
293
- warn "Installation complete, but gateway verification failed."
294
- warn "Check 'openclaw gateway status' and restart the gateway if needed."
295
- warn "Also ensure OpenClaw is updated to 2026.5.7 or above: openclaw update"
296
- warn "同时请确认 OpenClaw 已升级至 2026.5.7 或以上版本:openclaw update"
297
- fi
298
- log "--------------------------------------------------"