thomas-agentkit 0.3.0 → 0.4.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/README.md +17 -5
- package/dist/cli.js +323 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,16 +14,26 @@ Install templates into the current directory:
|
|
|
14
14
|
npx thomas-agentkit init
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
By default, `init` opens a short interactive setup flow in terminals. After choosing install options, you can optionally personalize repository-level template placeholders such as project name, description, issue tracker, docs paths, stack summary, and project commands.
|
|
18
|
+
|
|
17
19
|
Install into another directory:
|
|
18
20
|
|
|
19
21
|
```bash
|
|
20
22
|
npx thomas-agentkit init ./my-project
|
|
21
23
|
```
|
|
22
24
|
|
|
25
|
+
Accept defaults without prompts:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx thomas-agentkit init --yes
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`--yes` keeps installed templates generic and leaves placeholders for later editing.
|
|
32
|
+
|
|
23
33
|
Preview changes without writing files:
|
|
24
34
|
|
|
25
35
|
```bash
|
|
26
|
-
npx thomas-agentkit init --dry-run
|
|
36
|
+
npx thomas-agentkit init --yes --dry-run
|
|
27
37
|
```
|
|
28
38
|
|
|
29
39
|
Overwrite existing files:
|
|
@@ -44,7 +54,7 @@ Preview updates without writing files:
|
|
|
44
54
|
npx thomas-agentkit update --dry-run
|
|
45
55
|
```
|
|
46
56
|
|
|
47
|
-
|
|
57
|
+
Explicitly request the interactive flow:
|
|
48
58
|
|
|
49
59
|
```bash
|
|
50
60
|
npx thomas-agentkit init --interactive
|
|
@@ -97,6 +107,8 @@ Generated content
|
|
|
97
107
|
|
|
98
108
|
`agentkit update` only replaces content inside matching managed blocks. User edits before or after those blocks are preserved. Existing legacy files without managed blocks are reported as unmanaged and left untouched.
|
|
99
109
|
|
|
110
|
+
Interactive personalization only applies during `agentkit init` when files are created or overwritten. It does not write a config file, and `agentkit update` does not reapply personalized values.
|
|
111
|
+
|
|
100
112
|
## Presets
|
|
101
113
|
|
|
102
114
|
Presets add stack-specific guidance without scaffolding framework app files.
|
|
@@ -122,8 +134,8 @@ Options:
|
|
|
122
134
|
|
|
123
135
|
- `--force`: overwrite existing files
|
|
124
136
|
- `--dry-run`: print planned changes without writing files
|
|
125
|
-
- `-i, --interactive`: prompt for install options
|
|
126
|
-
- `-y, --yes`: accept defaults
|
|
137
|
+
- `-i, --interactive`: explicitly prompt for install options
|
|
138
|
+
- `-y, --yes`: accept defaults without prompts
|
|
127
139
|
- `--preset <name>`: install stack-specific guidance (`next`, `sveltekit`, `express`, `convex`, `fullstack`)
|
|
128
140
|
- `--list`: list bundled template files
|
|
129
141
|
- `--list-presets`: list available presets
|
|
@@ -136,7 +148,7 @@ For `agentkit update`, `--preset <name>` refreshes preset-specific managed conte
|
|
|
136
148
|
|
|
137
149
|
```bash
|
|
138
150
|
npm install
|
|
139
|
-
npm run dev -- init ./tmp-demo --dry-run
|
|
151
|
+
npm run dev -- init ./tmp-demo --yes --dry-run
|
|
140
152
|
npm run build
|
|
141
153
|
npm test
|
|
142
154
|
```
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { confirm, isCancel, select, text } from "@clack/prompts";
|
|
2
|
+
import { confirm, intro, isCancel, multiselect, select, text } from "@clack/prompts";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { constants as fsConstants } from "node:fs";
|
|
5
5
|
import { access, mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
@@ -11,6 +11,8 @@ const packageRoot = path.resolve(__dirname, "..");
|
|
|
11
11
|
const templatesDir = path.join(packageRoot, "templates");
|
|
12
12
|
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
13
13
|
const validPresets = ["next", "sveltekit", "express", "convex", "fullstack"];
|
|
14
|
+
const validProjectTypes = ["generic", ...validPresets];
|
|
15
|
+
const validAiTools = ["codex", "cursor", "claude", "copilot"];
|
|
14
16
|
const presetLabels = {
|
|
15
17
|
next: "Next.js",
|
|
16
18
|
sveltekit: "SvelteKit",
|
|
@@ -18,6 +20,17 @@ const presetLabels = {
|
|
|
18
20
|
convex: "Convex",
|
|
19
21
|
fullstack: "Fullstack",
|
|
20
22
|
};
|
|
23
|
+
const aiToolFiles = {
|
|
24
|
+
codex: ["AGENTS.md"],
|
|
25
|
+
cursor: [".cursor/rules/agentkit.md"],
|
|
26
|
+
claude: ["CLAUDE.md"],
|
|
27
|
+
copilot: [".github/copilot-instructions.md"],
|
|
28
|
+
};
|
|
29
|
+
const templateSetFiles = {
|
|
30
|
+
minimal: ["AGENTS.md"],
|
|
31
|
+
standard: ["AGENTS.md", "CODE-QUALITY.md", "DESIGN-SYSTEM.md", "WORKFLOWS.md"],
|
|
32
|
+
full: [],
|
|
33
|
+
};
|
|
21
34
|
const stackGuidance = {
|
|
22
35
|
next: `# Stack Guidance
|
|
23
36
|
|
|
@@ -101,6 +114,12 @@ async function getTemplateFiles(dir = templatesDir, base = templatesDir) {
|
|
|
101
114
|
function isPresetName(value) {
|
|
102
115
|
return validPresets.includes(value);
|
|
103
116
|
}
|
|
117
|
+
function isProjectTypeName(value) {
|
|
118
|
+
return validProjectTypes.includes(value);
|
|
119
|
+
}
|
|
120
|
+
function isAiToolName(value) {
|
|
121
|
+
return validAiTools.includes(value);
|
|
122
|
+
}
|
|
104
123
|
function formatPresetList() {
|
|
105
124
|
return validPresets.join(", ");
|
|
106
125
|
}
|
|
@@ -114,6 +133,38 @@ function resolvePreset(preset) {
|
|
|
114
133
|
}
|
|
115
134
|
return normalizedPreset;
|
|
116
135
|
}
|
|
136
|
+
export function resolveProjectPreset(projectType) {
|
|
137
|
+
if (!projectType) {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
const normalizedProjectType = projectType.toLowerCase();
|
|
141
|
+
if (!isProjectTypeName(normalizedProjectType)) {
|
|
142
|
+
throw new Error(`Unknown project type "${projectType}". Valid project types: ${validProjectTypes.join(", ")}.`);
|
|
143
|
+
}
|
|
144
|
+
return normalizedProjectType === "generic" ? undefined : normalizedProjectType;
|
|
145
|
+
}
|
|
146
|
+
export function getFilesForAiTools(aiTools) {
|
|
147
|
+
const files = new Set();
|
|
148
|
+
for (const aiTool of aiTools) {
|
|
149
|
+
if (!isAiToolName(aiTool)) {
|
|
150
|
+
throw new Error(`Unknown AI tool "${aiTool}". Valid AI tools: ${validAiTools.join(", ")}.`);
|
|
151
|
+
}
|
|
152
|
+
for (const file of aiToolFiles[aiTool]) {
|
|
153
|
+
files.add(file);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return [...files].sort();
|
|
157
|
+
}
|
|
158
|
+
export function getFilesForTemplateSet(templateSet, allTemplateFiles) {
|
|
159
|
+
if (templateSet === "full") {
|
|
160
|
+
return [...allTemplateFiles].sort();
|
|
161
|
+
}
|
|
162
|
+
return templateSetFiles[templateSet].filter((file) => allTemplateFiles.includes(file)).sort();
|
|
163
|
+
}
|
|
164
|
+
export function getSelectedTemplateFiles(templateSet, aiTools, allTemplateFiles) {
|
|
165
|
+
const files = new Set([...getFilesForTemplateSet(templateSet, allTemplateFiles), ...getFilesForAiTools(aiTools)]);
|
|
166
|
+
return [...files].filter((file) => allTemplateFiles.includes(file)).sort();
|
|
167
|
+
}
|
|
117
168
|
function getStackGuidance(preset) {
|
|
118
169
|
return preset === "fullstack" ? fullstackGuidance : stackGuidance[preset];
|
|
119
170
|
}
|
|
@@ -140,9 +191,190 @@ function addStackReference(file, content, preset) {
|
|
|
140
191
|
}
|
|
141
192
|
return `${content.trimEnd()}\n${stackNote}`;
|
|
142
193
|
}
|
|
194
|
+
function cleanPersonalizationValue(value) {
|
|
195
|
+
const trimmed = value?.trim();
|
|
196
|
+
return trimmed ? trimmed : undefined;
|
|
197
|
+
}
|
|
198
|
+
function replaceIfProvided(content, placeholder, value) {
|
|
199
|
+
const replacement = cleanPersonalizationValue(value);
|
|
200
|
+
return replacement ? content.replaceAll(placeholder, replacement) : content;
|
|
201
|
+
}
|
|
202
|
+
function getProvidedCommands(values) {
|
|
203
|
+
return [values.testCommand, values.lintCommand, values.buildCommand]
|
|
204
|
+
.map(cleanPersonalizationValue)
|
|
205
|
+
.filter((command) => Boolean(command));
|
|
206
|
+
}
|
|
207
|
+
function commandDescription(command, kind) {
|
|
208
|
+
const descriptions = {
|
|
209
|
+
test: "Run tests",
|
|
210
|
+
lint: "Run lint checks",
|
|
211
|
+
build: "Build or check the project",
|
|
212
|
+
};
|
|
213
|
+
return descriptions[kind] ?? command;
|
|
214
|
+
}
|
|
215
|
+
function replaceCommandBlock(content, commands) {
|
|
216
|
+
if (commands.length === 0) {
|
|
217
|
+
return content;
|
|
218
|
+
}
|
|
219
|
+
const commandBlock = ["```bash", ...commands, "```"].join("\n");
|
|
220
|
+
return content
|
|
221
|
+
.replace(/```bash\nnpm install\nnpm test\nnpm run build\nnpm run lint\n```/, commandBlock)
|
|
222
|
+
.replace(/```bash\nnpm test\nnpm run lint\nnpm run build\n```/, commandBlock);
|
|
223
|
+
}
|
|
224
|
+
function replaceAgentCommandTable(content, values) {
|
|
225
|
+
const rows = [
|
|
226
|
+
cleanPersonalizationValue(values.testCommand)
|
|
227
|
+
? `| \`${cleanPersonalizationValue(values.testCommand)}\` | ${commandDescription(values.testCommand ?? "", "test")} |`
|
|
228
|
+
: undefined,
|
|
229
|
+
cleanPersonalizationValue(values.lintCommand)
|
|
230
|
+
? `| \`${cleanPersonalizationValue(values.lintCommand)}\` | ${commandDescription(values.lintCommand ?? "", "lint")} |`
|
|
231
|
+
: undefined,
|
|
232
|
+
cleanPersonalizationValue(values.buildCommand)
|
|
233
|
+
? `| \`${cleanPersonalizationValue(values.buildCommand)}\` | ${commandDescription(values.buildCommand ?? "", "build")} |`
|
|
234
|
+
: undefined,
|
|
235
|
+
].filter((row) => Boolean(row));
|
|
236
|
+
if (rows.length === 0) {
|
|
237
|
+
return content;
|
|
238
|
+
}
|
|
239
|
+
const nextTable = ["| Command | Description |", "| --- | --- |", ...rows].join("\n");
|
|
240
|
+
return content.replace(/\| Command \| Description \|\n\| --- \| --- \|\n\| `npm run dev` \| Start the local development server \|\n\| `npm test` \| Run tests \|\n\| `npm run lint` \| Run lint checks \|\n\| `npm run build` \| Build the project \|/, nextTable);
|
|
241
|
+
}
|
|
242
|
+
function replaceStackSummary(content, stackSummary) {
|
|
243
|
+
const summary = cleanPersonalizationValue(stackSummary);
|
|
244
|
+
if (!summary) {
|
|
245
|
+
return content;
|
|
246
|
+
}
|
|
247
|
+
const stackItems = summary
|
|
248
|
+
.split(/\r?\n|,/)
|
|
249
|
+
.map((item) => item.trim())
|
|
250
|
+
.filter(Boolean)
|
|
251
|
+
.map((item) => `- ${item}`)
|
|
252
|
+
.join("\n");
|
|
253
|
+
return content.replace(/- \[Primary framework\]\n- \[Language\/runtime\]\n- \[Backend\/data layer\]\n- \[Styling system\]\n- \[Test tools\]\n- \[Lint\/format tools\]/, stackItems);
|
|
254
|
+
}
|
|
255
|
+
export function personalizeTemplateContent(file, content, values) {
|
|
256
|
+
if (!values) {
|
|
257
|
+
return content;
|
|
258
|
+
}
|
|
259
|
+
if (file === "PRD-TEMPLATE.md" ||
|
|
260
|
+
file === "IMPLEMENTATION-BRIEF-TEMPLATE.md" ||
|
|
261
|
+
file === ".github/pull_request_template.md") {
|
|
262
|
+
return content;
|
|
263
|
+
}
|
|
264
|
+
let personalized = content;
|
|
265
|
+
if (file === "AGENTS.md" || file === "DESIGN-SYSTEM.md") {
|
|
266
|
+
personalized = replaceIfProvided(personalized, "[Project Name]", values.projectName);
|
|
267
|
+
}
|
|
268
|
+
if (file === "AGENTS.md") {
|
|
269
|
+
personalized = replaceIfProvided(personalized, "[short project description]", values.projectDescription);
|
|
270
|
+
personalized = replaceIfProvided(personalized, "[issue tracker, e.g. Linear or GitHub Issues]", values.issueTracker);
|
|
271
|
+
personalized = replaceIfProvided(personalized, "[design system path, e.g. docs/design-system.md]", values.designSystemPath);
|
|
272
|
+
personalized = replaceIfProvided(personalized, "[design system path]", values.designSystemPath);
|
|
273
|
+
personalized = replaceIfProvided(personalized, "[briefs path, e.g. docs/briefs]", values.briefsPath);
|
|
274
|
+
personalized = replaceIfProvided(personalized, "[test command, e.g. npm test]", values.testCommand);
|
|
275
|
+
personalized = replaceIfProvided(personalized, "[lint command, e.g. npm run lint]", values.lintCommand);
|
|
276
|
+
personalized = replaceIfProvided(personalized, "[build/check command, e.g. npm run build]", values.buildCommand);
|
|
277
|
+
personalized = replaceAgentCommandTable(personalized, values);
|
|
278
|
+
personalized = replaceStackSummary(personalized, values.stackSummary);
|
|
279
|
+
}
|
|
280
|
+
if (file === "CLAUDE.md" || file === "CODE-QUALITY.md") {
|
|
281
|
+
personalized = replaceCommandBlock(personalized, getProvidedCommands(values));
|
|
282
|
+
}
|
|
283
|
+
return personalized;
|
|
284
|
+
}
|
|
285
|
+
async function promptForPersonalization() {
|
|
286
|
+
const shouldPersonalize = await confirm({
|
|
287
|
+
message: "Personalize template placeholders?",
|
|
288
|
+
initialValue: false,
|
|
289
|
+
});
|
|
290
|
+
if (isCancel(shouldPersonalize)) {
|
|
291
|
+
process.exit(130);
|
|
292
|
+
}
|
|
293
|
+
if (!shouldPersonalize) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
const projectName = await text({
|
|
297
|
+
message: "Project name",
|
|
298
|
+
placeholder: "[Project Name]",
|
|
299
|
+
});
|
|
300
|
+
if (isCancel(projectName)) {
|
|
301
|
+
process.exit(130);
|
|
302
|
+
}
|
|
303
|
+
const projectDescription = await text({
|
|
304
|
+
message: "Short project description",
|
|
305
|
+
placeholder: "[short project description]",
|
|
306
|
+
});
|
|
307
|
+
if (isCancel(projectDescription)) {
|
|
308
|
+
process.exit(130);
|
|
309
|
+
}
|
|
310
|
+
const issueTracker = await text({
|
|
311
|
+
message: "Issue tracker name",
|
|
312
|
+
placeholder: "Linear or GitHub Issues",
|
|
313
|
+
});
|
|
314
|
+
if (isCancel(issueTracker)) {
|
|
315
|
+
process.exit(130);
|
|
316
|
+
}
|
|
317
|
+
const designSystemPath = await text({
|
|
318
|
+
message: "Design system path",
|
|
319
|
+
placeholder: "docs/design-system.md",
|
|
320
|
+
});
|
|
321
|
+
if (isCancel(designSystemPath)) {
|
|
322
|
+
process.exit(130);
|
|
323
|
+
}
|
|
324
|
+
const briefsPath = await text({
|
|
325
|
+
message: "Briefs path",
|
|
326
|
+
placeholder: "docs/briefs",
|
|
327
|
+
});
|
|
328
|
+
if (isCancel(briefsPath)) {
|
|
329
|
+
process.exit(130);
|
|
330
|
+
}
|
|
331
|
+
const testCommand = await text({
|
|
332
|
+
message: "Test command",
|
|
333
|
+
placeholder: "npm test",
|
|
334
|
+
});
|
|
335
|
+
if (isCancel(testCommand)) {
|
|
336
|
+
process.exit(130);
|
|
337
|
+
}
|
|
338
|
+
const lintCommand = await text({
|
|
339
|
+
message: "Lint command",
|
|
340
|
+
placeholder: "npm run lint",
|
|
341
|
+
});
|
|
342
|
+
if (isCancel(lintCommand)) {
|
|
343
|
+
process.exit(130);
|
|
344
|
+
}
|
|
345
|
+
const buildCommand = await text({
|
|
346
|
+
message: "Build/check command",
|
|
347
|
+
placeholder: "npm run build",
|
|
348
|
+
});
|
|
349
|
+
if (isCancel(buildCommand)) {
|
|
350
|
+
process.exit(130);
|
|
351
|
+
}
|
|
352
|
+
const stackSummary = await text({
|
|
353
|
+
message: "Stack summary",
|
|
354
|
+
placeholder: "Next.js, TypeScript, Tailwind CSS, Vitest",
|
|
355
|
+
});
|
|
356
|
+
if (isCancel(stackSummary)) {
|
|
357
|
+
process.exit(130);
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
projectName,
|
|
361
|
+
projectDescription,
|
|
362
|
+
issueTracker,
|
|
363
|
+
designSystemPath,
|
|
364
|
+
briefsPath,
|
|
365
|
+
testCommand,
|
|
366
|
+
lintCommand,
|
|
367
|
+
buildCommand,
|
|
368
|
+
stackSummary,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
async function buildInitTemplateContent(file, preset, personalization) {
|
|
372
|
+
const content = await buildTemplateContent(file, preset);
|
|
373
|
+
return personalizeTemplateContent(file, content, personalization);
|
|
374
|
+
}
|
|
143
375
|
async function installTemplates(targetArg, options) {
|
|
144
376
|
const targetDir = path.resolve(process.cwd(), targetArg || ".");
|
|
145
|
-
const files = await getTemplateFiles();
|
|
377
|
+
const files = options.files ?? (await getTemplateFiles());
|
|
146
378
|
const preset = resolvePreset(options.preset);
|
|
147
379
|
const created = [];
|
|
148
380
|
const skipped = [];
|
|
@@ -150,7 +382,6 @@ async function installTemplates(targetArg, options) {
|
|
|
150
382
|
await mkdir(targetDir, { recursive: true });
|
|
151
383
|
}
|
|
152
384
|
for (const file of files) {
|
|
153
|
-
const source = path.join(templatesDir, file);
|
|
154
385
|
const destination = path.join(targetDir, file);
|
|
155
386
|
const destinationExists = await exists(destination);
|
|
156
387
|
if (destinationExists && !options.force) {
|
|
@@ -161,11 +392,11 @@ async function installTemplates(targetArg, options) {
|
|
|
161
392
|
if (!options.dryRun) {
|
|
162
393
|
await mkdir(path.dirname(destination), { recursive: true });
|
|
163
394
|
if (preset && file === "AGENTS.md") {
|
|
164
|
-
const content = await
|
|
165
|
-
await writeFile(destination, wrapManagedBlock(file,
|
|
395
|
+
const content = await buildInitTemplateContent(file, preset, options.personalization);
|
|
396
|
+
await writeFile(destination, wrapManagedBlock(file, content));
|
|
166
397
|
}
|
|
167
398
|
else {
|
|
168
|
-
const content = await
|
|
399
|
+
const content = await buildInitTemplateContent(file, preset, options.personalization);
|
|
169
400
|
await writeFile(destination, wrapManagedBlock(file, content));
|
|
170
401
|
}
|
|
171
402
|
}
|
|
@@ -301,42 +532,95 @@ function printUpdateResult(result, dryRun = false) {
|
|
|
301
532
|
}
|
|
302
533
|
async function resolveInteractiveTarget(target, options) {
|
|
303
534
|
const providedPreset = resolvePreset(options.preset);
|
|
304
|
-
|
|
535
|
+
const shouldPrompt = !options.yes && (options.interactive || process.stdin.isTTY);
|
|
536
|
+
if (!shouldPrompt) {
|
|
305
537
|
return target;
|
|
306
538
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
539
|
+
intro("Welcome to AgentKit");
|
|
540
|
+
let resolvedTarget = target;
|
|
541
|
+
if (!target || target === ".") {
|
|
542
|
+
const targetResponse = await text({
|
|
543
|
+
message: "Where should AgentKit install files?",
|
|
544
|
+
placeholder: ".",
|
|
545
|
+
defaultValue: ".",
|
|
546
|
+
});
|
|
547
|
+
if (isCancel(targetResponse)) {
|
|
548
|
+
process.exit(130);
|
|
549
|
+
}
|
|
550
|
+
resolvedTarget = targetResponse || ".";
|
|
314
551
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
552
|
+
if (!providedPreset) {
|
|
553
|
+
const projectTypeResponse = await select({
|
|
554
|
+
message: "What type of project is this?",
|
|
555
|
+
initialValue: "generic",
|
|
556
|
+
options: [
|
|
557
|
+
{ label: "Generic TypeScript project", value: "generic" },
|
|
558
|
+
{ label: "Next.js app", value: "next" },
|
|
559
|
+
{ label: "SvelteKit app", value: "sveltekit" },
|
|
560
|
+
{ label: "Express API", value: "express" },
|
|
561
|
+
{ label: "Convex app", value: "convex" },
|
|
562
|
+
{ label: "Fullstack app", value: "fullstack" },
|
|
563
|
+
],
|
|
564
|
+
});
|
|
565
|
+
if (isCancel(projectTypeResponse)) {
|
|
566
|
+
process.exit(130);
|
|
567
|
+
}
|
|
568
|
+
options.preset = resolveProjectPreset(projectTypeResponse);
|
|
569
|
+
}
|
|
570
|
+
const aiToolResponse = await multiselect({
|
|
571
|
+
message: "Which AI tools do you use?",
|
|
572
|
+
initialValues: ["codex", "cursor", "claude"],
|
|
573
|
+
options: [
|
|
574
|
+
{ label: "Codex", value: "codex" },
|
|
575
|
+
{ label: "Cursor", value: "cursor" },
|
|
576
|
+
{ label: "Claude Code", value: "claude" },
|
|
577
|
+
{ label: "GitHub Copilot", value: "copilot" },
|
|
578
|
+
],
|
|
318
579
|
});
|
|
319
|
-
if (isCancel(
|
|
580
|
+
if (isCancel(aiToolResponse)) {
|
|
320
581
|
process.exit(130);
|
|
321
582
|
}
|
|
322
|
-
const
|
|
323
|
-
message: "Which
|
|
324
|
-
initialValue:
|
|
583
|
+
const templateSetResponse = await select({
|
|
584
|
+
message: "Which template set do you want?",
|
|
585
|
+
initialValue: "standard",
|
|
325
586
|
options: [
|
|
326
|
-
{ label: "
|
|
327
|
-
{ label: "
|
|
328
|
-
{ label: "
|
|
329
|
-
{ label: "Express", value: "express" },
|
|
330
|
-
{ label: "Convex", value: "convex" },
|
|
331
|
-
{ label: "Fullstack", value: "fullstack" },
|
|
587
|
+
{ label: "Minimal", value: "minimal" },
|
|
588
|
+
{ label: "Standard", value: "standard" },
|
|
589
|
+
{ label: "Full", value: "full" },
|
|
332
590
|
],
|
|
333
591
|
});
|
|
334
|
-
if (isCancel(
|
|
592
|
+
if (isCancel(templateSetResponse)) {
|
|
335
593
|
process.exit(130);
|
|
336
594
|
}
|
|
337
|
-
|
|
338
|
-
options.
|
|
339
|
-
|
|
595
|
+
const templateFiles = await getTemplateFiles();
|
|
596
|
+
options.files = getSelectedTemplateFiles(templateSetResponse, aiToolResponse, templateFiles);
|
|
597
|
+
if (!options.force) {
|
|
598
|
+
const preset = resolvePreset(options.preset);
|
|
599
|
+
const installFiles = preset ? [...options.files, "STACK.md"] : options.files;
|
|
600
|
+
const targetDir = path.resolve(process.cwd(), resolvedTarget || ".");
|
|
601
|
+
const existingFiles = [];
|
|
602
|
+
for (const file of installFiles) {
|
|
603
|
+
if (await exists(path.join(targetDir, file))) {
|
|
604
|
+
existingFiles.push(file);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
if (existingFiles.length > 0) {
|
|
608
|
+
const conflictResponse = await select({
|
|
609
|
+
message: `Existing files found: ${existingFiles.join(", ")}. How should AgentKit handle conflicts?`,
|
|
610
|
+
initialValue: "skip",
|
|
611
|
+
options: [
|
|
612
|
+
{ label: "Skip existing files", value: "skip" },
|
|
613
|
+
{ label: "Overwrite existing files", value: "overwrite" },
|
|
614
|
+
],
|
|
615
|
+
});
|
|
616
|
+
if (isCancel(conflictResponse)) {
|
|
617
|
+
process.exit(130);
|
|
618
|
+
}
|
|
619
|
+
options.force = conflictResponse === "overwrite";
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
options.personalization = await promptForPersonalization();
|
|
623
|
+
return resolvedTarget || ".";
|
|
340
624
|
}
|
|
341
625
|
async function main() {
|
|
342
626
|
if (process.argv.slice(2).includes("--list")) {
|
|
@@ -365,7 +649,7 @@ Examples:
|
|
|
365
649
|
agentkit init
|
|
366
650
|
agentkit update
|
|
367
651
|
agentkit init --preset next
|
|
368
|
-
agentkit init ./my-project --dry-run
|
|
652
|
+
agentkit init ./my-project --yes --dry-run
|
|
369
653
|
agentkit --list-presets
|
|
370
654
|
agentkit --list`);
|
|
371
655
|
program
|
|
@@ -394,8 +678,10 @@ Examples:
|
|
|
394
678
|
});
|
|
395
679
|
await program.parseAsync(process.argv);
|
|
396
680
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
681
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === __filename) {
|
|
682
|
+
main().catch((error) => {
|
|
683
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
684
|
+
console.error(message);
|
|
685
|
+
process.exitCode = 1;
|
|
686
|
+
});
|
|
687
|
+
}
|