create-cogitator-app 0.2.1 → 0.3.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/README.md CHANGED
@@ -21,7 +21,7 @@ npx create-cogitator-app -y
21
21
  npx create-cogitator-app my-project -p openai --yes
22
22
  ```
23
23
 
24
- Prompts are shown only for values not given on the command line: project directory, template, provider, package manager, Docker Compose and git. With `-y` / `--yes` nothing is asked and the defaults fill the gaps: `my-agents`, `basic`, `ollama`, the detected package manager, Docker Compose on, git on. The target directory must be empty or not exist. After writing the files the scaffolder runs `<pm> install` and, unless disabled, creates a git repository with an initial commit.
24
+ Prompts are shown only for values not given on the command line: project directory, template, provider, package manager, Docker Compose and git. With `-y` / `--yes` nothing is asked and the defaults fill the gaps: `my-agents`, `basic`, `ollama`, the detected package manager, Docker Compose on, git on. The target directory must be empty or not exist. After writing the files the scaffolder runs `<pm> install` (skip it with `--no-install`) and, unless disabled, creates a git repository with an initial commit. A failed install or git step is reported and left for you to run by hand.
25
25
 
26
26
  Requires Node.js 22.12+.
27
27
 
@@ -46,6 +46,7 @@ Requires Node.js 22.12+.
46
46
  | `--pm <name>` | | Package manager (`pnpm`, `npm`, `yarn`, `bun`) |
47
47
  | `--docker` / `--no-docker` | | Include Docker Compose (Redis, Postgres, plus Ollama) |
48
48
  | `--git` / `--no-git` | | Initialize git repository |
49
+ | `--no-install` | | Write the files without running `<pm> install` |
49
50
  | `--yes` | `-y` | Don't prompt; use the defaults for every missing value |
50
51
 
51
52
  Unknown values for `--template`, `--provider` and `--pm` are ignored and asked for interactively (or replaced by the default with `--yes`). The package manager prompt defaults to the one that invoked the scaffolder (`npm_config_user_agent`), falling back to `pnpm`.
@@ -80,16 +81,16 @@ my-project/
80
81
 
81
82
  Template-specific sources:
82
83
 
83
- | Template | Files |
84
- | ------------ | -------------------------------------------------------------------------------------------------- |
85
- | `basic` | `src/index.ts`, `src/tools.ts` |
86
- | `memory` | `src/index.ts`, `src/tools.ts` |
87
- | `swarm` | `src/index.ts`, `src/tools.ts`, `src/agents/{researcher,writer,reviewer}.ts` |
88
- | `workflow` | `src/index.ts`, `src/agents.ts` |
89
- | `api-server` | `src/index.ts`, `src/agents.ts` |
90
- | `nextjs` | `src/lib/agent.ts`, `src/app/api/chat/route.ts`, `src/app/{page,layout}.tsx`, Next/Tailwind config |
84
+ | Template | Files |
85
+ | ------------ | ----------------------------------------------------------------------------------------------------------- |
86
+ | `basic` | `src/index.ts`, `src/tools.ts` |
87
+ | `memory` | `src/index.ts`, `src/tools.ts` |
88
+ | `swarm` | `src/index.ts`, `src/tools.ts`, `src/agents/{researcher,writer,reviewer}.ts` |
89
+ | `workflow` | `src/index.ts`, `src/agents.ts` |
90
+ | `api-server` | `src/index.ts`, `src/agents.ts` |
91
+ | `nextjs` | `src/lib/agent.ts`, `src/app/api/{chat,health}/route.ts`, `src/app/{page,layout}.tsx`, Next/Tailwind config |
91
92
 
92
- The generated code configures `Cogitator` in `src/` itself, reading the provider key from the environment. Copy `.env.example` to `.env` and fill it in, then run `pnpm dev` (or `npm run dev`, `yarn dev`, `bun dev`).
93
+ The generated code configures `Cogitator` in `src/` itself, reading the provider key from the environment. For the `api-server` and `nextjs` templates `cogitator.yml` also sets `deploy.health.path: /api/health`, the route the app serves, so `cogitator deploy` produces a container that reports healthy. Copy `.env.example` to `.env` and fill it in, then run `pnpm dev` (or `npm run dev`, `yarn dev`, `bun dev`).
93
94
 
94
95
  ## Programmatic API
95
96
 
@@ -105,18 +106,21 @@ const options: ProjectOptions = {
105
106
  packageManager: 'pnpm',
106
107
  docker: false,
107
108
  git: true,
109
+ install: false, // optional, default true
108
110
  };
109
111
 
110
- await scaffold(options);
112
+ const result = await scaffold(options);
113
+ // { files: ['package.json', 'src/index.ts', ...], install: { status: 'skipped' }, git: { status: 'done' } }
114
+ if (result.install.status === 'failed') console.error(result.install.error);
111
115
 
112
116
  // or: parse CLI arguments and prompt for the rest
113
117
  const fromCli = await collectOptions(parseArgs(process.argv.slice(2)));
114
118
  await scaffold(fromCli);
115
119
  ```
