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.
- package/README.md +27 -17
- package/package.json +1 -1
- package/src/cli.js +179 -77
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Jarvis Agent Factory · 贾维斯智能体工厂
|
|
2
2
|
|
|
3
3
|
[](./LICENSE)
|
|
4
|
-
[](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
|
|
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
|
-
|
|
59
|
-
jarvis init
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
jarvis
|
|
63
|
-
jarvis
|
|
64
|
-
jarvis
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
72
|
-
jarvis
|
|
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
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:
|
|
17
|
-
opencode:{ dir: '.opencode',desc: 'OpenCode — 55 agents
|
|
18
|
-
codex:
|
|
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
|
|
22
|
-
|
|
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
|
|
26
|
-
jarvis
|
|
27
|
-
jarvis
|
|
28
|
-
jarvis
|
|
29
|
-
jarvis
|
|
30
|
-
jarvis
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
--help
|
|
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
|
|
44
|
-
jarvis init
|
|
45
|
-
jarvis
|
|
46
|
-
jarvis
|
|
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
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
for (const a of
|
|
55
|
-
if (a === '
|
|
56
|
-
else if (a === '
|
|
57
|
-
else
|
|
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 {
|
|
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
|
|
72
|
-
const { flags, args } = parseFlags(rawArgs);
|
|
73
|
-
const cmd = args[0];
|
|
86
|
+
const { opts, positional } = parseArgs(process.argv.slice(2));
|
|
74
87
|
|
|
75
|
-
if (
|
|
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 '
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
for (
|
|
109
|
-
|
|
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
|
-
|
|
112
|
-
|
|
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 =
|
|
122
|
-
const scope =
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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❌
|
|
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
|
+
}
|