@cogitator-ai/cli 0.5.19 → 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.
Files changed (105) hide show
  1. package/README.md +105 -44
  2. package/dist/commands/add.d.ts +11 -0
  3. package/dist/commands/add.d.ts.map +1 -0
  4. package/dist/commands/add.js +79 -0
  5. package/dist/commands/add.js.map +1 -0
  6. package/dist/commands/assistant.d.ts.map +1 -1
  7. package/dist/commands/assistant.js +14 -12
  8. package/dist/commands/assistant.js.map +1 -1
  9. package/dist/commands/build.d.ts +16 -1
  10. package/dist/commands/build.d.ts.map +1 -1
  11. package/dist/commands/build.js +53 -48
  12. package/dist/commands/build.js.map +1 -1
  13. package/dist/commands/daemon.d.ts.map +1 -1
  14. package/dist/commands/daemon.js +17 -13
  15. package/dist/commands/daemon.js.map +1 -1
  16. package/dist/commands/deploy.d.ts +59 -0
  17. package/dist/commands/deploy.d.ts.map +1 -1
  18. package/dist/commands/deploy.js +181 -99
  19. package/dist/commands/deploy.js.map +1 -1
  20. package/dist/commands/dev.d.ts +14 -0
  21. package/dist/commands/dev.d.ts.map +1 -0
  22. package/dist/commands/dev.js +84 -0
  23. package/dist/commands/dev.js.map +1 -0
  24. package/dist/commands/doctor.d.ts +5 -0
  25. package/dist/commands/doctor.d.ts.map +1 -0
  26. package/dist/commands/doctor.js +52 -0
  27. package/dist/commands/doctor.js.map +1 -0
  28. package/dist/commands/eval.d.ts +12 -0
  29. package/dist/commands/eval.d.ts.map +1 -0
  30. package/dist/commands/eval.js +90 -0
  31. package/dist/commands/eval.js.map +1 -0
  32. package/dist/commands/init.d.ts +10 -33
  33. package/dist/commands/init.d.ts.map +1 -1
  34. package/dist/commands/init.js +89 -321
  35. package/dist/commands/init.js.map +1 -1
  36. package/dist/commands/logs.d.ts.map +1 -1
  37. package/dist/commands/logs.js +9 -6
  38. package/dist/commands/logs.js.map +1 -1
  39. package/dist/commands/mcp.d.ts +18 -0
  40. package/dist/commands/mcp.d.ts.map +1 -0
  41. package/dist/commands/mcp.js +155 -0
  42. package/dist/commands/mcp.js.map +1 -0
  43. package/dist/commands/models.d.ts.map +1 -1
  44. package/dist/commands/models.js +43 -15
  45. package/dist/commands/models.js.map +1 -1
  46. package/dist/commands/run.d.ts +17 -1
  47. package/dist/commands/run.d.ts.map +1 -1
  48. package/dist/commands/run.js +75 -28
  49. package/dist/commands/run.js.map +1 -1
  50. package/dist/commands/skill.d.ts.map +1 -1
  51. package/dist/commands/skill.js +23 -23
  52. package/dist/commands/skill.js.map +1 -1
  53. package/dist/commands/status.d.ts +21 -0
  54. package/dist/commands/status.d.ts.map +1 -1
  55. package/dist/commands/status.js +64 -39
  56. package/dist/commands/status.js.map +1 -1
  57. package/dist/commands/up.d.ts.map +1 -1
  58. package/dist/commands/up.js +26 -24
  59. package/dist/commands/up.js.map +1 -1
  60. package/dist/commands/wizard.d.ts.map +1 -1
  61. package/dist/commands/wizard.js +5 -0
  62. package/dist/commands/wizard.js.map +1 -1
  63. package/dist/index.js +9 -42
  64. package/dist/index.js.map +1 -1
  65. package/dist/program.d.ts +4 -0
  66. package/dist/program.d.ts.map +1 -0
  67. package/dist/program.js +61 -0
  68. package/dist/program.js.map +1 -0
  69. package/dist/utils/add.d.ts +81 -0
  70. package/dist/utils/add.d.ts.map +1 -0
  71. package/dist/utils/add.js +151 -0
  72. package/dist/utils/add.js.map +1 -0
  73. package/dist/utils/cli.d.ts +49 -0
  74. package/dist/utils/cli.d.ts.map +1 -0
  75. package/dist/utils/cli.js +106 -0
  76. package/dist/utils/cli.js.map +1 -0
  77. package/dist/utils/docs.d.ts +39 -0
  78. package/dist/utils/docs.d.ts.map +1 -0
  79. package/dist/utils/docs.js +198 -0
  80. package/dist/utils/docs.js.map +1 -0
  81. package/dist/utils/doctor.d.ts +41 -0
  82. package/dist/utils/doctor.d.ts.map +1 -0
  83. package/dist/utils/doctor.js +378 -0
  84. package/dist/utils/doctor.js.map +1 -0
  85. package/dist/utils/evals.d.ts +50 -0
  86. package/dist/utils/evals.d.ts.map +1 -0
  87. package/dist/utils/evals.js +78 -0
  88. package/dist/utils/evals.js.map +1 -0
  89. package/dist/utils/ollama.d.ts +5 -0
  90. package/dist/utils/ollama.d.ts.map +1 -1
  91. package/dist/utils/ollama.js +13 -5
  92. package/dist/utils/ollama.js.map +1 -1
  93. package/dist/utils/provider-models.d.ts +8 -2
  94. package/dist/utils/provider-models.d.ts.map +1 -1
  95. package/dist/utils/provider-models.js +32 -52
  96. package/dist/utils/provider-models.js.map +1 -1
  97. package/dist/utils/registry-worker.d.ts +2 -0
  98. package/dist/utils/registry-worker.d.ts.map +1 -0
  99. package/dist/utils/registry-worker.js +35 -0
  100. package/dist/utils/registry-worker.js.map +1 -0
  101. package/dist/utils/registry.d.ts +19 -0
  102. package/dist/utils/registry.d.ts.map +1 -0
  103. package/dist/utils/registry.js +58 -0
  104. package/dist/utils/registry.js.map +1 -0
  105. package/package.json +16 -10
