kaven-cli 0.4.0 → 0.4.1-alpha.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.
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.runEnvironmentBootstrap = runEnvironmentBootstrap;
40
+ const node_child_process_1 = require("node:child_process");
41
+ const fs = __importStar(require("node:fs"));
42
+ const path = __importStar(require("node:path"));
43
+ const ora_1 = __importDefault(require("ora"));
44
+ const chalk_1 = __importDefault(require("chalk"));
45
+ /**
46
+ * Runs the AIOX environment bootstrap process.
47
+ * This identifies the project stack and generates .aiox/ runtime configs.
48
+ */
49
+ async function runEnvironmentBootstrap(projectDir, options = {}) {
50
+ if (options.skipAiox)
51
+ return;
52
+ // Check if AIOX Core is installed
53
+ const aioxCorePath = path.join(projectDir, ".aiox-core");
54
+ if (!fs.existsSync(aioxCorePath)) {
55
+ // If not found in .aiox-core, check if it's a symlink (Dev environment)
56
+ const isDevLink = fs.existsSync(path.join(projectDir, ".aiox"));
57
+ if (!isDevLink) {
58
+ return; // Silent skip if AIOX is not present
59
+ }
60
+ }
61
+ const spinner = (0, ora_1.default)("Bootstrapping AIOX environment...").start();
62
+ try {
63
+ // The AIOX Core exposes a CLI at bin/aiox.js
64
+ // We call: node .aiox-core/bin/aiox.js devops environment-bootstrap --quiet
65
+ // Determine the bin path
66
+ const binPath = fs.existsSync(path.join(projectDir, ".aiox-core/bin/aiox.js"))
67
+ ? ".aiox-core/bin/aiox.js"
68
+ : ".aiox/bin/aiox.js"; // Fallback for dev symlink
69
+ (0, node_child_process_1.execSync)(`node ${binPath} devops environment-bootstrap --quiet`, {
70
+ cwd: projectDir,
71
+ stdio: "pipe",
72
+ timeout: 60000, // 1 minute timeout
73
+ });
74
+ spinner.succeed("AIOX environment bootstrapped");
75
+ }
76
+ catch (error) {
77
+ spinner.warn("AIOX environment bootstrap failed");
78
+ console.log(chalk_1.default.yellow(" ⚠ Run manually inside the project: kaven aiox bootstrap"));
79
+ if (process.env.KAVEN_DEBUG) {
80
+ console.error(chalk_1.default.gray(` Error: ${error.message}`));
81
+ }
82
+ }
83
+ }
@@ -10,6 +10,7 @@ const path_1 = __importDefault(require("path"));
10
10
  const fs_extra_1 = __importDefault(require("fs-extra"));
11
11
  const ProjectInitializer_1 = require("../../core/ProjectInitializer");
12
12
  const ConfigManager_1 = require("../../core/ConfigManager");
