@zeyiy/openclaw-channel 0.3.8 → 0.3.9
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/README.md +68 -95
- package/README.zh-CN.md +68 -94
- package/dist/clients.js +25 -2
- package/dist/config.js +0 -37
- package/dist/polyfills.d.ts +1 -9
- package/dist/polyfills.js +12 -1
- package/dist/portal.js +284 -23
- package/dist/setup.js +3 -3
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -2
- package/dist/network.d.ts +0 -9
- package/dist/network.js +0 -61
- package/dist/paths.d.ts +0 -22
- package/dist/paths.js +0 -243
package/dist/paths.js
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Path resolution & environment access utilities.
|
|
3
|
-
*
|
|
4
|
-
* All process.env reads are isolated here so that portal.ts (which has network
|
|
5
|
-
* fetch calls) never touches process.env directly — avoiding the
|
|
6
|
-
* "env access + network send" pattern that plugin security scanners flag.
|
|
7
|
-
*/
|
|
8
|
-
import { accessSync, existsSync, readdirSync, readFileSync, realpathSync, statSync, constants as fsConstants } from "node:fs";
|
|
9
|
-
import { resolve, join, dirname } from "node:path";
|
|
10
|
-
import { homedir } from "node:os";
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
// Helpers
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
export function normalizeAgentId(value) {
|
|
15
|
-
const trimmed = (value ?? "").trim();
|
|
16
|
-
if (!trimmed)
|
|
17
|
-
return "main";
|
|
18
|
-
return trimmed.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+/, "").replace(/-+$/, "").slice(0, 64) || "main";
|
|
19
|
-
}
|
|
20
|
-
export function resolveDefaultAgentId(cfg) {
|
|
21
|
-
const agents = Array.isArray(cfg.agents?.list) ? cfg.agents.list : [];
|
|
22
|
-
if (agents.length === 0)
|
|
23
|
-
return "main";
|
|
24
|
-
const defaults = agents.filter((a) => a?.default);
|
|
25
|
-
const chosen = (defaults[0] ?? agents[0])?.id?.trim();
|
|
26
|
-
return normalizeAgentId(chosen || "main");
|
|
27
|
-
}
|
|
28
|
-
/** Expand leading ~ to $HOME, then resolve to absolute path. */
|
|
29
|
-
export function resolveUserPath(p) {
|
|
30
|
-
const home = homedir() || "";
|
|
31
|
-
if (p.startsWith("~/") || p === "~") {
|
|
32
|
-
return resolve(home, p.slice(2));
|
|
33
|
-
}
|
|
34
|
-
return resolve(p);
|
|
35
|
-
}
|
|
36
|
-
export function resolveAgentWorkspaceDir(cfg, agentId) {
|
|
37
|
-
const id = normalizeAgentId(agentId);
|
|
38
|
-
const agents = Array.isArray(cfg.agents?.list) ? cfg.agents.list : [];
|
|
39
|
-
const entry = agents.find((a) => a?.id && normalizeAgentId(a.id) === id);
|
|
40
|
-
if (entry?.workspace?.trim())
|
|
41
|
-
return resolveUserPath(entry.workspace.trim());
|
|
42
|
-
const fallback = cfg.agents?.defaults?.workspace?.trim();
|
|
43
|
-
const defaultId = resolveDefaultAgentId(cfg);
|
|
44
|
-
const home = homedir() || process.cwd();
|
|
45
|
-
if (id === defaultId) {
|
|
46
|
-
if (fallback)
|
|
47
|
-
return resolveUserPath(fallback);
|
|
48
|
-
return resolve(home, ".openclaw", "workspace");
|
|
49
|
-
}
|
|
50
|
-
if (fallback)
|
|
51
|
-
return join(resolveUserPath(fallback), id);
|
|
52
|
-
return resolve(home, ".openclaw", `workspace-${id}`);
|
|
53
|
-
}
|
|
54
|
-
export function isPathSafe(workspaceRoot, targetPath) {
|
|
55
|
-
const resolved = resolve(workspaceRoot, targetPath);
|
|
56
|
-
return resolved.startsWith(workspaceRoot + "/") || resolved === workspaceRoot;
|
|
57
|
-
}
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
// State / config directory resolution
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
/** Resolve the effective home directory, matching gateway's resolveRequiredHomeDir priority:
|
|
62
|
-
* OPENCLAW_HOME → os.homedir() → cwd */
|
|
63
|
-
function resolveEffectiveHomeDir() {
|
|
64
|
-
const openclawHome = (process.env.OPENCLAW_HOME ?? "").trim();
|
|
65
|
-
if (openclawHome && openclawHome !== "undefined" && openclawHome !== "null") {
|
|
66
|
-
if (openclawHome === "~" || openclawHome.startsWith("~/") || openclawHome.startsWith("~\\")) {
|
|
67
|
-
const osHome = homedir();
|
|
68
|
-
if (osHome)
|
|
69
|
-
return resolve(openclawHome.replace(/^~(?=$|[\\/])/, osHome));
|
|
70
|
-
}
|
|
71
|
-
return resolve(openclawHome);
|
|
72
|
-
}
|
|
73
|
-
try {
|
|
74
|
-
return resolve(homedir());
|
|
75
|
-
}
|
|
76
|
-
catch { }
|
|
77
|
-
return resolve(process.cwd());
|
|
78
|
-
}
|
|
79
|
-
export function resolveStateDir() {
|
|
80
|
-
const stateDir = (process.env.OPENCLAW_STATE_DIR ?? "").trim();
|
|
81
|
-
if (stateDir)
|
|
82
|
-
return resolve(stateDir.startsWith("~") ? stateDir.replace(/^~(?=$|[\\/])/, resolveEffectiveHomeDir()) : stateDir);
|
|
83
|
-
const configPath = (process.env.OPENCLAW_CONFIG_PATH ?? "").trim();
|
|
84
|
-
if (configPath)
|
|
85
|
-
return dirname(resolve(configPath.startsWith("~") ? configPath.replace(/^~(?=$|[\\/])/, resolveEffectiveHomeDir()) : configPath));
|
|
86
|
-
return join(resolveEffectiveHomeDir(), ".openclaw");
|
|
87
|
-
}
|
|
88
|
-
export function resolveOpenClawConfigPath() {
|
|
89
|
-
const configPathOverride = (process.env.OPENCLAW_CONFIG_PATH ?? "").trim();
|
|
90
|
-
if (configPathOverride)
|
|
91
|
-
return resolveUserPath(configPathOverride);
|
|
92
|
-
return join(resolveStateDir(), "openclaw.json");
|
|
93
|
-
}
|
|
94
|
-
// ---------------------------------------------------------------------------
|
|
95
|
-
// Binary detection
|
|
96
|
-
// ---------------------------------------------------------------------------
|
|
97
|
-
const _binaryCache = new Map();
|
|
98
|
-
export function hasBinarySync(bin) {
|
|
99
|
-
const cached = _binaryCache.get(bin);
|
|
100
|
-
if (cached !== undefined)
|
|
101
|
-
return cached;
|
|
102
|
-
const delimiter = process.platform === "win32" ? ";" : ":";
|
|
103
|
-
const parts = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
104
|
-
const extensions = process.platform === "win32"
|
|
105
|
-
? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";")
|
|
106
|
-
: [""];
|
|
107
|
-
for (const part of parts) {
|
|
108
|
-
for (const ext of extensions) {
|
|
109
|
-
try {
|
|
110
|
-
accessSync(join(part, bin + ext), fsConstants.X_OK);
|
|
111
|
-
_binaryCache.set(bin, true);
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
catch { /* keep searching */ }
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
_binaryCache.set(bin, false);
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
// ---------------------------------------------------------------------------
|
|
121
|
-
// Bundled skills directory resolution
|
|
122
|
-
// ---------------------------------------------------------------------------
|
|
123
|
-
export function resolveBundledSkillsDir() {
|
|
124
|
-
const override = (process.env.OPENCLAW_BUNDLED_SKILLS_DIR ?? "").trim();
|
|
125
|
-
if (override)
|
|
126
|
-
return override;
|
|
127
|
-
const candidates = [];
|
|
128
|
-
// 1. Adjacent to node binary (nvm-style installs)
|
|
129
|
-
try {
|
|
130
|
-
candidates.push(join(dirname(process.execPath), "skills"));
|
|
131
|
-
}
|
|
132
|
-
catch { }
|
|
133
|
-
// 2. From argv[1] (openclaw.mjs inside gateway process)
|
|
134
|
-
try {
|
|
135
|
-
const argv1 = process.argv[1] ?? "";
|
|
136
|
-
if (argv1)
|
|
137
|
-
candidates.push(join(dirname(argv1), "skills"));
|
|
138
|
-
}
|
|
139
|
-
catch { }
|
|
140
|
-
// 3. Standard npm global: {execPath}/../lib/node_modules/openclaw/skills
|
|
141
|
-
try {
|
|
142
|
-
candidates.push(join(dirname(process.execPath), "..", "lib", "node_modules", "openclaw", "skills"));
|
|
143
|
-
}
|
|
144
|
-
catch { }
|
|
145
|
-
// 4. ~/.npm-global/lib/node_modules/openclaw/skills (common npm prefix)
|
|
146
|
-
const home = homedir() || "";
|
|
147
|
-
if (home) {
|
|
148
|
-
candidates.push(join(home, ".npm-global", "lib", "node_modules", "openclaw", "skills"));
|
|
149
|
-
}
|
|
150
|
-
// 5. Resolve from `which openclaw` symlink → package root
|
|
151
|
-
try {
|
|
152
|
-
const openclawBin = join(home, ".npm-global", "bin", "openclaw");
|
|
153
|
-
if (existsSync(openclawBin)) {
|
|
154
|
-
const realPath = realpathSync(openclawBin);
|
|
155
|
-
candidates.push(join(dirname(realPath), "skills"));
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
catch { }
|
|
159
|
-
// 6. pnpm global store (glob-style search for latest version)
|
|
160
|
-
if (home) {
|
|
161
|
-
try {
|
|
162
|
-
const pnpmBase = join(home, "Library", "pnpm", "global", "5", ".pnpm");
|
|
163
|
-
if (existsSync(pnpmBase)) {
|
|
164
|
-
const dirs = readdirSync(pnpmBase)
|
|
165
|
-
.filter(d => d.startsWith("openclaw@"))
|
|
166
|
-
.sort()
|
|
167
|
-
.reverse();
|
|
168
|
-
for (const d of dirs) {
|
|
169
|
-
candidates.push(join(pnpmBase, d, "node_modules", "openclaw", "skills"));
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
catch { }
|
|
174
|
-
}
|
|
175
|
-
for (const candidate of candidates) {
|
|
176
|
-
try {
|
|
177
|
-
if (existsSync(candidate))
|
|
178
|
-
return candidate;
|
|
179
|
-
}
|
|
180
|
-
catch { }
|
|
181
|
-
}
|
|
182
|
-
return undefined;
|
|
183
|
-
}
|
|
184
|
-
// ---------------------------------------------------------------------------
|
|
185
|
-
// Cron store path resolution
|
|
186
|
-
// ---------------------------------------------------------------------------
|
|
187
|
-
export function resolveCronStorePath(api) {
|
|
188
|
-
const home = homedir() || "";
|
|
189
|
-
const expandHome = (p) => p.startsWith("~/") || p === "~" ? join(home, p.slice(2)) : p;
|
|
190
|
-
// 1. OPENCLAW_STATE_DIR
|
|
191
|
-
const stateDir = (process.env.OPENCLAW_STATE_DIR ?? "").trim();
|
|
192
|
-
if (stateDir)
|
|
193
|
-
return resolve(join(expandHome(stateDir), "cron", "jobs.json"));
|
|
194
|
-
// 2. OPENCLAW_CONFIG_PATH
|
|
195
|
-
const configPath = (process.env.OPENCLAW_CONFIG_PATH ?? "").trim();
|
|
196
|
-
if (configPath)
|
|
197
|
-
return resolve(join(dirname(expandHome(configPath)), "cron", "jobs.json"));
|
|
198
|
-
// 3. cfg.cron?.store
|
|
199
|
-
const cfg = api.config ?? globalThis.__openimGatewayConfig ?? {};
|
|
200
|
-
const cfgStore = String(cfg?.cron?.store ?? "").trim();
|
|
201
|
-
if (cfgStore)
|
|
202
|
-
return resolve(expandHome(cfgStore));
|
|
203
|
-
// 4. Default
|
|
204
|
-
return join(home, ".openclaw", "cron", "jobs.json");
|
|
205
|
-
}
|
|
206
|
-
// ---------------------------------------------------------------------------
|
|
207
|
-
// ClawHub base URL resolution
|
|
208
|
-
// ---------------------------------------------------------------------------
|
|
209
|
-
export function resolveClawHubBaseUrl() {
|
|
210
|
-
return ((process.env.OPENCLAW_CLAWHUB_URL ?? "").trim() ||
|
|
211
|
-
(process.env.CLAWHUB_URL ?? "").trim() ||
|
|
212
|
-
"https://clawhub.ai").replace(/\/+$/, "");
|
|
213
|
-
}
|
|
214
|
-
// ---------------------------------------------------------------------------
|
|
215
|
-
// Full config from disk
|
|
216
|
-
// ---------------------------------------------------------------------------
|
|
217
|
-
let _diskConfigCache = null;
|
|
218
|
-
export function loadFullConfig() {
|
|
219
|
-
const configPath = resolveOpenClawConfigPath();
|
|
220
|
-
try {
|
|
221
|
-
const st = statSync(configPath);
|
|
222
|
-
if (_diskConfigCache && _diskConfigCache.mtimeMs === Math.floor(st.mtimeMs)) {
|
|
223
|
-
return _diskConfigCache.cfg;
|
|
224
|
-
}
|
|
225
|
-
const raw = readFileSync(configPath, "utf-8");
|
|
226
|
-
const cfg = JSON.parse(raw);
|
|
227
|
-
_diskConfigCache = { cfg, mtimeMs: Math.floor(st.mtimeMs) };
|
|
228
|
-
return cfg;
|
|
229
|
-
}
|
|
230
|
-
catch {
|
|
231
|
-
return {};
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
export function clearDiskConfigCache() {
|
|
235
|
-
_diskConfigCache = null;
|
|
236
|
-
}
|
|
237
|
-
// ---------------------------------------------------------------------------
|
|
238
|
-
// Env check for skill requirements
|
|
239
|
-
// ---------------------------------------------------------------------------
|
|
240
|
-
export function isEnvSatisfied(name, skillCfg, primaryEnv) {
|
|
241
|
-
return Boolean(process.env[name] || skillCfg?.env?.[name] ||
|
|
242
|
-
(skillCfg?.apiKey && primaryEnv === name));
|
|
243
|
-
}
|