@@ -0,0 +1,12 @@
1
+ import { Command } from 'commander';
2
+ interface EvalFlags {
3
+ json?: boolean;
4
+ report?: string;
5
+ maxCases?: string;
6
+ skipWithoutKey?: boolean;
7
+ }
8
+ /** Runs the eval suites and resolves with the exit code. */
9
+ export declare function runEvals(files: readonly string[], flags: EvalFlags): Promise<number>;
10
+ export declare const evalCommand: Command;
11
+ export {};
12
+ //# sourceMappingURL=eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../src/commands/eval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,UAAU,SAAS;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAUD,4DAA4D;AAC5D,wBAAsB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAwD1F;AAED,eAAO,MAAM,WAAW,SA4BpB,CAAC"}
@@ -0,0 +1,90 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { join, relative } from 'node:path';
4
+ import { loadConfig } from '@cogitator-ai/config';
5
+ import { CommandError, examplesHelp, reportFailure, UsageError } from '../utils/cli.js';
6
+ import { loadProjectEnv } from '../utils/doctor.js';
7
+ import { isEvalSuite, missingCredential, outcomeOf, resolveEvalFiles, } from '../utils/evals.js';
8
+ import { importUserModule } from '../utils/module-loader.js';
9
+ function positiveInteger(value) {
10
+ if (value === undefined)
11
+ return undefined;
12
+ const parsed = Number(value);
13
+ if (!Number.isInteger(parsed) || parsed < 1)
14
+ throw new UsageError('--max-cases takes a positive integer');
15
+ return parsed;
16
+ }
17
+ /** Runs the eval suites and resolves with the exit code. */
18
+ export async function runEvals(files, flags) {
19
+ const projectDir = process.cwd();
20
+ loadProjectEnv(projectDir);
21
+ const print = (line) => {
22
+ if (!flags.json)
23
+ console.log(line);
24
+ };
25
+ if (flags.skipWithoutKey) {
26
+ const missing = missingCredential(loadConfig());
27
+ if (missing) {
28
+ if (flags.json)
29
+ console.log(JSON.stringify({ ok: true, skipped: true, reason: `${missing} is not set` }));
30
+ else
31
+ print(chalk.yellow(`Skipping evals: ${missing} is not set`));
32
+ return 0;
33
+ }
34
+ }
35
+ const paths = resolveEvalFiles(projectDir, files);
36
+ if (paths.length === 0) {
37
+ throw new CommandError('No eval files found: add evals/<name>.eval.ts exporting an EvalSuite as default');
38
+ }
39
+ const outcomes = [];
40
+ for (const path of paths) {
41
+ const module = await importUserModule(path, projectDir);
42
+ const suite = module.default;
43
+ if (!isEvalSuite(suite)) {
44
+ throw new CommandError(`${path} must export an EvalSuite as its default export`);
45
+ }
46
+ print(chalk.bold(`\n${relative(projectDir, path)}`));
47
+ const result = await suite.run({ maxCases: positiveInteger(flags.maxCases) });
48
+ if (!flags.json)
49
+ result.report('console');
50
+ if (flags.report) {
51
+ const target = paths.length === 1 ? flags.report : join(flags.report, `${outcomes.length}.json`);
52
+ result.report('json', { path: target });
53
+ }
54
+ outcomes.push(outcomeOf(projectDir, path, result));
55
+ }
56
+ const ok = outcomes.every((outcome) => outcome.passed);
57
+ if (flags.json) {
58
+ console.log(JSON.stringify({ ok, skipped: false, suites: outcomes }, null, 2));
59
+ }
60
+ else {
61
+ const failed = outcomes.filter((outcome) => !outcome.passed);
62
+ print(failed.length === 0
63
+ ? chalk.green(`\n${outcomes.length} eval suite${outcomes.length === 1 ? '' : 's'} passed`)
64
+ : chalk.red(`\n${failed.length} of ${outcomes.length} eval suites failed: ${failed.map((f) => f.file).join(', ')}`));
65
+ }
66
+ return ok ? 0 : 1;
67
+ }
68
+ export const evalCommand = new Command('eval')
69
+ .description('Run the eval suites in evals/ (or the files given) and fail when an assertion fails')
70
+ .argument('[files...]', 'eval files or directories, default: every *.eval.ts under evals/')
71
+ .option('--json', 'print the results as JSON')
72
+ .option('--report <path>', 'also write a JSON report to this path')
73
+ .option('--max-cases <n>', 'run only the first n cases of each suite')
74
+ .option('--skip-without-key', 'exit 0 without running when the model has no API key, for CI on forks')
75
+ .addHelpText('after', examplesHelp([
76
+ ['cogitator eval', 'run every evals/*.eval.ts'],
77
+ ['cogitator eval evals/answers.eval.ts --max-cases 5', 'a quick subset'],
78
+ ['cogitator eval --json --report eval-report.json', 'results for CI'],
79
+ ]))
80
+ .action(async (files, flags) => {
81
+ let code;
82
+ try {
83
+ code = await runEvals(files, flags);
84
+ }
85
+ catch (error) {
86
+ code = reportFailure(error, { json: flags.json === true });
87
+ }
88
+ process.exit(code);
89
+ });
90
+ //# sourceMappingURL=eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.js","sourceRoot":"","sources":["../../src/commands/eval.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,13 @@
1
1
  import { Command } from 'commander';
