clawflowbang 1.0.1 → 1.1.0

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.
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Register command - Register a local skill or agent via symlink
3
+ */
4
+
5
+ const chalk = require("chalk");
6
+ const fs = require("fs-extra");
7
+ const path = require("path");
8
+ const ClawFlow = require("../index");
9
+
10
+ module.exports = async function registerCommand(targetPath) {
11
+ const hub = new ClawFlow();
12
+ const sourcePath = path.resolve(process.cwd(), targetPath || ".");
13
+
14
+ console.log(chalk.cyan.bold("\n🏷️ ClawFlow Register\n"));
15
+
16
+ // 1. Verify source
17
+ const skillYaml = path.join(sourcePath, "skill.yaml");
18
+ const agentYaml = path.join(sourcePath, "agent.yaml");
19
+ const skillMd = path.join(sourcePath, "SKILL.md");
20
+
21
+ if (
22
+ !fs.existsSync(skillYaml) &&
23
+ !fs.existsSync(agentYaml) &&
24
+ !fs.existsSync(skillMd)
25
+ ) {
26
+ console.error(
27
+ chalk.red(
28
+ `❌ Error: No skill.yaml, agent.yaml, or SKILL.md found at ${sourcePath}`,
29
+ ),
30
+ );
31
+ console.log(
32
+ chalk.gray(
33
+ " Please make sure you are in the correct directory or provide a path.",
34
+ ),
35
+ );
36
+ process.exit(1);
37
+ }
38
+
39
+ const name = path.basename(sourcePath);
40
+ const skillsPath = hub.config.getSkillsPath();
41
+ const targetPathInWorkspace = path.join(skillsPath, name);
42
+
43
+ // 2. Register via symlink
44
+ try {
45
+ process.stdout.write(chalk.white(` Registering ${chalk.bold(name)}... `));
46
+
47
+ fs.ensureDirSync(path.dirname(targetPathInWorkspace));
48
+ if (fs.existsSync(targetPathInWorkspace)) {
49
+ // Check if it's already a symlink
50
+ const stats = fs.lstatSync(targetPathInWorkspace);
51
+ if (stats.isSymbolicLink()) {
52
+ fs.removeSync(targetPathInWorkspace);
53
+ } else {
54
+ const { overwrite } = await require("inquirer").prompt([
55
+ {
56
+ type: "confirm",
57
+ name: "overwrite",
58
+ message: `\n Directory ${name} already exists in skills workspace. Overwrite with symlink?`,
59
+ default: false,
60
+ },
61
+ ]);
62
+ if (!overwrite) {
63
+ console.log(chalk.yellow("\n Aborted."));
64
+ return;
65
+ }
66
+ fs.removeSync(targetPathInWorkspace);
67
+ }
68
+ }
69
+
70
+ fs.ensureSymlinkSync(sourcePath, targetPathInWorkspace, "junction");
71
+ process.stdout.write(chalk.green("✓\n"));
72
+
73
+ // 3. Verification
74
+ console.log(chalk.gray(` Path: ${targetPathInWorkspace}`));
75
+ console.log(chalk.green("\n✅ Successfully registered to OpenClaw!"));
76
+ console.log(chalk.white("\nNext steps:"));
77
+ console.log(chalk.gray(' - Run "clawflow status" to see your skill'));
78
+ console.log(chalk.gray(' - Use "clawflow cron-add" to schedule it\n'));
79
+ } catch (err) {
80
+ console.error(chalk.red("\n❌ Registration failed:"), err.message);
81
+ process.exit(1);
82
+ }
83
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Update command - Check for updates
3
+ */
4
+
5
+ const chalk = require("chalk");
6
+ const pkg = require("../../package.json");
7
+ const { execSync } = require("child_process");
8
+
9
+ module.exports = async function updateCommand() {
10
+ console.log(chalk.cyan.bold("\n🔄 Checking for ClawFlow updates...\n"));
11
+ console.log(chalk.gray(` Current version: ${pkg.version}`));
12
+
13
+ try {
14
+ const latest = execSync(`npm show ${pkg.name} version`, { stdio: "pipe" })
15
+ .toString()
16
+ .trim();
17
+
18
+ if (latest === pkg.version) {
19
+ console.log(chalk.green("✨ You are already using the latest version!"));
20
+ } else {
21
+ console.log(
22
+ chalk.yellow(`🚀 A new version is available: ${chalk.bold(latest)}`),
23
+ );
24
+ console.log(chalk.white("\nTo update, run:"));
25
+ console.log(chalk.cyan(` npm install -g ${pkg.name}`));
26
+ }
27
+ } catch (e) {
28
+ console.log(
29
+ chalk.red(
30
+ "❌ Failed to check for updates. Please check your internet connection.",
31
+ ),
32
+ );
33
+ }
34
+ console.log();
35
+ };
@@ -6,13 +6,13 @@ const fs = require('fs-extra');
6
6
  const path = require('path');
7
7
  const os = require('os');
8
8
 
9
- class ConfigManager {
10
- constructor(configPath = null, options = {}) {
11
- this.configPath = configPath || this.getDefaultConfigPath();
12
- this.overrides = options;
13
- this.config = null;
14
- this.ensureDirectories();
15
- }
9
+ class ConfigManager {
10
+ constructor(configPath = null, options = {}) {
11
+ this.configPath = configPath || this.getDefaultConfigPath();
12
+ this.overrides = options;
13
+ this.config = null;
14
+ this.ensureDirectories();
15
+ }
16
16
 
17
17
  /**
18
18
  * ได้รับ default config path ตาม OS
@@ -32,55 +32,55 @@ class ConfigManager {
32
32
  /**
33
33
  * สร้างโฟลเดอร์ที่จำเป็น
34
34
  */
35
- ensureDirectories() {
36
- const configFile = path.join(this.configPath, 'config.json');
37
- const defaultConfig = this.getDefaultConfig();
38
- const existingConfig = fs.existsSync(configFile) ? fs.readJsonSync(configFile) : {};
39
- const mergedConfig = this.applyOpenClawOverrides({
40
- ...defaultConfig,
41
- ...existingConfig,
42
- openclaw: {
43
- ...defaultConfig.openclaw,
44
- ...(existingConfig.openclaw || {}),
45
- },
46
- });
47
-
48
- const dirs = [
49
- this.configPath,
50
- path.dirname(mergedConfig.openclaw.skillsPath),
51
- mergedConfig.openclaw.skillsPath,
52
- path.dirname(mergedConfig.openclaw.cronJobsFile),
53
- path.join(this.configPath, 'logs'),
54
- path.join(this.configPath, 'packages'),
55
- ];
56
-
57
- dirs.forEach((dir) => {
58
- fs.ensureDirSync(dir);
59
- });
60
-
61
- if (!fs.existsSync(configFile) || JSON.stringify(existingConfig) !== JSON.stringify(mergedConfig)) {
62
- fs.writeJsonSync(configFile, mergedConfig, { spaces: 2 });
63
- }
64
- }
35
+ ensureDirectories() {
36
+ const configFile = path.join(this.configPath, 'config.json');
37
+ const defaultConfig = this.getDefaultConfig();
38
+ const existingConfig = fs.existsSync(configFile) ? fs.readJsonSync(configFile) : {};
39
+ const mergedConfig = this.applyOpenClawOverrides({
40
+ ...defaultConfig,
41
+ ...existingConfig,
42
+ openclaw: {
43
+ ...defaultConfig.openclaw,
44
+ ...(existingConfig.openclaw || {}),
45
+ },
46
+ });
47
+
48
+ const dirs = [
49
+ this.configPath,
50
+ path.dirname(mergedConfig.openclaw.skillsPath),
51
+ mergedConfig.openclaw.skillsPath,
52
+ path.dirname(mergedConfig.openclaw.cronJobsFile),
53
+ path.join(this.configPath, 'logs'),
54
+ path.join(this.configPath, 'packages'),
55
+ ];
56
+
57
+ dirs.forEach((dir) => {
58
+ fs.ensureDirSync(dir);
59
+ });
60
+
61
+ if (!fs.existsSync(configFile) || JSON.stringify(existingConfig) !== JSON.stringify(mergedConfig)) {
62
+ fs.writeJsonSync(configFile, mergedConfig, { spaces: 2 });
63
+ }
64
+ }
65
65
 
66
66
  /**
67
67
  * Config เริ่มต้น
68
68
  */
69
- getDefaultConfig() {
70
- const openclawHome = path.join(os.homedir(), '.openclaw');
71
- const workspacePath = path.join(openclawHome, 'workspace');
72
-
73
- return {
74
- version: '1.0.0',
75
- openclaw: {
76
- baseUrl: 'http://localhost:3000',
77
- apiKey: null,
78
- cliBin: 'openclaw',
79
- clawhubBin: 'clawhub',
80
- workspacePath,
81
- skillsPath: path.join(workspacePath, 'skills'),
82
- cronJobsFile: path.join(openclawHome, 'cron', 'jobs.json'),
83
- },
69
+ getDefaultConfig() {
70
+ const openclawHome = path.join(os.homedir(), '.openclaw');
71
+ const workspacePath = path.join(openclawHome, 'workspace');
72
+
73
+ return {
74
+ version: '1.0.0',
75
+ openclaw: {
76
+ baseUrl: 'http://localhost:18789',
77
+ apiKey: null,
78
+ cliBin: 'openclaw',
79
+ clawhubBin: 'clawhub',
80
+ workspacePath,
81
+ skillsPath: path.join(workspacePath, 'skills'),
82
+ cronJobsFile: path.join(openclawHome, 'cron', 'jobs.json'),
83
+ },
84
84
  registry: {
85
85
  url: 'https://registry.clawflowhub.dev',
86
86
  cacheExpiry: 3600, // วินาที
@@ -93,34 +93,34 @@ class ConfigManager {
93
93
  installed: {},
94
94
  crons: [],
95
95
  lastUpdate: null,
96
- };
97
- }
98
-
99
- applyOpenClawOverrides(config) {
100
- return {
101
- ...config,
102
- openclaw: {
103
- ...(config.openclaw || {}),
104
- ...(this.overrides.skillsPath ? { skillsPath: this.overrides.skillsPath } : {}),
105
- ...(this.overrides.cronJobsFile ? { cronJobsFile: this.overrides.cronJobsFile } : {}),
106
- ...(this.overrides.openclawBin ? { cliBin: this.overrides.openclawBin } : {}),
107
- ...(this.overrides.clawhubBin ? { clawhubBin: this.overrides.clawhubBin } : {}),
108
- },
109
- };
110
- }
96
+ };
97
+ }
98
+
99
+ applyOpenClawOverrides(config) {
100
+ return {
101
+ ...config,
102
+ openclaw: {
103
+ ...(config.openclaw || {}),
104
+ ...(this.overrides.skillsPath ? { skillsPath: this.overrides.skillsPath } : {}),
105
+ ...(this.overrides.cronJobsFile ? { cronJobsFile: this.overrides.cronJobsFile } : {}),
106
+ ...(this.overrides.openclawBin ? { cliBin: this.overrides.openclawBin } : {}),
107
+ ...(this.overrides.clawhubBin ? { clawhubBin: this.overrides.clawhubBin } : {}),
108
+ },
109
+ };
110
+ }
111
111
 
112
112
  /**
113
113
  * โหลด config
114
114
  */
115
- loadConfig() {
116
- const configFile = path.join(this.configPath, 'config.json');
117
- if (fs.existsSync(configFile)) {
118
- this.config = fs.readJsonSync(configFile);
119
- } else {
120
- this.config = this.applyOpenClawOverrides(this.getDefaultConfig());
121
- }
122
- return this.config;
123
- }
115
+ loadConfig() {
116
+ const configFile = path.join(this.configPath, 'config.json');
117
+ if (fs.existsSync(configFile)) {
118
+ this.config = fs.readJsonSync(configFile);
119
+ } else {
120
+ this.config = this.applyOpenClawOverrides(this.getDefaultConfig());
121
+ }
122
+ return this.config;
123
+ }
124
124
 
125
125
  /**
126
126
  * บันทึก config
@@ -172,25 +172,25 @@ class ConfigManager {
172
172
  /**
173
173
  * ดึง path ของ skills
174
174
  */
175
- getSkillsPath() {
176
- const config = this.getConfig();
177
- return config.openclaw?.skillsPath || path.join(this.configPath, 'skills');
178
- }
175
+ getSkillsPath() {
176
+ const config = this.getConfig();
177
+ return config.openclaw?.skillsPath || path.join(this.configPath, 'skills');
178
+ }
179
179
 
180
180
  /**
181
181
  * ดึง path ของ crons
182
182
  */
183
- getCronsPath() {
184
- return path.dirname(this.getCronJobsFilePath());
185
- }
186
-
187
- /**
188
- * ดึง path ของ cron jobs file
189
- */
190
- getCronJobsFilePath() {
191
- const config = this.getConfig();
192
- return config.openclaw?.cronJobsFile || path.join(this.configPath, 'crons', 'jobs.json');
193
- }
183
+ getCronsPath() {
184
+ return path.dirname(this.getCronJobsFilePath());
185
+ }
186
+
187
+ /**
188
+ * ดึง path ของ cron jobs file
189
+ */
190
+ getCronJobsFilePath() {
191
+ const config = this.getConfig();
192
+ return config.openclaw?.cronJobsFile || path.join(this.configPath, 'crons', 'jobs.json');
193
+ }
194
194
 
195
195
  /**
196
196
  * ดึง path ของ logs
@@ -235,16 +235,16 @@ class ConfigManager {
235
235
  /**
236
236
  * เพิ่ม cronjob
237
237
  */
238
- addCron(cronInfo) {
239
- const config = this.getConfig();
240
- if (!config.crons) {
241
- config.crons = [];
242
- }
243
- config.crons.push({
244
- id: cronInfo.id || Date.now().toString(),
245
- ...cronInfo,
246
- createdAt: new Date().toISOString(),
247
- });
238
+ addCron(cronInfo) {
239
+ const config = this.getConfig();
240
+ if (!config.crons) {
241
+ config.crons = [];
242
+ }
243
+ config.crons.push({
244
+ id: cronInfo.id || Date.now().toString(),
245
+ ...cronInfo,
246
+ createdAt: new Date().toISOString(),
247
+ });
248
248
  this.saveConfig();
249
249
  return config.crons[config.crons.length - 1];
250
250
  }
@@ -252,37 +252,37 @@ class ConfigManager {
252
252
  /**
253
253
  * ลบ cronjob
254
254
  */
255
- removeCron(cronId) {
256
- const config = this.getConfig();
257
- if (config.crons) {
258
- config.crons = config.crons.filter(cron => cron.id !== cronId);
259
- this.saveConfig();
260
- }
261
- }
262
-
263
- /**
264
- * แก้ไข cronjob
265
- */
266
- updateCron(cronId, patch = {}) {
267
- const config = this.getConfig();
268
- if (!config.crons) {
269
- return null;
270
- }
271
-
272
- const idx = config.crons.findIndex((c) => c.id === cronId);
273
- if (idx === -1) {
274
- return null;
275
- }
276
-
277
- config.crons[idx] = {
278
- ...config.crons[idx],
279
- ...patch,
280
- updatedAt: new Date().toISOString(),
281
- };
282
- this.saveConfig();
283
-
284
- return config.crons[idx];
285
- }
255
+ removeCron(cronId) {
256
+ const config = this.getConfig();
257
+ if (config.crons) {
258
+ config.crons = config.crons.filter(cron => cron.id !== cronId);
259
+ this.saveConfig();
260
+ }
261
+ }
262
+
263
+ /**
264
+ * แก้ไข cronjob
265
+ */
266
+ updateCron(cronId, patch = {}) {
267
+ const config = this.getConfig();
268
+ if (!config.crons) {
269
+ return null;
270
+ }
271
+
272
+ const idx = config.crons.findIndex((c) => c.id === cronId);
273
+ if (idx === -1) {
274
+ return null;
275
+ }
276
+
277
+ config.crons[idx] = {
278
+ ...config.crons[idx],
279
+ ...patch,
280
+ updatedAt: new Date().toISOString(),
281
+ };
282
+ this.saveConfig();
283
+
284
+ return config.crons[idx];
285
+ }
286
286
 
287
287
  /**
288
288
  * ดึงรายการ cronjobs