jarvis-agent-factory 2.0.3 → 2.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.
Files changed (3) hide show
  1. package/README.md +27 -17
  2. package/package.json +1 -1
  3. package/src/cli.js +179 -77
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Jarvis Agent Factory · 贾维斯智能体工厂
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
4
- [![Version](https://img.shields.io/badge/version-v2.0.1-green)](https://gitee.com/wujl1124/JarvisAgentFactory/releases)
4
+ [![Version](https://img.shields.io/badge/version-v2.1.0-green)](https://gitee.com/wujl1124/JarvisAgentFactory/releases)
5
5
  <br>**简体中文** | [English](./README_EN.md)
6
6
 
7
7
  一套跨平台的多智能体(Multi-Agent)AI 编程助手配置集,定义了一条**从想法到交付的完整软件开发流水线**。支持 Claude Code、OpenCode、Codex 三平台,共享同一套工作流规范与技能体系。
8
8
 
9
- > **v2.0.1** — Claude Code 47 agents + 15 commands / OpenCode 55 agents(纯智能体切换) / Codex 45 agents + 42 skills(Skill 触发)
9
+ > **v2.1.0** — Claude Code 47 agents + 15 commands / OpenCode 55 agents(纯智能体切换) / Codex 45 agents + 42 skills(Skill 触发)
10
10
 
11
11
  ## 核心概念
12
12
 
@@ -53,23 +53,33 @@
53
53
 
54
54
  ```bash
55
55
  npm i -g jarvis-agent-factory
56
+ ```
56
57
 
57
- # 新项目一键安装
58
- jarvis init ./my-project
59
- jarvis init -y # 跳过确认
60
-
61
- # 按平台安装
62
- jarvis install claude
63
- jarvis install opencode
64
- jarvis install codex
65
-
66
- # 查看版本 / 检查更新
67
- jarvis version
68
- jarvis update
58
+ | 命令 | 说明 |
59
+ |------|------|
60
+ | `jarvis` | 引导当前目录(≡ `jarvis init .`) |
61
+ | `jarvis init [path]` | 初始化项目,安装全部三平台 + Playwright MCP 配置 |
62
+ | `jarvis add <p...> [path]` | 添加指定平台(`claude` `opencode` `codex` 可多选) |
63
+ | `jarvis remove <p...> [path]` | 移除指定平台 + 对应 MCP 配置 |
64
+ | `jarvis upgrade [path]` | 升级已安装的配置到最新版本 |
65
+ | `jarvis doctor [path]` | 健康检查 |
66
+ | `-g, --global` | 安装到用户全局目录 `~/.claude/` 等 |
67
+ | `-y, --yes` | 跳过覆盖确认 |
68
+ | `-v, --version` | 查看版本 |
69
+ | `-h, --help` | 帮助 |
69
70
 
70
- # 健康检查
71
- jarvis doctor
72
- jarvis list
71
+ ```bash
72
+ # 常用
73
+ jarvis # 引导当前目录
74
+ jarvis init my-app -y # 一键初始化
75
+ jarvis add claude # 追加 Claude Code
76
+ jarvis remove codex # 移除 Codex
77
+ jarvis upgrade # 升级配置
78
+ jarvis doctor # 检查
79
+
80
+ # 全局安装
81
+ jarvis init -g -y # 一键全局安装
82
+ jarvis add opencode -g # 全局追加 OpenCode
73
83
  ```
74
84
 
75
85
  ### 手动安装
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jarvis-agent-factory",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "description": "Jarvis Agent Factory CLI — 跨平台多智能体 AI 编程助手配置安装器 | Multi-agent AI coding assistant config installer for Claude Code / OpenCode / Codex",
5
5
  "keywords": [
6
6
  "jarvis",
package/src/cli.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { fileURLToPath } from 'node:url';
2
2
  import { dirname, resolve } from 'node:path';
3
- import { readFileSync } from 'node:fs';
3
+ import { readFileSync, existsSync, rmSync } from 'node:fs';
4
4
  import { execSync } from 'node:child_process';
5
+ import { createInterface } from 'node:readline';
5
6
  import { homedir } from 'node:os';
6
7
  import { install } from './install.js';
7
8
  import { doctor } from './doctor.js';
@@ -13,26 +14,31 @@ const PKG_VERSION = PKG.version;
13
14
  const PKG_NAME = PKG.name;
14
15
 
15
16
  const PLATFORMS = {
16
- claude: { dir: '.claude', desc: 'Claude Code — 47 agents + 15 commands + 27 skills' },
17
- opencode:{ dir: '.opencode',desc: 'OpenCode — 55 agents (智能体切换) + 27 skills' },
18
- codex: { dir: '.codex', desc: 'Codex — 45 agents + 42 skills (Skill触发)' },
17
+ claude: { dir: '.claude', desc: 'Claude Code — 47 agents + 15 commands + 27 skills' },
18
+ opencode: { dir: '.opencode', desc: 'OpenCode — 55 agents + 27 skills (agent switching)' },
19
+ codex: { dir: '.codex', desc: 'Codex — 45 agents + 42 skills (skill-triggered)' },
19
20
  };
20
21
 
21
- const HELP = `
22
- 🧠 Jarvis Agent Factory v${PKG_VERSION}
22
+ const ALL_PLATFORMS = Object.keys(PLATFORMS);
23
+
24
+ const HELP = `🧠 Jarvis Agent Factory v${PKG_VERSION}
25
+
26
+ Bootstrap multi-agent AI coding assistant configs
27
+ for Claude Code, OpenCode, and Codex.
23
28
 
24
29
  Usage:
25
- jarvis init [path] [--yes|-y] [--global|-g] 初始化项目(含 Playwright MCP 配置)
26
- jarvis install <platform> [path] [--yes|-y] [--global|-g] 安装指定平台
27
- jarvis update [path] [--yes|-y] 更新已安装的平台配置
28
- jarvis doctor [path] 健康检查
29
- jarvis version 查看版本 + 检查更新
30
- jarvis list 列出可用平台
30
+ jarvis [path] jarvis init [path]
31
+ jarvis init [path] Bootstrap project with all platforms + MCP
32
+ jarvis add <p...> [path] Add platform(s) to project
33
+ jarvis remove <p...> [path] Remove platform(s) from project
34
+ jarvis upgrade [path] Upgrade to latest config version
35
+ jarvis doctor [path] Verify installation
31
36
 
32
37
  Options:
33
- --yes, -y 跳过覆盖确认
34
- --global, -g 安装到用户全局目录(~/.claude/ etc)
35
- --help, -h 显示帮助
38
+ -g, --global Target user global directory instead of project
39
+ -y, --yes Skip confirmation prompts
40
+ -h, --help Show this help
41
+ -v, --version Show version
36
42
 
37
43
  Platforms:
38
44
  claude ${PLATFORMS.claude.desc}
@@ -40,23 +46,28 @@ Platforms:
40
46
  codex ${PLATFORMS.codex.desc}
41
47
 
42
48
  Examples:
43
- jarvis init ./my-project # 项目级安装(含 MCP)
44
- jarvis init --global -y # 全局安装,跳过确认
45
- jarvis install claude --global # 全局安装 Claude Code
46
- jarvis version # 查看版本
49
+ jarvis Bootstrap current directory
50
+ jarvis init my-app Bootstrap new project
51
+ jarvis add claude opencode Add platforms to current directory
52
+ jarvis add claude -g Add Claude Code globally
53
+ jarvis remove codex Remove Codex from project
54
+ jarvis upgrade Upgrade all configs
55
+ jarvis doctor Check current directory
47
56
  `;
48
57
 
49
58
  function showHelp() { console.log(HELP); }
50
59
 
51
- function parseFlags(args) {
52
- const flags = { yes: false, global: false };
53
- const cleaned = [];
54
- for (const a of args) {
55
- if (a === '--yes' || a === '-y') flags.yes = true;
56
- else if (a === '--global' || a === '-g') flags.global = true;
57
- else cleaned.push(a);
60
+ function parseArgs(raw) {
61
+ const opts = { yes: false, global: false };
62
+ const positional = [];
63
+ for (const a of raw) {
64
+ if (a === '-y' || a === '--yes') opts.yes = true;
65
+ else if (a === '-g' || a === '--global') opts.global = true;
66
+ else if (a === '-h' || a === '--help') { opts.help = true; return { opts, positional }; }
67
+ else if (a === '-v' || a === '--version') { opts.version = true; return { opts, positional }; }
68
+ else positional.push(a);
58
69
  }
59
- return { flags, args: cleaned };
70
+ return { opts, positional };
60
71
  }
61
72
 
62
73
  function checkLatest() {
@@ -67,80 +78,171 @@ function checkLatest() {
67
78
  } catch { return null; }
68
79
  }
69
80
 
81
+ function resolveTarget(path, isGlobal) {
82
+ return isGlobal ? resolve('.') : resolve(path || '.');
83
+ }
84
+
70
85
  export async function run() {
71
- const rawArgs = process.argv.slice(2);
72
- const { flags, args } = parseFlags(rawArgs);
73
- const cmd = args[0];
86
+ const { opts, positional } = parseArgs(process.argv.slice(2));
74
87
 
75
- if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') { showHelp(); return; }
88
+ if (opts.help) { showHelp(); return; }
89
+ if (opts.version) {
90
+ console.log(`${PKG_NAME} v${PKG_VERSION}`);
91
+ const latest = checkLatest();
92
+ if (latest && latest !== PKG_VERSION) {
93
+ console.log(`\n Update available: v${latest} → npm i -g ${PKG_NAME}@latest`);
94
+ }
95
+ return;
96
+ }
97
+
98
+ const cmd = positional[0];
99
+
100
+ // jarvis (no args) ≡ jarvis init .
101
+ if (!cmd) {
102
+ const target = resolve('.');
103
+ const scope = opts.global ? '~ (global)' : target;
104
+ console.log(`\n🚀 Jarvis v${PKG_VERSION}\n`);
105
+ console.log(` Target: ${scope}\n`);
106
+ for (const name of ALL_PLATFORMS) {
107
+ await install({ platform: name, target, pkgRoot: PKG_ROOT, platforms: PLATFORMS, force: opts.yes, global: opts.global });
108
+ }
109
+ console.log(`\n✅ Done! \`jarvis doctor\` to verify.\n`);
110
+ return;
111
+ }
76
112
 
77
113
  switch (cmd) {
78
- case 'version':
79
- case '--version':
80
- case '-v': {
81
- console.log(`${PKG_NAME} v${PKG_VERSION}`);
82
- const latest = checkLatest();
83
- if (latest && latest !== PKG_VERSION) {
84
- console.log(`\n ⚡ Update available: v${latest} (current: v${PKG_VERSION})`);
85
- console.log(` Run: npm i -g ${PKG_NAME}@latest`);
114
+ case 'init': {
115
+ const path = positional[1];
116
+ const target = resolveTarget(path, opts.global);
117
+ const scope = opts.global ? '~ (global)' : target;
118
+ console.log(`\n🚀 Jarvis v${PKG_VERSION}\n`);
119
+ console.log(` Target: ${scope}\n`);
120
+ for (const name of ALL_PLATFORMS) {
121
+ await install({ platform: name, target, pkgRoot: PKG_ROOT, platforms: PLATFORMS, force: opts.yes, global: opts.global });
86
122
  }
123
+ console.log(`\n✅ Done!\n`);
87
124
  break;
88
125
  }
89
- case 'update': {
90
- const latest = checkLatest();
91
- if (latest && latest !== PKG_VERSION) {
92
- console.log(`\n⬆️ CLI update: v${PKG_VERSION} → v${latest}`);
93
- console.log(` Run: npm i -g ${PKG_NAME}@latest\n`);
126
+
127
+ case 'add': {
128
+ const platforms = [];
129
+ let path = '.';
130
+ for (let i = 1; i < positional.length; i++) {
131
+ const p = positional[i];
132
+ if (PLATFORMS[p]) platforms.push(p);
133
+ else if (!p.startsWith('-')) path = p;
94
134
  }
95
- const target = resolve(args[1] || '.');
96
- console.log(`🔄 Updating configs → ${target}\n`);
97
- for (const name of Object.keys(PLATFORMS)) {
98
- await install({ platform: name, target, pkgRoot: PKG_ROOT, platforms: PLATFORMS, force: flags.yes, global: flags.global });
135
+ if (platforms.length === 0) {
136
+ console.error('\n❌ No valid platform specified.\n');
137
+ console.log(`Valid platforms: ${ALL_PLATFORMS.join(', ')}\n`);
138
+ return;
139
+ }
140
+ const target = resolveTarget(path, opts.global);
141
+ const scope = opts.global ? '~ (global)' : target;
142
+ console.log(`\n📦 Adding to ${scope}\n`);
143
+ for (const name of platforms) {
144
+ await install({ platform: name, target, pkgRoot: PKG_ROOT, platforms: PLATFORMS, force: opts.yes, global: opts.global });
99
145
  }
100
146
  console.log(`\n✅ Done!\n`);
101
147
  break;
102
148
  }
103
- case 'init': {
104
- const target = resolve(args[1] || '.');
105
- const scope = flags.global ? `~ (global)` : target;
106
- console.log(`\n🚀 Jarvis Agent Factory v${PKG_VERSION}\n`);
107
- console.log(` Target: ${scope}\n`);
108
- for (const name of Object.keys(PLATFORMS)) {
109
- await install({ platform: name, target, pkgRoot: PKG_ROOT, platforms: PLATFORMS, force: flags.yes, global: flags.global });
149
+
150
+ case 'remove':
151
+ case 'rm': {
152
+ const platforms = [];
153
+ let path = '.';
154
+ for (let i = 1; i < positional.length; i++) {
155
+ const p = positional[i];
156
+ if (PLATFORMS[p]) platforms.push(p);
157
+ else if (!p.startsWith('-')) path = p;
110
158
  }
111
- console.log(`\n✅ Done! Run \`jarvis doctor\` to verify.\n`);
112
- break;
113
- }
114
- case 'install': {
115
- const platform = args[1];
116
- if (!platform || !PLATFORMS[platform]) {
117
- console.error(`\n❌ Unknown platform: ${platform || '(none)'}\n`);
118
- console.log(`Available: ${Object.keys(PLATFORMS).join(', ')}\n`);
159
+ if (platforms.length === 0) {
160
+ console.error('\n❌ No valid platform specified.\n');
161
+ console.log(`Valid platforms: ${ALL_PLATFORMS.join(', ')}\n`);
119
162
  return;
120
163
  }
121
- const target = resolve(args[2] || '.');
122
- const scope = flags.global ? `~ (global)` : target;
123
- console.log(`\n📦 Installing ${platform} ${scope}\n`);
124
- await install({ platform, target, pkgRoot: PKG_ROOT, platforms: PLATFORMS, force: flags.yes, global: flags.global });
164
+ const target = resolveTarget(path, opts.global);
165
+ const scope = opts.global ? '~ (global)' : target;
166
+ for (const name of platforms) {
167
+ const dir = opts.global ? (GLOBAL_ROOTS[name]) : resolve(target, PLATFORMS[name].dir);
168
+ if (existsSync(dir)) {
169
+ if (!opts.yes) {
170
+ const ok = await confirm(` Remove ${dir}? [y/N] `);
171
+ if (!ok) { console.log(` ⏭ Skipped ${name}`); continue; }
172
+ }
173
+ rmSync(dir, { recursive: true, force: true });
174
+ console.log(` - ${PLATFORMS[name].dir.padEnd(10)} removed`);
175
+ // Also remove MCP config
176
+ removeMcp(name, target, opts.global);
177
+ } else {
178
+ console.log(` ⏭ ${PLATFORMS[name].dir.padEnd(10)} not found`);
179
+ }
180
+ }
125
181
  console.log(`\n✅ Done!\n`);
126
182
  break;
127
183
  }
128
- case 'doctor': {
129
- const target = resolve(args[1] || '.');
130
- doctor({ target, platforms: PLATFORMS, pkgRoot: PKG_ROOT });
184
+
185
+ case 'upgrade':
186
+ case 'update': {
187
+ // Check CLI self-upgrade
188
+ const latest = checkLatest();
189
+ if (latest && latest !== PKG_VERSION) {
190
+ console.log(`\n⬆️ CLI: v${PKG_VERSION} → v${latest}`);
191
+ console.log(` npm i -g ${PKG_NAME}@latest\n`);
192
+ }
193
+ const path = positional[1];
194
+ const target = resolveTarget(path, opts.global);
195
+ const scope = opts.global ? '~ (global)' : target;
196
+ console.log(`🔄 Upgrading → ${scope}\n`);
197
+ for (const name of ALL_PLATFORMS) {
198
+ const dir = opts.global ? GLOBAL_ROOTS[name] : resolve(target, PLATFORMS[name].dir);
199
+ if (existsSync(dir)) {
200
+ await install({ platform: name, target, pkgRoot: PKG_ROOT, platforms: PLATFORMS, force: opts.yes, global: opts.global });
201
+ } else {
202
+ console.log(` ⏭ ${PLATFORMS[name].dir} not installed, skipped`);
203
+ }
204
+ }
205
+ console.log(`\n✅ Done!\n`);
131
206
  break;
132
207
  }
133
- case 'list': {
134
- console.log('\n📋 Available platforms:\n');
135
- for (const [name, info] of Object.entries(PLATFORMS)) {
136
- console.log(` ${name.padEnd(10)} ${info.desc}`);
137
- }
138
- console.log('');
208
+
209
+ case 'doctor':
210
+ case 'check': {
211
+ const path = positional[1];
212
+ const target = resolveTarget(path, opts.global);
213
+ doctor({ target, platforms: PLATFORMS, pkgRoot: PKG_ROOT, global: opts.global });
139
214
  break;
140
215
  }
216
+
141
217
  default: {
142
- console.error(`\n❌ Unknown command: ${cmd}\n`);
218
+ console.error(`\n❌ Unknown command: ${cmd}\n`);
143
219
  showHelp();
144
220
  }
145
221
  }
146
222
  }
223
+
224
+ const GLOBAL_ROOTS = {
225
+ claude: resolve(homedir(), '.claude'),
226
+ opencode: resolve(homedir(), '.config', 'opencode'),
227
+ codex: resolve(homedir(), '.codex'),
228
+ };
229
+
230
+ function removeMcp(platform, target, isGlobal) {
231
+ const files = {
232
+ claude: '.mcp.json',
233
+ opencode: 'opencode.json',
234
+ codex: '.codex/config.toml',
235
+ };
236
+ const f = files[platform];
237
+ if (!f) return;
238
+ const dest = isGlobal ? resolve(homedir(), f) : resolve(target, f);
239
+ if (existsSync(dest)) {
240
+ rmSync(dest, { recursive: true, force: true });
241
+ console.log(` - ${f.padEnd(18)} removed`);
242
+ }
243
+ }
244
+
245
+ async function confirm(q) {
246
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
247
+ return new Promise(res => { rl.question(q, a => { rl.close(); res(a.toLowerCase() === 'y' || a.toLowerCase() === 'yes'); }); });
248
+ }