116
120
 
117
- `scaffold()` writes the files, installs dependencies with `packageManager` and initializes git when `git` is `true`; it throws when `path` exists and is not empty.
121
+ `scaffold()` writes the files, installs dependencies with `packageManager` unless `install` is `false`, and initializes git when `git` is `true`. It throws when `path` exists and is not empty. A failed install or git step does not throw: the returned `ScaffoldResult` lists the generated `files` and reports each step as `{ status: 'done' }`, `{ status: 'skipped' }` or `{ status: 'failed', error }`, and the project stays on disk.
118
122
 
119
- Other exports: `getTemplate(name)` and `templateChoices` (template generators and their labels), `detectPackageManager()`, `devCommand(pm)`, `defaultModels`, `providerConfig(provider)` and `providerEnvKey(provider)`, and the types `ProjectOptions`, `Template`, `LLMProvider`, `PackageManager` and `TemplateFile`.
123
+ Other exports: `getTemplate(name)` and `templateChoices` (template generators and their labels), `detectPackageManager()`, `devCommand(pm)`, `defaultModels`, `providerConfig(provider)` and `providerEnvKey(provider)`, and the types `ProjectOptions`, `ScaffoldResult`, `ScaffoldStep`, `Template`, `LLMProvider`, `PackageManager` and `TemplateFile`.
120
124
 
121
125
  ## License
122
126
 
package/dist/index.js CHANGED
@@ -550,7 +550,9 @@ var workflowTemplate = {
550
550
  };
551
551
 
552
552
  // src/templates/api-server.ts