2
+ import { validateProjectName, type ProjectSpecInput } from 'create-cogitator-app';
2
3
  import { type SetupProvider } from '../utils/provider-models.js';
3
4
  export type InitChannel = 'telegram' | 'discord' | 'slack' | 'webchat';
4
5
  export type InitMemory = 'memory' | 'sqlite' | 'postgres';
5
- export type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';
6
6
  export interface InitAnswers {
7
7
  projectName: string;
8
8
  provider: SetupProvider;
9
9
  apiKey: string;
10
+ /** `provider/model`, as the model prompt offers it. */
10
11
  model: string;
11
12
  channels: InitChannel[];
12
13
  telegramToken?: string;
@@ -17,39 +18,15 @@ export interface InitAnswers {
17
18
  memory: InitMemory;
18
19
  databaseUrl?: string;
19
20
  }
20
- export interface ScaffoldOptions {
21
- dependencyVersions: Record<string, string>;
22
- /** When `pnpm`, a pnpm-workspace.yaml allowing the native dependency builds is generated */
23
- packageManager?: PackageManager;
24
- }
21
+ export declare const DEFAULT_POSTGRES_URL = "postgresql://cogitator:cogitator@localhost:5432/cogitator";
22
+ export { validateProjectName };
25
23
  /**
26
- * pnpm 10.26+ skips dependency build scripts unless they are allowed, and pnpm 11 fails the
27
- * install instead. These are the native/binary packages a Cogitator project pulls in.
24
+ * The project `cogitator init` creates: the `channels` preset of
25
+ * create-cogitator-app with the answers, so both commands generate the same
26
+ * code from the same engine.
28
27
  */
29
- export declare const PNPM_ALLOWED_BUILDS: readonly ["better-sqlite3", "esbuild", "sharp"];
30
- export declare const DEFAULT_POSTGRES_URL = "postgresql://cogitator:cogitator@localhost:5432/cogitator";
31
- export declare function validateProjectName(name: string): string | undefined;
32
- export declare function resolveDependencyVersions(cliPackageJson?: string): Record<string, string>;
33
- export declare function detectPackageManager(userAgent?: string | undefined): PackageManager;
34
- export declare function buildPackageJson(answers: InitAnswers, options: ScaffoldOptions): string;
35
- export declare function buildEnvFile(answers: InitAnswers): string | null;
36
- export declare function buildGatewayFile(answers: InitAnswers): string;
37
- export declare function buildAgentFile(answers: InitAnswers): string;
38
- export declare function buildGitignore(answers: InitAnswers): string;
39
- export declare const TSCONFIG: {
40
- compilerOptions: {
41
- target: string;
42
- module: string;
43
- moduleResolution: string;
44
- strict: boolean;
45
- esModuleInterop: boolean;
46
- skipLibCheck: boolean;
47
- outDir: string;
48
- rootDir: string;
49
- };
50
- include: string[];
51
- };
52
- export declare function buildProjectFiles(answers: InitAnswers, options: ScaffoldOptions): Record<string, string>;
53
- export declare function writeProjectFiles(projectPath: string, files: Record<string, string>): void;
28
+ export declare function initSpec(answers: InitAnswers, packageManager?: "pnpm" | "npm" | "yarn" | "bun"): ProjectSpecInput;
29
+ /** What `cogitator init` writes to `.env`: the provider key, the channel tokens and a custom database URL. */
30
+ export declare function initSecrets(answers: InitAnswers): Record<string, string>;
54
31
  export declare const initCommand: Command;
55
32
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,6BAA6B,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AACvE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAC1D,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,4FAA4F;IAC5F,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,iDAAkD,CAAC;AAEnF,eAAO,MAAM,oBAAoB,8DAA8D,CAAC;AAIhG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQpE;AAED,wBAAgB,yBAAyB,CACvC,cAAc,GAAE,MAA4E,GAC3F,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAsBxB;AAED,wBAAgB,oBAAoB,CAClC,SAAS,qBAAoC,GAC5C,cAAc,CAIhB;AAMD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CAyCvF;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAkBhE;AAyBD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CA0F7D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAyB3D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAI3D;AAED,eAAO,MAAM,QAAQ;;;;;;;;;;;;CAYpB,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBxB;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAM1F;AAuID,eAAO,MAAM,WAAW,SAsEpB,CAAC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EASL,mBAAmB,EACnB,KAAK,gBAAgB,EAEtB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,6BAA6B,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AACvE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,8DAA8D,CAAC;AAEhG,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAE/B;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,WAAW,EACpB,cAAc,kCAAyB,GACtC,gBAAgB,CAalB;AAED,8GAA8G;AAC9G,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBxE;AAiJD,eAAO,MAAM,WAAW,SA6ErB,CAAC"}
@@ -1,297 +1,55 @@
1
1
  import { Command } from 'commander';
2
- import { writeFileSync, mkdirSync, existsSync, readFileSync } from 'node:fs';
3
- import { dirname, join, resolve } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { execFileSync } from 'node:child_process';
2
+ import { resolve } from 'node:path';
6
3
  import * as p from '@clack/prompts';
7
4
  import chalk from 'chalk';
5
+ import { detectPackageManager, detectPackageManagerSpec, firstRunNotice, parseSpec, payloadFor, scaffold, sendTelemetry, telemetryDisabledReason, validateProjectName, } from 'create-cogitator-app';
8
6
  import { printBanner } from '../utils/logger.js';
9
- import { formatEnvLine } from '../utils/env.js';
10
- import { DEFAULT_OLLAMA_URL, resolveOllamaUrl } from '../utils/ollama.js';
7
+ import { errorMessage, EXIT, examplesHelp } from '../utils/cli.js';
8
+ import { resolveOllamaUrl } from '../utils/ollama.js';
11
9
  import { API_KEY_ENV, fetchOllamaModelOptions, fetchProviderModels, isSetupProvider, } from '../utils/provider-models.js';
10
+ export const DEFAULT_POSTGRES_URL = 'postgresql://cogitator:cogitator@localhost:5432/cogitator';
11
+ export { validateProjectName };
12
12
  /**
13
- * pnpm 10.26+ skips dependency build scripts unless they are allowed, and pnpm 11 fails the
14
- * install instead. These are the native/binary packages a Cogitator project pulls in.
13
+ * The project `cogitator init` creates: the `channels` preset of
14
+ * create-cogitator-app with the answers, so both commands generate the same
15
+ * code from the same engine.
15
16
  */
16
- export const PNPM_ALLOWED_BUILDS = ['better-sqlite3', 'esbuild', 'sharp'];
17
- export const DEFAULT_POSTGRES_URL = 'postgresql://cogitator:cogitator@localhost:5432/cogitator';
18
- const PROJECT_NAME = /^[a-z0-9][a-z0-9._-]*$/;
19
- const COGITATOR_PACKAGES = ['@cogitator-ai/core', '@cogitator-ai/channels', '@cogitator-ai/memory'];
20
- export function validateProjectName(name) {
21
- const trimmed = name.trim();
22
- if (!trimmed)
23
- return 'Name is required';
24
- if (trimmed.length > 214)
25
- return 'Name must be 214 characters or fewer';
26
- if (!PROJECT_NAME.test(trimmed)) {
27
- return 'Use lowercase letters, digits, ".", "_" or "-" (must start with a letter or digit)';
28
- }
29
- return undefined;
30
- }
31
- export function resolveDependencyVersions(cliPackageJson = join(dirname(fileURLToPath(import.meta.url)), '../../package.json')) {
32
- const versions = {};
33
- let deps = {};
34
- try {
35
- const parsed = JSON.parse(readFileSync(cliPackageJson, 'utf-8'));
36
- if (typeof parsed === 'object' && parsed !== null && 'dependencies' in parsed) {
37
- const value = parsed.dependencies;
38
- if (typeof value === 'object' && value !== null)
39
- deps = Object.fromEntries(Object.entries(value));
40
- }
41
- }
42
- catch {
43
- deps = {};
44
- }
45
- for (const name of COGITATOR_PACKAGES) {
46
- const range = deps[name];
47
- versions[name] =
48
- typeof range === 'string' && /^\^?~?\d/.test(range)
49
- ? `^${range.replace(/^[\^~]/, '')}`
50
- : 'latest';
51
- }
52
- return versions;
53
- }
54
- export function detectPackageManager(userAgent = process.env.npm_config_user_agent) {
55
- const name = userAgent?.split('/')[0];
56
- if (name === 'npm' || name === 'yarn' || name === 'bun' || name === 'pnpm')
57
- return name;
58
- return 'pnpm';
59
- }
60
- function runScript(pm, script) {
61
- return pm === 'npm' ? `npm run ${script}` : `${pm} ${script}`;
62
- }
63
- export function buildPackageJson(answers, options) {
64
- const deps = {
65
- ...options.dependencyVersions,
66
- zod: '^4.0.0',
67
- };
68
- if (answers.channels.includes('telegram'))
69
- deps.grammy = '^1.20.0';
70
- if (answers.channels.includes('discord'))
71
- deps['discord.js'] = '^14.0.0';
72
- if (answers.channels.includes('slack'))
73
- deps['@slack/bolt'] = '^4.0.0';
74
- if (answers.channels.includes('webchat'))
75
- deps.ws = '^8.18.0';
76
- if (answers.memory === 'sqlite')
77
- deps['better-sqlite3'] = '^11.6.0';
78
- if (answers.memory === 'postgres')
79
- deps.pg = '^8.18.0';
80
- const sortedDeps = Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));
81
- return (JSON.stringify({
17
+ export function initSpec(answers, packageManager = detectPackageManager()) {
18
+ const prefix = `${answers.provider}/`;
19
+ return {
82
20
  name: answers.projectName,
83
- version: '0.1.0',
84
- private: true,
85
- type: 'module',
86
- engines: { node: '>=22.12.0' },
87
- scripts: {
88
- dev: 'tsx watch src/agent.ts',
89
- start: 'tsx src/agent.ts',
90
- build: 'tsc',
91
- },
92
- dependencies: sortedDeps,
93
- devDependencies: {
94
- '@types/node': '^22.0.0',
95
- tsx: '^4.21.0',
96
- typescript: '^5.3.0',
97
- },
98
- }, null, 2) + '\n');
21
+ preset: 'channels',
22
+ app: 'channels',
23
+ channels: answers.channels,
24
+ memory: answers.memory,
25
+ features: [],
26
+ provider: answers.provider,
27
+ model: answers.model.startsWith(prefix) ? answers.model.slice(prefix.length) : answers.model,
28
+ packageManager,
29
+ };
99
30
  }
