conductor-4-all 0.0.4 → 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 +160 -94
- package/dist/index.js +159 -93
- 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
|
|
|
@@ -51,6 +51,11 @@ async function promptForAgent() {
|
|
|
51
51
|
name: "Antigravity",
|
|
52
52
|
value: "antigravity",
|
|
53
53
|
description: "Google's agentic coding assistant"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "Cursor",
|
|
57
|
+
value: "cursor",
|
|
58
|
+
description: "Cursor IDE's AI agent"
|
|
54
59
|
}
|
|
55
60
|
],
|
|
56
61
|
default: "opencode"
|
|
@@ -58,9 +63,9 @@ async function promptForAgent() {
|
|
|
58
63
|
return answer;
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
// src/
|
|
62
|
-
var import_fs_extra = __toESM(require("fs-extra"), 1);
|
|
66
|
+
// src/generators/ConfigurableGenerator.ts
|
|
63
67
|
var import_path2 = require("path");
|
|
68
|
+
var import_fs_extra = __toESM(require("fs-extra"), 1);
|
|
64
69
|
var import_smol_toml = require("smol-toml");
|
|
65
70
|
|
|
66
71
|
// src/utils/template.ts
|
|
@@ -99,97 +104,160 @@ async function loadTemplate(templatePath) {
|
|
|
99
104
|
return (0, import_promises.readFile)(fullPath, "utf-8");
|
|
100
105
|
}
|
|
101
106
|
|
|
102
|
-
// src/
|
|
107
|
+
// src/generators/ConfigurableGenerator.ts
|
|
103
108
|
var { existsSync, ensureDir, writeFile, copy } = import_fs_extra.default;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
let agentDir;
|
|
109
|
-
let setupFile;
|
|
110
|
-
if (agentType === "claude-code") {
|
|
111
|
-
agentDir = ".claude";
|
|
112
|
-
setupFile = (0, import_path2.join)(targetDir, agentDir, "commands", "conductor:setup.md");
|
|
113
|
-
} else if (agentType === "antigravity") {
|
|
114
|
-
agentDir = ".agent";
|
|
115
|
-
setupFile = (0, import_path2.join)(targetDir, agentDir, "workflows", "conductor:setup.md");
|
|
116
|
-
} else {
|
|
117
|
-
agentDir = ".opencode";
|
|
118
|
-
setupFile = (0, import_path2.join)(targetDir, agentDir, "commands", "conductor:setup.md");
|
|
119
|
-
}
|
|
120
|
-
const agentPath = (0, import_path2.join)(targetDir, agentDir);
|
|
121
|
-
const conductorPath = (0, import_path2.join)(agentPath, "conductor");
|
|
122
|
-
if (existsSync(conductorPath) && existsSync(setupFile)) {
|
|
123
|
-
throw new Error(`Conductor (${agentType}) is already installed in: ${targetDir}`);
|
|
124
|
-
}
|
|
125
|
-
return targetDir;
|
|
126
|
-
}
|
|
127
|
-
async function createConductorDirectories(targetDir, agentType) {
|
|
128
|
-
let agentDir;
|
|
129
|
-
let commandsDir;
|
|
130
|
-
if (agentType === "claude-code") {
|
|
131
|
-
agentDir = ".claude";
|
|
132
|
-
commandsDir = "commands";
|
|
133
|
-
} else if (agentType === "antigravity") {
|
|
134
|
-
agentDir = ".agent";
|
|
135
|
-
commandsDir = "workflows";
|
|
136
|
-
} else {
|
|
137
|
-
agentDir = ".opencode";
|
|
138
|
-
commandsDir = "commands";
|
|
139
|
-
}
|
|
140
|
-
const agentPath = (0, import_path2.join)(targetDir, agentDir);
|
|
141
|
-
await ensureDir((0, import_path2.join)(agentPath, commandsDir));
|
|
142
|
-
await ensureDir((0, import_path2.join)(agentPath, "conductor"));
|
|
143
|
-
}
|
|
144
|
-
async function copyTemplateFiles(targetDir, agentType) {
|
|
145
|
-
const commands = ["setup", "newTrack", "implement", "status", "revert"];
|
|
146
|
-
let agentDir;
|
|
147
|
-
let commandsDir;
|
|
148
|
-
if (agentType === "claude-code") {
|
|
149
|
-
agentDir = ".claude";
|
|
150
|
-
commandsDir = "commands";
|
|
151
|
-
} else if (agentType === "antigravity") {
|
|
152
|
-
agentDir = ".agent";
|
|
153
|
-
commandsDir = "workflows";
|
|
154
|
-
} else {
|
|
155
|
-
agentDir = ".opencode";
|
|
156
|
-
commandsDir = "commands";
|
|
157
|
-
}
|
|
158
|
-
const agentPath = (0, import_path2.join)(targetDir, agentDir);
|
|
159
|
-
const targetCommandsDir = (0, import_path2.join)(agentPath, commandsDir);
|
|
160
|
-
const templateRoot = await getTemplateRoot();
|
|
161
|
-
const installPath = (0, import_path2.join)(agentDir, "conductor");
|
|
162
|
-
try {
|
|
163
|
-
const templateSource = (0, import_path2.join)(templateRoot, "templates");
|
|
164
|
-
const templateDest = (0, import_path2.join)(agentPath, "conductor", "templates");
|
|
165
|
-
await copy(templateSource, templateDest);
|
|
166
|
-
} catch (e) {
|
|
167
|
-
console.warn("Failed to copy templates directory:", e);
|
|
109
|
+
function processTemplateContent(tomlContent, installPath, agentType) {
|
|
110
|
+
const parsed = (0, import_smol_toml.parse)(tomlContent);
|
|
111
|
+
if (!parsed.prompt) {
|
|
112
|
+
return null;
|
|
168
113
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const parsed = (0, import_smol_toml.parse)(tomlContent);
|
|
175
|
-
if (!parsed.prompt) {
|
|
176
|
-
console.warn(`Warning: No prompt found in ${cmd}.toml`);
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
let prompt = parsed.prompt;
|
|
180
|
-
prompt = prompt.replace(/__\$\$CODE_AGENT_INSTALL_PATH\$\$__/g, installPath);
|
|
181
|
-
finalContent = substituteVariables(prompt, { agent_type: agentType });
|
|
182
|
-
if (parsed.description) {
|
|
183
|
-
finalContent = `---
|
|
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 `---
|
|
184
119
|
description: ${parsed.description}
|
|
185
120
|
---
|
|
186
121
|
${finalContent}`;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
122
|
+
}
|
|
123
|
+
return finalContent;
|
|
124
|
+
}
|
|
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;
|
|
140
|
+
}
|
|
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();
|
|
149
|
+
try {
|
|
150
|
+
const templateSource = (0, import_path2.join)(templateRoot, "templates");
|
|
151
|
+
const templateDest = (0, import_path2.join)(agentPath, "conductor", "templates");
|
|
152
|
+
await copy(templateSource, templateDest);
|
|
190
153
|
} catch (e) {
|
|
191
|
-
console.warn(
|
|
154
|
+
console.warn("Failed to copy templates directory:", e);
|
|
192
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();
|
|
193
261
|
}
|
|
194
262
|
}
|
|
195
263
|
|
|
@@ -202,15 +270,13 @@ async function installHandler(argv) {
|
|
|
202
270
|
console.log("Step 1: Prompting for agent selection...");
|
|
203
271
|
const agent = await promptForAgent();
|
|
204
272
|
console.log(`\u2714 Selected agent: ${agent}`);
|
|
273
|
+
const generator = getGenerator(agent);
|
|
205
274
|
console.log("\nStep 2: Validating project directory...");
|
|
206
|
-
const validatedPath = await
|
|
275
|
+
const validatedPath = await generator.validate(targetDir);
|
|
207
276
|
console.log(`\u2714 Validation complete: ${validatedPath}`);
|
|
208
|
-
console.log("\nStep 3:
|
|
209
|
-
await
|
|
210
|
-
console.log("\u2714
|
|
211
|
-
console.log("\nStep 4: Copying template files...");
|
|
212
|
-
await copyTemplateFiles(validatedPath, agent);
|
|
213
|
-
console.log("\u2714 Templates copied");
|
|
277
|
+
console.log("\nStep 3: Generating files...");
|
|
278
|
+
await generator.generate(validatedPath);
|
|
279
|
+
console.log("\u2714 Files generated");
|
|
214
280
|
console.log("\n\u2714 Conductor initialized successfully!");
|
|
215
281
|
} catch (err) {
|
|
216
282
|
console.error("\n\u2718 Installation failed:", err instanceof Error ? err.message : err);
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,11 @@ async function promptForAgent() {
|
|
|
24
24
|
name: "Antigravity",
|
|
25
25
|
value: "antigravity",
|
|
26
26
|
description: "Google's agentic coding assistant"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "Cursor",
|
|
30
|
+
value: "cursor",
|
|
31
|
+
description: "Cursor IDE's AI agent"
|
|
27
32
|
}
|
|
28
33
|
],
|
|
29
34
|
default: "opencode"
|
|
@@ -31,9 +36,9 @@ async function promptForAgent() {
|
|
|
31
36
|
return answer;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
// src/
|
|
35
|
-
import fs from "fs-extra";
|
|
39
|
+
// src/generators/ConfigurableGenerator.ts
|
|
36
40
|
import { join as join2 } from "path";
|
|
41
|
+
import fs from "fs-extra";
|
|
37
42
|
import { parse } from "smol-toml";
|
|
38
43
|
|
|
39
44
|
// src/utils/template.ts
|
|
@@ -72,97 +77,160 @@ async function loadTemplate(templatePath) {
|
|
|
72
77
|
return readFile(fullPath, "utf-8");
|
|
73
78
|
}
|
|
74
79
|
|
|
75
|
-
// src/
|
|
80
|
+
// src/generators/ConfigurableGenerator.ts
|
|
76
81
|
var { existsSync, ensureDir, writeFile, copy } = fs;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
let agentDir;
|
|
82
|
-
let setupFile;
|
|
83
|
-
if (agentType === "claude-code") {
|
|
84
|
-
agentDir = ".claude";
|
|
85
|
-
setupFile = join2(targetDir, agentDir, "commands", "conductor:setup.md");
|
|
86
|
-
} else if (agentType === "antigravity") {
|
|
87
|
-
agentDir = ".agent";
|
|
88
|
-
setupFile = join2(targetDir, agentDir, "workflows", "conductor:setup.md");
|
|
89
|
-
} else {
|
|
90
|
-
agentDir = ".opencode";
|
|
91
|
-
setupFile = join2(targetDir, agentDir, "commands", "conductor:setup.md");
|
|
92
|
-
}
|
|
93
|
-
const agentPath = join2(targetDir, agentDir);
|
|
94
|
-
const conductorPath = join2(agentPath, "conductor");
|
|
95
|
-
if (existsSync(conductorPath) && existsSync(setupFile)) {
|
|
96
|
-
throw new Error(`Conductor (${agentType}) is already installed in: ${targetDir}`);
|
|
97
|
-
}
|
|
98
|
-
return targetDir;
|
|
99
|
-
}
|
|
100
|
-
async function createConductorDirectories(targetDir, agentType) {
|
|
101
|
-
let agentDir;
|
|
102
|
-
let commandsDir;
|
|
103
|
-
if (agentType === "claude-code") {
|
|
104
|
-
agentDir = ".claude";
|
|
105
|
-
commandsDir = "commands";
|
|
106
|
-
} else if (agentType === "antigravity") {
|
|
107
|
-
agentDir = ".agent";
|
|
108
|
-
commandsDir = "workflows";
|
|
109
|
-
} else {
|
|
110
|
-
agentDir = ".opencode";
|
|
111
|
-
commandsDir = "commands";
|
|
112
|
-
}
|
|
113
|
-
const agentPath = join2(targetDir, agentDir);
|
|
114
|
-
await ensureDir(join2(agentPath, commandsDir));
|
|
115
|
-
await ensureDir(join2(agentPath, "conductor"));
|
|
116
|
-
}
|
|
117
|
-
async function copyTemplateFiles(targetDir, agentType) {
|
|
118
|
-
const commands = ["setup", "newTrack", "implement", "status", "revert"];
|
|
119
|
-
let agentDir;
|
|
120
|
-
let commandsDir;
|
|
121
|
-
if (agentType === "claude-code") {
|
|
122
|
-
agentDir = ".claude";
|
|
123
|
-
commandsDir = "commands";
|
|
124
|
-
} else if (agentType === "antigravity") {
|
|
125
|
-
agentDir = ".agent";
|
|
126
|
-
commandsDir = "workflows";
|
|
127
|
-
} else {
|
|
128
|
-
agentDir = ".opencode";
|
|
129
|
-
commandsDir = "commands";
|
|
130
|
-
}
|
|
131
|
-
const agentPath = join2(targetDir, agentDir);
|
|
132
|
-
const targetCommandsDir = join2(agentPath, commandsDir);
|
|
133
|
-
const templateRoot = await getTemplateRoot();
|
|
134
|
-
const installPath = join2(agentDir, "conductor");
|
|
135
|
-
try {
|
|
136
|
-
const templateSource = join2(templateRoot, "templates");
|
|
137
|
-
const templateDest = join2(agentPath, "conductor", "templates");
|
|
138
|
-
await copy(templateSource, templateDest);
|
|
139
|
-
} catch (e) {
|
|
140
|
-
console.warn("Failed to copy templates directory:", e);
|
|
82
|
+
function processTemplateContent(tomlContent, installPath, agentType) {
|
|
83
|
+
const parsed = parse(tomlContent);
|
|
84
|
+
if (!parsed.prompt) {
|
|
85
|
+
return null;
|
|
141
86
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const parsed = parse(tomlContent);
|
|
148
|
-
if (!parsed.prompt) {
|
|
149
|
-
console.warn(`Warning: No prompt found in ${cmd}.toml`);
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
let prompt = parsed.prompt;
|
|
153
|
-
prompt = prompt.replace(/__\$\$CODE_AGENT_INSTALL_PATH\$\$__/g, installPath);
|
|
154
|
-
finalContent = substituteVariables(prompt, { agent_type: agentType });
|
|
155
|
-
if (parsed.description) {
|
|
156
|
-
finalContent = `---
|
|
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 `---
|
|
157
92
|
description: ${parsed.description}
|
|
158
93
|
---
|
|
159
94
|
${finalContent}`;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
95
|
+
}
|
|
96
|
+
return finalContent;
|
|
97
|
+
}
|
|
98
|
+
var ConfigurableGenerator = class {
|
|
99
|
+
constructor(config) {
|
|
100
|
+
this.config = config;
|
|
101
|
+
}
|
|
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();
|
|
122
|
+
try {
|
|
123
|
+
const templateSource = join2(templateRoot, "templates");
|
|
124
|
+
const templateDest = join2(agentPath, "conductor", "templates");
|
|
125
|
+
await copy(templateSource, templateDest);
|
|
163
126
|
} catch (e) {
|
|
164
|
-
console.warn(
|
|
127
|
+
console.warn("Failed to copy templates directory:", e);
|
|
165
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();
|
|
166
234
|
}
|
|
167
235
|
}
|
|
168
236
|
|
|
@@ -175,15 +243,13 @@ async function installHandler(argv) {
|
|
|
175
243
|
console.log("Step 1: Prompting for agent selection...");
|
|
176
244
|
const agent = await promptForAgent();
|
|
177
245
|
console.log(`\u2714 Selected agent: ${agent}`);
|
|
246
|
+
const generator = getGenerator(agent);
|
|
178
247
|
console.log("\nStep 2: Validating project directory...");
|
|
179
|
-
const validatedPath = await
|
|
248
|
+
const validatedPath = await generator.validate(targetDir);
|
|
180
249
|
console.log(`\u2714 Validation complete: ${validatedPath}`);
|
|
181
|
-
console.log("\nStep 3:
|
|
182
|
-
await
|
|
183
|
-
console.log("\u2714
|
|
184
|
-
console.log("\nStep 4: Copying template files...");
|
|
185
|
-
await copyTemplateFiles(validatedPath, agent);
|
|
186
|
-
console.log("\u2714 Templates copied");
|
|
250
|
+
console.log("\nStep 3: Generating files...");
|
|
251
|
+
await generator.generate(validatedPath);
|
|
252
|
+
console.log("\u2714 Files generated");
|
|
187
253
|
console.log("\n\u2714 Conductor initialized successfully!");
|
|
188
254
|
} catch (err) {
|
|
189
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",
|