conductor-4-all 0.0.3 → 0.0.5
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 +17 -29
- package/dist/index.cjs +168 -56
- package/dist/index.js +167 -55
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# Conductor for All
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://badge.fury.io/js/conductor-4-all)
|
|
4
|
+
|
|
5
|
+
<img src="./conductor_banner.png" height="400" alt="Conductor for All Banner" />
|
|
6
|
+
|
|
7
|
+
[English](./README.md) | [中文](./README_zh.md) | [日本語](./README_ja.md) | [한국어](./README_ko.md)
|
|
8
|
+
|
|
9
|
+
**Conductor for All** is a standalone command-line tool designed to bring the [Conductor](https://github.com/gemini-cli-extensions/conductor) spec-driven development methodology to *any* coding environment.
|
|
4
10
|
|
|
5
11
|
Originally tied to the Gemini CLI extension, this project aims to decouple the methodology, allowing developers to install and initialize Conductor workflows in their projects so they can be leveraged by **any** AI Coding Agent (e.g., Claude Code, Cline, Cursor, Windsurf) or IDE.
|
|
6
12
|
|
|
@@ -12,36 +18,29 @@ Originally tied to the Gemini CLI extension, this project aims to decouple the m
|
|
|
12
18
|
|
|
13
19
|
## 🚀 Usage
|
|
14
20
|
|
|
15
|
-
### 1.
|
|
16
|
-
|
|
17
|
-
#### Global Installation via npm (Recommended)
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npm install -g conductor-4-all
|
|
21
|
-
```
|
|
21
|
+
### 1. Setup Conductor in Your Project
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
To initialize Conductor in your project, simply run the following command in your project root:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
|
|
27
|
-
npm run build
|
|
26
|
+
npx conductor-4-all install
|
|
28
27
|
```
|
|
29
28
|
|
|
30
|
-
### 2.
|
|
29
|
+
### 2. Alternative: Build from Source
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
If you prefer to build from source:
|
|
33
32
|
|
|
34
33
|
```bash
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# If built from source:
|
|
34
|
+
pnpm install
|
|
35
|
+
pnpm build
|
|
39
36
|
node dist/index.js install
|
|
40
37
|
```
|
|
41
38
|
|
|
42
39
|
You will be prompted to select your AI Coding Agent:
|
|
43
40
|
- **Opencode**
|
|
44
41
|
- **Claude Code**
|
|
42
|
+
- **Antigravity**
|
|
43
|
+
- **Cursor**
|
|
45
44
|
|
|
46
45
|
This will verify the environment and install the necessary Conductor files:
|
|
47
46
|
- **Commands:** Agent-specific prompt files (e.g., `.opencode/commands/conductor:setup.md`) that your agent can execute.
|
|
@@ -58,19 +57,8 @@ Once installed, you can instruct your AI Agent to perform Conductor tasks using
|
|
|
58
57
|
|
|
59
58
|
*Note: The exact invocation syntax depends on your specific agent's slash command or file context capabilities.*
|
|
60
59
|
|
|
61
|
-
## 🛠️ Contribution Guide
|
|
62
|
-
|
|
63
|
-
We follow a strict spec-driven development workflow ourselves!
|
|
64
|
-
|
|
65
|
-
- **Workflow:** Please read [`conductor/workflow.md`](./conductor/workflow.md) for our detailed development protocols (Tasks, TDD, Commits).
|
|
66
|
-
- **Tech Stack:** Check [`conductor/tech-stack.md`](./conductor/tech-stack.md) for approved technologies (TypeScript/Node.js).
|
|
67
|
-
- **Product Guidelines:** See [`conductor/product-guidelines.md`](./conductor/product-guidelines.md) for design philosophy.
|
|
68
60
|
|
|
69
|
-
To start contributing:
|
|
70
|
-
1. Read the docs above.
|
|
71
|
-
2. Pick a task from `conductor/tracks.md` (or propose one).
|
|
72
|
-
3. Follow the **Conductor Workflow** to implement it.
|
|
73
61
|
|
|
74
62
|
## 🙏 Acknowledgements
|
|
75
63
|
|
|
76
|
-
This project is inspired by and based on the
|
|
64
|
+
This project is inspired by and based on the [Conductor](https://github.com/gemini-cli-extensions/conductor) methodology originally developed for the **Gemini CLI**. We aim to extend its benefits to the broader developer ecosystem.
|
package/dist/index.cjs
CHANGED
|
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
mod
|
|
24
24
|
));
|
|
25
25
|
|
|
26
|
-
// node_modules/tsup/assets/cjs_shims.js
|
|
26
|
+
// node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js
|
|
27
27
|
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
28
28
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
29
29
|
|
|
@@ -40,12 +40,22 @@ async function promptForAgent() {
|
|
|
40
40
|
{
|
|
41
41
|
name: "OpenCode",
|
|
42
42
|
value: "opencode",
|
|
43
|
-
description: "
|
|
43
|
+
description: "The open source AI coding agent"
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
name: "Claude Code",
|
|
47
47
|
value: "claude-code",
|
|
48
|
-
description: "Anthropic
|
|
48
|
+
description: "Anthropic's coding assistant"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "Antigravity",
|
|
52
|
+
value: "antigravity",
|
|
53
|
+
description: "Google's agentic coding assistant"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "Cursor",
|
|
57
|
+
value: "cursor",
|
|
58
|
+
description: "Cursor IDE's AI agent"
|
|
49
59
|
}
|
|
50
60
|
],
|
|
51
61
|
default: "opencode"
|
|
@@ -53,9 +63,9 @@ async function promptForAgent() {
|
|
|
53
63
|
return answer;
|
|
54
64
|
}
|
|
55
65
|
|
|
56
|
-
// src/
|
|
57
|
-
var import_fs_extra = __toESM(require("fs-extra"), 1);
|
|
66
|
+
// src/generators/ConfigurableGenerator.ts
|
|
58
67
|
var import_path2 = require("path");
|
|
68
|
+
var import_fs_extra = __toESM(require("fs-extra"), 1);
|
|
59
69
|
var import_smol_toml = require("smol-toml");
|
|
60
70
|
|
|
61
71
|
// src/utils/template.ts
|
|
@@ -94,56 +104,160 @@ async function loadTemplate(templatePath) {
|
|
|
94
104
|
return (0, import_promises.readFile)(fullPath, "utf-8");
|
|
95
105
|
}
|
|
96
106
|
|
|
97
|
-
// src/
|
|
107
|
+
// src/generators/ConfigurableGenerator.ts
|
|
98
108
|
var { existsSync, ensureDir, writeFile, copy } = import_fs_extra.default;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const agentPath = (0, import_path2.join)(targetDir, agentDir);
|
|
115
|
-
await ensureDir((0, import_path2.join)(agentPath, "commands"));
|
|
116
|
-
await ensureDir((0, import_path2.join)(agentPath, "conductor"));
|
|
109
|
+
function processTemplateContent(tomlContent, installPath, agentType) {
|
|
110
|
+
const parsed = (0, import_smol_toml.parse)(tomlContent);
|
|
111
|
+
if (!parsed.prompt) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
let prompt = parsed.prompt;
|
|
115
|
+
prompt = prompt.replace(/__\$\$CODE_AGENT_INSTALL_PATH\$\$__/g, installPath);
|
|
116
|
+
const finalContent = substituteVariables(prompt, { agent_type: agentType });
|
|
117
|
+
if (parsed.description) {
|
|
118
|
+
return `---
|
|
119
|
+
description: ${parsed.description}
|
|
120
|
+
---
|
|
121
|
+
${finalContent}`;
|
|
122
|
+
}
|
|
123
|
+
return finalContent;
|
|
117
124
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
125
|
+
var ConfigurableGenerator = class {
|
|
126
|
+
constructor(config) {
|
|
127
|
+
this.config = config;
|
|
128
|
+
}
|
|
129
|
+
async validate(targetDir) {
|
|
130
|
+
if (!existsSync(targetDir)) {
|
|
131
|
+
throw new Error(`Target directory does not exist: ${targetDir}`);
|
|
132
|
+
}
|
|
133
|
+
const { agentDir, commandsDir, displayName } = this.config;
|
|
134
|
+
const setupFile = (0, import_path2.join)(targetDir, agentDir, commandsDir, "conductor:setup.md");
|
|
135
|
+
const conductorPath = (0, import_path2.join)(targetDir, agentDir, "conductor");
|
|
136
|
+
if (existsSync(conductorPath) && existsSync(setupFile)) {
|
|
137
|
+
throw new Error(`Conductor (${displayName}) is already installed in: ${targetDir}`);
|
|
138
|
+
}
|
|
139
|
+
return targetDir;
|
|
131
140
|
}
|
|
132
|
-
|
|
141
|
+
async generate(targetDir) {
|
|
142
|
+
const { agentDir, commandsDir, agentType } = this.config;
|
|
143
|
+
const agentPath = (0, import_path2.join)(targetDir, agentDir);
|
|
144
|
+
const targetCommandsDir = (0, import_path2.join)(agentPath, commandsDir);
|
|
145
|
+
const installPath = (0, import_path2.join)(agentDir, "conductor");
|
|
146
|
+
await ensureDir(targetCommandsDir);
|
|
147
|
+
await ensureDir((0, import_path2.join)(agentPath, "conductor"));
|
|
148
|
+
const templateRoot = await getTemplateRoot();
|
|
133
149
|
try {
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
console.warn(`Warning: No prompt found in ${cmd}.toml`);
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
let prompt = parsed.prompt;
|
|
141
|
-
prompt = prompt.replace(/__\$\$CODE_AGENT_INSTALL_PATH\$\$__/g, installPath);
|
|
142
|
-
const finalPrompt = substituteVariables(prompt, { agent_type: agentType });
|
|
143
|
-
await writeFile((0, import_path2.join)(commandsDir, `conductor:${cmd}.md`), finalPrompt);
|
|
150
|
+
const templateSource = (0, import_path2.join)(templateRoot, "templates");
|
|
151
|
+
const templateDest = (0, import_path2.join)(agentPath, "conductor", "templates");
|
|
152
|
+
await copy(templateSource, templateDest);
|
|
144
153
|
} catch (e) {
|
|
145
|
-
console.warn(
|
|
154
|
+
console.warn("Failed to copy templates directory:", e);
|
|
146
155
|
}
|
|
156
|
+
const commands = ["setup", "newTrack", "implement", "status", "revert"];
|
|
157
|
+
for (const cmd of commands) {
|
|
158
|
+
try {
|
|
159
|
+
const tomlContent = await loadTemplate(`commands/${cmd}.toml`);
|
|
160
|
+
const finalContent = processTemplateContent(tomlContent, installPath, agentType);
|
|
161
|
+
if (finalContent) {
|
|
162
|
+
const fileName = `conductor:${cmd}.md`;
|
|
163
|
+
await writeFile((0, import_path2.join)(targetCommandsDir, fileName), finalContent);
|
|
164
|
+
}
|
|
165
|
+
} catch (e) {
|
|
166
|
+
console.warn(`Failed to process ${cmd}:`, e);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// src/generators/factory.ts
|
|
173
|
+
function createGenerator(config) {
|
|
174
|
+
return new ConfigurableGenerator(config);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/generators/config.ts
|
|
178
|
+
var AGENT_CONFIGS = {
|
|
179
|
+
opencode: {
|
|
180
|
+
agentType: "opencode",
|
|
181
|
+
agentDir: ".opencode",
|
|
182
|
+
commandsDir: "commands",
|
|
183
|
+
displayName: "OpenCode"
|
|
184
|
+
},
|
|
185
|
+
"claude-code": {
|
|
186
|
+
agentType: "claude-code",
|
|
187
|
+
agentDir: ".claude",
|
|
188
|
+
commandsDir: "commands",
|
|
189
|
+
displayName: "Claude Code"
|
|
190
|
+
},
|
|
191
|
+
antigravity: {
|
|
192
|
+
agentType: "antigravity",
|
|
193
|
+
agentDir: ".agent",
|
|
194
|
+
commandsDir: "workflows",
|
|
195
|
+
displayName: "Antigravity"
|
|
196
|
+
},
|
|
197
|
+
cursor: {
|
|
198
|
+
agentType: "cursor",
|
|
199
|
+
agentDir: ".cursor",
|
|
200
|
+
commandsDir: "commands",
|
|
201
|
+
displayName: "Cursor"
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// src/generators/OpenCodeGenerator.ts
|
|
206
|
+
var OpenCodeGenerator = class {
|
|
207
|
+
generator = createGenerator(AGENT_CONFIGS.opencode);
|
|
208
|
+
validate(targetDir) {
|
|
209
|
+
return this.generator.validate(targetDir);
|
|
210
|
+
}
|
|
211
|
+
generate(targetDir) {
|
|
212
|
+
return this.generator.generate(targetDir);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// src/generators/ClaudeCodeGenerator.ts
|
|
217
|
+
var ClaudeCodeGenerator = class {
|
|
218
|
+
generator = createGenerator(AGENT_CONFIGS["claude-code"]);
|
|
219
|
+
validate(targetDir) {
|
|
220
|
+
return this.generator.validate(targetDir);
|
|
221
|
+
}
|
|
222
|
+
generate(targetDir) {
|
|
223
|
+
return this.generator.generate(targetDir);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// src/generators/AntigravityGenerator.ts
|
|
228
|
+
var AntigravityGenerator = class {
|
|
229
|
+
generator = createGenerator(AGENT_CONFIGS.antigravity);
|
|
230
|
+
validate(targetDir) {
|
|
231
|
+
return this.generator.validate(targetDir);
|
|
232
|
+
}
|
|
233
|
+
generate(targetDir) {
|
|
234
|
+
return this.generator.generate(targetDir);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// src/generators/CursorGenerator.ts
|
|
239
|
+
var CursorGenerator = class {
|
|
240
|
+
generator = createGenerator(AGENT_CONFIGS.cursor);
|
|
241
|
+
validate(targetDir) {
|
|
242
|
+
return this.generator.validate(targetDir);
|
|
243
|
+
}
|
|
244
|
+
generate(targetDir) {
|
|
245
|
+
return this.generator.generate(targetDir);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// src/generators/index.ts
|
|
250
|
+
function getGenerator(agentType) {
|
|
251
|
+
switch (agentType) {
|
|
252
|
+
case "claude-code":
|
|
253
|
+
return new ClaudeCodeGenerator();
|
|
254
|
+
case "antigravity":
|
|
255
|
+
return new AntigravityGenerator();
|
|
256
|
+
case "cursor":
|
|
257
|
+
return new CursorGenerator();
|
|
258
|
+
case "opencode":
|
|
259
|
+
default:
|
|
260
|
+
return new OpenCodeGenerator();
|
|
147
261
|
}
|
|
148
262
|
}
|
|
149
263
|
|
|
@@ -156,15 +270,13 @@ async function installHandler(argv) {
|
|
|
156
270
|
console.log("Step 1: Prompting for agent selection...");
|
|
157
271
|
const agent = await promptForAgent();
|
|
158
272
|
console.log(`\u2714 Selected agent: ${agent}`);
|
|
273
|
+
const generator = getGenerator(agent);
|
|
159
274
|
console.log("\nStep 2: Validating project directory...");
|
|
160
|
-
const validatedPath = await
|
|
275
|
+
const validatedPath = await generator.validate(targetDir);
|
|
161
276
|
console.log(`\u2714 Validation complete: ${validatedPath}`);
|
|
162
|
-
console.log("\nStep 3:
|
|
163
|
-
await
|
|
164
|
-
console.log("\u2714
|
|
165
|
-
console.log("\nStep 4: Copying template files...");
|
|
166
|
-
await copyTemplateFiles(validatedPath, agent);
|
|
167
|
-
console.log("\u2714 Templates copied");
|
|
277
|
+
console.log("\nStep 3: Generating files...");
|
|
278
|
+
await generator.generate(validatedPath);
|
|
279
|
+
console.log("\u2714 Files generated");
|
|
168
280
|
console.log("\n\u2714 Conductor initialized successfully!");
|
|
169
281
|
} catch (err) {
|
|
170
282
|
console.error("\n\u2718 Installation failed:", err instanceof Error ? err.message : err);
|
package/dist/index.js
CHANGED
|
@@ -13,12 +13,22 @@ async function promptForAgent() {
|
|
|
13
13
|
{
|
|
14
14
|
name: "OpenCode",
|
|
15
15
|
value: "opencode",
|
|
16
|
-
description: "
|
|
16
|
+
description: "The open source AI coding agent"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
name: "Claude Code",
|
|
20
20
|
value: "claude-code",
|
|
21
|
-
description: "Anthropic
|
|
21
|
+
description: "Anthropic's coding assistant"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "Antigravity",
|
|
25
|
+
value: "antigravity",
|
|
26
|
+
description: "Google's agentic coding assistant"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "Cursor",
|
|
30
|
+
value: "cursor",
|
|
31
|
+
description: "Cursor IDE's AI agent"
|
|
22
32
|
}
|
|
23
33
|
],
|
|
24
34
|
default: "opencode"
|
|
@@ -26,9 +36,9 @@ async function promptForAgent() {
|
|
|
26
36
|
return answer;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
|
-
// src/
|
|
30
|
-
import fs from "fs-extra";
|
|
39
|
+
// src/generators/ConfigurableGenerator.ts
|
|
31
40
|
import { join as join2 } from "path";
|
|
41
|
+
import fs from "fs-extra";
|
|
32
42
|
import { parse } from "smol-toml";
|
|
33
43
|
|
|
34
44
|
// src/utils/template.ts
|
|
@@ -67,56 +77,160 @@ async function loadTemplate(templatePath) {
|
|
|
67
77
|
return readFile(fullPath, "utf-8");
|
|
68
78
|
}
|
|
69
79
|
|
|
70
|
-
// src/
|
|
80
|
+
// src/generators/ConfigurableGenerator.ts
|
|
71
81
|
var { existsSync, ensureDir, writeFile, copy } = fs;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const agentPath = join2(targetDir, agentDir);
|
|
88
|
-
await ensureDir(join2(agentPath, "commands"));
|
|
89
|
-
await ensureDir(join2(agentPath, "conductor"));
|
|
82
|
+
function processTemplateContent(tomlContent, installPath, agentType) {
|
|
83
|
+
const parsed = parse(tomlContent);
|
|
84
|
+
if (!parsed.prompt) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
let prompt = parsed.prompt;
|
|
88
|
+
prompt = prompt.replace(/__\$\$CODE_AGENT_INSTALL_PATH\$\$__/g, installPath);
|
|
89
|
+
const finalContent = substituteVariables(prompt, { agent_type: agentType });
|
|
90
|
+
if (parsed.description) {
|
|
91
|
+
return `---
|
|
92
|
+
description: ${parsed.description}
|
|
93
|
+
---
|
|
94
|
+
${finalContent}`;
|
|
95
|
+
}
|
|
96
|
+
return finalContent;
|
|
90
97
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const agentPath = join2(targetDir, agentDir);
|
|
95
|
-
const commandsDir = join2(agentPath, "commands");
|
|
96
|
-
const templateRoot = await getTemplateRoot();
|
|
97
|
-
const installPath = join2(targetDir, agentDir, "conductor");
|
|
98
|
-
try {
|
|
99
|
-
const templateSource = join2(templateRoot, "templates");
|
|
100
|
-
const templateDest = join2(agentPath, "conductor", "templates");
|
|
101
|
-
await copy(templateSource, templateDest);
|
|
102
|
-
} catch (e) {
|
|
103
|
-
console.warn("Failed to copy templates directory:", e);
|
|
98
|
+
var ConfigurableGenerator = class {
|
|
99
|
+
constructor(config) {
|
|
100
|
+
this.config = config;
|
|
104
101
|
}
|
|
105
|
-
|
|
102
|
+
async validate(targetDir) {
|
|
103
|
+
if (!existsSync(targetDir)) {
|
|
104
|
+
throw new Error(`Target directory does not exist: ${targetDir}`);
|
|
105
|
+
}
|
|
106
|
+
const { agentDir, commandsDir, displayName } = this.config;
|
|
107
|
+
const setupFile = join2(targetDir, agentDir, commandsDir, "conductor:setup.md");
|
|
108
|
+
const conductorPath = join2(targetDir, agentDir, "conductor");
|
|
109
|
+
if (existsSync(conductorPath) && existsSync(setupFile)) {
|
|
110
|
+
throw new Error(`Conductor (${displayName}) is already installed in: ${targetDir}`);
|
|
111
|
+
}
|
|
112
|
+
return targetDir;
|
|
113
|
+
}
|
|
114
|
+
async generate(targetDir) {
|
|
115
|
+
const { agentDir, commandsDir, agentType } = this.config;
|
|
116
|
+
const agentPath = join2(targetDir, agentDir);
|
|
117
|
+
const targetCommandsDir = join2(agentPath, commandsDir);
|
|
118
|
+
const installPath = join2(agentDir, "conductor");
|
|
119
|
+
await ensureDir(targetCommandsDir);
|
|
120
|
+
await ensureDir(join2(agentPath, "conductor"));
|
|
121
|
+
const templateRoot = await getTemplateRoot();
|
|
106
122
|
try {
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
console.warn(`Warning: No prompt found in ${cmd}.toml`);
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
let prompt = parsed.prompt;
|
|
114
|
-
prompt = prompt.replace(/__\$\$CODE_AGENT_INSTALL_PATH\$\$__/g, installPath);
|
|
115
|
-
const finalPrompt = substituteVariables(prompt, { agent_type: agentType });
|
|
116
|
-
await writeFile(join2(commandsDir, `conductor:${cmd}.md`), finalPrompt);
|
|
123
|
+
const templateSource = join2(templateRoot, "templates");
|
|
124
|
+
const templateDest = join2(agentPath, "conductor", "templates");
|
|
125
|
+
await copy(templateSource, templateDest);
|
|
117
126
|
} catch (e) {
|
|
118
|
-
console.warn(
|
|
127
|
+
console.warn("Failed to copy templates directory:", e);
|
|
119
128
|
}
|
|
129
|
+
const commands = ["setup", "newTrack", "implement", "status", "revert"];
|
|
130
|
+
for (const cmd of commands) {
|
|
131
|
+
try {
|
|
132
|
+
const tomlContent = await loadTemplate(`commands/${cmd}.toml`);
|
|
133
|
+
const finalContent = processTemplateContent(tomlContent, installPath, agentType);
|
|
134
|
+
if (finalContent) {
|
|
135
|
+
const fileName = `conductor:${cmd}.md`;
|
|
136
|
+
await writeFile(join2(targetCommandsDir, fileName), finalContent);
|
|
137
|
+
}
|
|
138
|
+
} catch (e) {
|
|
139
|
+
console.warn(`Failed to process ${cmd}:`, e);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/generators/factory.ts
|
|
146
|
+
function createGenerator(config) {
|
|
147
|
+
return new ConfigurableGenerator(config);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/generators/config.ts
|
|
151
|
+
var AGENT_CONFIGS = {
|
|
152
|
+
opencode: {
|
|
153
|
+
agentType: "opencode",
|
|
154
|
+
agentDir: ".opencode",
|
|
155
|
+
commandsDir: "commands",
|
|
156
|
+
displayName: "OpenCode"
|
|
157
|
+
},
|
|
158
|
+
"claude-code": {
|
|
159
|
+
agentType: "claude-code",
|
|
160
|
+
agentDir: ".claude",
|
|
161
|
+
commandsDir: "commands",
|
|
162
|
+
displayName: "Claude Code"
|
|
163
|
+
},
|
|
164
|
+
antigravity: {
|
|
165
|
+
agentType: "antigravity",
|
|
166
|
+
agentDir: ".agent",
|
|
167
|
+
commandsDir: "workflows",
|
|
168
|
+
displayName: "Antigravity"
|
|
169
|
+
},
|
|
170
|
+
cursor: {
|
|
171
|
+
agentType: "cursor",
|
|
172
|
+
agentDir: ".cursor",
|
|
173
|
+
commandsDir: "commands",
|
|
174
|
+
displayName: "Cursor"
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/generators/OpenCodeGenerator.ts
|
|
179
|
+
var OpenCodeGenerator = class {
|
|
180
|
+
generator = createGenerator(AGENT_CONFIGS.opencode);
|
|
181
|
+
validate(targetDir) {
|
|
182
|
+
return this.generator.validate(targetDir);
|
|
183
|
+
}
|
|
184
|
+
generate(targetDir) {
|
|
185
|
+
return this.generator.generate(targetDir);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// src/generators/ClaudeCodeGenerator.ts
|
|
190
|
+
var ClaudeCodeGenerator = class {
|
|
191
|
+
generator = createGenerator(AGENT_CONFIGS["claude-code"]);
|
|
192
|
+
validate(targetDir) {
|
|
193
|
+
return this.generator.validate(targetDir);
|
|
194
|
+
}
|
|
195
|
+
generate(targetDir) {
|
|
196
|
+
return this.generator.generate(targetDir);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// src/generators/AntigravityGenerator.ts
|
|
201
|
+
var AntigravityGenerator = class {
|
|
202
|
+
generator = createGenerator(AGENT_CONFIGS.antigravity);
|
|
203
|
+
validate(targetDir) {
|
|
204
|
+
return this.generator.validate(targetDir);
|
|
205
|
+
}
|
|
206
|
+
generate(targetDir) {
|
|
207
|
+
return this.generator.generate(targetDir);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/generators/CursorGenerator.ts
|
|
212
|
+
var CursorGenerator = class {
|
|
213
|
+
generator = createGenerator(AGENT_CONFIGS.cursor);
|
|
214
|
+
validate(targetDir) {
|
|
215
|
+
return this.generator.validate(targetDir);
|
|
216
|
+
}
|
|
217
|
+
generate(targetDir) {
|
|
218
|
+
return this.generator.generate(targetDir);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// src/generators/index.ts
|
|
223
|
+
function getGenerator(agentType) {
|
|
224
|
+
switch (agentType) {
|
|
225
|
+
case "claude-code":
|
|
226
|
+
return new ClaudeCodeGenerator();
|
|
227
|
+
case "antigravity":
|
|
228
|
+
return new AntigravityGenerator();
|
|
229
|
+
case "cursor":
|
|
230
|
+
return new CursorGenerator();
|
|
231
|
+
case "opencode":
|
|
232
|
+
default:
|
|
233
|
+
return new OpenCodeGenerator();
|
|
120
234
|
}
|
|
121
235
|
}
|
|
122
236
|
|
|
@@ -129,15 +243,13 @@ async function installHandler(argv) {
|
|
|
129
243
|
console.log("Step 1: Prompting for agent selection...");
|
|
130
244
|
const agent = await promptForAgent();
|
|
131
245
|
console.log(`\u2714 Selected agent: ${agent}`);
|
|
246
|
+
const generator = getGenerator(agent);
|
|
132
247
|
console.log("\nStep 2: Validating project directory...");
|
|
133
|
-
const validatedPath = await
|
|
248
|
+
const validatedPath = await generator.validate(targetDir);
|
|
134
249
|
console.log(`\u2714 Validation complete: ${validatedPath}`);
|
|
135
|
-
console.log("\nStep 3:
|
|
136
|
-
await
|
|
137
|
-
console.log("\u2714
|
|
138
|
-
console.log("\nStep 4: Copying template files...");
|
|
139
|
-
await copyTemplateFiles(validatedPath, agent);
|
|
140
|
-
console.log("\u2714 Templates copied");
|
|
250
|
+
console.log("\nStep 3: Generating files...");
|
|
251
|
+
await generator.generate(validatedPath);
|
|
252
|
+
console.log("\u2714 Files generated");
|
|
141
253
|
console.log("\n\u2714 Conductor initialized successfully!");
|
|
142
254
|
} catch (err) {
|
|
143
255
|
console.error("\n\u2718 Installation failed:", err instanceof Error ? err.message : err);
|
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor-4-all",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Conductor spec-driven development CLI - TypeScript/Node.js version",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/hlhr202/Conductor-for-all.git"
|
|
8
8
|
},
|
|
9
9
|
"homepage": "https://github.com/hlhr202/Conductor-for-all",
|
|
10
|
+
"packageManager": "pnpm@10.24.0",
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=18"
|
|
13
|
+
},
|
|
10
14
|
"type": "module",
|
|
11
15
|
"bin": {
|
|
12
16
|
"conductor": "./dist/index.js",
|