100
- export function buildEnvFile(answers) {
101
- const lines = [];
31
+ /** What `cogitator init` writes to `.env`: the provider key, the channel tokens and a custom database URL. */
32
+ export function initSecrets(answers) {
33
+ const secrets = {};
102
34
  if (answers.provider !== 'ollama' && answers.apiKey) {
103
- lines.push(formatEnvLine(API_KEY_ENV[answers.provider], answers.apiKey));
35
+ secrets[API_KEY_ENV[answers.provider]] = answers.apiKey;
104
36
  }
105
37
  if (answers.telegramToken)
106
- lines.push(formatEnvLine('TELEGRAM_BOT_TOKEN', answers.telegramToken));
38
+ secrets.TELEGRAM_BOT_TOKEN = answers.telegramToken;
107
39
  if (answers.discordToken)
108
- lines.push(formatEnvLine('DISCORD_BOT_TOKEN', answers.discordToken));
40
+ secrets.DISCORD_BOT_TOKEN = answers.discordToken;
109
41
  if (answers.slackToken)
110
- lines.push(formatEnvLine('SLACK_BOT_TOKEN', answers.slackToken));
111
- if (answers.slackSigningSecret) {
112
- lines.push(formatEnvLine('SLACK_SIGNING_SECRET', answers.slackSigningSecret));
113
- }
42
+ secrets.SLACK_BOT_TOKEN = answers.slackToken;
43
+ if (answers.slackSigningSecret)
44
+ secrets.SLACK_SIGNING_SECRET = answers.slackSigningSecret;
114
45
  if (answers.slackAppToken)
115
- lines.push(formatEnvLine('SLACK_APP_TOKEN', answers.slackAppToken));
116
- if (answers.memory === 'postgres') {
117
- lines.push(formatEnvLine('DATABASE_URL', answers.databaseUrl ?? DEFAULT_POSTGRES_URL));
118
- }
119
- return lines.length > 0 ? lines.join('\n') + '\n' : null;
120
- }
121
- function memorySetup(memory) {
122
- switch (memory) {
123
- case 'sqlite':
124
- return {
125
- importName: 'SQLiteAdapter',
126
- code: `const memory = new SQLiteAdapter({ provider: 'sqlite', path: './data/memory.db' });`,
127
- };
128
- case 'postgres':
129
- return {
130
- importName: 'PostgresAdapter',
131
- code: `const memory = new PostgresAdapter({
132
- provider: 'postgres',
133
- connectionString: requireEnv('DATABASE_URL'),
134
- });`,
135
- };
136
- case 'memory':
137
- return {
138
- importName: 'InMemoryAdapter',
139
- code: `const memory = new InMemoryAdapter({ provider: 'memory' });`,
140
- };
141
- }
142
- }
143
- export function buildGatewayFile(answers) {
144
- const channelImports = [];
145
- const channelSetup = [];
146
- for (const ch of answers.channels) {
147
- switch (ch) {
148
- case 'telegram':
149
- channelImports.push('telegramChannel');
150
- channelSetup.push(` telegramChannel({ token: requireEnv('TELEGRAM_BOT_TOKEN') }),`);
151
- break;
152
- case 'discord':
153
- channelImports.push('discordChannel');
154
- channelSetup.push(` discordChannel({ token: requireEnv('DISCORD_BOT_TOKEN'), mentionOnly: true }),`);
155
- break;
156
- case 'slack':
157
- channelImports.push('slackChannel');
158
- channelSetup.push(` slackChannel({\n token: requireEnv('SLACK_BOT_TOKEN'),\n signingSecret: requireEnv('SLACK_SIGNING_SECRET'),\n appToken: process.env.SLACK_APP_TOKEN,\n }),`);
159
- break;
160
- case 'webchat':
161
- channelImports.push('webchatChannel');
162
- channelSetup.push(` webchatChannel({ port: 18789 }),`);
163
- break;
164
- }
165
- }
166
- const providerConfig = answers.provider === 'ollama'
167
- ? ` ollama: { baseUrl: process.env.OLLAMA_URL ?? '${DEFAULT_OLLAMA_URL}' },`
168
- : ` ${answers.provider}: { apiKey: requireEnv('${API_KEY_ENV[answers.provider]}') },`;
169
- const memory = memorySetup(answers.memory);
170
- return `import { existsSync } from 'node:fs';
171
- import { fileURLToPath } from 'node:url';
172
- import { Cogitator, Agent } from '@cogitator-ai/core';
173
- import { Gateway, ${channelImports.join(', ')} } from '@cogitator-ai/channels';
174
- import { ${memory.importName} } from '@cogitator-ai/memory';
175
-
176
- const envFile = fileURLToPath(new URL('../.env', import.meta.url));
177
- if (existsSync(envFile)) process.loadEnvFile(envFile);
178
-
179
- function requireEnv(name: string): string {
180
- const value = process.env[name];
181
- if (!value) throw new Error(\`Missing environment variable \${name} (see .env)\`);
182
- return value;
183
- }
184
-
185
- const agent = new Agent({
186
- name: 'assistant',
187
- model: '${answers.model}',
188
- instructions: \`You are a helpful personal AI assistant.
189
- Be concise and friendly. Use tools when available.\`,
190
- });
191
-
192
- const cogitator = new Cogitator({
193
- llm: {
194
- defaultProvider: '${answers.provider}',
195
- providers: {
196
- ${providerConfig}
197
- },
198
- },
199
- });
200
-
201
- ${memory.code}
202
-
203
- const connected = await memory.connect();
204
- if (!connected.success) {
205
- throw new Error(\`Failed to connect memory: \${connected.error}\`);
206
- }
207
-
208
- export const gateway = new Gateway({
209
- agent,
210
- cogitator,
211
- channels: [
212
- ${channelSetup.join('\n')}
213
- ],
214
- memory,
215
- session: {
216
- compaction: { strategy: 'hybrid', threshold: 50, keepRecent: 10 },
217
- },
218
- stream: { flushInterval: 500, minChunkSize: 20 },
219
- onError: (err, msg) => {
220
- console.error(\`[error] \${msg.channelType}:\${msg.userId} — \${err.message}\`);
221
- },
222
- });
223
- `;
224
- }
225
- export function buildAgentFile(answers) {
226
- const webchatLine = answers.channels.includes('webchat')
227
- ? ` console.log('WebChat: ws://localhost:18789/ws');\n`
228
- : '';
229
- return `import { gateway } from './gateway.js';
230
-
231
- let stopping = false;
232
-
233
- async function shutdown(signal: string) {
234
- if (stopping) return;
235
- stopping = true;
236
- console.log(\`\\nReceived \${signal}, shutting down...\`);
237
- await gateway.stop();
238
- process.exit(0);
239
- }
240
-
241
- process.once('SIGINT', () => void shutdown('SIGINT'));
242
- process.once('SIGTERM', () => void shutdown('SIGTERM'));
243
-
244
- await gateway.start();
245
-
246
- console.log('Assistant is running!');
247
- console.log('Connected channels:', gateway.stats.connectedChannels.join(', '));
248
- ${webchatLine}`;
249
- }
250
- export function buildGitignore(answers) {
251
- const lines = ['node_modules/', 'dist/', '.env', '*.log', '.cogitator/'];
252
- if (answers.memory === 'sqlite')
253
- lines.push('data/');
254
- return lines.join('\n') + '\n';
255
- }
256
- export const TSCONFIG = {
257
- compilerOptions: {
258
- target: 'ES2022',
259
- module: 'NodeNext',
260
- moduleResolution: 'NodeNext',
261
- strict: true,
262
- esModuleInterop: true,
263
- skipLibCheck: true,
264
- outDir: './dist',
265
- rootDir: './src',
266
- },
267
- include: ['src/**/*'],
268
- };
269
- export function buildProjectFiles(answers, options) {
270
- const files = {
271
- 'package.json': buildPackageJson(answers, options),
272
- 'tsconfig.json': JSON.stringify(TSCONFIG, null, 2) + '\n',
273
- 'src/gateway.ts': buildGatewayFile(answers),
274
- 'src/agent.ts': buildAgentFile(answers),
275
- '.gitignore': buildGitignore(answers),
276
- };
277
- const env = buildEnvFile(answers);
278
- if (env)
279
- files['.env'] = env;
280
- if (options.packageManager === 'pnpm') {
281
- files['pnpm-workspace.yaml'] = [
282
- 'allowBuilds:',
283
- ...PNPM_ALLOWED_BUILDS.map((name) => ` ${name}: true`),
284
- '',
285
- ].join('\n');
286
- }
287
- return files;
288
- }
289
- export function writeProjectFiles(projectPath, files) {
290
- for (const [relativePath, content] of Object.entries(files)) {
291
- const fullPath = join(projectPath, relativePath);
292
- mkdirSync(dirname(fullPath), { recursive: true });
293
- writeFileSync(fullPath, content, relativePath === '.env' ? { mode: 0o600 } : undefined);
46
+ secrets.SLACK_APP_TOKEN = answers.slackAppToken;
47
+ if (answers.memory === 'postgres' &&
48
+ answers.databaseUrl &&
49
+ answers.databaseUrl !== DEFAULT_POSTGRES_URL) {
50
+ secrets.DATABASE_URL = answers.databaseUrl;
294
51
  }
52
+ return secrets;
295
53
  }
296
54
  function cancelled() {
297
55
  p.cancel('Setup cancelled');
@@ -367,7 +125,7 @@ async function collectAnswers(nameArg) {
367
125
  options: [
368
126
  { value: 'sqlite', label: 'SQLite (recommended)', hint: 'zero config, file-based' },
369
127
  { value: 'memory', label: 'In-memory', hint: 'no persistence, for testing' },
370
- { value: 'postgres', label: 'PostgreSQL', hint: 'production-grade' },
128
+ { value: 'postgres', label: 'PostgreSQL', hint: 'production-grade, runs in Docker' },
371
129
  ],
372
130
  }));
373
131
  const memory = memoryChoice === 'memory' || memoryChoice === 'postgres' ? memoryChoice : 'sqlite';
@@ -393,63 +151,73 @@ async function collectAnswers(nameArg) {
393
151
  databaseUrl,
394
152
  };
395
153
  }