13
+ const aiox_bootstrap_1 = require("./aiox-bootstrap");
13
14
  async function promptAnswers(projectName) {
14
15
  // Dynamic import to keep startup fast and avoid issues if not installed
15
16
  const { input, select } = await import("@inquirer/prompts");
@@ -143,6 +144,16 @@ async function initProject(projectName, options) {
143
144
  const squadResult = await initializer.installSquad(targetDir);
144
145
  if (squadResult.installed) {
145
146
  squadSpinner.succeed("kaven-squad installed in squads/kaven-squad/");
147
+ // Install AIOX Core runtime (non-fatal)
148
+ const aioxSpinner = (0, ora_1.default)("Activating AIOX Core...").start();
149
+ const aioxResult = await initializer.installAIOXCore(targetDir);
150
+ if (aioxResult.installed) {
151
+ aioxSpinner.succeed("AIOX Core activated — agents online");
152
+ }
153
+ else {
154
+ aioxSpinner.warn(`AIOX Core not activated automatically (${aioxResult.reason})`);
155
+ console.log(chalk_1.default.yellow(` Run inside the project: npx aiox-core install`));
156
+ }
146
157
  }
147
158
  else if (squadResult.reason === "already-exists") {
148
159
  squadSpinner.info("kaven-squad already installed — skipping");
@@ -154,6 +165,8 @@ async function initProject(projectName, options) {
154
165
  }
155
166
  // Health check
156
167
  const healthCheckSpinner = (0, ora_1.default)("Running health check...").start();
168
+ // AIOX Environment Bootstrap
169
+ await (0, aiox_bootstrap_1.runEnvironmentBootstrap)(targetDir, { skipAiox: options.skipAiox });
157
170
  const health = await initializer.healthCheck(targetDir);
158
171
  if (health.healthy) {
159
172
  healthCheckSpinner.succeed("Health check passed");
@@ -177,9 +190,9 @@ async function initProject(projectName, options) {
177
190
  console.log(chalk_1.default.gray("For more help, visit: https://docs.kaven.site/getting-started"));
178
191
  if (options.withSquad) {
179
192
  console.log();
180
- console.log(chalk_1.default.bold("AIOX Squad next step:"));
181
- console.log(chalk_1.default.cyan(" node /path/to/aiox-core/bin/aiox.js install --quiet --merge"));
182
- console.log(chalk_1.default.gray(" (replace /path/to/aiox-core with your AIOX installation path)"));
193
+ console.log(chalk_1.default.bold("AIOX Agents:"));
194
+ console.log(chalk_1.default.cyan(` cd ${name}`));
195
+ console.log(chalk_1.default.cyan(" # Type @dev in Claude Code to start with AI agents"));
183
196
  }
184
197
  // Save project defaults to config for future use
185
198
  await ConfigManager_1.configManager.initialize();
@@ -9,6 +9,7 @@ exports.moduleListActivation = moduleListActivation;
9
9
  const chalk_1 = __importDefault(require("chalk"));
10
10
  const ora_1 = __importDefault(require("ora"));
11
11
  const node_path_1 = __importDefault(require("node:path"));
12
+ const prompts_1 = require("@inquirer/prompts");
12
13
  const SchemaActivator_1 = require("../../core/SchemaActivator");
13
14
  const TelemetryBuffer_1 = require("../../infrastructure/TelemetryBuffer");
14
15
  // ============================================================
@@ -20,36 +21,36 @@ function findModuleDef(moduleId) {
20
21
  function assertSchemaExists(exists, root) {
21
22
  if (!exists) {
22
23
  const fullPath = node_path_1.default.join(root, "packages", "database", "prisma", "schema.extended.prisma");
23
- console.error(chalk_1.default.red(`\nErro: Schema não encontrado em: ${fullPath}`));
24
- console.error(chalk_1.default.gray("Certifique-se de que o caminho fornecido é a raiz de um projeto Kaven válido."));
24
+ console.error(chalk_1.default.red(`\nError: Schema not found at: ${fullPath}`));
25
+ console.error(chalk_1.default.gray("Make sure you are in the root of a valid Kaven project."));
25
26
  process.exit(1);
26
27
  }
27
28
  }
28
29
  // ============================================================
29
30
  // kaven module activate <name>
30
31
  // ============================================================
31
- async function moduleActivate(moduleName, projectRoot) {
32
+ async function moduleActivate(moduleName, projectRoot, options = {}) {
32
33
  const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
33
34
  const startTime = Date.now();
34
35
  telemetry.capture("cli.module.activate.start", { moduleName });
35
36
  const root = projectRoot ?? process.cwd();
36
37
  const activator = new SchemaActivator_1.SchemaActivator(root);
37
- const spinner = (0, ora_1.default)(`Ativando módulo ${moduleName}...`).start();
38
+ const spinner = (0, ora_1.default)(`Activating module ${moduleName}...`).start();
38
39
  try {
39
- // 1. Validar que o schema existe
40
+ // 1. Validate schema exists
40
41
  const exists = await activator.exists();
41
42
  spinner.stop();
42
43
  assertSchemaExists(exists, root);
43
- // 2. Validar que o módulo é conhecido
44
+ // 2. Validate module is known
44
45
  const def = findModuleDef(moduleName);
45
46
  if (!def) {
46
- console.error(chalk_1.default.red(`\nMódulo desconhecido: "${moduleName}".`));
47
- console.error(chalk_1.default.gray(`Módulos disponíveis: ${SchemaActivator_1.KAVEN_MODULES.map((m) => m.id).join(", ")}`));
47
+ console.error(chalk_1.default.red(`\nUnknown module: "${moduleName}".`));
48
+ console.error(chalk_1.default.gray(`Available modules: ${SchemaActivator_1.KAVEN_MODULES.map((m) => m.id).join(", ")}`));
48
49
  process.exit(1);
49
50
  }
50
- // 3. Verificar dependências
51
+ // 3. Check dependencies
51
52
  if (def.dependsOn.length > 0) {
52
- spinner.start("Verificando dependências...");
53
+ spinner.start("Checking dependencies...");
53
54
  const depStatuses = [];
54
55
  for (const depId of def.dependsOn) {
55
56
  const depDef = findModuleDef(depId);
@@ -61,28 +62,59 @@ async function moduleActivate(moduleName, projectRoot) {
61
62
  const missing = depStatuses.filter((s) => !s.active);
62
63
  if (missing.length > 0) {
63
64
  spinner.stop();
64
- console.error(chalk_1.default.red(`\nDependências inativas para "${moduleName}": ${missing.map((m) => m.id).join(", ")}`));
65
- console.error(chalk_1.default.gray(`Ative as dependências primeiro:\n${missing.map((m) => ` kaven module activate ${m.id}`).join("\n")}`));
66
- process.exit(1);
65
+ // Auto-activate deps if --with-deps
66
+ if (options.withDeps) {
67
+ for (const dep of missing) {
68
+ await moduleActivate(dep.id, projectRoot, { ...options, withDeps: true });
69
+ }
70
+ }
71
+ else {
72
+ console.error(chalk_1.default.red(`\nInactive dependencies for "${moduleName}": ${missing.map((m) => m.id).join(", ")}`));
73
+ console.error(chalk_1.default.gray(`Activate them first:\n${missing.map((m) => ` kaven module activate ${m.id}`).join("\n")}`));
74
+ console.log(chalk_1.default.gray("\nOr use --with-deps to activate them automatically."));
75
+ process.exit(1);
76
+ }
67
77
  }
68
78
  spinner.stop();
69
79
  }
70
- // 4. Verificar se está ativo
80
+ // 4. Check if already active
71
81
  const current = await activator.getModuleStatus(def);
72
82
  if (current.active) {
73
- console.log(chalk_1.default.yellow(`\nMódulo "${def.label}" está ativo.`));
83
+ console.log(chalk_1.default.yellow(`\nModule "${def.label}" is already active.`));
74
84
  return;
75
85
  }
76
- // 5. Ativar
77
- spinner.start(`Descomentando modelos de ${def.label} no schema...`);
86
+ // 5. Confirm if not --yes
87
+ if (!options.yes) {
88
+ const ok = await (0, prompts_1.confirm)({
89
+ message: `Activate module "${def.label}"? This will uncomment ${def.models.length} model(s) in the schema.`,
90
+ default: true,
91
+ });
92
+ if (!ok) {
93
+ console.log(chalk_1.default.gray("\nActivation aborted."));
94
+ return;
95
+ }
96
+ }
97
+ // 6. Dry run
98
+ if (options.dryRun) {
99
+ console.log(chalk_1.default.bold(`\n--- DRY RUN: Activating ${def.label} ---`));
100
+ console.log(`Models to uncomment: ${def.models.join(", ")}`);
101
+ if (def.enums.length > 0) {
102
+ console.log(`Enums to uncomment: ${def.enums.join(", ")}`);
103
+ }
104
+ return;
105
+ }
106
+ // 7. Activate
107
+ spinner.start(`Uncommenting ${def.label} models in schema...`);
78
108
  await activator.activateModule(def);
79
- spinner.succeed(chalk_1.default.green(`\nMódulo ${def.label} ativado. ${def.models.length} models adicionados: ${def.models.join(", ")}`));
80
- console.log(chalk_1.default.cyan("\nSugestão: Execute `pnpm db:generate && pnpm db:migrate` para aplicar as mudanças."));
109
+ spinner.succeed(chalk_1.default.green(`\nModule ${def.label} activated. ${def.models.length} models added: ${def.models.join(", ")}`));
110
+ if (!options.skipMigrate) {
111
+ console.log(chalk_1.default.cyan("\nNext step: Run `pnpm db:generate && pnpm db:migrate` to apply changes."));
112
+ }
81
113
  telemetry.capture("cli.module.activate.success", { moduleName: def.id, models: def.models.length }, Date.now() - startTime);
82
114
  await telemetry.flush();
83
115
  }
84
116
  catch (error) {
85
- spinner.fail(chalk_1.default.red(`Falha ao ativar módulo: ${error instanceof Error ? error.message : String(error)}`));
117
+ spinner.fail(chalk_1.default.red(`Failed to activate module: ${error instanceof Error ? error.message : String(error)}`));
86
118
  telemetry.capture("cli.module.activate.error", { moduleName, error: error.message }, Date.now() - startTime);
87
119
  await telemetry.flush();
88
120
  process.exit(1);
@@ -91,27 +123,27 @@ async function moduleActivate(moduleName, projectRoot) {
91
123
  // ============================================================
92
124
  // kaven module deactivate <name>
93
125
  // ============================================================
94
- async function moduleDeactivate(moduleName, projectRoot) {
126
+ async function moduleDeactivate(moduleName, projectRoot, options = {}) {
95
127
  const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
96
128
  const startTime = Date.now();
97
129
  telemetry.capture("cli.module.deactivate.start", { moduleName });
98
130
  const root = projectRoot ?? process.cwd();
99
131
  const activator = new SchemaActivator_1.SchemaActivator(root);
100
- const spinner = (0, ora_1.default)(`Desativando módulo ${moduleName}...`).start();
132
+ const spinner = (0, ora_1.default)(`Deactivating module ${moduleName}...`).start();
101
133
  try {
102
- // 1. Validar que o schema existe
134
+ // 1. Validate schema exists
103
135
  const exists = await activator.exists();
104
136
  spinner.stop();
105
137
  assertSchemaExists(exists, root);
106
- // 2. Validar módulo
138
+ // 2. Validate module
107
139
  const def = findModuleDef(moduleName);
108
140
  if (!def) {
109
- console.error(chalk_1.default.red(`\nMódulo desconhecido: "${moduleName}".`));
110
- console.error(chalk_1.default.gray(`Módulos disponíveis: ${SchemaActivator_1.KAVEN_MODULES.map((m) => m.id).join(", ")}`));
141
+ console.error(chalk_1.default.red(`\nUnknown module: "${moduleName}".`));
142
+ console.error(chalk_1.default.gray(`Available modules: ${SchemaActivator_1.KAVEN_MODULES.map((m) => m.id).join(", ")}`));
111
143
  process.exit(1);
112
144
  }
113
- // 3. Verificar se outros módulos ativos dependem deste
114
- spinner.start("Verificando dependências reversas...");
145
+ // 3. Check for active dependents
146
+ spinner.start("Checking reverse dependencies...");
115
147
  const dependents = [];
116
148
  for (const candidate of SchemaActivator_1.KAVEN_MODULES) {
117
149
  if (candidate.id === def.id)
@@ -125,28 +157,37 @@ async function moduleDeactivate(moduleName, projectRoot) {
125
157
  }
126
158
  if (dependents.length > 0) {
127
159
  spinner.stop();
128
- console.error(chalk_1.default.red(`\nNão é possível desativar "${moduleName}": os seguintes módulos dependem dele e estão ativos:`));
160
+ console.error(chalk_1.default.red(`\nCannot deactivate "${moduleName}": the following active modules depend on it:`));
129
161
  console.error(chalk_1.default.gray(` ${dependents.join(", ")}`));
130
- console.error(chalk_1.default.gray(`Desative-os primeiro:\n${dependents.map((d) => ` kaven module deactivate ${d}`).join("\n")}`));
162
+ console.error(chalk_1.default.gray(`Deactivate them first:\n${dependents.map((d) => ` kaven module deactivate ${d}`).join("\n")}`));
131
163
  process.exit(1);
132
164
  }
133
- // 4. Verificar se está inativo
165
+ // 4. Check if already inactive
134
166
  const current = await activator.getModuleStatus(def);
135
167
  if (!current.active) {
136
168
  spinner.stop();
137
- console.log(chalk_1.default.yellow(`\nMódulo "${def.label}" está inativo.`));
169
+ console.log(chalk_1.default.yellow(`\nModule "${def.label}" is already inactive.`));
138
170
  return;
139
171
  }
140
- // 5. Desativar
141
- spinner.start(`Comentando modelos de ${def.label} no schema...`);
172
+ // 5. Dry run
173
+ if (options.dryRun) {
174
+ spinner.stop();
175
+ console.log(chalk_1.default.bold(`\n--- DRY RUN: Deactivating ${def.label} ---`));
176
+ console.log(`Models to comment: ${def.models.join(", ")}`);
177
+ return;
178
+ }
179
+ // 6. Deactivate
180
+ spinner.start(`Commenting ${def.label} models in schema...`);
142
181
  await activator.deactivateModule(def);
143
- spinner.succeed(chalk_1.default.green(`\nMódulo ${def.label} desativado com sucesso.`));
144
- console.log(chalk_1.default.cyan("\nSugestão: Execute `pnpm db:generate && pnpm db:migrate` para aplicar as mudanças."));
182
+ spinner.succeed(chalk_1.default.green(`\nModule ${def.label} deactivated successfully.`));
183
+ if (!options.skipMigrate) {
184
+ console.log(chalk_1.default.cyan("\nNext step: Run `pnpm db:generate && pnpm db:migrate` to apply changes."));
185
+ }
145
186
  telemetry.capture("cli.module.deactivate.success", { moduleName: def.id }, Date.now() - startTime);
146
187
  await telemetry.flush();
147
188
  }
148
189
  catch (error) {
149
- spinner.fail(chalk_1.default.red(`Falha ao desativar módulo: ${error instanceof Error ? error.message : String(error)}`));
190
+ spinner.fail(chalk_1.default.red(`Failed to deactivate module: ${error instanceof Error ? error.message : String(error)}`));
150
191
  telemetry.capture("cli.module.deactivate.error", { moduleName, error: error.message }, Date.now() - startTime);
151
192
  await telemetry.flush();
152
193
  process.exit(1);
@@ -159,9 +200,9 @@ async function moduleListActivation(projectRoot) {
159
200
  const root = projectRoot ?? process.cwd();
160
201
  const activator = new SchemaActivator_1.SchemaActivator(root);
161
202
  const schemaExists = await activator.exists();
162
- // Cabeçalho da tabela
203
+ // Table header
163
204
  const COL = {
164
- module: 14,
205
+ module: 18,
165
206
  status: 10,
166
207
  models: 44,
167
208
  deps: 20,
@@ -172,7 +213,7 @@ async function moduleListActivation(projectRoot) {
172
213
  chalk_1.default.bold("Depends on");
173
214
  const divider = "─".repeat(COL.module + COL.status + COL.models + COL.deps);
174
215
  console.log();
175
- console.log(chalk_1.default.blue("Módulos Kaven disponíveis\n"));
216
+ console.log(chalk_1.default.blue("Kaven Schema Modules\n"));
176
217
  console.log(header);
177
218
  console.log(chalk_1.default.gray(divider));
178
219
  if (!schemaExists) {
@@ -184,8 +225,8 @@ async function moduleListActivation(projectRoot) {
184
225
  console.log(`${modCol}${statusCol}${modelsCol}${depsCol}`);
185
226
  }
186
227
  console.log();
187
- console.log(chalk_1.default.yellow("Atenção: schema.extended.prisma não encontrado. Status não pode ser determinado."));
188
- console.log(chalk_1.default.gray("Execute este comando na raiz de um projeto Kaven para ver o status real."));
228
+ console.log(chalk_1.default.yellow("Warning: schema.extended.prisma not found. Status cannot be determined."));
229
+ console.log(chalk_1.default.gray("Run this command in the root of a Kaven project to see real status."));
189
230
  return;
190
231
  }
191
232
  for (const def of SchemaActivator_1.KAVEN_MODULES) {
@@ -200,7 +241,5 @@ async function moduleListActivation(projectRoot) {
200
241
  console.log(`${modCol}${statusColored}${modelsCol}${depsCol}`);
201
242
  }
202
243
  console.log();
203
- console.log(chalk_1.default.gray("Core (sempre ativo): Tenant, User, Role, Capability, AuthSession, AuditLog"));
204
- console.log();
205
- console.log(chalk_1.default.gray("Para ativar: kaven module activate <name> | Para desativar: kaven module deactivate <name>"));
244
+ console.log(chalk_1.default.gray("To activate: kaven module activate <name> | To deactivate: kaven module deactivate <name>"));
206
245
  }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.marketplaceList = marketplaceList;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const module_registry_1 = require("../../lib/module-registry");
11
+ const schema_modifier_1 = require("../../lib/schema-modifier");
12
+ /**
13
+ * Finds the Prisma schema file in the project
14
+ */
15
+ function findSchemaPath(root) {
16
+ const searchPath = root || process.cwd();
17
+ const paths = [
18
+ path_1.default.join(searchPath, "packages/database/prisma/schema.extended.prisma"),
19
+ path_1.default.join(searchPath, "prisma/schema.prisma"),
20
+ ];
21
+ for (const p of paths) {
22
+ if (fs_extra_1.default.existsSync(p))
23
+ return p;
24
+ }
25
+ throw new Error("Prisma schema file not found.");
26
+ }
27
+ async function marketplaceList(root) {
28
+ try {
29
+ const schemaPath = findSchemaPath(root);
30
+ const content = await fs_extra_1.default.readFile(schemaPath, "utf-8");
31
+ console.log(`\n ${chalk_1.default.bold.underline("Kaven Schema Modules")}\n`);
32
+ const active = module_registry_1.MODULE_REGISTRY.filter(m => (0, schema_modifier_1.isModuleActive)(content, m.models));
33
+ const inactive = module_registry_1.MODULE_REGISTRY.filter(m => !(0, schema_modifier_1.isModuleActive)(content, m.models));
34
+ console.log(chalk_1.default.green(" ACTIVE"));
35
+ active.forEach(m => {
36
+ const suffix = m.id === "core" ? chalk_1.default.gray(" (always active)") : "";
37
+ console.log(` ${chalk_1.default.green("✓")} ${m.id.padEnd(15)} ${m.name} (${m.models.length} models)${suffix}`);
38
+ });
39
+ if (inactive.length > 0) {
40
+ console.log(`\\n ${chalk_1.default.yellow("INACTIVE")}`);
41
+ inactive.forEach(m => {
42
+ const deps = m.dependsOn.length > 0 ? chalk_1.default.gray(` (requires: ${m.dependsOn.join(", ")})`) : "";
43
+ console.log(` ${chalk_1.default.gray("○")} ${m.id.padEnd(15)} ${m.name} (${m.models.length} models)${deps}`);
44
+ });
45
+ }
46
+ console.log();
47
+ }
48
+ catch (error) {
49
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
50
+ }
51
+ }
@@ -81,6 +81,9 @@ class ProjectInitializer {
81
81
  "apps/api/package.json",
82
82
  "apps/admin/package.json",
83
83
  "apps/tenant/package.json",
84
+ "docs/architecture/tech-stack.md",
85
+ "docs/architecture/source-tree.md",
86
+ "docs/architecture/coding-standards.md",
84
87
  ];
85
88
  for (const relFile of filesToProcess) {
86
89
  const filePath = path_1.default.join(targetDir, relFile);
@@ -142,6 +145,20 @@ class ProjectInitializer {
142
145
  }
143
146
  return { installed: true };
144
147
  }
148
+ /**
149
+ * Install AIOX Core runtime into the project via npx.
150
+ * Non-fatal — if it fails, user gets instructions to run manually.
151
+ */
152
+ async installAIOXCore(targetDir) {
153
+ const exitCode = await runCommand('npx', ['aiox-core@5.0.3', 'install', '--quiet'], targetDir);
154
+ if (exitCode !== 0) {
155
+ return {
156
+ installed: false,
157
+ reason: `npx aiox-core exited with code ${exitCode}`,
158
+ };
159
+ }
160
+ return { installed: true };
161
+ }
145
162
  /** Health check after project initialization. */
146
163
  async healthCheck(targetDir) {
147
164
  const issues = [];
@@ -47,6 +47,14 @@ exports.KAVEN_MODULES = [
47
47
  enums: ["TrackingSource"],
48
48
  dependsOn: [],
49
49
  },
50
+ {
51
+ id: "service-tokens",
52
+ label: "Service Tokens",
53
+ description: "Agent authentication tokens for AIOX integration",
54
+ models: ["ServiceToken"],
55
+ enums: [],
56
+ dependsOn: [],
57
+ },
50
58
  ];
51
59
  // ============================================================
52
60
  // Marcadores de seção no schema
package/dist/index.js CHANGED
@@ -22,12 +22,13 @@ const index_3 = require("./commands/cache/index");
22
22
  const index_4 = require("./commands/config/index");
23
23
  const features_1 = require("./commands/config/features");
24
24
  const index_5 = require("./commands/init-ci/index");
25
+ const aiox_1 = require("./commands/aiox");
25
26
  const main = () => {
26
27
  const program = new commander_1.Command();
27
28
  program
28
29
  .name("kaven")
29
30
  .description("The official CLI for the Kaven SaaS boilerplate ecosystem")
30
- .version("0.2.0-alpha.1")
31
+ .version("0.4.1-alpha.0")
31
32
  .addHelpText("after", `
32
33
  Examples:
33
34
  $ kaven init my-saas-app Bootstrap a new Kaven project
@@ -52,6 +53,7 @@ Support: https://github.com/kaven-co/kaven-cli/issues
52
53
  .option("--force", "Overwrite existing directory if it exists")
53
54
  .option("--template <path>", "Path to a local template or custom git repository URL")
54
55
  .option("--with-squad", "Install kaven-squad (AIOX) into squads/kaven-squad/ after scaffold")
56
+ .option("--skip-aiox", "Skip AIOX environment bootstrap")
55
57
  .addHelpText("after", `
56
58
  Examples:
57
59
  $ kaven init my-app Interactive setup
@@ -66,6 +68,7 @@ Examples:
66
68
  force: opts.force,
67
69
  template: opts.template,
68
70
  withSquad: opts.withSquad,
71
+ skipAiox: opts.skipAiox,
69
72
  }));
70
73
  /**
71
74
  * Modules Group
@@ -142,6 +145,10 @@ Examples:
142
145
  moduleCommand
143
146
  .command("activate <name> [root]")
144
147
  .description("Activate a Kaven schema module by uncommenting its models in schema.extended.prisma")
148
+ .option("--with-deps", "Automatically activate required dependencies")
149
+ .option("--skip-migrate", "Skip db:generate and db:migrate after activation")
150
+ .option("--dry-run", "Show affected models without modifying schema")
151
+ .option("--yes", "Skip confirmation prompt")
145
152
  .addHelpText("after", `
146
153
  Modules: billing, projects, notifications
147
154
 
@@ -149,11 +156,15 @@ Examples:
149
156
  $ kaven module activate billing
150
157
  $ kaven module activate projects
151
158
  $ kaven module activate projects ./my-app
159
+ $ kaven module activate billing --with-deps
152
160
  `)
153
- .action((name, root) => (0, activate_1.moduleActivate)(name, root));
161
+ .action((name, root, opts) => (0, activate_1.moduleActivate)(name, root, opts));
154
162
  moduleCommand
155
163
  .command("deactivate <name> [root]")
156
164
  .description("Deactivate a Kaven schema module by commenting its models in schema.extended.prisma")
165
+ .option("--skip-migrate", "Skip db:generate and db:migrate")
166
+ .option("--dry-run", "Show affected models without modifying schema")
167
+ .option("--yes", "Skip confirmation prompt")
157
168
  .addHelpText("after", `
158
169
  Modules: billing, projects, notifications
159
170
 
@@ -162,7 +173,7 @@ Examples:
162
173
  $ kaven module deactivate projects
163
174
  $ kaven module deactivate projects ./my-app
164
175
  `)
165
- .action((name, root) => (0, activate_1.moduleDeactivate)(name, root));
176
+ .action((name, root, opts) => (0, activate_1.moduleDeactivate)(name, root, opts));
166
177
  moduleCommand
167
178
  .command("list [root]")
168
179
  .description("List available Kaven schema modules with their status, models, and dependencies")
@@ -395,9 +406,14 @@ Examples:
395
406
  $ kaven init-ci --dry-run Show what would be created
396
407
  `)
397
408
  .action((opts) => (0, index_5.initCi)({ dryRun: opts.dryRun }));
398
- program.parse();
409
+ /**
410
+ * AIOX Commands
411
+ */
412
+ (0, aiox_1.registerAioxCommand)(program);
413
+ program.parse(process.argv);
399
414
  };
400
415
  exports.main = main;
416
+ // Execute main if this is the entry point
401
417
  if (require.main === module) {
402
418
  (0, exports.main)();
403
419
  }
@@ -33,6 +33,28 @@ async function loadConfigApiUrl() {
33
33
  }
34
34
  return null;
35
35
  }
36
+ /**
37
+ * Load a service token for agent-to-service auth.
38
+ * Resolution order: KAVEN_SERVICE_TOKEN env → ~/.kaven/config.json#serviceToken
39
+ */
40
+ async function loadServiceToken() {
41
+ if (process.env.KAVEN_SERVICE_TOKEN) {
42
+ return process.env.KAVEN_SERVICE_TOKEN;
43
+ }
44
+ try {
45
+ const configPath = path_1.default.join(os_1.default.homedir(), ".kaven", "config.json");
46
+ if (await fs_extra_1.default.pathExists(configPath)) {
47
+ const config = await fs_extra_1.default.readJson(configPath);
48
+ if (typeof config.serviceToken === "string" && config.serviceToken) {
49
+ return config.serviceToken;
50
+ }
51
+ }
52
+ }
53
+ catch {
54
+ // Ignore config read errors
55
+ }
56
+ return null;
57
+ }
36
58
  /** Resolve base URL from env → config file → default. */
37
59
  async function resolveBaseUrl() {
38
60
  if (process.env.KAVEN_API_URL) {
@@ -91,6 +113,10 @@ class MarketplaceClient {
91
113
  const token = await this.authService.getValidToken();
92
114
  headers["Authorization"] = `Bearer ${token}`;
93
115
  }
116
+ const serviceToken = await loadServiceToken();
117
+ if (serviceToken) {
118
+ headers["X-Service-Token"] = serviceToken;
119
+ }
94
120
  debug(`${method} ${url}`);
95
121
  const controller = new AbortController();
96
122
  const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);