@agiflowai/aicode-toolkit 0.6.0 → 1.0.2

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/dist/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_services = require('./services-s1vmufE4.cjs');
2
+ const require_services = require('./services-C6lqyioO.cjs');
3
3
  const require_mcp = require('./mcp-Dwt8nYQV.cjs');
4
4
  let commander = require("commander");
5
5
  commander = require_services.__toESM(commander);
@@ -11,13 +11,15 @@ let fs_extra = require("fs-extra");
11
11
  fs_extra = require_services.__toESM(fs_extra);
12
12
  let __inquirer_prompts = require("@inquirer/prompts");
13
13
  __inquirer_prompts = require_services.__toESM(__inquirer_prompts);
14
+ let ora = require("ora");
15
+ ora = require_services.__toESM(ora);
14
16
  let xstate = require("xstate");
15
17
  xstate = require_services.__toESM(xstate);
16
18
 
17
19
  //#region package.json
18
20
  var name = "@agiflowai/aicode-toolkit";
19
21
  var description = "AI-powered code toolkit CLI for scaffolding, architecture management, and development workflows";
20
- var version = "0.6.0";
22
+ var version = "1.0.1";
21
23
  var license = "AGPL-3.0";
22
24
  var author = "AgiflowIO";
23
25
  var repository = {
@@ -63,6 +65,7 @@ var dependencies = {
63
65
  "gradient-string": "^3.0.0",
64
66
  "js-yaml": "4.1.0",
65
67
  "liquidjs": "10.21.1",
68
+ "ora": "^9.0.0",
66
69
  "pino": "^10.0.0",
67
70
  "pino-pretty": "^13.1.1",
68
71
  "xstate": "^5.23.0",
@@ -74,7 +77,8 @@ var devDependencies = {
74
77
  "@types/js-yaml": "^4.0.9",
75
78
  "@types/node": "^22.0.0",
76
79
  "tsdown": "^0.15.6",
77
- "typescript": "5.9.3"
80
+ "typescript": "5.9.3",
81
+ "unplugin-raw": "^0.6.3"
78
82
  };
79
83
  var publishConfig = { "access": "public" };
80
84
  var type = "module";
@@ -186,7 +190,6 @@ const initMachine = (0, xstate.createMachine)({
186
190
  projectType: void 0,
187
191
  projectPath: void 0,
188
192
  repositoryExists: false,
189
- detectionConfidence: void 0,
190
193
  detectionIndicators: void 0,
191
194
  templatesPath: void 0,
192
195
  tmpTemplatesPath: void 0,
@@ -194,6 +197,8 @@ const initMachine = (0, xstate.createMachine)({
194
197
  selectedMcpServers: void 0,
195
198
  detectedCodingAgent: void 0,
196
199
  codingAgent: void 0,
200
+ detectedSpecTool: void 0,
201
+ useSpecDrivenApproach: void 0,
197
202
  options: input$1.options,
198
203
  error: void 0
199
204
  }),
@@ -222,18 +227,14 @@ const initMachine = (0, xstate.createMachine)({
222
227
  input: ({ context }) => ({ workspaceRoot: context.workspaceRoot }),
223
228
  onDone: [{
224
229
  target: "checkingSkipTemplates",
225
- guard: ({ event }) => event.output.confidence === "high",
230
+ guard: ({ event }) => event.output.projectType !== void 0,
226
231
  actions: (0, xstate.assign)({
227
232
  projectType: ({ event }) => event.output.projectType,
228
- detectionConfidence: ({ event }) => event.output.confidence,
229
233
  detectionIndicators: ({ event }) => event.output.indicators
230
234
  })
231
235
  }, {
232
236
  target: "promptingProjectType",
233
- actions: (0, xstate.assign)({
234
- detectionConfidence: ({ event }) => event.output.confidence,
235
- detectionIndicators: ({ event }) => event.output.indicators
236
- })
237
+ actions: (0, xstate.assign)({ detectionIndicators: ({ event }) => event.output.indicators })
237
238
  }],
238
239
  onError: {
239
240
  target: "failed",
@@ -244,6 +245,7 @@ const initMachine = (0, xstate.createMachine)({
244
245
  src: "promptProjectType",
245
246
  input: ({ context }) => ({
246
247
  providedProjectType: context.options.projectType,
248
+ detectedProjectType: context.projectType,
247
249
  detectionIndicators: context.detectionIndicators
248
250
  }),
249
251
  onDone: {
@@ -315,7 +317,7 @@ const initMachine = (0, xstate.createMachine)({
315
317
  promptingMcpSelection: { invoke: {
316
318
  src: "promptMcpSelection",
317
319
  onDone: {
318
- target: "downloadingTemplates",
320
+ target: "checkingTemplatesFolder",
319
321
  actions: (0, xstate.assign)({ selectedMcpServers: ({ event }) => event.output })
320
322
  },
321
323
  onError: {
@@ -323,6 +325,29 @@ const initMachine = (0, xstate.createMachine)({
323
325
  actions: (0, xstate.assign)({ error: ({ event }) => event.error })
324
326
  }
325
327
  } },
328
+ checkingTemplatesFolder: { invoke: {
329
+ src: "checkTemplatesFolder",
330
+ input: ({ context }) => ({ workspaceRoot: context.workspaceRoot }),
331
+ onDone: [{
332
+ target: "creatingConfig",
333
+ guard: ({ event }) => event.output.skipDownload === true,
334
+ actions: (0, xstate.assign)({
335
+ templatesPath: ({ event }) => event.output.templatesPath,
336
+ skipDownload: ({ event }) => event.output.skipDownload,
337
+ selectedTemplates: ({ event }) => event.output.existingTemplates
338
+ })
339
+ }, {
340
+ target: "downloadingTemplates",
341
+ actions: (0, xstate.assign)({
342
+ templatesPath: ({ event }) => event.output.templatesPath,
343
+ skipDownload: ({ event }) => event.output.skipDownload
344
+ })
345
+ }],
346
+ onError: {
347
+ target: "failed",
348
+ actions: (0, xstate.assign)({ error: ({ event }) => event.error })
349
+ }
350
+ } },
326
351
  downloadingTemplates: { invoke: {
327
352
  src: "downloadTemplates",
328
353
  onDone: {
@@ -363,14 +388,12 @@ const initMachine = (0, xstate.createMachine)({
363
388
  input: ({ context }) => ({
364
389
  tmpTemplatesPath: context.tmpTemplatesPath,
365
390
  workspaceRoot: context.workspaceRoot,
391
+ templatesPath: context.templatesPath,
366
392
  selectedTemplates: context.selectedTemplates,
367
393
  projectType: context.projectType,
368
394
  selectedMcpServers: context.selectedMcpServers
369
395
  }),
370
- onDone: {
371
- target: "creatingConfig",
372
- actions: (0, xstate.assign)({ templatesPath: ({ event }) => event.output })
373
- },
396
+ onDone: { target: "creatingConfig" },
374
397
  onError: {
375
398
  target: "failed",
376
399
  actions: (0, xstate.assign)({ error: ({ event }) => event.error })
@@ -381,6 +404,7 @@ const initMachine = (0, xstate.createMachine)({
381
404
  input: ({ context }) => ({
382
405
  workspaceRoot: context.workspaceRoot,
383
406
  projectType: context.projectType,
407
+ templatesPath: context.templatesPath,
384
408
  selectedTemplates: context.selectedTemplates
385
409
  }),
386
410
  onDone: { target: "checkingSkipMcp" },
@@ -392,7 +416,7 @@ const initMachine = (0, xstate.createMachine)({
392
416
  checkingSkipMcp: { always: [{
393
417
  target: "detectingCodingAgent",
394
418
  guard: ({ context }) => !context.options.skipMcp
395
- }, { target: "cleaningUp" }] },
419
+ }, { target: "detectingSpecTool" }] },
396
420
  detectingCodingAgent: { invoke: {
397
421
  src: "detectCodingAgent",
398
422
  input: ({ context }) => ({ workspaceRoot: context.workspaceRoot }),
@@ -423,6 +447,66 @@ const initMachine = (0, xstate.createMachine)({
423
447
  workspaceRoot: context.workspaceRoot,
424
448
  codingAgent: context.codingAgent
425
449
  }),
450
+ onDone: { target: "detectingSpecTool" },
451
+ onError: {
452
+ target: "failed",
453
+ actions: (0, xstate.assign)({ error: ({ event }) => event.error })
454
+ }
455
+ } },
456
+ detectingSpecTool: { invoke: {
457
+ src: "detectSpecTool",
458
+ input: ({ context }) => ({ workspaceRoot: context.workspaceRoot }),
459
+ onDone: {
460
+ target: "promptingSpecDrivenApproach",
461
+ actions: (0, xstate.assign)({ detectedSpecTool: ({ event }) => event.output })
462
+ },
463
+ onError: { target: "cleaningUp" }
464
+ } },
465
+ promptingSpecDrivenApproach: { invoke: {
466
+ src: "promptSpecDrivenApproach",
467
+ input: ({ context }) => ({ detectedSpecTool: context.detectedSpecTool }),
468
+ onDone: [{
469
+ target: "settingUpSpec",
470
+ guard: ({ event }) => event.output === true,
471
+ actions: (0, xstate.assign)({ useSpecDrivenApproach: () => true })
472
+ }, {
473
+ target: "cleaningUp",
474
+ actions: (0, xstate.assign)({ useSpecDrivenApproach: () => false })
475
+ }],
476
+ onError: { target: "cleaningUp" }
477
+ } },
478
+ settingUpSpec: { invoke: {
479
+ src: "setupSpec",
480
+ input: ({ context }) => ({
481
+ workspaceRoot: context.workspaceRoot,
482
+ isAlreadyInstalled: context.detectedSpecTool !== null,
483
+ selectedMcpServers: context.selectedMcpServers,
484
+ codingAgent: context.codingAgent
485
+ }),
486
+ onDone: [{
487
+ target: "promptingSpecInstructions",
488
+ guard: ({ context }) => context.detectedSpecTool === null
489
+ }, { target: "cleaningUp" }],
490
+ onError: {
491
+ target: "failed",
492
+ actions: (0, xstate.assign)({ error: ({ event }) => event.error })
493
+ }
494
+ } },
495
+ promptingSpecInstructions: { invoke: {
496
+ src: "promptSpecInstructions",
497
+ onDone: [{
498
+ target: "updatingSpecInstructions",
499
+ guard: ({ event }) => event.output === true
500
+ }, { target: "cleaningUp" }],
501
+ onError: { target: "cleaningUp" }
502
+ } },
503
+ updatingSpecInstructions: { invoke: {
504
+ src: "updateSpecInstructions",
505
+ input: ({ context }) => ({
506
+ workspaceRoot: context.workspaceRoot,
507
+ selectedMcpServers: context.selectedMcpServers,
508
+ codingAgent: context.codingAgent
509
+ }),
426
510
  onDone: { target: "cleaningUp" },
427
511
  onError: {
428
512
  target: "failed",
@@ -458,6 +542,7 @@ const initActors = {
458
542
  checkWorkspaceExists: (0, xstate.fromPromise)(async () => {
459
543
  const workspaceRoot = await require_services.findWorkspaceRoot();
460
544
  if (workspaceRoot) {
545
+ __agiflowai_aicode_utils.print.divider();
461
546
  __agiflowai_aicode_utils.print.info(`Found workspace at: ${workspaceRoot}`);
462
547
  return {
463
548
  exists: true,
@@ -467,62 +552,11 @@ const initActors = {
467
552
  return { exists: false };
468
553
  }),
469
554
  detectProjectType: (0, xstate.fromPromise)(async ({ input: input$1 }) => {
470
- __agiflowai_aicode_utils.print.info("\nDetecting project type...");
471
- const nxJsonPath = node_path.default.join(input$1.workspaceRoot, "nx.json");
472
- const lernaJsonPath = node_path.default.join(input$1.workspaceRoot, "lerna.json");
473
- const pnpmWorkspacePath = node_path.default.join(input$1.workspaceRoot, "pnpm-workspace.yaml");
474
- const turboJsonPath = node_path.default.join(input$1.workspaceRoot, "turbo.json");
475
- const indicators = [];
476
- let projectType;
477
- let confidence = "low";
478
- if (await fs_extra.pathExists(nxJsonPath)) {
479
- indicators.push("nx.json found");
480
- projectType = __agiflowai_aicode_utils.ProjectType.MONOREPO;
481
- confidence = "high";
482
- }
483
- if (await fs_extra.pathExists(lernaJsonPath)) {
484
- indicators.push("lerna.json found");
485
- projectType = __agiflowai_aicode_utils.ProjectType.MONOREPO;
486
- confidence = "high";
487
- }
488
- if (await fs_extra.pathExists(pnpmWorkspacePath)) {
489
- indicators.push("pnpm-workspace.yaml found");
490
- projectType = __agiflowai_aicode_utils.ProjectType.MONOREPO;
491
- confidence = "high";
492
- }
493
- if (await fs_extra.pathExists(turboJsonPath)) {
494
- indicators.push("turbo.json found");
495
- projectType = __agiflowai_aicode_utils.ProjectType.MONOREPO;
496
- confidence = "high";
497
- }
498
- const packageJsonPath = node_path.default.join(input$1.workspaceRoot, "package.json");
499
- if (await fs_extra.pathExists(packageJsonPath)) {
500
- if ((await fs_extra.readJson(packageJsonPath)).workspaces) {
501
- indicators.push("package.json with workspaces found");
502
- projectType = __agiflowai_aicode_utils.ProjectType.MONOREPO;
503
- if (confidence !== "high") confidence = "medium";
504
- }
505
- }
506
- const toolkitYamlPath = node_path.default.join(input$1.workspaceRoot, "toolkit.yaml");
507
- if (await fs_extra.pathExists(toolkitYamlPath)) {
508
- const toolkitConfig = await __agiflowai_aicode_utils.TemplatesManagerService.readToolkitConfig(input$1.workspaceRoot);
509
- if (toolkitConfig?.projectType) {
510
- indicators.push(`toolkit.yaml specifies ${toolkitConfig.projectType}`);
511
- projectType = toolkitConfig.projectType;
512
- confidence = "high";
513
- }
514
- }
515
- if (!projectType) {
516
- projectType = __agiflowai_aicode_utils.ProjectType.MONOLITH;
517
- indicators.push("No monorepo indicators found, assuming monolith");
518
- confidence = "low";
519
- }
520
- if (confidence === "high") __agiflowai_aicode_utils.print.success(`Detected ${projectType} project (high confidence)`);
521
- return {
522
- projectType,
523
- confidence,
524
- indicators
525
- };
555
+ __agiflowai_aicode_utils.print.divider();
556
+ __agiflowai_aicode_utils.print.info("Detecting project type...");
557
+ const result = await (0, __agiflowai_aicode_utils.detectProjectType)(input$1.workspaceRoot);
558
+ if (result.projectType) __agiflowai_aicode_utils.print.success(`Detected ${result.projectType} project`);
559
+ return result;
526
560
  }),
527
561
  promptProjectType: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
528
562
  if (actorInput.providedProjectType) {
@@ -530,23 +564,30 @@ const initActors = {
530
564
  __agiflowai_aicode_utils.print.info(`Project type: ${projectType}`);
531
565
  return projectType;
532
566
  }
567
+ if (actorInput.detectedProjectType) {
568
+ __agiflowai_aicode_utils.print.info(`Using detected project type: ${actorInput.detectedProjectType}`);
569
+ return actorInput.detectedProjectType;
570
+ }
533
571
  if (actorInput.detectionIndicators && actorInput.detectionIndicators.length > 0) {
534
572
  __agiflowai_aicode_utils.print.info("\nDetection results:");
535
573
  for (const indicator of actorInput.detectionIndicators) __agiflowai_aicode_utils.print.indent(`• ${indicator}`);
536
574
  __agiflowai_aicode_utils.print.newline();
537
575
  }
538
- return await (0, __inquirer_prompts.select)({
576
+ __agiflowai_aicode_utils.print.divider();
577
+ const result = await (0, __inquirer_prompts.select)({
539
578
  message: "Select project type:",
540
579
  choices: [{
541
- name: "Monolith - Single application structure",
580
+ name: "Monolith Single application structure",
542
581
  value: __agiflowai_aicode_utils.ProjectType.MONOLITH,
543
- description: "Traditional single-application project structure"
582
+ description: "\n Traditional single-application project structure"
544
583
  }, {
545
- name: "Monorepo - Multiple packages/apps in one repository",
584
+ name: "Monorepo Multiple packages/apps in one repository",
546
585
  value: __agiflowai_aicode_utils.ProjectType.MONOREPO,
547
- description: "Multiple packages managed together (uses workspaces)"
586
+ description: "\n Multiple packages managed together (uses workspaces)"
548
587
  }]
549
588
  });
589
+ __agiflowai_aicode_utils.print.info("");
590
+ return result;
550
591
  }),
551
592
  promptProjectName: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
552
593
  const newProjectService = new require_services.NewProjectService(actorInput.providedName, void 0);
@@ -558,49 +599,171 @@ const initActors = {
558
599
  __agiflowai_aicode_utils.print.info(`Project name: ${trimmedName}`);
559
600
  return trimmedName;
560
601
  }
561
- return await (0, __inquirer_prompts.input)({
562
- message: "Enter your project name:",
563
- validate: (value) => newProjectService.validateProjectName(value)
602
+ __agiflowai_aicode_utils.print.divider();
603
+ const result = await (0, __inquirer_prompts.input)({
604
+ message: "Enter your project name (press Enter to use current directory):",
605
+ validate: (value) => {
606
+ if (!value || value.trim() === "") return true;
607
+ return newProjectService.validateProjectName(value);
608
+ }
564
609
  });
610
+ __agiflowai_aicode_utils.print.info("");
611
+ if (!result || result.trim() === "") return ".";
612
+ return result;
565
613
  }),
566
614
  createProjectDirectory: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
567
- const projectPath = node_path.default.join(process.cwd(), actorInput.projectName.trim());
568
- await new require_services.NewProjectService(void 0, void 0).createProjectDirectory(projectPath, actorInput.projectName);
569
- return { projectPath };
615
+ if (actorInput.projectName === ".") {
616
+ const projectPath = process.cwd();
617
+ __agiflowai_aicode_utils.print.success(`Using current directory: ${projectPath}`);
618
+ return { projectPath };
619
+ }
620
+ const spinner = (0, ora.default)("Creating project directory...").start();
621
+ try {
622
+ const projectPath = node_path.default.join(process.cwd(), actorInput.projectName.trim());
623
+ await new require_services.NewProjectService(void 0, void 0).createProjectDirectory(projectPath, actorInput.projectName);
624
+ spinner.succeed(`Created project directory: ${projectPath}`);
625
+ return { projectPath };
626
+ } catch (error) {
627
+ spinner.fail("Failed to create project directory");
628
+ throw error;
629
+ }
570
630
  }),
571
631
  promptGitSetup: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
572
632
  const newProjectService = new require_services.NewProjectService(void 0, void 0);
573
- if (await (0, __inquirer_prompts.confirm)({
633
+ __agiflowai_aicode_utils.print.divider();
634
+ const hasExistingRepo = await (0, __inquirer_prompts.confirm)({
574
635
  message: "Do you have an existing Git repository you want to use?",
575
636
  default: false
576
- })) {
637
+ });
638
+ __agiflowai_aicode_utils.print.info("");
639
+ if (hasExistingRepo) {
640
+ __agiflowai_aicode_utils.print.divider();
577
641
  const repoUrl = await (0, __inquirer_prompts.input)({
578
- message: "Enter Git repository URL:",
579
- validate: (value) => newProjectService.validateRepositoryUrl(value)
642
+ message: "Enter Git repository URL (press Enter to skip):",
643
+ validate: (value) => {
644
+ if (!value || value.trim() === "") return true;
645
+ return newProjectService.validateRepositoryUrl(value);
646
+ }
580
647
  });
581
- await newProjectService.cloneExistingRepository(repoUrl.trim(), actorInput.projectPath);
582
- } else if (await (0, __inquirer_prompts.confirm)({
583
- message: "Initialize a new Git repository?",
584
- default: true
585
- })) await newProjectService.initializeGitRepository(actorInput.projectPath);
648
+ __agiflowai_aicode_utils.print.info("");
649
+ if (repoUrl && repoUrl.trim() !== "") {
650
+ const spinner = (0, ora.default)("Cloning repository...").start();
651
+ try {
652
+ await newProjectService.cloneExistingRepository(repoUrl.trim(), actorInput.projectPath);
653
+ spinner.succeed("Repository cloned successfully");
654
+ } catch (error) {
655
+ spinner.fail("Failed to clone repository");
656
+ throw error;
657
+ }
658
+ } else __agiflowai_aicode_utils.print.info("Skipped cloning repository");
659
+ } else {
660
+ __agiflowai_aicode_utils.print.divider();
661
+ const initGit = await (0, __inquirer_prompts.confirm)({
662
+ message: "Initialize a new Git repository?",
663
+ default: true
664
+ });
665
+ __agiflowai_aicode_utils.print.info("");
666
+ if (initGit) {
667
+ const spinner = (0, ora.default)("Initializing Git repository...").start();
668
+ try {
669
+ await newProjectService.initializeGitRepository(actorInput.projectPath);
670
+ spinner.succeed("Git repository initialized");
671
+ } catch (error) {
672
+ spinner.fail("Failed to initialize Git repository");
673
+ throw error;
674
+ }
675
+ }
676
+ }
586
677
  }),
587
678
  promptMcpSelection: (0, xstate.fromPromise)(async () => {
588
- return await (await import("@inquirer/prompts").then((m) => m.checkbox))({
679
+ const checkbox = await import("@inquirer/prompts").then((m) => m.checkbox);
680
+ const choices = Object.values(require_mcp.MCPServer).map((server) => ({
681
+ name: require_mcp.MCP_SERVER_INFO[server].name,
682
+ value: server,
683
+ description: `\n ${require_mcp.MCP_SERVER_INFO[server].description}`,
684
+ checked: true
685
+ }));
686
+ __agiflowai_aicode_utils.print.divider();
687
+ const selected = await checkbox({
589
688
  message: "Select MCP servers to configure:",
590
- choices: Object.values(require_mcp.MCPServer).map((server) => ({
591
- name: require_mcp.MCP_SERVER_INFO[server].name,
592
- value: server,
593
- description: require_mcp.MCP_SERVER_INFO[server].description,
594
- checked: true
595
- })),
689
+ choices,
596
690
  validate: (answer) => {
597
691
  if (answer.length === 0) return "Please select at least one MCP server";
598
692
  return true;
599
693
  }
600
694
  });
695
+ __agiflowai_aicode_utils.print.info("");
696
+ return selected;
697
+ }),
698
+ checkTemplatesFolder: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
699
+ try {
700
+ const fs = await import("node:fs/promises");
701
+ const defaultTemplatesPath = node_path.default.join(actorInput.workspaceRoot, "templates");
702
+ let templatesExists = false;
703
+ try {
704
+ await fs.access(defaultTemplatesPath);
705
+ templatesExists = true;
706
+ } catch {
707
+ templatesExists = false;
708
+ }
709
+ let finalTemplatesPath = defaultTemplatesPath;
710
+ let skipDownload = false;
711
+ if (templatesExists) {
712
+ __agiflowai_aicode_utils.print.divider();
713
+ __agiflowai_aicode_utils.print.info(`Templates folder already exists at: ${defaultTemplatesPath}`);
714
+ const useDifferentDir = await (0, __inquirer_prompts.confirm)({
715
+ message: "Would you like to use a different directory for templates?",
716
+ default: false
717
+ });
718
+ __agiflowai_aicode_utils.print.info("");
719
+ if (useDifferentDir) {
720
+ __agiflowai_aicode_utils.print.divider();
721
+ const customDir = await (0, __inquirer_prompts.input)({
722
+ message: "Enter custom templates directory path (relative to workspace root):",
723
+ default: "templates",
724
+ validate: (value) => {
725
+ if (!value || value.trim() === "") return "Please enter a valid directory path";
726
+ return true;
727
+ }
728
+ });
729
+ __agiflowai_aicode_utils.print.info("");
730
+ finalTemplatesPath = node_path.default.join(actorInput.workspaceRoot, customDir.trim());
731
+ try {
732
+ await fs.mkdir(finalTemplatesPath, { recursive: true });
733
+ __agiflowai_aicode_utils.print.success(`Created templates directory at: ${finalTemplatesPath}`);
734
+ } catch (error) {
735
+ throw new Error(`Failed to create templates directory at ${finalTemplatesPath}: ${error.message}`);
736
+ }
737
+ } else {
738
+ skipDownload = true;
739
+ __agiflowai_aicode_utils.print.info("Using existing templates folder");
740
+ }
741
+ }
742
+ let existingTemplates;
743
+ if (skipDownload) try {
744
+ existingTemplates = (await new require_services.TemplateSelectionService(finalTemplatesPath).listTemplates()).map((t) => t.name);
745
+ } catch (_error) {
746
+ __agiflowai_aicode_utils.print.warning("Could not read existing templates, will proceed anyway");
747
+ }
748
+ return {
749
+ templatesPath: finalTemplatesPath,
750
+ skipDownload,
751
+ existingTemplates
752
+ };
753
+ } catch (error) {
754
+ throw new Error(`Failed to check templates folder: ${error.message}`);
755
+ }
601
756
  }),
602
757
  downloadTemplates: (0, xstate.fromPromise)(async () => {
603
- return await new require_services.TemplateSelectionService().downloadTemplatesToTmp(DEFAULT_TEMPLATE_REPO);
758
+ const spinner = (0, ora.default)("Downloading templates from AgiFlow/aicode-toolkit...").start();
759
+ try {
760
+ const tmpPath = await new require_services.TemplateSelectionService().downloadTemplatesToTmp(DEFAULT_TEMPLATE_REPO);
761
+ spinner.succeed("Templates downloaded successfully");
762
+ return tmpPath;
763
+ } catch (error) {
764
+ spinner.fail("Failed to download templates");
765
+ throw error;
766
+ }
604
767
  }),
605
768
  listTemplates: (0, xstate.fromPromise)(async ({ input: input$1 }) => {
606
769
  const templates = await new require_services.TemplateSelectionService(input$1.tmpTemplatesPath).listTemplates();
@@ -611,37 +774,52 @@ const initActors = {
611
774
  promptTemplateSelection: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
612
775
  const templates = await new require_services.TemplateSelectionService(actorInput.tmpTemplatesPath).listTemplates();
613
776
  if (templates.length === 0) throw new Error("No templates available");
614
- if (actorInput.projectType === __agiflowai_aicode_utils.ProjectType.MONOLITH) return [await (0, __inquirer_prompts.select)({
615
- message: "Select template (monolith allows only one):",
616
- choices: templates.map((t) => ({
777
+ if (actorInput.projectType === __agiflowai_aicode_utils.ProjectType.MONOLITH) {
778
+ const choices$1 = templates.map((t) => ({
617
779
  name: t.name,
618
780
  value: t.name,
619
- description: t.description
620
- }))
621
- })];
622
- const selected = await (await import("@inquirer/prompts").then((m) => m.checkbox))({
781
+ description: t.description ? `\n ${t.description}` : void 0
782
+ }));
783
+ __agiflowai_aicode_utils.print.divider();
784
+ const selected$1 = await (0, __inquirer_prompts.select)({
785
+ message: "Select template (monolith allows only one):",
786
+ choices: choices$1
787
+ });
788
+ __agiflowai_aicode_utils.print.info("");
789
+ return [selected$1];
790
+ }
791
+ const checkbox = await import("@inquirer/prompts").then((m) => m.checkbox);
792
+ const choices = templates.map((t) => ({
793
+ name: t.name,
794
+ value: t.name,
795
+ description: t.description ? `\n ${t.description}` : void 0,
796
+ checked: true
797
+ }));
798
+ __agiflowai_aicode_utils.print.divider();
799
+ const selected = await checkbox({
623
800
  message: "Select templates (use space to select, enter to confirm):",
624
- choices: templates.map((t) => ({
625
- name: t.name,
626
- value: t.name,
627
- description: t.description,
628
- checked: true
629
- }))
801
+ choices
630
802
  });
803
+ __agiflowai_aicode_utils.print.info("");
631
804
  if (selected.length === 0) throw new Error("Please select at least one template");
632
805
  return selected;
633
806
  }),
634
807
  copyTemplates: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
635
- const templateSelectionService = new require_services.TemplateSelectionService(actorInput.tmpTemplatesPath);
636
- const templatesPath = node_path.default.join(actorInput.workspaceRoot, "templates");
637
- await templateSelectionService.copyTemplates(actorInput.selectedTemplates, templatesPath, actorInput.projectType, actorInput.selectedMcpServers);
638
- return templatesPath;
808
+ const spinner = (0, ora.default)("Copying templates to workspace...").start();
809
+ try {
810
+ await new require_services.TemplateSelectionService(actorInput.tmpTemplatesPath).copyTemplates(actorInput.selectedTemplates, actorInput.templatesPath, actorInput.projectType, actorInput.selectedMcpServers);
811
+ spinner.succeed(`Templates copied to ${actorInput.templatesPath}`);
812
+ return actorInput.templatesPath;
813
+ } catch (error) {
814
+ spinner.fail("Failed to copy templates");
815
+ throw error;
816
+ }
639
817
  }),
640
818
  createConfig: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
641
819
  if (actorInput.projectType === __agiflowai_aicode_utils.ProjectType.MONOLITH) {
642
820
  const toolkitConfig = {
643
821
  version: "1.0",
644
- templatesPath: "templates",
822
+ templatesPath: node_path.default.relative(actorInput.workspaceRoot, actorInput.templatesPath) || "templates",
645
823
  projectType: "monolith",
646
824
  sourceTemplate: actorInput.selectedTemplates[0]
647
825
  };
@@ -662,20 +840,120 @@ const initActors = {
662
840
  __agiflowai_aicode_utils.print.info(`Using detected coding agent: ${actorInput.detectedAgent}`);
663
841
  return actorInput.detectedAgent;
664
842
  }
665
- return await (0, __inquirer_prompts.select)({
843
+ const agents = require_services.CodingAgentService.getAvailableAgents();
844
+ __agiflowai_aicode_utils.print.divider();
845
+ const selected = await (0, __inquirer_prompts.select)({
666
846
  message: "Select coding agent for MCP configuration:",
667
- choices: require_services.CodingAgentService.getAvailableAgents().map((agent) => ({
847
+ choices: agents.map((agent) => ({
668
848
  name: agent.name,
669
849
  value: agent.value,
670
- description: agent.description
850
+ description: `\n ${agent.description}`
671
851
  }))
672
852
  });
853
+ __agiflowai_aicode_utils.print.info("");
854
+ return selected;
673
855
  }),
674
856
  configureMCP: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
675
- await new require_services.CodingAgentService(actorInput.workspaceRoot).setupMCP(actorInput.codingAgent);
857
+ const spinner = (0, ora.default)(`Setting up MCP for ${actorInput.codingAgent}...`).start();
858
+ try {
859
+ await new require_services.CodingAgentService(actorInput.workspaceRoot).setupMCP(actorInput.codingAgent);
860
+ spinner.succeed("MCP configuration completed");
861
+ } catch (error) {
862
+ spinner.fail("Failed to configure MCP");
863
+ throw error;
864
+ }
676
865
  }),
677
866
  cleanup: (0, xstate.fromPromise)(async ({ input: input$1 }) => {
678
- if (input$1.tmpTemplatesPath) await new require_services.TemplateSelectionService(input$1.tmpTemplatesPath).cleanup();
867
+ if (input$1.tmpTemplatesPath) {
868
+ const spinner = (0, ora.default)("Cleaning up temporary files...").start();
869
+ try {
870
+ await new require_services.TemplateSelectionService(input$1.tmpTemplatesPath).cleanup();
871
+ spinner.succeed("Cleaned up temporary files");
872
+ } catch (_error) {
873
+ spinner.warn("Could not clean up all temporary files");
874
+ }
875
+ }
876
+ }),
877
+ detectSpecTool: (0, xstate.fromPromise)(async ({ input: input$1 }) => {
878
+ __agiflowai_aicode_utils.print.info("\nDetecting spec tools...");
879
+ const detectedTool = await new require_services.SpecToolService(input$1.workspaceRoot).detectSpecTool();
880
+ if (detectedTool) __agiflowai_aicode_utils.print.success(`Detected ${require_services.SPEC_TOOL_INFO[detectedTool].name} in workspace`);
881
+ else __agiflowai_aicode_utils.print.info("No spec tool detected");
882
+ return detectedTool;
883
+ }),
884
+ promptSpecDrivenApproach: (0, xstate.fromPromise)(async ({ input: actorInput }) => {
885
+ if (actorInput.detectedSpecTool) {
886
+ __agiflowai_aicode_utils.print.divider();
887
+ const result$1 = await (0, __inquirer_prompts.confirm)({
888
+ message: `${require_services.SPEC_TOOL_INFO[actorInput.detectedSpecTool].name} is installed. Would you like to update the agent instructions for spec-driven development?`,
889
+ default: true
890
+ });
891
+ __agiflowai_aicode_utils.print.info("");
892
+ return result$1;
893
+ }
894
+ __agiflowai_aicode_utils.print.divider();
895
+ const result = await (0, __inquirer_prompts.confirm)({
896
+ message: "Would you like to install OpenSpec for spec-driven development? This helps AI assistants agree on what to build before writing code.",
897
+ default: false
898
+ });
899
+ __agiflowai_aicode_utils.print.info("");
900
+ return result;
901
+ }),
902
+ setupSpec: (0, xstate.fromPromise)(async ({ input: input$1 }) => {
903
+ const codingAgentService = new require_services.CodingAgentService(input$1.workspaceRoot);
904
+ const specToolService = new require_services.SpecToolService(input$1.workspaceRoot, require_services.SpecTool.OPENSPEC, codingAgentService);
905
+ if (input$1.isAlreadyInstalled) {
906
+ const spinner = (0, ora.default)("Updating OpenSpec agent instructions...").start();
907
+ try {
908
+ const enabledMcps = {
909
+ scaffoldMcp: input$1.selectedMcpServers?.includes(require_mcp.MCPServer.SCAFFOLD) ?? false,
910
+ architectMcp: input$1.selectedMcpServers?.includes(require_mcp.MCPServer.ARCHITECT) ?? false,
911
+ projectType: input$1.projectType
912
+ };
913
+ await specToolService.updateInstructions(enabledMcps, input$1.codingAgent);
914
+ spinner.succeed("OpenSpec agent instructions updated");
915
+ } catch (error) {
916
+ spinner.fail("Failed to update OpenSpec instructions");
917
+ throw error;
918
+ }
919
+ } else {
920
+ const spinner = (0, ora.default)("Initializing OpenSpec...").start();
921
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
922
+ spinner.stop();
923
+ try {
924
+ await specToolService.initializeSpec();
925
+ __agiflowai_aicode_utils.print.success("OpenSpec initialized successfully");
926
+ } catch (error) {
927
+ __agiflowai_aicode_utils.print.error("Failed to initialize OpenSpec");
928
+ throw error;
929
+ }
930
+ }
931
+ }),
932
+ promptSpecInstructions: (0, xstate.fromPromise)(async () => {
933
+ __agiflowai_aicode_utils.print.divider();
934
+ const result = await (0, __inquirer_prompts.confirm)({
935
+ message: "Would you like to update the agent instructions with OpenSpec workflow guidance?",
936
+ default: true
937
+ });
938
+ __agiflowai_aicode_utils.print.info("");
939
+ return result;
940
+ }),
941
+ updateSpecInstructions: (0, xstate.fromPromise)(async ({ input: input$1 }) => {
942
+ const spinner = (0, ora.default)("Updating OpenSpec agent instructions...").start();
943
+ try {
944
+ const codingAgentService = new require_services.CodingAgentService(input$1.workspaceRoot);
945
+ const specToolService = new require_services.SpecToolService(input$1.workspaceRoot, require_services.SpecTool.OPENSPEC, codingAgentService);
946
+ const enabledMcps = {
947
+ scaffoldMcp: input$1.selectedMcpServers?.includes(require_mcp.MCPServer.SCAFFOLD) ?? false,
948
+ architectMcp: input$1.selectedMcpServers?.includes(require_mcp.MCPServer.ARCHITECT) ?? false,
949
+ projectType: input$1.projectType
950
+ };
951
+ await specToolService.updateInstructions(enabledMcps, input$1.codingAgent);
952
+ spinner.succeed("OpenSpec agent instructions updated");
953
+ } catch (error) {
954
+ spinner.fail("Failed to update OpenSpec instructions");
955
+ throw error;
956
+ }
679
957
  })
680
958
  };
681
959
  /**