mycohive-claw 4.0.1 → 4.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mycohive-claw",
3
- "version": "4.0.1",
3
+ "version": "4.0.3",
4
4
  "description": "OpenClaw Plugin for Multi-Agent Orchestration with LLM Intent Routing",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -29,7 +29,7 @@
29
29
  "build": "tsc",
30
30
  "dev": "tsc --watch",
31
31
  "typecheck": "tsc --noEmit",
32
- "postinstall": "node scripts/postinstall.js"
32
+ "postinstall": "node scripts/postinstall.cjs"
33
33
  },
34
34
  "openclaw": {
35
35
  "extensions": [
@@ -0,0 +1,192 @@
1
+ /**
2
+ * postinstall.cjs
3
+ * Version: 4.0.0
4
+ *
5
+ * Auto-register plugin after npm install.
6
+ * No manual configuration needed.
7
+ */
8
+
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+ const { execSync } = require("child_process");
12
+
13
+ // Find OpenClaw config path
14
+ function findOpenClawConfig() {
15
+ const candidates = [
16
+ // Linux/macOS
17
+ path.join(process.env.HOME || "", ".openclaw", "config.yml"),
18
+ path.join(process.env.HOME || "", ".openclaw", "config.yaml"),
19
+ path.join(process.env.HOME || "", ".config", "openclaw", "config.yml"),
20
+ path.join(process.env.HOME || "", ".config", "openclaw", "config.yaml"),
21
+ // Windows
22
+ path.join(process.env.APPDATA || "", "openclaw", "config.yml"),
23
+ path.join(process.env.APPDATA || "", "openclaw", "config.yaml"),
24
+ path.join(process.env.USERPROFILE || "", ".openclaw", "config.yml"),
25
+ path.join(process.env.USERPROFILE || "", ".openclaw", "config.yaml"),
26
+ // Server/container
27
+ "/etc/openclaw/config.yml",
28
+ "/etc/openclaw/config.yaml",
29
+ // Local project
30
+ ".openclaw.yml",
31
+ ".openclaw.yaml",
32
+ "openclaw.config.yml",
33
+ "openclaw.config.yaml",
34
+ ];
35
+
36
+ for (const p of candidates) {
37
+ if (fs.existsSync(p)) return p;
38
+ }
39
+ return null;
40
+ }
41
+
42
+ // Try CLI to get config path
43
+ function findViaCLI() {
44
+ try {
45
+ const out = execSync(
46
+ "openclaw config 2>/dev/null || openclaw info 2>/dev/null || echo NOT_FOUND",
47
+ { encoding: "utf-8", timeout: 5000 }
48
+ );
49
+ const lines = out.split("\n");
50
+ for (const line of lines) {
51
+ const match = line.match(/[\/\\]?[\w\-\\/.]+\.ya?ml/);
52
+ if (match && fs.existsSync(match[0])) return match[0];
53
+ }
54
+ } catch { /* ignore */ }
55
+ return null;
56
+ }
57
+
58
+ // Minimal YAML parser (no external deps)
59
+ function parseYaml(content) {
60
+ const result = {};
61
+ const lines = content.split("\n");
62
+ let currentSection = null;
63
+ let sectionIndent = 0;
64
+
65
+ for (let rawLine of lines) {
66
+ const line = rawLine.replace(/#[^\n]*$/, "").trimEnd();
67
+ if (!line) continue;
68
+
69
+ const indent = line.search(/\S/);
70
+ const isArrayItem = line.trimStart().startsWith("- ");
71
+
72
+ if (indent === 0) {
73
+ const colonIdx = line.indexOf(":");
74
+ if (colonIdx <= 0) continue;
75
+ const key = line.slice(0, colonIdx).trim();
76
+ const val = line.slice(colonIdx + 1).trim();
77
+ if (val === "" || val === "|" || val === ">") {
78
+ currentSection = key;
79
+ sectionIndent = 0;
80
+ result[key] = {};
81
+ } else {
82
+ result[key] = val.replace(/^["']|["']$/g, "");
83
+ currentSection = null;
84
+ }
85
+ } else if (indent > sectionIndent && currentSection && typeof result[currentSection] === "object") {
86
+ const colonIdx = line.indexOf(":");
87
+ if (colonIdx <= 0) continue;
88
+ const key = line.trimStart().slice(0, colonIdx - indent).trim();
89
+ const val = line.slice(colonIdx + 1).trim();
90
+ if (isArrayItem) {
91
+ if (!Array.isArray(result[currentSection][key])) {
92
+ result[currentSection][key] = [];
93
+ }
94
+ if (val) result[currentSection][key].push(val.replace(/^["']|["']$/g, ""));
95
+ } else if (val === "" || val === "|" || val === ">") {
96
+ result[currentSection][key] = {};
97
+ } else {
98
+ result[currentSection][key] = val.replace(/^["']|["']$/g, "");
99
+ }
100
+ }
101
+ }
102
+ return result;
103
+ }
104
+
105
+ // Serialize to YAML
106
+ function toYaml(obj, indent = 0) {
107
+ const sp = " ".repeat(indent);
108
+ let out = "";
109
+ for (const [k, v] of Object.entries(obj)) {
110
+ if (v === null || v === undefined) continue;
111
+ if (typeof v === "object" && !Array.isArray(v)) {
112
+ out += `${sp}${k}:\n${toYaml(v, indent + 1)}`;
113
+ } else if (Array.isArray(v)) {
114
+ out += `${sp}${k}:\n`;
115
+ for (const item of v) {
116
+ if (typeof item === "object") {
117
+ const inner = toYaml(item, indent + 2);
118
+ out += `${sp} -\n${inner}`;
119
+ } else {
120
+ out += `${sp} - ${item}\n`;
121
+ }
122
+ }
123
+ } else {
124
+ out += `${sp}${k}: ${v}\n`;
125
+ }
126
+ }
127
+ return out;
128
+ }
129
+
130
+ function main() {
131
+ console.log("[MycoHive-Claw] postinstall running...");
132
+
133
+ const packageDir = path.resolve(__dirname, "..");
134
+ const distIndex = path.join(packageDir, "dist", "index.js");
135
+
136
+ if (!fs.existsSync(distIndex)) {
137
+ console.warn("[MycoHive-Claw] dist/index.js not found, skipping");
138
+ return;
139
+ }
140
+
141
+ // Find config
142
+ let configPath = findViaCLI() || findOpenClawConfig();
143
+
144
+ if (!configPath) {
145
+ // Create default config
146
+ console.log("[MycoHive-Claw] Creating default config...");
147
+ const openclawDir = path.join(process.env.HOME || ".", ".openclaw");
148
+ configPath = path.join(openclawDir, "config.yml");
149
+ try {
150
+ fs.mkdirSync(openclawDir, { recursive: true });
151
+ const defaultConfig = {
152
+ plugins: {
153
+ entries: {},
154
+ allow: ["restart"],
155
+ },
156
+ };
157
+ defaultConfig.plugins.entries.mycohive = { path: packageDir, enabled: true };
158
+ fs.writeFileSync(configPath, toYaml(defaultConfig), "utf-8");
159
+ console.log(`[MycoHive-Claw] Created: ${configPath}`);
160
+ } catch (err) {
161
+ console.error(`[MycoHive-Claw] Create failed: ${err.message}`);
162
+ }
163
+ return;
164
+ }
165
+
166
+ // Read and update existing config
167
+ try {
168
+ const raw = fs.readFileSync(configPath, "utf-8");
169
+ const config = parseYaml(raw);
170
+
171
+ // Init plugins section
172
+ if (!config.plugins) config.plugins = {};
173
+ if (!config.plugins.entries) config.plugins.entries = {};
174
+ if (!config.plugins.allow) config.plugins.allow = [];
175
+
176
+ // Register plugin
177
+ config.plugins.entries.mycohive = { path: packageDir, enabled: true };
178
+
179
+ // Add "restart" to allow list so openclaw restart works
180
+ if (!config.plugins.allow.includes("restart")) {
181
+ config.plugins.allow.push("restart");
182
+ }
183
+
184
+ fs.writeFileSync(configPath, toYaml(config), "utf-8");
185
+ console.log(`[MycoHive-Claw] Registered in: ${configPath}`);
186
+ console.log("[MycoHive-Claw] Run 'openclaw restart' to load the plugin");
187
+ } catch (err) {
188
+ console.error(`[MycoHive-Claw] Update failed: ${err.message}`);
189
+ }
190
+ }
191
+
192
+ main();
@@ -1,235 +0,0 @@
1
- /**
2
- * postinstall.js
3
- * 版本: v4.0.0
4
- *
5
- * npm install 后自动执行:检测 OpenClaw 配置并注册插件。
6
- * 目标:实现安装后即用,无需手动配置。
7
- */
8
-
9
- const fs = require("fs");
10
- const path = require("path");
11
-
12
- // 尝试找到 OpenClaw 配置目录
13
- function findOpenClawConfig() {
14
- const possiblePaths = [
15
- // Linux/macOS 全局
16
- path.join(process.env.HOME || "", ".openclaw", "config.yml"),
17
- path.join(process.env.HOME || "", ".openclaw", "config.yaml"),
18
- path.join(process.env.HOME || "", ".config", "openclaw", "config.yml"),
19
- path.join(process.env.HOME || "", ".config", "openclaw", "config.yaml"),
20
- // Windows
21
- path.join(process.env.APPDATA || "", "openclaw", "config.yml"),
22
- path.join(process.env.APPDATA || "", "openclaw", "config.yaml"),
23
- path.join(process.env.USERPROFILE || "", ".openclaw", "config.yml"),
24
- path.join(process.env.USERPROFILE || "", ".openclaw", "config.yaml"),
25
- // 容器/服务端
26
- "/etc/openclaw/config.yml",
27
- "/etc/openclaw/config.yaml",
28
- // 本地项目
29
- ".openclaw.yml",
30
- ".openclaw.yaml",
31
- "openclaw.config.yml",
32
- "openclaw.config.yaml",
33
- ];
34
-
35
- for (const p of possiblePaths) {
36
- if (fs.existsSync(p)) {
37
- return p;
38
- }
39
- }
40
- return null;
41
- }
42
-
43
- // 尝试通过 openclaw CLI 查找配置路径
44
- function findOpenClawConfigViaCLI() {
45
- try {
46
- const { execSync } = require("child_process");
47
- // 尝试获取 openclaw 配置路径
48
- const out = execSync("openclaw config 2>/dev/null || openclaw info 2>/dev/null || echo NOT_FOUND", {
49
- encoding: "utf-8",
50
- timeout: 5000,
51
- });
52
- const lines = out.split("\n");
53
- for (const line of lines) {
54
- if (line.includes("config") || line.includes("Config") || line.includes(".yml") || line.includes(".yaml")) {
55
- const match = line.match(/[\/\\]?[\w\-\\/.]+\.ya?ml/);
56
- if (match && fs.existsSync(match[0])) {
57
- return match[0];
58
- }
59
- }
60
- }
61
- } catch {
62
- // CLI 不可用或超时,忽略
63
- }
64
- return null;
65
- }
66
-
67
- // 解析 YAML(简化版,不依赖外部库)
68
- function parseYaml(content) {
69
- const result = {};
70
- const lines = content.split("\n");
71
- let currentKey = null;
72
- let indent = 0;
73
-
74
- for (let line of lines) {
75
- // 移除行尾注释
76
- line = line.replace(/\s*#.*$/, "").trimRight();
77
- if (!line || line.startsWith("#")) continue;
78
-
79
- const lineIndent = line.search(/\S/);
80
- const isArrayItem = line.trimStart().startsWith("- ");
81
-
82
- if (lineIndent === 0) {
83
- const colonIdx = line.indexOf(":");
84
- if (colonIdx > 0) {
85
- const key = line.slice(0, colonIdx).trim();
86
- const value = line.slice(colonIdx + 1).trim();
87
- if (value === "" || value === "|" || value === ">") {
88
- currentKey = key;
89
- indent = lineIndent;
90
- if (!result[key]) result[key] = {};
91
- } else {
92
- result[key] = value.replace(/^["']|["']$/g, "");
93
- currentKey = null;
94
- }
95
- }
96
- } else if (lineIndent > indent && currentKey && typeof result[currentKey] === "object") {
97
- const colonIdx = line.indexOf(":");
98
- if (colonIdx > 0) {
99
- const key = line.slice(lineIndent).slice(0, colonIdx - lineIndent).trim();
100
- const value = line.slice(colonIdx + 1).trim();
101
- if (value === "" || value === "|" || value === ">") {
102
- result[currentKey][key] = {};
103
- } else {
104
- result[currentKey][key] = value.replace(/^["']|["']$/g, "");
105
- }
106
- }
107
- }
108
- }
109
- return result;
110
- }
111
-
112
- // 序列化回 YAML
113
- function toYaml(obj, indent = 0) {
114
- const spaces = " ".repeat(indent);
115
- let out = "";
116
-
117
- for (const [key, value] of Object.entries(obj)) {
118
- if (value === null || value === undefined) continue;
119
-
120
- if (typeof value === "object" && !Array.isArray(value)) {
121
- out += `${spaces}${key}:\n${toYaml(value, indent + 1)}`;
122
- } else if (Array.isArray(value)) {
123
- out += `${spaces}${key}:\n`;
124
- for (const item of value) {
125
- if (typeof item === "object") {
126
- out += `${spaces} -\n${toYaml(item, indent + 2)}`;
127
- } else {
128
- out += `${spaces} - ${item}\n`;
129
- }
130
- }
131
- } else {
132
- out += `${spaces}${key}: ${value}\n`;
133
- }
134
- }
135
- return out;
136
- }
137
-
138
- // 在配置对象中插入插件配置
139
- function injectPluginConfig(config, pluginPath) {
140
- const pluginName = "mycohive";
141
-
142
- // 确保 plugins 存在
143
- if (!config.plugins) config.plugins = {};
144
- if (!config.plugins.entries) config.plugins.entries = {};
145
-
146
- // 注入插件配置
147
- config.plugins.entries[pluginName] = {
148
- path: pluginPath,
149
- enabled: true,
150
- };
151
-
152
- // 确保 plugins.allow 包含必要权限
153
- if (!config.plugins.allow) {
154
- config.plugins.allow = [];
155
- }
156
- const requiredAllows = ["restart"];
157
- for (const perm of requiredAllows) {
158
- if (!config.plugins.allow.includes(perm)) {
159
- config.plugins.allow.push(perm);
160
- }
161
- }
162
-
163
- return config;
164
- }
165
-
166
- // 写入配置文件
167
- function writeConfig(configPath, config) {
168
- const yaml = toYaml(config);
169
- fs.writeFileSync(configPath, yaml, "utf-8");
170
- }
171
-
172
- async function main() {
173
- console.log("[MycoHive-Claw] Running postinstall...");
174
-
175
- // 找到当前包的位置
176
- const packageDir = path.resolve(__dirname, "..");
177
- const distIndex = path.join(packageDir, "dist", "index.js");
178
-
179
- if (!fs.existsSync(distIndex)) {
180
- console.warn("[MycoHive-Claw] dist/index.js not found, skipping auto-config (run npm build first)");
181
- return;
182
- }
183
-
184
- // 1. 查找 OpenClaw 配置
185
- let configPath = findOpenClawConfigViaCLI() || findOpenClawConfig();
186
-
187
- if (!configPath) {
188
- console.log("[MycoHive-Claw] OpenClaw config not found, creating default config...");
189
-
190
- // 创建默认配置目录和文件
191
- const openclawDir = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".openclaw");
192
- configPath = path.join(openclawDir, "config.yml");
193
-
194
- try {
195
- if (!fs.existsSync(openclawDir)) {
196
- fs.mkdirSync(openclawDir, { recursive: true });
197
- }
198
-
199
- const defaultConfig = {
200
- plugins: {
201
- entries: {},
202
- allow: ["restart"],
203
- },
204
- };
205
- injectPluginConfig(defaultConfig, packageDir);
206
- writeConfig(configPath, defaultConfig);
207
- console.log(`[MycoHive-Claw] Created default config at: ${configPath}`);
208
- console.log("[MycoHive-Claw] Run 'openclaw restart' to load the plugin");
209
- } catch (err) {
210
- console.error("[MycoHive-Claw] Failed to create config:", err.message);
211
- }
212
- return;
213
- }
214
-
215
- // 2. 读取现有配置
216
- try {
217
- const content = fs.readFileSync(configPath, "utf-8");
218
- let config = parseYaml(content);
219
-
220
- if (Object.keys(config).length === 0) {
221
- // 解析失败,使用空配置
222
- config = { plugins: { entries: {}, allow: [] } };
223
- }
224
-
225
- injectPluginConfig(config, packageDir);
226
- writeConfig(configPath, config);
227
-
228
- console.log(`[MycoHive-Claw] Plugin registered in: ${configPath}`);
229
- console.log("[MycoHive-Claw] Run 'openclaw restart' to load the plugin, or it will auto-load on next start");
230
- } catch (err) {
231
- console.error("[MycoHive-Claw] Failed to update config:", err.message);
232
- }
233
- }
234
-
235
- main().catch(console.error);