154
+ function clackLogger() {
155
+ const spinner = p.spinner();
156
+ return {
157
+ start: (message) => spinner.start(message),
158
+ done: (message) => spinner.stop(message),
159
+ fail: (message) => spinner.error(message),
160
+ warn: (message) => p.log.warn(message),
161
+ };
162
+ }
396
163
  export const initCommand = new Command('init')
397
- .description('Create a new Cogitator AI assistant project')
164
+ .description('Create a messaging assistant project (Telegram, Discord, Slack, WebChat)')
398
165
  .argument('[name]', 'Project name')
399
166
  .option('--no-install', 'Skip dependency installation')
167
+ .option('--no-git', 'Skip creating a git repository')
168
+ .option('--no-telemetry', 'Send no anonymous usage event')
169
+ .addHelpText('after', examplesHelp([
170
+ ['cogitator init my-bot', 'a messaging assistant, asked step by step'],
171
+ ['cogitator init my-bot --no-install', 'write the files, install later'],
172
+ ]))
400
173
  .action(async (nameArg, options) => {
401
174
  printBanner();
402
175
  p.intro(chalk.bgCyan(chalk.black(' cogitator init ')));
176
+ const telemetry = telemetryDisabledReason({ flag: options.telemetry }) === undefined;
177
+ if (telemetry) {
178
+ const notice = firstRunNotice();
179
+ if (notice)
180
+ p.log.info(chalk.dim(notice));
181
+ }
403
182
  if (nameArg !== undefined) {
404
183
  const error = validateProjectName(nameArg);
405
184
  if (error) {
406
185
  p.cancel(`Invalid project name "${nameArg}": ${error}`);
407
- process.exit(1);
186
+ process.exitCode = EXIT.usage;
187
+ return;
408
188
  }
409
189
  }
410
190
  const answers = await collectAnswers(nameArg?.trim());
411
- const projectPath = resolve(process.cwd(), answers.projectName);
412
- if (existsSync(projectPath)) {
413
- p.cancel(`Directory "${answers.projectName}" already exists`);
414
- process.exit(1);
191
+ const directory = resolve(process.cwd(), answers.projectName);
192
+ const spec = initSpec(answers);
193
+ let result;
194
+ try {
195
+ result = await scaffold(spec, {
196
+ directory,
197
+ secrets: initSecrets(answers),
198
+ packageManagerSpec: detectPackageManagerSpec(detectPackageManager()),
199
+ install: options.install,
200
+ git: options.git,
201
+ log: clackLogger(),
202
+ });
203
+ }
204
+ catch (error) {
205
+ if (telemetry)
206
+ await sendTelemetry(payloadFor(parseSpec(spec), 'failure'));
207
+ p.cancel(errorMessage(error));
208
+ process.exitCode = EXIT.failed;
209
+ return;
210
+ }
211
+ if (telemetry) {
212
+ await sendTelemetry(payloadFor(result.plan.spec, result.install.status === 'failed' ? 'failure' : 'success'));
415
213
  }
416
- const pm = detectPackageManager();
417
- const files = buildProjectFiles(answers, {
418
- dependencyVersions: resolveDependencyVersions(),
419
- packageManager: pm,
214
+ const steps = result.plan.nextSteps({
215
+ directory: answers.projectName,
216
+ installed: result.install.status === 'done',
217
+ keyWritten: true,
218
+ modelReady: answers.provider !== 'ollama',
420
219
  });
421
- let installed = false;
422
- await p.tasks([
423
- {
424
- title: 'Creating project structure',
425
- task: () => {
426
- writeProjectFiles(projectPath, files);
427
- return 'Project files created';
428
- },
429
- },
430
- {
431
- title: `Installing dependencies with ${pm}`,
432
- enabled: options.install,
433
- task: () => {
434
- try {
435
- execFileSync(pm, ['install'], { cwd: projectPath, stdio: 'pipe' });
436
- installed = true;
437
- return 'Dependencies installed';
438
- }
439
- catch {
440
- return `Install failed — run "${pm} install" manually`;
441
- }
442
- },
443
- },
444
- ]);
445
- p.note([
446
- `cd ${answers.projectName}`,
447
- installed ? '' : `${pm} install`,
448
- `${runScript(pm, 'dev')} # start with hot reload`,
449
- `cogitator assistant # or run with the live dashboard`,
450
- ]
451
- .filter(Boolean)
452
- .join('\n'), 'Next steps', { format: (line) => chalk.dim(line) });
220
+ p.note(steps.map((step) => `${step.command}${step.note ? ` # ${step.note}` : ''}`).join('\n'), 'Next steps', { format: (line) => chalk.dim(line) });
453
221
  p.outro(`${chalk.green('Your assistant is ready!')} Channels: ${chalk.cyan(answers.channels.join(', '))}`);
454
222
  });
455
223
  //# sourceMappingURL=init.js.map