clawflowbang 1.0.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.
package/.eslintrc.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "root": true,
3
+ "env": {
4
+ "node": true,
5
+ "es2021": true
6
+ },
7
+ "extends": [
8
+ "eslint:recommended"
9
+ ],
10
+ "parserOptions": {
11
+ "ecmaVersion": 12
12
+ },
13
+ "ignorePatterns": [
14
+ "node_modules/",
15
+ "coverage/"
16
+ ],
17
+ "rules": {
18
+ "no-console": "off",
19
+ "no-unused-vars": [
20
+ "warn",
21
+ {
22
+ "argsIgnorePattern": "^_",
23
+ "varsIgnorePattern": "^_"
24
+ }
25
+ ]
26
+ },
27
+ "overrides": [
28
+ {
29
+ "files": [
30
+ "**/*.test.js",
31
+ "__tests__/**/*.js"
32
+ ],
33
+ "env": {
34
+ "jest": true
35
+ }
36
+ }
37
+ ]
38
+ }
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # ClawFlow
@@ -0,0 +1,52 @@
1
+ const fs = require('fs-extra');
2
+ const os = require('os');
3
+ const path = require('path');
4
+ const ConfigManager = require('../src/core/ConfigManager');
5
+
6
+ function makeTempDir(prefix) {
7
+ return fs.mkdtempSync(path.join(os.tmpdir(), prefix));
8
+ }
9
+
10
+ describe('ConfigManager', () => {
11
+ test('applies path and bin overrides into openclaw config', () => {
12
+ const configDir = makeTempDir('cfh-config-');
13
+ const skillsPath = path.join(configDir, 'custom-skills');
14
+ const cronJobsFile = path.join(configDir, 'custom-cron', 'jobs.json');
15
+
16
+ const manager = new ConfigManager(configDir, {
17
+ skillsPath,
18
+ cronJobsFile,
19
+ openclawBin: '/usr/local/bin/openclaw',
20
+ clawhubBin: '/usr/local/bin/clawhub',
21
+ });
22
+
23
+ const config = manager.getConfig();
24
+ expect(config.openclaw.skillsPath).toBe(skillsPath);
25
+ expect(config.openclaw.cronJobsFile).toBe(cronJobsFile);
26
+ expect(config.openclaw.cliBin).toBe('/usr/local/bin/openclaw');
27
+ expect(config.openclaw.clawhubBin).toBe('/usr/local/bin/clawhub');
28
+ expect(manager.getCronJobsFilePath()).toBe(cronJobsFile);
29
+ });
30
+
31
+ test('addCron preserves provided id and updateCron mutates fields', () => {
32
+ const configDir = makeTempDir('cfh-config-');
33
+ const manager = new ConfigManager(configDir);
34
+
35
+ manager.addCron({
36
+ id: 'job-123',
37
+ skill: 'crypto-price',
38
+ schedule: '*/5 * * * *',
39
+ });
40
+
41
+ const updated = manager.updateCron('job-123', {
42
+ schedule: '0 * * * *',
43
+ description: 'hourly',
44
+ });
45
+
46
+ expect(updated).toBeTruthy();
47
+ expect(updated.id).toBe('job-123');
48
+ expect(updated.schedule).toBe('0 * * * *');
49
+ expect(updated.description).toBe('hourly');
50
+ expect(updated.updatedAt).toBeTruthy();
51
+ });
52
+ });
@@ -0,0 +1,26 @@
1
+ const { normalizeCronExpression } = require('../src/core/CronFormat');
2
+
3
+ describe('CronFormat.normalizeCronExpression', () => {
4
+ test('accepts valid cron expressions as-is', () => {
5
+ expect(normalizeCronExpression('*/5 * * * *')).toBe('*/5 * * * *');
6
+ });
7
+
8
+ test('normalizes preset aliases', () => {
9
+ expect(normalizeCronExpression('@daily')).toBe('0 0 * * *');
10
+ expect(normalizeCronExpression('@hourly')).toBe('0 * * * *');
11
+ });
12
+
13
+ test('normalizes shorthand durations', () => {
14
+ expect(normalizeCronExpression('15m')).toBe('*/15 * * * *');
15
+ expect(normalizeCronExpression('every 2h')).toBe('0 */2 * * *');
16
+ expect(normalizeCronExpression('1d')).toBe('0 0 */1 * *');
17
+ });
18
+
19
+ test('throws on invalid cron expressions', () => {
20
+ expect(() => normalizeCronExpression('abc def')).toThrow(/ไม่ถูกต้อง/);
21
+ });
22
+
23
+ test('throws on unsupported duration shorthands', () => {
24
+ expect(() => normalizeCronExpression('70m')).toThrow(/ไม่รองรับ/);
25
+ });
26
+ });
@@ -0,0 +1,65 @@
1
+ const fs = require('fs-extra');
2
+ const os = require('os');
3
+ const path = require('path');
4
+ const ConfigManager = require('../src/core/ConfigManager');
5
+ const CronManager = require('../src/core/CronManager');
6
+
7
+ function makeTempDir(prefix) {
8
+ return fs.mkdtempSync(path.join(os.tmpdir(), prefix));
9
+ }
10
+
11
+ describe('CronManager local mode', () => {
12
+ test('add/edit/list/remove lifecycle works with normalized schedules', async () => {
13
+ const root = makeTempDir('cfh-cron-');
14
+ const configPath = path.join(root, 'config');
15
+ const cronJobsFile = path.join(root, 'cron', 'jobs.json');
16
+
17
+ const configManager = new ConfigManager(configPath, {
18
+ cronJobsFile,
19
+ openclawBin: 'notfound-openclaw',
20
+ });
21
+ const cronManager = new CronManager(configManager);
22
+
23
+ expect(cronManager.useOpenClawCron).toBe(false);
24
+
25
+ const added = await cronManager.add('smoke-skill', 'every 15m', { foo: 'bar' }, 'demo');
26
+ expect(added.id).toBeTruthy();
27
+ expect(added.schedule).toBe('*/15 * * * *');
28
+
29
+ const listed = cronManager.list();
30
+ expect(listed).toHaveLength(1);
31
+ expect(listed[0].schedule).toBe('*/15 * * * *');
32
+
33
+ const edited = await cronManager.edit(added.id, {
34
+ schedule: '@daily',
35
+ description: 'daily run',
36
+ params: { foo: 'baz' },
37
+ });
38
+ expect(edited.schedule).toBe('0 0 * * *');
39
+ expect(edited.description).toBe('daily run');
40
+ expect(edited.params).toEqual({ foo: 'baz' });
41
+
42
+ const listedAfterEdit = cronManager.list();
43
+ expect(listedAfterEdit).toHaveLength(1);
44
+ expect(listedAfterEdit[0].schedule).toBe('0 0 * * *');
45
+
46
+ await cronManager.remove(added.id);
47
+ expect(cronManager.list()).toEqual([]);
48
+
49
+ cronManager.stopAll();
50
+ });
51
+
52
+ test('rejects invalid schedules', async () => {
53
+ const root = makeTempDir('cfh-cron-');
54
+ const configPath = path.join(root, 'config');
55
+ const cronJobsFile = path.join(root, 'cron', 'jobs.json');
56
+
57
+ const configManager = new ConfigManager(configPath, {
58
+ cronJobsFile,
59
+ openclawBin: 'notfound-openclaw',
60
+ });
61
+ const cronManager = new CronManager(configManager);
62
+
63
+ await expect(cronManager.add('smoke-skill', 'wrong schedule', {})).rejects.toThrow(/ไม่ถูกต้อง/);
64
+ });
65
+ });
@@ -0,0 +1,51 @@
1
+ const OpenClawCLI = require('../src/core/OpenClawCLI');
2
+
3
+ function createCli() {
4
+ return new OpenClawCLI({
5
+ getConfig() {
6
+ return {
7
+ openclaw: {
8
+ cliBin: 'openclaw',
9
+ clawhubBin: 'clawhub',
10
+ },
11
+ };
12
+ },
13
+ });
14
+ }
15
+
16
+ describe('OpenClawCLI git fallback helpers', () => {
17
+ test('resolveGitRepository from explicit fields', () => {
18
+ const cli = createCli();
19
+ expect(
20
+ cli.resolveGitRepository({
21
+ name: 'crypto-price',
22
+ repository: 'https://github.com/acme/crypto-price.git',
23
+ }),
24
+ ).toBe('https://github.com/acme/crypto-price.git');
25
+ });
26
+
27
+ test('resolveGitRepository from github source + owner/repo name', () => {
28
+ const cli = createCli();
29
+ expect(
30
+ cli.resolveGitRepository({
31
+ source: 'github',
32
+ name: 'acme/my-skill',
33
+ }),
34
+ ).toBe('https://github.com/acme/my-skill.git');
35
+ });
36
+
37
+ test('resolveSkillDirName from url and scoped names', () => {
38
+ const cli = createCli();
39
+ expect(
40
+ cli.resolveSkillDirName({
41
+ name: 'https://github.com/acme/skill-x.git',
42
+ }),
43
+ ).toBe('skill-x');
44
+
45
+ expect(
46
+ cli.resolveSkillDirName({
47
+ name: 'acme/skill-y',
48
+ }),
49
+ ).toBe('skill-y');
50
+ });
51
+ });
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { program } = require('commander');
4
+ const chalk = require('chalk');
5
+ const pkg = require('../package.json');
6
+
7
+ // Import commands
8
+ const installCommand = require('../src/commands/install');
9
+ const listCommand = require('../src/commands/list');
10
+ const removeCommand = require('../src/commands/remove');
11
+ const cronCommand = require('../src/commands/cron');
12
+ const statusCommand = require('../src/commands/status');
13
+ const initCommand = require('../src/commands/init');
14
+ const searchCommand = require('../src/commands/search');
15
+
16
+ // Banner
17
+ console.log(chalk.cyan.bold(`
18
+ ╔══════════════════════════════════════════════════════════╗
19
+ ║ ║
20
+ ║ 🐾 ${chalk.white.bold('ClawFlow')} - Skill & Cron Installer for OpenClaw ║
21
+ ║ ║
22
+ ║ ${chalk.gray('ติดตั้ง skill พร้อมตั้งค่าใช้งานทันที')} ║
23
+ ║ ║
24
+ ╚══════════════════════════════════════════════════════════╝
25
+ `));
26
+
27
+ program
28
+ .name('clawflow')
29
+ .description('ติดตั้ง OpenClaw skills พร้อม cronjob ให้พร้อมใช้งาน')
30
+ .version(pkg.version, '-v, --version', 'แสดงเวอร์ชัน');
31
+
32
+ // Install command
33
+ program
34
+ .command('install <package>')
35
+ .alias('i')
36
+ .description('ติดตั้ง package พร้อม skills และ cronjobs')
37
+ .option('-g, --global', 'ติดตั้งแบบ global')
38
+ .option('-c, --config <path>', 'ระบุ path ของ config file')
39
+ .option('--skills-path <path>', 'ระบุ path ของ OpenClaw workspace skills')
40
+ .option('--cron-jobs <path>', 'ระบุ path ของ OpenClaw cron jobs.json')
41
+ .option('--openclaw-bin <path>', 'ระบุ binary ของ openclaw CLI')
42
+ .option('--clawhub-bin <path>', 'ระบุ binary ของ clawhub CLI')
43
+ .option('--no-cron', 'ติดตั้ง skill โดยไม่ตั้ง cronjob')
44
+ .option('--dry-run', 'แสดงว่าจะทำอะไรบ้างโดยไม่ติดตั้งจริง')
45
+ .action(installCommand);
46
+
47
+ // List command
48
+ program
49
+ .command('list')
50
+ .alias('ls')
51
+ .description('แสดงรายการ packages และ skills ที่ติดตั้ง')
52
+ .option('-a, --available', 'แสดง packages ที่สามารถติดตั้งได้')
53
+ .option('-i, --installed', 'แสดง packages ที่ติดตั้งแล้ว (default)')
54
+ .option('--npm', 'รวม packages จาก npm registry (ใช้กับ --available)')
55
+ .action(listCommand);
56
+
57
+ // Search command
58
+ program
59
+ .command('search <query>')
60
+ .alias('find')
61
+ .description('ค้นหา packages ใน registry')
62
+ .option('--no-npm', 'ไม่รวมผลลัพธ์จาก npm registry')
63
+ .action(searchCommand);
64
+
65
+ // Remove command
66
+ program
67
+ .command('remove <package>')
68
+ .alias('rm')
69
+ .description('ถอนการติดตั้ง package')
70
+ .option('-g, --global', 'ถอนการติดตั้งแบบ global')
71
+ .option('--keep-config', 'เก็บ config file ไว้')
72
+ .action(removeCommand);
73
+
74
+ // Cron command group
75
+ program
76
+ .command('cron-list')
77
+ .description('แสดงรายการ cronjobs ทั้งหมด')
78
+ .action(cronCommand.list);
79
+
80
+ program
81
+ .command('cron-add <skill>')
82
+ .description('เพิ่ม cronjob สำหรับ skill')
83
+ .option('-s, --schedule <expression>', 'cron schedule expression', '*/5 * * * *')
84
+ .option('-e, --every <duration>', 'รูปแบบย่อ เช่น 5m, 1h, 2d')
85
+ .option('-d, --description <text>', 'คำอธิบาย cronjob')
86
+ .option('-p, --params <json>', 'parameters สำหรับ skill')
87
+ .action(cronCommand.add);
88
+
89
+ program
90
+ .command('cron-edit <id>')
91
+ .description('แก้ไข cronjob')
92
+ .option('-s, --schedule <expression>', 'cron schedule expression ใหม่')
93
+ .option('-e, --every <duration>', 'รูปแบบย่อ เช่น 5m, 1h, 2d')
94
+ .option('-d, --description <text>', 'คำอธิบายใหม่')
95
+ .option('-p, --params <json>', 'parameters ใหม่ของ skill')
96
+ .action(cronCommand.edit);
97
+
98
+ program
99
+ .command('cron-remove <id>')
100
+ .description('ลบ cronjob')
101
+ .action(cronCommand.remove);
102
+
103
+ // Status command
104
+ program
105
+ .command('status')
106
+ .description('แสดงสถานะระบบ')
107
+ .action(statusCommand);
108
+
109
+ // Init command
110
+ program
111
+ .command('init')
112
+ .description('เริ่มต้นใช้งาน ClawFlow ในตำแหน่งปัจจุบัน')
113
+ .option('-f, --force', 'เขียนทับ config เดิม')
114
+ .action(initCommand);
115
+
116
+ // Global error handler
117
+ process.on('unhandledRejection', (err) => {
118
+ console.error(chalk.red('\n❌ เกิดข้อผิดพลาด:'), err.message);
119
+ if (process.env.DEBUG) {
120
+ console.error(err.stack);
121
+ }
122
+ process.exit(1);
123
+ });
124
+
125
+ program.parse();
@@ -0,0 +1,179 @@
1
+ # ClawFlow Package Format
2
+
3
+ Packages สำหรับ ClawFlow สามารถ publish ขึ้น npm registry ได้โดยมีรูปแบบดังนี้:
4
+
5
+ ## 1. การระบุว่าเป็น ClawFlow Package
6
+
7
+ มี 3 วิธี:
8
+
9
+ ### วิธีที่ 1: ใช้ Scope `@clawflow/`
10
+ ```json
11
+ {
12
+ "name": "@clawflow/trading-kit"
13
+ }
14
+ ```
15
+
16
+ ### วิธีที่ 2: ใช้ Keyword
17
+ ```json
18
+ {
19
+ "name": "my-awesome-kit",
20
+ "keywords": ["clawflow", "trading", "crypto"]
21
+ }
22
+ ```
23
+
24
+ ### วิธีที่ 3: ใช้ Field `clawflow` ใน package.json
25
+ ```json
26
+ {
27
+ "name": "my-awesome-kit",
28
+ "clawflow": {
29
+ "skills": [...],
30
+ "crons": [...]
31
+ }
32
+ }
33
+ ```
34
+
35
+ ## 2. Package Structure
36
+
37
+ ```
38
+ my-package/
39
+ ├── package.json # ต้องมี keyword "clawflow" หรือ field clawflow
40
+ ├── clawflow.json # (optional) แยก config ออกมา
41
+ ├── README.md
42
+ └── (other files)
43
+ ```
44
+
45
+ ## 3. clawflow.json Format
46
+
47
+ ```json
48
+ {
49
+ "$schema": "https://clawflowhub.dev/schema/v1.json",
50
+ "skills": [
51
+ {
52
+ "name": "binance-pro",
53
+ "version": "^1.0.0",
54
+ "source": "openclaw",
55
+ "repository": "https://github.com/owner/binance-pro-skill.git",
56
+ "description": "Binance trading skill"
57
+ }
58
+ ],
59
+ "crons": [
60
+ {
61
+ "skill": "crypto-price",
62
+ "schedule": "*/5 * * * *",
63
+ "params": {
64
+ "symbols": ["BTC", "ETH", "SOL"]
65
+ },
66
+ "description": "เช็คราคาคริปโตทุก 5 นาที",
67
+ "enabled": true
68
+ }
69
+ ],
70
+ "config": {
71
+ "binance-pro": {
72
+ "apiKey": {
73
+ "env": "BINANCE_API_KEY",
74
+ "required": true,
75
+ "description": "Binance API Key"
76
+ },
77
+ "secretKey": {
78
+ "env": "BINANCE_SECRET_KEY",
79
+ "required": true,
80
+ "description": "Binance Secret Key"
81
+ }
82
+ }
83
+ },
84
+ "postInstall": "กรุณาตั้งค่า BINANCE_API_KEY และ BINANCE_SECRET_KEY ใน environment variables"
85
+ }
86
+ ```
87
+
88
+ ## 4. Field Descriptions
89
+
90
+ ### skills
91
+ รายการ skills ที่จะติดตั้ง
92
+
93
+ | Field | Type | Required | Description |
94
+ |-------|------|----------|-------------|
95
+ | `name` | string | Yes | ชื่อ skill |
96
+ | `version` | string | No | เวอร์ชัน (semver) |
97
+ | `source` | string | No | แหล่งที่มา (openclaw, npm, github) |
98
+ | `repository`/`repo`/`git` | string | No | Git URL สำหรับ fallback เมื่อหา skill ใน clawhub ไม่เจอ |
99
+ | `branch`/`tag`/`ref` | string | No | branch/tag/ref สำหรับ git clone |
100
+ | `description` | string | No | คำอธิบาย |
101
+
102
+ ### crons
103
+ รายการ cronjobs ที่จะสร้าง
104
+
105
+ | Field | Type | Required | Description |
106
+ |-------|------|----------|-------------|
107
+ | `skill` | string | Yes | ชื่อ skill ที่จะรัน |
108
+ | `schedule` | string | Yes | Cron expression |
109
+ | `params` | object | No | Parameters ที่ส่งให้ skill |
110
+ | `description` | string | No | คำอธิบาย |
111
+ | `enabled` | boolean | No | เปิดใช้งานหรือไม่ (default: true) |
112
+
113
+ ### config
114
+ Schema สำหรับการตั้งค่า package
115
+
116
+ | Field | Type | Required | Description |
117
+ |-------|------|----------|-------------|
118
+ | `env` | string | No | ชื่อ environment variable |
119
+ | `required` | boolean | No | บังคับต้องมีหรือไม่ |
120
+ | `default` | any | No | ค่า default |
121
+ | `description` | string | No | คำอธิบาย |
122
+ | `type` | string | No | ประเภท (string, number, array, object) |
123
+
124
+ ## 5. ตัวอย่าง package.json สมบูรณ์
125
+
126
+ ```json
127
+ {
128
+ "name": "@clawflowhub/trading-kit",
129
+ "version": "1.0.0",
130
+ "description": "ชุดเครื่องมือสำหรับเทรดคริปโต",
131
+ "keywords": ["clawflowhub", "trading", "crypto", "binance"],
132
+ "author": "Your Name",
133
+ "license": "MIT",
134
+ "clawflowhub": {
135
+ "skills": [
136
+ { "name": "binance-pro", "version": "^1.0.0", "source": "openclaw" },
137
+ { "name": "crypto-price", "version": "^1.0.0", "source": "openclaw" }
138
+ ],
139
+ "crons": [
140
+ {
141
+ "skill": "crypto-price",
142
+ "schedule": "*/5 * * * *",
143
+ "params": { "symbols": ["BTC", "ETH"] },
144
+ "description": "เช็คราคาทุก 5 นาที"
145
+ }
146
+ ],
147
+ "config": {
148
+ "binance-pro": {
149
+ "apiKey": { "env": "BINANCE_API_KEY", "required": true }
150
+ }
151
+ }
152
+ }
153
+ }
154
+ ```
155
+
156
+ ## 6. Publishing
157
+
158
+ ```bash
159
+ # Publish ขึ้น npm
160
+ npm publish --access public
161
+
162
+ # ถ้าเป็น scoped package (@clawflowhub/xxx)
163
+ npm publish --access public
164
+ ```
165
+
166
+ ## 7. การติดตั้ง
167
+
168
+ หลังจาก publish แล้ว ผู้ใช้สามารถติดตั้งได้โดย:
169
+
170
+ ```bash
171
+ # ติดตั้งจาก npm
172
+ clawflowhub install @clawflowhub/trading-kit
173
+
174
+ # หรือ
175
+ clawflowhub install my-awesome-kit
176
+
177
+ # ติดตั้งเวอร์ชันเฉพาะ
178
+ clawflowhub install @clawflowhub/trading-kit@1.0.0
179
+ ```
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@clawflow/example-kit",
3
+ "version": "1.0.0",
4
+ "description": "ตัวอย่าง ClawFlow Package สำหรับ npm registry",
5
+ "keywords": [
6
+ "clawflow",
7
+ "example",
8
+ "demo"
9
+ ],
10
+ "author": "ClawFlow Team",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/clawflow/example-kit.git"
15
+ },
16
+ "clawflow": {
17
+ "skills": [
18
+ {
19
+ "name": "hello-world",
20
+ "version": "^1.0.0",
21
+ "source": "openclaw",
22
+ "description": "พูดว่า Hello World"
23
+ },
24
+ {
25
+ "name": "time-logger",
26
+ "version": "^1.0.0",
27
+ "source": "openclaw",
28
+ "description": "บันทึกเวลาปัจจุบัน"
29
+ }
30
+ ],
31
+ "crons": [
32
+ {
33
+ "skill": "time-logger",
34
+ "schedule": "0 * * * *",
35
+ "params": {
36
+ "format": "ISO"
37
+ },
38
+ "description": "บันทึกเวลาทุกชั่วโมง",
39
+ "enabled": true
40
+ }
41
+ ],
42
+ "config": {
43
+ "time-logger": {
44
+ "timezone": {
45
+ "default": "Asia/Bangkok",
46
+ "type": "string",
47
+ "description": "Timezone สำหรับการบันทึกเวลา"
48
+ }
49
+ }
50
+ },
51
+ "postInstall": "ตัวอย่าง Package ติดตั้งสำเร็จแล้ว! ลองตั้งค่า timezone ได้ใน config"
52
+ }
53
+ }
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "clawflowbang",
3
+ "version": "1.0.0",
4
+ "description": "Skill + Cron Installer for OpenClaw - ติดตั้ง skill พร้อมตั้งค่าใช้งานทันที",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "clawflow": "bin/clawflowhub.js",
8
+ "clawflowhub": "bin/clawflowhub.js",
9
+ "cfh": "bin/clawflowhub.js"
10
+ },
11
+ "scripts": {
12
+ "start": "node bin/clawflowhub.js",
13
+ "test": "jest",
14
+ "lint": "eslint src/ bin/"
15
+ },
16
+ "keywords": [
17
+ "openclaw",
18
+ "skill",
19
+ "cron",
20
+ "installer",
21
+ "automation",
22
+ "clawhub",
23
+ "clawflow"
24
+ ],
25
+ "author": "ClawFlow Team",
26
+ "license": "MIT",
27
+ "dependencies": {
28
+ "commander": "^11.0.0",
29
+ "chalk": "^4.1.2",
30
+ "ora": "^5.4.1",
31
+ "inquirer": "^8.2.6",
32
+ "fs-extra": "^11.1.1",
33
+ "node-cron": "^3.0.3",
34
+ "axios": "^1.5.0",
35
+ "yaml": "^2.3.2",
36
+ "semver": "^7.5.4"
37
+ },
38
+ "devDependencies": {
39
+ "jest": "^29.6.4",
40
+ "eslint": "^8.47.0"
41
+ },
42
+ "engines": {
43
+ "node": ">=16.0.0"
44
+ }
45
+ }