553
+ var BASE_PATH = "/api";
553
554
  var apiServerTemplate = {
555
+ healthPath: `${BASE_PATH}/health`,
554
556
  files(options) {
555
557
  const model = defaultModels[options.provider];
556
558
  const agentsTs = [
@@ -602,7 +604,7 @@ var apiServerTemplate = {
602
604
  ` cogitator,`,
603
605
  ` agents: { assistant, coder },`,
604
606
  ` config: {`,
605
- ` basePath: '/api',`,
607
+ ` basePath: '${BASE_PATH}',`,
606
608
  ` enableSwagger: true,`,
607
609
  ` cors: { origin: '*' },`,
608
610
  ` swagger: {`,
@@ -617,7 +619,7 @@ var apiServerTemplate = {
617
619
  ``,
618
620
  ` app.listen(port, () => {`,
619
621
  ` console.log(\`Server running at http://localhost:\${port}\`)`,
620
- ` console.log(\`Swagger docs at http://localhost:\${port}/api/docs\`)`,
622
+ ` console.log(\`Swagger docs at http://localhost:\${port}${BASE_PATH}/docs\`)`,
621
623
  ` })`,
622
624
  `}`,
623
625
  ``,
@@ -633,7 +635,7 @@ var apiServerTemplate = {
633
635
  return {
634
636
  "@cogitator-ai/core": "latest",
635
637
  "@cogitator-ai/express": "latest",
636
- express: "^4.21.0",
638
+ express: "^5.2.1",
637
639
  zod: ZOD_VERSION
638
640
  };
639
641
  },
@@ -642,7 +644,7 @@ var apiServerTemplate = {
642
644
  typescript: "^5.8.0",
643
645
  tsx: "^4.19.0",
644
646
  "@types/node": "^22.0.0",
645
- "@types/express": "^5.0.0"
647
+ "@types/express": "^5.0.6"
646
648
  };
647
649
  },
648
650
  scripts() {
@@ -657,6 +659,7 @@ var apiServerTemplate = {
657
659
 
658
660
  // src/templates/nextjs.ts
659
661
  var nextjsTemplate = {
662
+ healthPath: "/api/health",
660
663
  files(options) {
661
664
  const model = defaultModels[options.provider];
662
665
  const agentTs = [
@@ -694,6 +697,12 @@ var nextjsTemplate = {
694
697
  `export const POST = createChatHandler(cogitator, agent)`,
695
698
  ``
696
699
  ].join("\n");
700
+ const healthRouteTs = [
701
+ `export function GET() {`,
702
+ ` return Response.json({ status: 'ok' })`,
703
+ `}`,
704
+ ``
705
+ ].join("\n");
697
706
  const pageTsx = [
698
707
  `'use client'`,
699
708
  ``,
@@ -860,6 +869,7 @@ var nextjsTemplate = {
860
869
  return [
861
870
  { path: "src/lib/agent.ts", content: agentTs },
862
871
  { path: "src/app/api/chat/route.ts", content: routeTs },
872
+ { path: "src/app/api/health/route.ts", content: healthRouteTs },
863
873
  { path: "src/app/page.tsx", content: pageTsx },
864
874
  { path: "src/app/layout.tsx", content: layoutTsx },
865
875
  { path: "src/app/globals.css", content: globalsCss },
@@ -983,6 +993,10 @@ function parseArgs(args) {
983
993
  parsed.git = true;
984
994
  } else if (arg === "--no-git") {
985
995
  parsed.git = false;
996
+ } else if (arg === "--install") {
997
+ parsed.install = true;
998
+ } else if (arg === "--no-install") {
999
+ parsed.install = false;
986
1000
  } else if (arg === "-y" || arg === "--yes") {
987
1001
  parsed.yes = true;
988
1002
  } else if (!arg.startsWith("-") && !parsed.name) {
@@ -1075,7 +1089,8 @@ async function collectOptions(args) {
1075
1089
  provider,
1076
1090
  packageManager,
1077
1091
  docker,
1078
- git
1092
+ git,
1093
+ ...args.install !== void 0 && { install: args.install }
1079
1094
  };
1080
1095
  }
1081
1096
 
@@ -1226,6 +1241,10 @@ function generateCogitatorYml(provider, template) {
1226
1241
  " url: ${REDIS_URL:-redis://localhost:6379}"
1227
1242
  );
1228
1243
  }
1244
+ const healthPath = template ? getTemplate(template).healthPath : void 0;
1245
+ if (healthPath) {
1246
+ lines.push("", "deploy:", " health:", ` path: ${healthPath}`);
1247
+ }
1229
1248
  lines.push("");
1230
1249
  return { path: "cogitator.yml", content: lines.join("\n") };
1231
1250
  }
@@ -1357,6 +1376,17 @@ function collectFiles(options) {
1357
1376
  }
1358
1377
  return files;
1359
1378
  }
1379
+ function runStep(spinner2, messages, step) {
1380
+ spinner2.start(messages.start);
1381
+ try {
1382
+ step();
1383
+ spinner2.stop(messages.done);
1384
+ return { status: "done" };
1385
+ } catch (error) {
1386
+ spinner2.stop(messages.failed);
1387
+ return { status: "failed", error: error instanceof Error ? error : new Error(String(error)) };
1388
+ }
1389
+ }
1360
1390
  async function scaffold(options) {
1361
1391
  if (fs.existsSync(options.path) && fs.readdirSync(options.path).length > 0) {
1362
1392
  throw new Error(`Directory "${options.path}" already exists and is not empty`);
@@ -1369,22 +1399,25 @@ async function scaffold(options) {
1369
1399
  writeFile(options.path, file);
1370
1400
  }
1371
1401
  s.stop("Generated project files");
1372
- s.start("Installing dependencies");
1373
- try {
1374
- installDependencies(options.path, options.packageManager);
1375
- s.stop("Installed dependencies");
1376
- } catch {
1377
- s.stop("Failed to install dependencies \u2014 run manually");
1378
- }
1379
- if (options.git && isGitInstalled()) {
1380
- s.start("Initializing git repository");
1381
- try {
1382
- initGitRepo(options.path);
1383
- s.stop("Initialized git repository");
1384
- } catch {
1385
- s.stop("Failed to initialize git \u2014 run manually");
1386
- }
1387
- }
1402
+ const install = options.install === false ? { status: "skipped" } : runStep(
1403
+ s,
1404
+ {
1405
+ start: "Installing dependencies",
1406
+ done: "Installed dependencies",
1407
+ failed: `Failed to install dependencies, run "${options.packageManager} install" yourself`
1408
+ },
1409
+ () => installDependencies(options.path, options.packageManager)
1410
+ );
1411
+ const git = options.git && isGitInstalled() ? runStep(
1412
+ s,
1413
+ {
1414
+ start: "Initializing git repository",
1415
+ done: "Initialized git repository",
1416
+ failed: 'Failed to initialize git, run "git init" yourself'
1417
+ },
1418
+ () => initGitRepo(options.path)
1419
+ ) : { status: "skipped" };
1420
+ return { files: files.map((file) => file.path), install, git };
1388
1421
  }
1389
1422
 
1390
1423
  // src/index.ts
@@ -1394,13 +1427,21 @@ async function main() {
1394
1427
  p3.intro(pc2.cyan("Let's build something with AI agents"));
1395
1428
  const args = parseArgs(process.argv.slice(2));
1396
1429
  const options = await collectOptions(args);
1397
- await scaffold(options);
1430
+ const result = await scaffold(options);
1431
+ if (result.install.status === "failed") {
1432
+ p3.log.warn(`${options.packageManager} install failed: ${result.install.error.message}`);
1433
+ }
1434
+ if (result.git.status === "failed") {
1435
+ p3.log.warn(`git init failed: ${result.git.error.message}`);
1436
+ }
1398
1437
  const dev = devCommand(options.packageManager);
1438
+ const install = result.install.status === "done" ? [] : [` ${pc2.cyan(`${options.packageManager} install`)}`];
1399
1439
  p3.outro(
1400
1440
  [
1401
1441
  pc2.green("Done! ") + "Next steps:",
1402
1442
  "",
1403
1443
  ` ${pc2.cyan("cd")} ${options.name}`,
1444
+ ...install,
1404
1445
  ` ${pc2.cyan(dev)}`,
1405
1446
  "",
1406
1447
  pc2.dim(`Docs: ${DOCS_URL}`)