thomas-agentkit 0.6.0 → 0.6.1
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.js +188 -243
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -212,49 +212,68 @@ function assertKnownKeys(value, validKeys, name) {
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
|
+
function optionalConfigString(rawConfig, key) {
|
|
216
|
+
const value = rawConfig[key];
|
|
217
|
+
if (value === undefined) {
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
if (typeof value !== "string") {
|
|
221
|
+
throw new Error(`${configFileName} ${key} must be a string.`);
|
|
222
|
+
}
|
|
223
|
+
return value;
|
|
224
|
+
}
|
|
225
|
+
function readConfigAiTools(value) {
|
|
226
|
+
if (value === undefined) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
if (!Array.isArray(value)) {
|
|
230
|
+
throw new Error(`${configFileName} aiTools must be an array.`);
|
|
231
|
+
}
|
|
232
|
+
return value.map((aiTool) => {
|
|
233
|
+
if (typeof aiTool !== "string" || !isAiToolName(aiTool)) {
|
|
234
|
+
throw new Error(`Unknown AI tool "${String(aiTool)}". Valid AI tools: ${validAiTools.join(", ")}.`);
|
|
235
|
+
}
|
|
236
|
+
return aiTool;
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function readConfigPersonalization(value) {
|
|
240
|
+
if (value === undefined) {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
assertPlainObject(value, `${configFileName} personalization`);
|
|
244
|
+
assertKnownKeys(value, personalizationKeys, `${configFileName} personalization`);
|
|
245
|
+
const personalization = {};
|
|
246
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
247
|
+
if (typeof entry !== "string") {
|
|
248
|
+
throw new Error(`${configFileName} personalization.${key} must be a string.`);
|
|
249
|
+
}
|
|
250
|
+
personalization[key] = entry;
|
|
251
|
+
}
|
|
252
|
+
return personalization;
|
|
253
|
+
}
|
|
215
254
|
function parseConfig(rawConfig, configPath) {
|
|
216
255
|
assertPlainObject(rawConfig, configFileName);
|
|
217
256
|
assertKnownKeys(rawConfig, configKeys, configFileName);
|
|
257
|
+
const preset = optionalConfigString(rawConfig, "preset");
|
|
258
|
+
const templateSet = optionalConfigString(rawConfig, "templateSet");
|
|
259
|
+
const designSystem = optionalConfigString(rawConfig, "designSystem");
|
|
218
260
|
const config = {};
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
throw new Error(`${configFileName} preset must be a string.`);
|
|
222
|
-
}
|
|
223
|
-
config.preset = resolvePreset(rawConfig.preset);
|
|
261
|
+
if (preset !== undefined) {
|
|
262
|
+
config.preset = resolvePreset(preset);
|
|
224
263
|
}
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
throw new Error(`${configFileName} templateSet must be a string.`);
|
|
228
|
-
}
|
|
229
|
-
config.templateSet = resolveTemplateSet(rawConfig.templateSet);
|
|
264
|
+
if (templateSet !== undefined) {
|
|
265
|
+
config.templateSet = resolveTemplateSet(templateSet);
|
|
230
266
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
config.aiTools = rawConfig.aiTools.map((aiTool) => {
|
|
236
|
-
if (typeof aiTool !== "string" || !isAiToolName(aiTool)) {
|
|
237
|
-
throw new Error(`Unknown AI tool "${String(aiTool)}". Valid AI tools: ${validAiTools.join(", ")}.`);
|
|
238
|
-
}
|
|
239
|
-
return aiTool;
|
|
240
|
-
});
|
|
267
|
+
const aiTools = readConfigAiTools(rawConfig.aiTools);
|
|
268
|
+
if (aiTools !== undefined) {
|
|
269
|
+
config.aiTools = aiTools;
|
|
241
270
|
}
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (rawConfig.personalization !== undefined) {
|
|
249
|
-
assertPlainObject(rawConfig.personalization, `${configFileName} personalization`);
|
|
250
|
-
assertKnownKeys(rawConfig.personalization, personalizationKeys, `${configFileName} personalization`);
|
|
251
|
-
config.personalization = {};
|
|
252
|
-
for (const [key, value] of Object.entries(rawConfig.personalization)) {
|
|
253
|
-
if (typeof value !== "string") {
|
|
254
|
-
throw new Error(`${configFileName} personalization.${key} must be a string.`);
|
|
255
|
-
}
|
|
256
|
-
config.personalization[key] = value;
|
|
257
|
-
}
|
|
271
|
+
if (designSystem !== undefined) {
|
|
272
|
+
config.designSystem = resolveDesignSystem(designSystem);
|
|
273
|
+
}
|
|
274
|
+
const personalization = readConfigPersonalization(rawConfig.personalization);
|
|
275
|
+
if (personalization !== undefined) {
|
|
276
|
+
config.personalization = personalization;
|
|
258
277
|
}
|
|
259
278
|
if (config.preset === undefined && rawConfig.preset !== undefined) {
|
|
260
279
|
throw new Error(`Invalid preset in ${configPath}.`);
|
|
@@ -495,161 +514,84 @@ export function shouldPromptForInit(options, streams) {
|
|
|
495
514
|
}
|
|
496
515
|
return Boolean(streams.stdin?.isTTY || streams.stdout?.isTTY);
|
|
497
516
|
}
|
|
517
|
+
function resolvePrompt(value) {
|
|
518
|
+
if (isCancel(value)) {
|
|
519
|
+
process.exit(130);
|
|
520
|
+
}
|
|
521
|
+
return value;
|
|
522
|
+
}
|
|
523
|
+
async function promptForTextValue(message, placeholder, defaultValue) {
|
|
524
|
+
return resolvePrompt(await text({ message, placeholder, defaultValue }));
|
|
525
|
+
}
|
|
498
526
|
async function promptForPersonalization(defaults) {
|
|
499
|
-
const shouldPersonalize = await confirm({
|
|
527
|
+
const shouldPersonalize = resolvePrompt(await confirm({
|
|
500
528
|
message: "Personalize template placeholders?",
|
|
501
529
|
initialValue: Boolean(defaults),
|
|
502
|
-
});
|
|
503
|
-
if (isCancel(shouldPersonalize)) {
|
|
504
|
-
process.exit(130);
|
|
505
|
-
}
|
|
530
|
+
}));
|
|
506
531
|
if (!shouldPersonalize) {
|
|
507
532
|
return undefined;
|
|
508
533
|
}
|
|
509
|
-
const projectName = await text({
|
|
510
|
-
message: "Project name",
|
|
511
|
-
placeholder: "[Project Name]",
|
|
512
|
-
defaultValue: defaults?.projectName,
|
|
513
|
-
});
|
|
514
|
-
if (isCancel(projectName)) {
|
|
515
|
-
process.exit(130);
|
|
516
|
-
}
|
|
517
|
-
const projectDescription = await text({
|
|
518
|
-
message: "Short project description",
|
|
519
|
-
placeholder: "[short project description]",
|
|
520
|
-
defaultValue: defaults?.projectDescription,
|
|
521
|
-
});
|
|
522
|
-
if (isCancel(projectDescription)) {
|
|
523
|
-
process.exit(130);
|
|
524
|
-
}
|
|
525
|
-
const issueTracker = await text({
|
|
526
|
-
message: "Issue tracker name",
|
|
527
|
-
placeholder: "Linear or GitHub Issues",
|
|
528
|
-
defaultValue: defaults?.issueTracker,
|
|
529
|
-
});
|
|
530
|
-
if (isCancel(issueTracker)) {
|
|
531
|
-
process.exit(130);
|
|
532
|
-
}
|
|
533
|
-
const designSystemPath = await text({
|
|
534
|
-
message: "Design system path",
|
|
535
|
-
placeholder: "docs/design-system.md",
|
|
536
|
-
defaultValue: defaults?.designSystemPath,
|
|
537
|
-
});
|
|
538
|
-
if (isCancel(designSystemPath)) {
|
|
539
|
-
process.exit(130);
|
|
540
|
-
}
|
|
541
|
-
const briefsPath = await text({
|
|
542
|
-
message: "Briefs path",
|
|
543
|
-
placeholder: "docs/briefs",
|
|
544
|
-
defaultValue: defaults?.briefsPath,
|
|
545
|
-
});
|
|
546
|
-
if (isCancel(briefsPath)) {
|
|
547
|
-
process.exit(130);
|
|
548
|
-
}
|
|
549
|
-
const testCommand = await text({
|
|
550
|
-
message: "Test command",
|
|
551
|
-
placeholder: "npm test",
|
|
552
|
-
defaultValue: defaults?.testCommand,
|
|
553
|
-
});
|
|
554
|
-
if (isCancel(testCommand)) {
|
|
555
|
-
process.exit(130);
|
|
556
|
-
}
|
|
557
|
-
const lintCommand = await text({
|
|
558
|
-
message: "Lint command",
|
|
559
|
-
placeholder: "npm run lint",
|
|
560
|
-
defaultValue: defaults?.lintCommand,
|
|
561
|
-
});
|
|
562
|
-
if (isCancel(lintCommand)) {
|
|
563
|
-
process.exit(130);
|
|
564
|
-
}
|
|
565
|
-
const buildCommand = await text({
|
|
566
|
-
message: "Build/check command",
|
|
567
|
-
placeholder: "npm run build",
|
|
568
|
-
defaultValue: defaults?.buildCommand,
|
|
569
|
-
});
|
|
570
|
-
if (isCancel(buildCommand)) {
|
|
571
|
-
process.exit(130);
|
|
572
|
-
}
|
|
573
|
-
const stackSummary = await text({
|
|
574
|
-
message: "Stack summary",
|
|
575
|
-
placeholder: "Next.js, TypeScript, Tailwind CSS, Vitest",
|
|
576
|
-
defaultValue: defaults?.stackSummary,
|
|
577
|
-
});
|
|
578
|
-
if (isCancel(stackSummary)) {
|
|
579
|
-
process.exit(130);
|
|
580
|
-
}
|
|
581
534
|
return {
|
|
582
|
-
projectName,
|
|
583
|
-
projectDescription,
|
|
584
|
-
issueTracker,
|
|
585
|
-
designSystemPath,
|
|
586
|
-
briefsPath,
|
|
587
|
-
testCommand,
|
|
588
|
-
lintCommand,
|
|
589
|
-
buildCommand,
|
|
590
|
-
stackSummary,
|
|
535
|
+
projectName: await promptForTextValue("Project name", "[Project Name]", defaults?.projectName),
|
|
536
|
+
projectDescription: await promptForTextValue("Short project description", "[short project description]", defaults?.projectDescription),
|
|
537
|
+
issueTracker: await promptForTextValue("Issue tracker name", "Linear or GitHub Issues", defaults?.issueTracker),
|
|
538
|
+
designSystemPath: await promptForTextValue("Design system path", "docs/design-system.md", defaults?.designSystemPath),
|
|
539
|
+
briefsPath: await promptForTextValue("Briefs path", "docs/briefs", defaults?.briefsPath),
|
|
540
|
+
testCommand: await promptForTextValue("Test command", "npm test", defaults?.testCommand),
|
|
541
|
+
lintCommand: await promptForTextValue("Lint command", "npm run lint", defaults?.lintCommand),
|
|
542
|
+
buildCommand: await promptForTextValue("Build/check command", "npm run build", defaults?.buildCommand),
|
|
543
|
+
stackSummary: await promptForTextValue("Stack summary", "Next.js, TypeScript, Tailwind CSS, Vitest", defaults?.stackSummary),
|
|
591
544
|
};
|
|
592
545
|
}
|
|
593
546
|
async function buildInitTemplateContent(file, preset, personalization, designSystem) {
|
|
594
547
|
const content = await buildTemplateContent(file, preset, designSystem);
|
|
595
548
|
return personalizeTemplateContent(file, content, personalization);
|
|
596
549
|
}
|
|
550
|
+
async function installFileIfAllowed(targetDir, file, options, result, getContent) {
|
|
551
|
+
const destination = path.join(targetDir, file);
|
|
552
|
+
if ((await exists(destination)) && !options.force) {
|
|
553
|
+
result.skipped.push(file);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
result.created.push(file);
|
|
557
|
+
if (options.dryRun) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
await mkdir(path.dirname(destination), { recursive: true });
|
|
561
|
+
await writeFile(destination, await getContent());
|
|
562
|
+
}
|
|
563
|
+
async function resolveInitTemplateFiles(options) {
|
|
564
|
+
const allTemplateFiles = await getTemplateFiles();
|
|
565
|
+
if (options.files) {
|
|
566
|
+
return options.files;
|
|
567
|
+
}
|
|
568
|
+
if (options.templateSet || options.aiTools) {
|
|
569
|
+
return getSelectedTemplateFiles(options.templateSet ?? "full", options.aiTools ?? [], allTemplateFiles);
|
|
570
|
+
}
|
|
571
|
+
return allTemplateFiles;
|
|
572
|
+
}
|
|
597
573
|
async function installTemplates(targetArg, options) {
|
|
598
574
|
const targetDir = path.resolve(process.cwd(), targetArg || ".");
|
|
599
|
-
const
|
|
600
|
-
const files = options.files ??
|
|
601
|
-
(options.templateSet || options.aiTools
|
|
602
|
-
? getSelectedTemplateFiles(options.templateSet ?? "full", options.aiTools ?? [], allTemplateFiles)
|
|
603
|
-
: allTemplateFiles);
|
|
575
|
+
const files = await resolveInitTemplateFiles(options);
|
|
604
576
|
const preset = resolvePreset(options.preset);
|
|
605
577
|
const designSystem = effectiveDesignSystem(options.designSystem);
|
|
606
|
-
const
|
|
607
|
-
const skipped = [];
|
|
578
|
+
const result = { targetDir, created: [], skipped: [] };
|
|
608
579
|
if (!options.dryRun) {
|
|
609
580
|
await mkdir(targetDir, { recursive: true });
|
|
610
581
|
}
|
|
611
582
|
if (options.writeConfig) {
|
|
612
|
-
|
|
613
|
-
const destinationExists = await exists(destination);
|
|
614
|
-
if (destinationExists && !options.force) {
|
|
615
|
-
skipped.push(configFileName);
|
|
616
|
-
}
|
|
617
|
-
else {
|
|
618
|
-
created.push(configFileName);
|
|
619
|
-
if (!options.dryRun) {
|
|
620
|
-
await writeFile(destination, serializeConfig(getResolvedConfig(options)));
|
|
621
|
-
}
|
|
622
|
-
}
|
|
583
|
+
await installFileIfAllowed(targetDir, configFileName, options, result, () => serializeConfig(getResolvedConfig(options)));
|
|
623
584
|
}
|
|
624
585
|
for (const file of files) {
|
|
625
|
-
|
|
626
|
-
const destinationExists = await exists(destination);
|
|
627
|
-
if (destinationExists && !options.force) {
|
|
628
|
-
skipped.push(file);
|
|
629
|
-
continue;
|
|
630
|
-
}
|
|
631
|
-
created.push(file);
|
|
632
|
-
if (!options.dryRun) {
|
|
633
|
-
await mkdir(path.dirname(destination), { recursive: true });
|
|
586
|
+
await installFileIfAllowed(targetDir, file, options, result, async () => {
|
|
634
587
|
const content = await buildInitTemplateContent(file, preset, options.personalization, designSystem);
|
|
635
|
-
|
|
636
|
-
}
|
|
588
|
+
return wrapManagedBlock(file, content);
|
|
589
|
+
});
|
|
637
590
|
}
|
|
638
591
|
if (preset) {
|
|
639
|
-
|
|
640
|
-
const destination = path.join(targetDir, stackFile);
|
|
641
|
-
const destinationExists = await exists(destination);
|
|
642
|
-
if (destinationExists && !options.force) {
|
|
643
|
-
skipped.push(stackFile);
|
|
644
|
-
}
|
|
645
|
-
else {
|
|
646
|
-
created.push(stackFile);
|
|
647
|
-
if (!options.dryRun) {
|
|
648
|
-
await writeFile(destination, wrapManagedBlock(stackFile, getStackGuidance(preset)));
|
|
649
|
-
}
|
|
650
|
-
}
|
|
592
|
+
await installFileIfAllowed(targetDir, "STACK.md", options, result, () => wrapManagedBlock("STACK.md", getStackGuidance(preset)));
|
|
651
593
|
}
|
|
652
|
-
return
|
|
594
|
+
return result;
|
|
653
595
|
}
|
|
654
596
|
function replaceManagedBlock(file, existingContent, nextContent) {
|
|
655
597
|
const id = getTemplateId(file);
|
|
@@ -770,110 +712,113 @@ function printUpdateResult(result, dryRun = false) {
|
|
|
770
712
|
console.log("All managed AgentKit files are current.");
|
|
771
713
|
}
|
|
772
714
|
}
|
|
773
|
-
async function
|
|
774
|
-
|
|
775
|
-
const shouldPrompt = shouldPromptForInit(options, process);
|
|
776
|
-
if (!shouldPrompt) {
|
|
715
|
+
async function promptForTarget(target) {
|
|
716
|
+
if (target && target !== ".") {
|
|
777
717
|
return target;
|
|
778
718
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
{ label: "Fullstack app", value: "fullstack" },
|
|
803
|
-
],
|
|
804
|
-
});
|
|
805
|
-
if (isCancel(projectTypeResponse)) {
|
|
806
|
-
process.exit(130);
|
|
807
|
-
}
|
|
808
|
-
options.preset = resolveProjectPreset(projectTypeResponse);
|
|
809
|
-
}
|
|
810
|
-
const aiToolResponse = await multiselect({
|
|
719
|
+
return (resolvePrompt(await text({
|
|
720
|
+
message: "Where should AgentKit install files?",
|
|
721
|
+
placeholder: ".",
|
|
722
|
+
defaultValue: ".",
|
|
723
|
+
})) || ".");
|
|
724
|
+
}
|
|
725
|
+
async function promptForProjectPreset() {
|
|
726
|
+
const projectType = resolvePrompt(await select({
|
|
727
|
+
message: "What type of project is this?",
|
|
728
|
+
initialValue: "generic",
|
|
729
|
+
options: [
|
|
730
|
+
{ label: "Generic TypeScript project", value: "generic" },
|
|
731
|
+
{ label: "Next.js app", value: "next" },
|
|
732
|
+
{ label: "SvelteKit app", value: "sveltekit" },
|
|
733
|
+
{ label: "Express API", value: "express" },
|
|
734
|
+
{ label: "Convex app", value: "convex" },
|
|
735
|
+
{ label: "Fullstack app", value: "fullstack" },
|
|
736
|
+
],
|
|
737
|
+
}));
|
|
738
|
+
return resolveProjectPreset(projectType);
|
|
739
|
+
}
|
|
740
|
+
async function promptForAiTools(defaults) {
|
|
741
|
+
return resolvePrompt(await multiselect({
|
|
811
742
|
message: "Which AI tools do you use?",
|
|
812
|
-
initialValues:
|
|
743
|
+
initialValues: defaults ?? ["codex", "cursor", "claude"],
|
|
813
744
|
options: [
|
|
814
745
|
{ label: "Codex", value: "codex" },
|
|
815
746
|
{ label: "Cursor", value: "cursor" },
|
|
816
747
|
{ label: "Claude Code", value: "claude" },
|
|
817
748
|
{ label: "GitHub Copilot", value: "copilot" },
|
|
818
749
|
],
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
const templateSetResponse = await select({
|
|
750
|
+
}));
|
|
751
|
+
}
|
|
752
|
+
async function promptForTemplateSet(defaultValue) {
|
|
753
|
+
return resolvePrompt(await select({
|
|
824
754
|
message: "Which template set do you want?",
|
|
825
|
-
initialValue:
|
|
755
|
+
initialValue: defaultValue ?? "standard",
|
|
826
756
|
options: [
|
|
827
757
|
{ label: "Minimal", value: "minimal" },
|
|
828
758
|
{ label: "Standard", value: "standard" },
|
|
829
759
|
{ label: "Full", value: "full" },
|
|
830
760
|
],
|
|
831
|
-
});
|
|
832
|
-
|
|
833
|
-
|
|
761
|
+
}));
|
|
762
|
+
}
|
|
763
|
+
async function promptForDesignSystem(defaultValue) {
|
|
764
|
+
return resolvePrompt(await select({
|
|
765
|
+
message: "Which design system guidance?",
|
|
766
|
+
initialValue: effectiveDesignSystem(defaultValue),
|
|
767
|
+
options: validDesignSystems.map((value) => ({ label: designSystemLabels[value], value })),
|
|
768
|
+
}));
|
|
769
|
+
}
|
|
770
|
+
async function findExistingInstallFiles(target, files) {
|
|
771
|
+
const targetDir = path.resolve(process.cwd(), target || ".");
|
|
772
|
+
const existingFiles = [];
|
|
773
|
+
for (const file of files) {
|
|
774
|
+
if (await exists(path.join(targetDir, file))) {
|
|
775
|
+
existingFiles.push(file);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return existingFiles;
|
|
779
|
+
}
|
|
780
|
+
async function promptForConflictStrategy(existingFiles) {
|
|
781
|
+
return resolvePrompt(await select({
|
|
782
|
+
message: `Existing files found: ${existingFiles.join(", ")}. How should AgentKit handle conflicts?`,
|
|
783
|
+
initialValue: "skip",
|
|
784
|
+
options: [
|
|
785
|
+
{ label: "Skip existing files", value: "skip" },
|
|
786
|
+
{ label: "Overwrite existing files", value: "overwrite" },
|
|
787
|
+
],
|
|
788
|
+
}));
|
|
789
|
+
}
|
|
790
|
+
async function applyInteractiveSelections(resolvedTarget, providedPreset, options) {
|
|
791
|
+
if (!providedPreset) {
|
|
792
|
+
options.preset = await promptForProjectPreset();
|
|
834
793
|
}
|
|
794
|
+
const aiTools = await promptForAiTools(options.aiTools);
|
|
795
|
+
const templateSet = await promptForTemplateSet(options.templateSet);
|
|
835
796
|
const templateFiles = await getTemplateFiles();
|
|
836
|
-
options.templateSet =
|
|
837
|
-
options.aiTools =
|
|
838
|
-
options.files = getSelectedTemplateFiles(
|
|
839
|
-
if (
|
|
840
|
-
|
|
841
|
-
message: "Which design system guidance?",
|
|
842
|
-
initialValue: effectiveDesignSystem(options.designSystem),
|
|
843
|
-
options: validDesignSystems.map((value) => ({ label: designSystemLabels[value], value })),
|
|
844
|
-
});
|
|
845
|
-
if (isCancel(designSystemResponse)) {
|
|
846
|
-
process.exit(130);
|
|
847
|
-
}
|
|
848
|
-
options.designSystem = designSystemResponse;
|
|
797
|
+
options.templateSet = templateSet;
|
|
798
|
+
options.aiTools = aiTools;
|
|
799
|
+
options.files = getSelectedTemplateFiles(templateSet, aiTools, templateFiles);
|
|
800
|
+
if (templateSet === "standard" || templateSet === "full") {
|
|
801
|
+
options.designSystem = await promptForDesignSystem(options.designSystem);
|
|
849
802
|
}
|
|
850
803
|
if (!options.force) {
|
|
851
804
|
const preset = resolvePreset(options.preset);
|
|
852
805
|
const installFiles = preset ? [...options.files, "STACK.md"] : options.files;
|
|
853
|
-
const
|
|
854
|
-
const existingFiles = [];
|
|
855
|
-
for (const file of installFiles) {
|
|
856
|
-
if (await exists(path.join(targetDir, file))) {
|
|
857
|
-
existingFiles.push(file);
|
|
858
|
-
}
|
|
859
|
-
}
|
|
806
|
+
const existingFiles = await findExistingInstallFiles(resolvedTarget, installFiles);
|
|
860
807
|
if (existingFiles.length > 0) {
|
|
861
|
-
|
|
862
|
-
message: `Existing files found: ${existingFiles.join(", ")}. How should AgentKit handle conflicts?`,
|
|
863
|
-
initialValue: "skip",
|
|
864
|
-
options: [
|
|
865
|
-
{ label: "Skip existing files", value: "skip" },
|
|
866
|
-
{ label: "Overwrite existing files", value: "overwrite" },
|
|
867
|
-
],
|
|
868
|
-
});
|
|
869
|
-
if (isCancel(conflictResponse)) {
|
|
870
|
-
process.exit(130);
|
|
871
|
-
}
|
|
872
|
-
options.force = conflictResponse === "overwrite";
|
|
808
|
+
options.force = (await promptForConflictStrategy(existingFiles)) === "overwrite";
|
|
873
809
|
}
|
|
874
810
|
}
|
|
811
|
+
}
|
|
812
|
+
async function resolveInteractiveTarget(target, options) {
|
|
813
|
+
const providedPreset = resolvePreset(options.preset);
|
|
814
|
+
if (!shouldPromptForInit(options, process)) {
|
|
815
|
+
return target;
|
|
816
|
+
}
|
|
817
|
+
intro("Welcome to AgentKit");
|
|
818
|
+
const resolvedTarget = await promptForTarget(target);
|
|
819
|
+
await applyInteractiveSelections(resolvedTarget, providedPreset, options);
|
|
875
820
|
options.personalization = await promptForPersonalization(options.personalization);
|
|
876
|
-
return resolvedTarget
|
|
821
|
+
return resolvedTarget;
|
|
877
822
|
}
|
|
878
823
|
async function main() {
|
|
879
824
|
if (process.argv.slice(2).includes("--list")) {
|