@agiflowai/aicode-toolkit 0.6.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/LICENSE +661 -0
- package/README.md +151 -0
- package/dist/cli.cjs +732 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +727 -0
- package/dist/index.cjs +17 -0
- package/dist/index.d.cts +282 -0
- package/dist/index.d.ts +282 -0
- package/dist/index.js +4 -0
- package/dist/mcp-Bdxvi2Ej.cjs +4 -0
- package/dist/mcp-BmhiAfeF.js +47 -0
- package/dist/mcp-CZIiB-6Y.js +3 -0
- package/dist/mcp-Dwt8nYQV.cjs +65 -0
- package/dist/services-DNldrNnu.js +739 -0
- package/dist/services-s1vmufE4.cjs +859 -0
- package/package.json +85 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { MCPServer, MCP_SERVER_INFO } from "./mcp-BmhiAfeF.js";
|
|
3
|
+
import { CodingAgentService, NewProjectService, TemplateSelectionService, cloneRepository, cloneSubdirectory, displayBanner, findWorkspaceRoot, parseGitHubUrl } from "./services-DNldrNnu.js";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { ProjectType, TemplatesManagerService, icons, messages, print, sections } from "@agiflowai/aicode-utils";
|
|
7
|
+
import * as fs from "fs-extra";
|
|
8
|
+
import { confirm, input, select } from "@inquirer/prompts";
|
|
9
|
+
import { assign, createActor, createMachine, fromPromise } from "xstate";
|
|
10
|
+
|
|
11
|
+
//#region package.json
|
|
12
|
+
var name = "@agiflowai/aicode-toolkit";
|
|
13
|
+
var description = "AI-powered code toolkit CLI for scaffolding, architecture management, and development workflows";
|
|
14
|
+
var version = "0.6.0";
|
|
15
|
+
var license = "AGPL-3.0";
|
|
16
|
+
var author = "AgiflowIO";
|
|
17
|
+
var repository = {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/AgiFlow/aicode-toolkit.git",
|
|
20
|
+
"directory": "apps/aicode-toolkit"
|
|
21
|
+
};
|
|
22
|
+
var homepage = "https://github.com/AgiFlow/aicode-toolkit#readme";
|
|
23
|
+
var bugs = { "url": "https://github.com/AgiFlow/aicode-toolkit/issues" };
|
|
24
|
+
var keywords = [
|
|
25
|
+
"mcp",
|
|
26
|
+
"model-context-protocol",
|
|
27
|
+
"scaffold",
|
|
28
|
+
"boilerplate",
|
|
29
|
+
"template",
|
|
30
|
+
"code-generation",
|
|
31
|
+
"nextjs",
|
|
32
|
+
"react",
|
|
33
|
+
"vite"
|
|
34
|
+
];
|
|
35
|
+
var bin = { "aicode": "./dist/cli.cjs" };
|
|
36
|
+
var main$1 = "./dist/index.cjs";
|
|
37
|
+
var types = "./dist/index.d.cts";
|
|
38
|
+
var module = "./dist/index.js";
|
|
39
|
+
var files = ["dist", "README.md"];
|
|
40
|
+
var scripts = {
|
|
41
|
+
"dev": "node --loader ts-node/esm src/cli.ts",
|
|
42
|
+
"build": "tsdown",
|
|
43
|
+
"test": "vitest --run",
|
|
44
|
+
"typecheck": "tsc --noEmit"
|
|
45
|
+
};
|
|
46
|
+
var dependencies = {
|
|
47
|
+
"@agiflowai/aicode-utils": "workspace:*",
|
|
48
|
+
"@agiflowai/coding-agent-bridge": "workspace:*",
|
|
49
|
+
"@composio/json-schema-to-zod": "0.1.15",
|
|
50
|
+
"@inquirer/prompts": "^7.8.6",
|
|
51
|
+
"@modelcontextprotocol/sdk": "1.19.1",
|
|
52
|
+
"chalk": "5.6.2",
|
|
53
|
+
"commander": "14.0.1",
|
|
54
|
+
"execa": "^9.5.2",
|
|
55
|
+
"express": "^4.21.2",
|
|
56
|
+
"fs-extra": "11.3.2",
|
|
57
|
+
"gradient-string": "^3.0.0",
|
|
58
|
+
"js-yaml": "4.1.0",
|
|
59
|
+
"liquidjs": "10.21.1",
|
|
60
|
+
"pino": "^10.0.0",
|
|
61
|
+
"pino-pretty": "^13.1.1",
|
|
62
|
+
"xstate": "^5.23.0",
|
|
63
|
+
"zod": "3.25.76"
|
|
64
|
+
};
|
|
65
|
+
var devDependencies = {
|
|
66
|
+
"@types/express": "^5.0.0",
|
|
67
|
+
"@types/fs-extra": "^11.0.4",
|
|
68
|
+
"@types/js-yaml": "^4.0.9",
|
|
69
|
+
"@types/node": "^22.0.0",
|
|
70
|
+
"tsdown": "^0.15.6",
|
|
71
|
+
"typescript": "5.9.3"
|
|
72
|
+
};
|
|
73
|
+
var publishConfig = { "access": "public" };
|
|
74
|
+
var type = "module";
|
|
75
|
+
var exports = {
|
|
76
|
+
".": {
|
|
77
|
+
"import": "./dist/index.js",
|
|
78
|
+
"require": "./dist/index.cjs"
|
|
79
|
+
},
|
|
80
|
+
"./cli": {
|
|
81
|
+
"import": "./dist/cli.js",
|
|
82
|
+
"require": "./dist/cli.cjs"
|
|
83
|
+
},
|
|
84
|
+
"./package.json": "./package.json"
|
|
85
|
+
};
|
|
86
|
+
var package_default = {
|
|
87
|
+
name,
|
|
88
|
+
description,
|
|
89
|
+
version,
|
|
90
|
+
license,
|
|
91
|
+
author,
|
|
92
|
+
repository,
|
|
93
|
+
homepage,
|
|
94
|
+
bugs,
|
|
95
|
+
keywords,
|
|
96
|
+
bin,
|
|
97
|
+
main: main$1,
|
|
98
|
+
types,
|
|
99
|
+
module,
|
|
100
|
+
files,
|
|
101
|
+
scripts,
|
|
102
|
+
dependencies,
|
|
103
|
+
devDependencies,
|
|
104
|
+
publishConfig,
|
|
105
|
+
type,
|
|
106
|
+
exports
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/commands/add.ts
|
|
111
|
+
/**
|
|
112
|
+
* Add command - add a template to templates folder
|
|
113
|
+
*/
|
|
114
|
+
const addCommand = new Command("add").description("Add a template to templates folder").requiredOption("--name <name>", "Template name").requiredOption("--url <url>", "URL of the template repository to download").option("--path <path>", "Override templates folder path (uses toolkit.yaml config by default)").option("--type <type>", "Template type: boilerplate or scaffold", "boilerplate").action(async (options) => {
|
|
115
|
+
try {
|
|
116
|
+
const templatesPath = options.path ? path.resolve(options.path) : await TemplatesManagerService.findTemplatesPath();
|
|
117
|
+
const templateType = options.type.toLowerCase();
|
|
118
|
+
const templateName = options.name;
|
|
119
|
+
const templateUrl = options.url;
|
|
120
|
+
if (templateType !== "boilerplate" && templateType !== "scaffold") {
|
|
121
|
+
messages.error("Invalid template type. Use: boilerplate or scaffold");
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
const targetFolder = path.join(templatesPath, `${templateType}s`, templateName);
|
|
125
|
+
if (await fs.pathExists(targetFolder)) {
|
|
126
|
+
messages.error(`Template '${templateName}' already exists at ${targetFolder}`);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
print.info(`${icons.download} Downloading template '${templateName}' from ${templateUrl}...`);
|
|
130
|
+
await fs.ensureDir(path.dirname(targetFolder));
|
|
131
|
+
const parsedUrl = parseGitHubUrl(templateUrl);
|
|
132
|
+
try {
|
|
133
|
+
if (parsedUrl.isSubdirectory && parsedUrl.branch && parsedUrl.subdirectory) {
|
|
134
|
+
print.info(`${icons.folder} Detected subdirectory: ${parsedUrl.subdirectory} (branch: ${parsedUrl.branch})`);
|
|
135
|
+
await cloneSubdirectory(parsedUrl.repoUrl, parsedUrl.branch, parsedUrl.subdirectory, targetFolder);
|
|
136
|
+
} else await cloneRepository(parsedUrl.repoUrl, targetFolder);
|
|
137
|
+
messages.success(`Template '${templateName}' added successfully!`);
|
|
138
|
+
print.header(`\n${icons.folder} Template location:`);
|
|
139
|
+
print.indent(targetFolder);
|
|
140
|
+
const configFiles = [path.join(targetFolder, "boilerplate.yaml"), path.join(targetFolder, "scaffold.yaml")];
|
|
141
|
+
let hasConfig = false;
|
|
142
|
+
for (const configFile of configFiles) if (await fs.pathExists(configFile)) {
|
|
143
|
+
print.header(`\n${icons.config} Configuration file found:`);
|
|
144
|
+
print.indent(path.basename(configFile));
|
|
145
|
+
hasConfig = true;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
if (!hasConfig) {
|
|
149
|
+
messages.warning("Warning: No configuration file found (boilerplate.yaml or scaffold.yaml)");
|
|
150
|
+
print.indent("You may need to create one manually.");
|
|
151
|
+
}
|
|
152
|
+
sections.nextSteps([`Review the template in ${targetFolder}`, `Test it with: scaffold-mcp ${templateType} list`]);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (error.message.includes("not found") || error.message.includes("command not found")) messages.error("git command not found. Please install git first.");
|
|
155
|
+
else if (error.message.includes("Authentication failed")) messages.error("Authentication failed. Make sure you have access to the repository.");
|
|
156
|
+
else if (error.message.includes("Repository not found")) messages.error("Repository not found. Check the URL and try again.");
|
|
157
|
+
else messages.error("Failed to clone repository:", error);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
} catch (error) {
|
|
161
|
+
messages.error("Error adding template:", error);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/states/init-machine.ts
|
|
168
|
+
/**
|
|
169
|
+
* Init command state machine
|
|
170
|
+
* Pure declarative state machine definition
|
|
171
|
+
* Actors are provided externally for better separation of concerns
|
|
172
|
+
*/
|
|
173
|
+
const initMachine = createMachine({
|
|
174
|
+
id: "init",
|
|
175
|
+
types: {},
|
|
176
|
+
initial: "displayingBanner",
|
|
177
|
+
context: ({ input: input$1 }) => ({
|
|
178
|
+
workspaceRoot: void 0,
|
|
179
|
+
projectName: void 0,
|
|
180
|
+
projectType: void 0,
|
|
181
|
+
projectPath: void 0,
|
|
182
|
+
repositoryExists: false,
|
|
183
|
+
detectionConfidence: void 0,
|
|
184
|
+
detectionIndicators: void 0,
|
|
185
|
+
templatesPath: void 0,
|
|
186
|
+
tmpTemplatesPath: void 0,
|
|
187
|
+
selectedTemplates: void 0,
|
|
188
|
+
selectedMcpServers: void 0,
|
|
189
|
+
detectedCodingAgent: void 0,
|
|
190
|
+
codingAgent: void 0,
|
|
191
|
+
options: input$1.options,
|
|
192
|
+
error: void 0
|
|
193
|
+
}),
|
|
194
|
+
states: {
|
|
195
|
+
displayingBanner: { invoke: {
|
|
196
|
+
src: "displayBanner",
|
|
197
|
+
onDone: { target: "checkingWorkspace" }
|
|
198
|
+
} },
|
|
199
|
+
checkingWorkspace: { invoke: {
|
|
200
|
+
src: "checkWorkspaceExists",
|
|
201
|
+
onDone: [{
|
|
202
|
+
target: "detectingProjectType",
|
|
203
|
+
guard: ({ event }) => event.output.exists === true,
|
|
204
|
+
actions: assign({
|
|
205
|
+
workspaceRoot: ({ event }) => event.output.workspaceRoot,
|
|
206
|
+
repositoryExists: () => true
|
|
207
|
+
})
|
|
208
|
+
}, {
|
|
209
|
+
target: "creatingNewProject",
|
|
210
|
+
guard: ({ event }) => event.output.exists === false,
|
|
211
|
+
actions: assign({ repositoryExists: () => false })
|
|
212
|
+
}]
|
|
213
|
+
} },
|
|
214
|
+
detectingProjectType: { invoke: {
|
|
215
|
+
src: "detectProjectType",
|
|
216
|
+
input: ({ context }) => ({ workspaceRoot: context.workspaceRoot }),
|
|
217
|
+
onDone: [{
|
|
218
|
+
target: "checkingSkipTemplates",
|
|
219
|
+
guard: ({ event }) => event.output.confidence === "high",
|
|
220
|
+
actions: assign({
|
|
221
|
+
projectType: ({ event }) => event.output.projectType,
|
|
222
|
+
detectionConfidence: ({ event }) => event.output.confidence,
|
|
223
|
+
detectionIndicators: ({ event }) => event.output.indicators
|
|
224
|
+
})
|
|
225
|
+
}, {
|
|
226
|
+
target: "promptingProjectType",
|
|
227
|
+
actions: assign({
|
|
228
|
+
detectionConfidence: ({ event }) => event.output.confidence,
|
|
229
|
+
detectionIndicators: ({ event }) => event.output.indicators
|
|
230
|
+
})
|
|
231
|
+
}],
|
|
232
|
+
onError: {
|
|
233
|
+
target: "failed",
|
|
234
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
235
|
+
}
|
|
236
|
+
} },
|
|
237
|
+
promptingProjectType: { invoke: {
|
|
238
|
+
src: "promptProjectType",
|
|
239
|
+
input: ({ context }) => ({
|
|
240
|
+
providedProjectType: context.options.projectType,
|
|
241
|
+
detectionIndicators: context.detectionIndicators
|
|
242
|
+
}),
|
|
243
|
+
onDone: {
|
|
244
|
+
target: "checkingSkipTemplates",
|
|
245
|
+
actions: assign({ projectType: ({ event }) => event.output })
|
|
246
|
+
},
|
|
247
|
+
onError: {
|
|
248
|
+
target: "failed",
|
|
249
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
250
|
+
}
|
|
251
|
+
} },
|
|
252
|
+
creatingNewProject: {
|
|
253
|
+
initial: "promptingProjectName",
|
|
254
|
+
states: {
|
|
255
|
+
promptingProjectName: { invoke: {
|
|
256
|
+
src: "promptProjectName",
|
|
257
|
+
input: ({ context }) => ({ providedName: context.options.name }),
|
|
258
|
+
onDone: {
|
|
259
|
+
target: "creatingProjectDirectory",
|
|
260
|
+
actions: assign({ projectName: ({ event }) => event.output })
|
|
261
|
+
},
|
|
262
|
+
onError: {
|
|
263
|
+
target: "#init.failed",
|
|
264
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
265
|
+
}
|
|
266
|
+
} },
|
|
267
|
+
creatingProjectDirectory: { invoke: {
|
|
268
|
+
src: "createProjectDirectory",
|
|
269
|
+
input: ({ context }) => ({ projectName: context.projectName }),
|
|
270
|
+
onDone: {
|
|
271
|
+
target: "promptingGitSetup",
|
|
272
|
+
actions: assign({
|
|
273
|
+
projectPath: ({ event }) => event.output.projectPath,
|
|
274
|
+
workspaceRoot: ({ event }) => event.output.projectPath
|
|
275
|
+
})
|
|
276
|
+
},
|
|
277
|
+
onError: {
|
|
278
|
+
target: "#init.failed",
|
|
279
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
280
|
+
}
|
|
281
|
+
} },
|
|
282
|
+
promptingGitSetup: { invoke: {
|
|
283
|
+
src: "promptGitSetup",
|
|
284
|
+
input: ({ context }) => ({ projectPath: context.projectPath }),
|
|
285
|
+
onDone: { target: "promptingProjectType" },
|
|
286
|
+
onError: {
|
|
287
|
+
target: "#init.failed",
|
|
288
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
289
|
+
}
|
|
290
|
+
} },
|
|
291
|
+
promptingProjectType: { invoke: {
|
|
292
|
+
src: "promptProjectType",
|
|
293
|
+
input: ({ context }) => ({ providedProjectType: context.options.projectType }),
|
|
294
|
+
onDone: {
|
|
295
|
+
target: "#init.checkingSkipTemplates",
|
|
296
|
+
actions: assign({ projectType: ({ event }) => event.output })
|
|
297
|
+
},
|
|
298
|
+
onError: {
|
|
299
|
+
target: "#init.failed",
|
|
300
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
301
|
+
}
|
|
302
|
+
} }
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
checkingSkipTemplates: { always: [{
|
|
306
|
+
target: "promptingMcpSelection",
|
|
307
|
+
guard: ({ context }) => !context.options.skipTemplates
|
|
308
|
+
}, { target: "checkingSkipMcp" }] },
|
|
309
|
+
promptingMcpSelection: { invoke: {
|
|
310
|
+
src: "promptMcpSelection",
|
|
311
|
+
onDone: {
|
|
312
|
+
target: "downloadingTemplates",
|
|
313
|
+
actions: assign({ selectedMcpServers: ({ event }) => event.output })
|
|
314
|
+
},
|
|
315
|
+
onError: {
|
|
316
|
+
target: "failed",
|
|
317
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
318
|
+
}
|
|
319
|
+
} },
|
|
320
|
+
downloadingTemplates: { invoke: {
|
|
321
|
+
src: "downloadTemplates",
|
|
322
|
+
onDone: {
|
|
323
|
+
target: "listingTemplates",
|
|
324
|
+
actions: assign({ tmpTemplatesPath: ({ event }) => event.output })
|
|
325
|
+
},
|
|
326
|
+
onError: {
|
|
327
|
+
target: "failed",
|
|
328
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
329
|
+
}
|
|
330
|
+
} },
|
|
331
|
+
listingTemplates: { invoke: {
|
|
332
|
+
src: "listTemplates",
|
|
333
|
+
input: ({ context }) => ({ tmpTemplatesPath: context.tmpTemplatesPath }),
|
|
334
|
+
onDone: { target: "promptingTemplateSelection" },
|
|
335
|
+
onError: {
|
|
336
|
+
target: "failed",
|
|
337
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
338
|
+
}
|
|
339
|
+
} },
|
|
340
|
+
promptingTemplateSelection: { invoke: {
|
|
341
|
+
src: "promptTemplateSelection",
|
|
342
|
+
input: ({ context }) => ({
|
|
343
|
+
tmpTemplatesPath: context.tmpTemplatesPath,
|
|
344
|
+
projectType: context.projectType
|
|
345
|
+
}),
|
|
346
|
+
onDone: {
|
|
347
|
+
target: "copyingTemplates",
|
|
348
|
+
actions: assign({ selectedTemplates: ({ event }) => event.output })
|
|
349
|
+
},
|
|
350
|
+
onError: {
|
|
351
|
+
target: "failed",
|
|
352
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
353
|
+
}
|
|
354
|
+
} },
|
|
355
|
+
copyingTemplates: { invoke: {
|
|
356
|
+
src: "copyTemplates",
|
|
357
|
+
input: ({ context }) => ({
|
|
358
|
+
tmpTemplatesPath: context.tmpTemplatesPath,
|
|
359
|
+
workspaceRoot: context.workspaceRoot,
|
|
360
|
+
selectedTemplates: context.selectedTemplates,
|
|
361
|
+
projectType: context.projectType,
|
|
362
|
+
selectedMcpServers: context.selectedMcpServers
|
|
363
|
+
}),
|
|
364
|
+
onDone: {
|
|
365
|
+
target: "creatingConfig",
|
|
366
|
+
actions: assign({ templatesPath: ({ event }) => event.output })
|
|
367
|
+
},
|
|
368
|
+
onError: {
|
|
369
|
+
target: "failed",
|
|
370
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
371
|
+
}
|
|
372
|
+
} },
|
|
373
|
+
creatingConfig: { invoke: {
|
|
374
|
+
src: "createConfig",
|
|
375
|
+
input: ({ context }) => ({
|
|
376
|
+
workspaceRoot: context.workspaceRoot,
|
|
377
|
+
projectType: context.projectType,
|
|
378
|
+
selectedTemplates: context.selectedTemplates
|
|
379
|
+
}),
|
|
380
|
+
onDone: { target: "checkingSkipMcp" },
|
|
381
|
+
onError: {
|
|
382
|
+
target: "failed",
|
|
383
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
384
|
+
}
|
|
385
|
+
} },
|
|
386
|
+
checkingSkipMcp: { always: [{
|
|
387
|
+
target: "detectingCodingAgent",
|
|
388
|
+
guard: ({ context }) => !context.options.skipMcp
|
|
389
|
+
}, { target: "cleaningUp" }] },
|
|
390
|
+
detectingCodingAgent: { invoke: {
|
|
391
|
+
src: "detectCodingAgent",
|
|
392
|
+
input: ({ context }) => ({ workspaceRoot: context.workspaceRoot }),
|
|
393
|
+
onDone: {
|
|
394
|
+
target: "promptingCodingAgent",
|
|
395
|
+
actions: assign({ detectedCodingAgent: ({ event }) => event.output })
|
|
396
|
+
},
|
|
397
|
+
onError: {
|
|
398
|
+
target: "failed",
|
|
399
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
400
|
+
}
|
|
401
|
+
} },
|
|
402
|
+
promptingCodingAgent: { invoke: {
|
|
403
|
+
src: "promptCodingAgent",
|
|
404
|
+
input: ({ context }) => ({ detectedAgent: context.detectedCodingAgent }),
|
|
405
|
+
onDone: {
|
|
406
|
+
target: "configuringMCP",
|
|
407
|
+
actions: assign({ codingAgent: ({ event }) => event.output })
|
|
408
|
+
},
|
|
409
|
+
onError: {
|
|
410
|
+
target: "failed",
|
|
411
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
412
|
+
}
|
|
413
|
+
} },
|
|
414
|
+
configuringMCP: { invoke: {
|
|
415
|
+
src: "configureMCP",
|
|
416
|
+
input: ({ context }) => ({
|
|
417
|
+
workspaceRoot: context.workspaceRoot,
|
|
418
|
+
codingAgent: context.codingAgent
|
|
419
|
+
}),
|
|
420
|
+
onDone: { target: "cleaningUp" },
|
|
421
|
+
onError: {
|
|
422
|
+
target: "failed",
|
|
423
|
+
actions: assign({ error: ({ event }) => event.error })
|
|
424
|
+
}
|
|
425
|
+
} },
|
|
426
|
+
cleaningUp: { invoke: {
|
|
427
|
+
src: "cleanup",
|
|
428
|
+
input: ({ context }) => ({ tmpTemplatesPath: context.tmpTemplatesPath }),
|
|
429
|
+
onDone: { target: "completed" },
|
|
430
|
+
onError: { target: "completed" }
|
|
431
|
+
} },
|
|
432
|
+
completed: { type: "final" },
|
|
433
|
+
failed: { type: "final" }
|
|
434
|
+
}
|
|
435
|
+
}, { guards: {} });
|
|
436
|
+
|
|
437
|
+
//#endregion
|
|
438
|
+
//#region src/commands/init.ts
|
|
439
|
+
const DEFAULT_TEMPLATE_REPO = {
|
|
440
|
+
owner: "AgiFlow",
|
|
441
|
+
repo: "aicode-toolkit",
|
|
442
|
+
branch: "main",
|
|
443
|
+
path: "templates"
|
|
444
|
+
};
|
|
445
|
+
/**
|
|
446
|
+
* Actor implementations for the init V2 state machine
|
|
447
|
+
*/
|
|
448
|
+
const initActors = {
|
|
449
|
+
displayBanner: fromPromise(async () => {
|
|
450
|
+
displayBanner();
|
|
451
|
+
}),
|
|
452
|
+
checkWorkspaceExists: fromPromise(async () => {
|
|
453
|
+
const workspaceRoot = await findWorkspaceRoot();
|
|
454
|
+
if (workspaceRoot) {
|
|
455
|
+
print.info(`Found workspace at: ${workspaceRoot}`);
|
|
456
|
+
return {
|
|
457
|
+
exists: true,
|
|
458
|
+
workspaceRoot
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
return { exists: false };
|
|
462
|
+
}),
|
|
463
|
+
detectProjectType: fromPromise(async ({ input: input$1 }) => {
|
|
464
|
+
print.info("\nDetecting project type...");
|
|
465
|
+
const nxJsonPath = path.join(input$1.workspaceRoot, "nx.json");
|
|
466
|
+
const lernaJsonPath = path.join(input$1.workspaceRoot, "lerna.json");
|
|
467
|
+
const pnpmWorkspacePath = path.join(input$1.workspaceRoot, "pnpm-workspace.yaml");
|
|
468
|
+
const turboJsonPath = path.join(input$1.workspaceRoot, "turbo.json");
|
|
469
|
+
const indicators = [];
|
|
470
|
+
let projectType;
|
|
471
|
+
let confidence = "low";
|
|
472
|
+
if (await fs.pathExists(nxJsonPath)) {
|
|
473
|
+
indicators.push("nx.json found");
|
|
474
|
+
projectType = ProjectType.MONOREPO;
|
|
475
|
+
confidence = "high";
|
|
476
|
+
}
|
|
477
|
+
if (await fs.pathExists(lernaJsonPath)) {
|
|
478
|
+
indicators.push("lerna.json found");
|
|
479
|
+
projectType = ProjectType.MONOREPO;
|
|
480
|
+
confidence = "high";
|
|
481
|
+
}
|
|
482
|
+
if (await fs.pathExists(pnpmWorkspacePath)) {
|
|
483
|
+
indicators.push("pnpm-workspace.yaml found");
|
|
484
|
+
projectType = ProjectType.MONOREPO;
|
|
485
|
+
confidence = "high";
|
|
486
|
+
}
|
|
487
|
+
if (await fs.pathExists(turboJsonPath)) {
|
|
488
|
+
indicators.push("turbo.json found");
|
|
489
|
+
projectType = ProjectType.MONOREPO;
|
|
490
|
+
confidence = "high";
|
|
491
|
+
}
|
|
492
|
+
const packageJsonPath = path.join(input$1.workspaceRoot, "package.json");
|
|
493
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
494
|
+
if ((await fs.readJson(packageJsonPath)).workspaces) {
|
|
495
|
+
indicators.push("package.json with workspaces found");
|
|
496
|
+
projectType = ProjectType.MONOREPO;
|
|
497
|
+
if (confidence !== "high") confidence = "medium";
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
const toolkitYamlPath = path.join(input$1.workspaceRoot, "toolkit.yaml");
|
|
501
|
+
if (await fs.pathExists(toolkitYamlPath)) {
|
|
502
|
+
const toolkitConfig = await TemplatesManagerService.readToolkitConfig(input$1.workspaceRoot);
|
|
503
|
+
if (toolkitConfig?.projectType) {
|
|
504
|
+
indicators.push(`toolkit.yaml specifies ${toolkitConfig.projectType}`);
|
|
505
|
+
projectType = toolkitConfig.projectType;
|
|
506
|
+
confidence = "high";
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
if (!projectType) {
|
|
510
|
+
projectType = ProjectType.MONOLITH;
|
|
511
|
+
indicators.push("No monorepo indicators found, assuming monolith");
|
|
512
|
+
confidence = "low";
|
|
513
|
+
}
|
|
514
|
+
if (confidence === "high") print.success(`Detected ${projectType} project (high confidence)`);
|
|
515
|
+
return {
|
|
516
|
+
projectType,
|
|
517
|
+
confidence,
|
|
518
|
+
indicators
|
|
519
|
+
};
|
|
520
|
+
}),
|
|
521
|
+
promptProjectType: fromPromise(async ({ input: actorInput }) => {
|
|
522
|
+
if (actorInput.providedProjectType) {
|
|
523
|
+
const projectType = actorInput.providedProjectType;
|
|
524
|
+
print.info(`Project type: ${projectType}`);
|
|
525
|
+
return projectType;
|
|
526
|
+
}
|
|
527
|
+
if (actorInput.detectionIndicators && actorInput.detectionIndicators.length > 0) {
|
|
528
|
+
print.info("\nDetection results:");
|
|
529
|
+
for (const indicator of actorInput.detectionIndicators) print.indent(`• ${indicator}`);
|
|
530
|
+
print.newline();
|
|
531
|
+
}
|
|
532
|
+
return await select({
|
|
533
|
+
message: "Select project type:",
|
|
534
|
+
choices: [{
|
|
535
|
+
name: "Monolith - Single application structure",
|
|
536
|
+
value: ProjectType.MONOLITH,
|
|
537
|
+
description: "Traditional single-application project structure"
|
|
538
|
+
}, {
|
|
539
|
+
name: "Monorepo - Multiple packages/apps in one repository",
|
|
540
|
+
value: ProjectType.MONOREPO,
|
|
541
|
+
description: "Multiple packages managed together (uses workspaces)"
|
|
542
|
+
}]
|
|
543
|
+
});
|
|
544
|
+
}),
|
|
545
|
+
promptProjectName: fromPromise(async ({ input: actorInput }) => {
|
|
546
|
+
const newProjectService = new NewProjectService(actorInput.providedName, void 0);
|
|
547
|
+
const providedName = newProjectService.getProvidedName();
|
|
548
|
+
if (providedName) {
|
|
549
|
+
const trimmedName = providedName.trim();
|
|
550
|
+
const validationResult = newProjectService.validateProjectName(trimmedName);
|
|
551
|
+
if (validationResult !== true) throw new Error(validationResult);
|
|
552
|
+
print.info(`Project name: ${trimmedName}`);
|
|
553
|
+
return trimmedName;
|
|
554
|
+
}
|
|
555
|
+
return await input({
|
|
556
|
+
message: "Enter your project name:",
|
|
557
|
+
validate: (value) => newProjectService.validateProjectName(value)
|
|
558
|
+
});
|
|
559
|
+
}),
|
|
560
|
+
createProjectDirectory: fromPromise(async ({ input: actorInput }) => {
|
|
561
|
+
const projectPath = path.join(process.cwd(), actorInput.projectName.trim());
|
|
562
|
+
await new NewProjectService(void 0, void 0).createProjectDirectory(projectPath, actorInput.projectName);
|
|
563
|
+
return { projectPath };
|
|
564
|
+
}),
|
|
565
|
+
promptGitSetup: fromPromise(async ({ input: actorInput }) => {
|
|
566
|
+
const newProjectService = new NewProjectService(void 0, void 0);
|
|
567
|
+
if (await confirm({
|
|
568
|
+
message: "Do you have an existing Git repository you want to use?",
|
|
569
|
+
default: false
|
|
570
|
+
})) {
|
|
571
|
+
const repoUrl = await input({
|
|
572
|
+
message: "Enter Git repository URL:",
|
|
573
|
+
validate: (value) => newProjectService.validateRepositoryUrl(value)
|
|
574
|
+
});
|
|
575
|
+
await newProjectService.cloneExistingRepository(repoUrl.trim(), actorInput.projectPath);
|
|
576
|
+
} else if (await confirm({
|
|
577
|
+
message: "Initialize a new Git repository?",
|
|
578
|
+
default: true
|
|
579
|
+
})) await newProjectService.initializeGitRepository(actorInput.projectPath);
|
|
580
|
+
}),
|
|
581
|
+
promptMcpSelection: fromPromise(async () => {
|
|
582
|
+
return await (await import("@inquirer/prompts").then((m) => m.checkbox))({
|
|
583
|
+
message: "Select MCP servers to configure:",
|
|
584
|
+
choices: Object.values(MCPServer).map((server) => ({
|
|
585
|
+
name: MCP_SERVER_INFO[server].name,
|
|
586
|
+
value: server,
|
|
587
|
+
description: MCP_SERVER_INFO[server].description,
|
|
588
|
+
checked: true
|
|
589
|
+
})),
|
|
590
|
+
validate: (answer) => {
|
|
591
|
+
if (answer.length === 0) return "Please select at least one MCP server";
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
}),
|
|
596
|
+
downloadTemplates: fromPromise(async () => {
|
|
597
|
+
return await new TemplateSelectionService().downloadTemplatesToTmp(DEFAULT_TEMPLATE_REPO);
|
|
598
|
+
}),
|
|
599
|
+
listTemplates: fromPromise(async ({ input: input$1 }) => {
|
|
600
|
+
const templates = await new TemplateSelectionService(input$1.tmpTemplatesPath).listTemplates();
|
|
601
|
+
print.header("\nAvailable templates:");
|
|
602
|
+
for (const template of templates) print.item(`${template.name}${template.description ? ` - ${template.description}` : ""}`);
|
|
603
|
+
return templates;
|
|
604
|
+
}),
|
|
605
|
+
promptTemplateSelection: fromPromise(async ({ input: actorInput }) => {
|
|
606
|
+
const templates = await new TemplateSelectionService(actorInput.tmpTemplatesPath).listTemplates();
|
|
607
|
+
if (templates.length === 0) throw new Error("No templates available");
|
|
608
|
+
if (actorInput.projectType === ProjectType.MONOLITH) return [await select({
|
|
609
|
+
message: "Select template (monolith allows only one):",
|
|
610
|
+
choices: templates.map((t) => ({
|
|
611
|
+
name: t.name,
|
|
612
|
+
value: t.name,
|
|
613
|
+
description: t.description
|
|
614
|
+
}))
|
|
615
|
+
})];
|
|
616
|
+
const selected = await (await import("@inquirer/prompts").then((m) => m.checkbox))({
|
|
617
|
+
message: "Select templates (use space to select, enter to confirm):",
|
|
618
|
+
choices: templates.map((t) => ({
|
|
619
|
+
name: t.name,
|
|
620
|
+
value: t.name,
|
|
621
|
+
description: t.description,
|
|
622
|
+
checked: true
|
|
623
|
+
}))
|
|
624
|
+
});
|
|
625
|
+
if (selected.length === 0) throw new Error("Please select at least one template");
|
|
626
|
+
return selected;
|
|
627
|
+
}),
|
|
628
|
+
copyTemplates: fromPromise(async ({ input: actorInput }) => {
|
|
629
|
+
const templateSelectionService = new TemplateSelectionService(actorInput.tmpTemplatesPath);
|
|
630
|
+
const templatesPath = path.join(actorInput.workspaceRoot, "templates");
|
|
631
|
+
await templateSelectionService.copyTemplates(actorInput.selectedTemplates, templatesPath, actorInput.projectType, actorInput.selectedMcpServers);
|
|
632
|
+
return templatesPath;
|
|
633
|
+
}),
|
|
634
|
+
createConfig: fromPromise(async ({ input: actorInput }) => {
|
|
635
|
+
if (actorInput.projectType === ProjectType.MONOLITH) {
|
|
636
|
+
const toolkitConfig = {
|
|
637
|
+
version: "1.0",
|
|
638
|
+
templatesPath: "templates",
|
|
639
|
+
projectType: "monolith",
|
|
640
|
+
sourceTemplate: actorInput.selectedTemplates[0]
|
|
641
|
+
};
|
|
642
|
+
print.info("\nCreating toolkit.yaml...");
|
|
643
|
+
await TemplatesManagerService.writeToolkitConfig(toolkitConfig, actorInput.workspaceRoot);
|
|
644
|
+
print.success("toolkit.yaml created");
|
|
645
|
+
}
|
|
646
|
+
}),
|
|
647
|
+
detectCodingAgent: fromPromise(async ({ input: actorInput }) => {
|
|
648
|
+
print.info("\nDetecting coding agent...");
|
|
649
|
+
const detectedAgent = await CodingAgentService.detectCodingAgent(actorInput.workspaceRoot);
|
|
650
|
+
if (detectedAgent) print.success(`Detected ${detectedAgent} in workspace`);
|
|
651
|
+
else print.info("No coding agent detected automatically");
|
|
652
|
+
return detectedAgent;
|
|
653
|
+
}),
|
|
654
|
+
promptCodingAgent: fromPromise(async ({ input: actorInput }) => {
|
|
655
|
+
if (actorInput.detectedAgent) {
|
|
656
|
+
print.info(`Using detected coding agent: ${actorInput.detectedAgent}`);
|
|
657
|
+
return actorInput.detectedAgent;
|
|
658
|
+
}
|
|
659
|
+
return await select({
|
|
660
|
+
message: "Select coding agent for MCP configuration:",
|
|
661
|
+
choices: CodingAgentService.getAvailableAgents().map((agent) => ({
|
|
662
|
+
name: agent.name,
|
|
663
|
+
value: agent.value,
|
|
664
|
+
description: agent.description
|
|
665
|
+
}))
|
|
666
|
+
});
|
|
667
|
+
}),
|
|
668
|
+
configureMCP: fromPromise(async ({ input: actorInput }) => {
|
|
669
|
+
await new CodingAgentService(actorInput.workspaceRoot).setupMCP(actorInput.codingAgent);
|
|
670
|
+
}),
|
|
671
|
+
cleanup: fromPromise(async ({ input: input$1 }) => {
|
|
672
|
+
if (input$1.tmpTemplatesPath) await new TemplateSelectionService(input$1.tmpTemplatesPath).cleanup();
|
|
673
|
+
})
|
|
674
|
+
};
|
|
675
|
+
/**
|
|
676
|
+
* Init command - improved V2 implementation
|
|
677
|
+
*/
|
|
678
|
+
const initCommand = new Command("init").description("Initialize project with templates and MCP configuration").option("--name <name>", "Project name (for new projects)").option("--project-type <type>", "Project type: monolith or monorepo (for new projects)").option("--skip-templates", "Skip template download and selection").option("--skip-mcp", "Skip MCP configuration").action(async (options) => {
|
|
679
|
+
try {
|
|
680
|
+
const actor = createActor(initMachine.provide({ actors: initActors }), { input: { options: {
|
|
681
|
+
name: options.name,
|
|
682
|
+
projectType: options.projectType,
|
|
683
|
+
skipTemplates: options.skipTemplates || false,
|
|
684
|
+
skipMcp: options.skipMcp || false
|
|
685
|
+
} } });
|
|
686
|
+
actor.start();
|
|
687
|
+
await new Promise((resolve, reject) => {
|
|
688
|
+
const subscription = actor.subscribe((state) => {
|
|
689
|
+
if (state.matches("completed")) {
|
|
690
|
+
subscription.unsubscribe();
|
|
691
|
+
resolve();
|
|
692
|
+
} else if (state.matches("failed")) {
|
|
693
|
+
subscription.unsubscribe();
|
|
694
|
+
reject(new Error(state.context.error?.message || "Unknown error"));
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
});
|
|
698
|
+
const { templatesPath, projectType } = actor.getSnapshot().context;
|
|
699
|
+
print.header("\nSetup Complete!");
|
|
700
|
+
if (templatesPath) print.info(`Templates location: ${templatesPath}`);
|
|
701
|
+
if (projectType) print.info(`Project type: ${projectType}`);
|
|
702
|
+
const gradient = await import("gradient-string");
|
|
703
|
+
print.newline();
|
|
704
|
+
console.log(gradient.default.pastel.multiline("🎉 Congratulations! Your project is ready to go!"));
|
|
705
|
+
print.newline();
|
|
706
|
+
} catch (error) {
|
|
707
|
+
print.error(`\nError: ${error.message}`);
|
|
708
|
+
process.exit(1);
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
//#endregion
|
|
713
|
+
//#region src/cli.ts
|
|
714
|
+
/**
|
|
715
|
+
* Main entry point
|
|
716
|
+
*/
|
|
717
|
+
async function main() {
|
|
718
|
+
const program = new Command();
|
|
719
|
+
program.name("aicode").description("AI-powered code toolkit CLI for scaffolding, architecture management, and development workflows").version(package_default.version);
|
|
720
|
+
program.addCommand(initCommand);
|
|
721
|
+
program.addCommand(addCommand);
|
|
722
|
+
await program.parseAsync(process.argv);
|
|
723
|
+
}
|
|
724
|
+
main();
|
|
725
|
+
|
|
726
|
+
//#endregion
|
|
727
|
+
export { };
|