@jvittechs/j 1.0.23 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -42,7 +42,7 @@ function checkNodeVersion() {
42
42
  }
43
43
 
44
44
  // src/cli.ts
45
- import { Command as Command78 } from "commander";
45
+ import { Command as Command79 } from "commander";
46
46
 
47
47
  // src/errors/index.ts
48
48
  var Jai1Error = class extends Error {
@@ -169,7 +169,7 @@ import { basename as basename4 } from "path";
169
169
  // package.json
170
170
  var package_default = {
171
171
  name: "@jvittechs/j",
172
- version: "1.0.23",
172
+ version: "1.0.25",
173
173
  description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Supports both `j` and `jai1` commands. Please contact TeamAI for usage instructions.",
174
174
  type: "module",
175
175
  bin: {
@@ -4204,9 +4204,59 @@ function showGuide(name) {
4204
4204
  console.log();
4205
4205
  }
4206
4206
 
4207
- // src/commands/doctor.ts
4207
+ // src/commands/quickstart.ts
4208
4208
  import { Command as Command13 } from "commander";
4209
4209
  import chalk9 from "chalk";
4210
+ function createQuickstartCommand() {
4211
+ const cmd = new Command13("quickstart").description("H\u01B0\u1EDBng d\u1EABn nhanh theo t\u1EEBng t\xECnh hu\u1ED1ng ph\xE1t tri\u1EC3n").action(() => {
4212
+ const name = getCliName();
4213
+ showQuickstart(name);
4214
+ });
4215
+ return cmd;
4216
+ }
4217
+ function showQuickstart(name) {
4218
+ console.log(chalk9.cyan.bold("\n\u{1F680} Quickstart - B\u1EAFt \u0111\u1EA7u t\u1EEB \u0111\xE2u?\n"));
4219
+ console.log(chalk9.dim("Ch\u1ECDn t\xECnh hu\u1ED1ng ph\xF9 h\u1EE3p v\u1EDBi b\u1EA1n:\n"));
4220
+ console.log(chalk9.bold("\u2501\u2501\u2501 \u{1F3C1} M\u1EDAI B\u1EAET \u0110\u1EA6U \u2501\u2501\u2501"));
4221
+ console.log(` ${chalk9.cyan(`${name} doctor`)} Ki\u1EC3m tra project \u0111\xE3 setup \u0111\xFAng ch\u01B0a`);
4222
+ console.log(` ${chalk9.cyan(`${name} guide`)} Xem to\xE0n b\u1ED9 h\u01B0\u1EDBng d\u1EABn CLI commands`);
4223
+ console.log(` ${chalk9.cyan(`${name} t guide`)} H\u01B0\u1EDBng d\u1EABn chi ti\u1EBFt task management`);
4224
+ console.log();
4225
+ console.log(chalk9.bold("\u2501\u2501\u2501 \u{1F4CB} L\xCAN K\u1EBE HO\u1EA0CH \u2501\u2501\u2501"));
4226
+ console.log(` ${chalk9.cyan("/develop-feature")} Ph\xE1t tri\u1EC3n t\xEDnh n\u0103ng m\u1EDBi (FRD \u2192 TDD \u2192 Code)`);
4227
+ console.log(` ${chalk9.cyan("/plan")} L\xEAn k\u1EBF ho\u1EA1ch nhanh \u2192 t\u1EA1o tasks \u2192 implement`);
4228
+ console.log(` ${chalk9.cyan("/improve")} Ph\xE2n t\xEDch & \u0111\u1EC1 xu\u1EA5t c\u1EA3i thi\u1EC7n project`);
4229
+ console.log();
4230
+ console.log(chalk9.bold("\u2501\u2501\u2501 \u2705 L\xC0M VI\u1EC6C V\u1EDAI TASKS \u2501\u2501\u2501"));
4231
+ console.log(` ${chalk9.cyan("/pick-next-task")} Resume ho\u1EB7c b\u1EAFt \u0111\u1EA7u task ti\u1EBFp theo`);
4232
+ console.log(` ${chalk9.cyan("/review-tasks")} Review danh s\xE1ch tasks, ph\xE1t hi\u1EC7n v\u1EA5n \u0111\u1EC1`);
4233
+ console.log(` ${chalk9.cyan(`${name} t ready`)} Xem c\xE1c tasks s\u1EB5n s\xE0ng \u0111\u1EC3 l\xE0m`);
4234
+ console.log(` ${chalk9.cyan(`${name} t summary`)} Dashboard t\u1ED5ng quan tasks`);
4235
+ console.log();
4236
+ console.log(chalk9.bold("\u2501\u2501\u2501 \u{1F50D} CH\u1EA4T L\u01AF\u1EE2NG CODE \u2501\u2501\u2501"));
4237
+ console.log(` ${chalk9.cyan("/review-local-changes")} Review code thay \u0111\u1ED5i tr\u01B0\u1EDBc khi commit`);
4238
+ console.log(` ${chalk9.cyan("/commit-it")} Commit an to\xE0n v\u1EDBi message chi ti\u1EBFt`);
4239
+ console.log(` ${chalk9.cyan("/fix-bug")} Ph\xE2n t\xEDch & s\u1EEDa bug`);
4240
+ console.log();
4241
+ console.log(chalk9.bold("\u2501\u2501\u2501 \u{1F4DD} T\xC0I LI\u1EC6U \u2501\u2501\u2501"));
4242
+ console.log(` ${chalk9.cyan("/gen-feature-doc")} T\u1EA1o t\xE0i li\u1EC7u cho 1 t\xEDnh n\u0103ng`);
4243
+ console.log(` ${chalk9.cyan("/gen-all-features-doc")} T\u1EA1o t\xE0i li\u1EC7u cho to\xE0n b\u1ED9 t\xEDnh n\u0103ng`);
4244
+ console.log(` ${chalk9.cyan("/gen-project-overview")} T\u1EA1o t\u1ED5ng quan project`);
4245
+ console.log();
4246
+ console.log(chalk9.yellow.bold("\u2501\u2501\u2501 \u{1F4A1} FLOW PH\xC1T TRI\u1EC2N PH\u1ED4 BI\u1EBEN \u2501\u2501\u2501"));
4247
+ console.log(chalk9.dim(" 1. Ki\u1EC3m tra setup \u2192 j doctor"));
4248
+ console.log(chalk9.dim(" 2. L\xEAn k\u1EBF ho\u1EA1ch \u2192 /develop-feature ho\u1EB7c /plan"));
4249
+ console.log(chalk9.dim(" 3. L\xE0m task \u2192 /pick-next-task"));
4250
+ console.log(chalk9.dim(" 4. Review & commit \u2192 /review-local-changes \u2192 /commit-it"));
4251
+ console.log(chalk9.dim(" 5. Ki\u1EC3m tra tasks c\xF2n l\u1EA1i \u2192 /review-tasks"));
4252
+ console.log();
4253
+ console.log(chalk9.dim(`\u{1F4A1} Ch\u1EA1y "${name} guide" \u0111\u1EC3 xem \u0111\u1EA7y \u0111\u1EE7 danh s\xE1ch commands.`));
4254
+ console.log();
4255
+ }
4256
+
4257
+ // src/commands/doctor.ts
4258
+ import { Command as Command14 } from "commander";
4259
+ import chalk10 from "chalk";
4210
4260
  import { promises as fs9 } from "fs";
4211
4261
  import { join as join6 } from "path";
4212
4262
  var CORE_FILES = [
@@ -4225,7 +4275,7 @@ var CORE_FILES = [
4225
4275
  "skills/latest-version"
4226
4276
  ];
4227
4277
  function createDoctorCommand() {
4228
- const cmd = new Command13("doctor").description("Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i").option("--json", "Output as JSON").action(async (options) => {
4278
+ const cmd = new Command14("doctor").description("Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i").option("--json", "Output as JSON").action(async (options) => {
4229
4279
  await runDoctor(options);
4230
4280
  });
4231
4281
  return cmd;
@@ -4234,8 +4284,8 @@ async function runDoctor(options) {
4234
4284
  const name = getCliName();
4235
4285
  const results = [];
4236
4286
  if (!options.json) {
4237
- console.log(chalk9.cyan.bold("\n\u{1FA7A} Jai1 Doctor\n"));
4238
- console.log(chalk9.dim(` \u0110ang ki\u1EC3m tra project t\u1EA1i: ${process.cwd()}
4287
+ console.log(chalk10.cyan.bold("\n\u{1FA7A} Jai1 Doctor\n"));
4288
+ console.log(chalk10.dim(` \u0110ang ki\u1EC3m tra project t\u1EA1i: ${process.cwd()}
4239
4289
  `));
4240
4290
  }
4241
4291
  results.push(await checkAuth(name));
@@ -4248,19 +4298,19 @@ async function runDoctor(options) {
4248
4298
  return;
4249
4299
  }
4250
4300
  for (const result of results) {
4251
- const icon = result.passed ? chalk9.green("\u2713") : chalk9.red("\u2717");
4252
- const label = result.passed ? chalk9.green(result.message) : chalk9.red(result.message);
4253
- console.log(` ${icon} ${chalk9.bold(result.name)}: ${label}`);
4301
+ const icon = result.passed ? chalk10.green("\u2713") : chalk10.red("\u2717");
4302
+ const label = result.passed ? chalk10.green(result.message) : chalk10.red(result.message);
4303
+ console.log(` ${icon} ${chalk10.bold(result.name)}: ${label}`);
4254
4304
  if (result.details && result.details.length > 0) {
4255
4305
  for (const detail of result.details) {
4256
- console.log(chalk9.dim(` ${detail}`));
4306
+ console.log(chalk10.dim(` ${detail}`));
4257
4307
  }
4258
4308
  }
4259
4309
  if (!result.passed && result.suggestion) {
4260
4310
  const lines = result.suggestion.split("\n");
4261
- console.log(chalk9.yellow(` \u{1F4A1} ${lines[0]}`));
4311
+ console.log(chalk10.yellow(` \u{1F4A1} ${lines[0]}`));
4262
4312
  for (const line of lines.slice(1)) {
4263
- console.log(chalk9.yellow(` ${line}`));
4313
+ console.log(chalk10.yellow(` ${line}`));
4264
4314
  }
4265
4315
  }
4266
4316
  console.log();
@@ -4268,11 +4318,11 @@ async function runDoctor(options) {
4268
4318
  const passed = results.filter((r) => r.passed).length;
4269
4319
  const total = results.length;
4270
4320
  if (passed === total) {
4271
- console.log(chalk9.green.bold(` \u2705 T\u1EA5t c\u1EA3 ${total} ki\u1EC3m tra \u0111\xE3 pass!
4321
+ console.log(chalk10.green.bold(` \u2705 T\u1EA5t c\u1EA3 ${total} ki\u1EC3m tra \u0111\xE3 pass!
4272
4322
  `));
4273
4323
  } else {
4274
4324
  console.log(
4275
- chalk9.yellow(` \u26A0\uFE0F ${passed}/${total} ki\u1EC3m tra pass. Xem g\u1EE3i \xFD \u1EDF tr\xEAn \u0111\u1EC3 s\u1EEDa.
4325
+ chalk10.yellow(` \u26A0\uFE0F ${passed}/${total} ki\u1EC3m tra pass. Xem g\u1EE3i \xFD \u1EDF tr\xEAn \u0111\u1EC3 s\u1EEDa.
4276
4326
  `)
4277
4327
  );
4278
4328
  }
@@ -4428,7 +4478,7 @@ async function checkIde(cliName) {
4428
4478
  }
4429
4479
 
4430
4480
  // src/commands/chat.ts
4431
- import { Command as Command14 } from "commander";
4481
+ import { Command as Command15 } from "commander";
4432
4482
  import React12 from "react";
4433
4483
  import { render as render3 } from "ink";
4434
4484
 
@@ -6070,15 +6120,15 @@ async function handleChatCommand(options) {
6070
6120
  }
6071
6121
  }
6072
6122
  function createChatCommand() {
6073
- const cmd = new Command14("chat").description("AI chat with Jai1 LLM Proxy (default: web browser)").option("--model <model>", "Initial model to use (e.g., gpt-4o, claude-3-opus)").option("-t, --terminal", "Use terminal TUI mode instead of web browser").option("--port <port>", "Port for web server (default: auto-find available port)").option("--no-open", "Don't auto-open browser (web mode only)").action(async (options) => {
6123
+ const cmd = new Command15("chat").description("AI chat with Jai1 LLM Proxy (default: web browser)").option("--model <model>", "Initial model to use (e.g., gpt-4o, claude-3-opus)").option("-t, --terminal", "Use terminal TUI mode instead of web browser").option("--port <port>", "Port for web server (default: auto-find available port)").option("--no-open", "Don't auto-open browser (web mode only)").action(async (options) => {
6074
6124
  await handleChatCommand(options);
6075
6125
  });
6076
6126
  return cmd;
6077
6127
  }
6078
6128
 
6079
6129
  // src/commands/openai-keys.ts
6080
- import { Command as Command15 } from "commander";
6081
- import chalk10 from "chalk";
6130
+ import { Command as Command16 } from "commander";
6131
+ import chalk11 from "chalk";
6082
6132
  import boxen3 from "boxen";
6083
6133
  function maskKey2(key) {
6084
6134
  if (key.length <= 8) return "****";
@@ -6092,17 +6142,17 @@ async function handleOpenAiKeysCommand(options) {
6092
6142
  }
6093
6143
  const service = new LlmProxyService(config);
6094
6144
  console.log(
6095
- boxen3(chalk10.cyan.bold("\u{1F4E1} Jai1 LLM Proxy - OpenAI Compatible API"), {
6145
+ boxen3(chalk11.cyan.bold("\u{1F4E1} Jai1 LLM Proxy - OpenAI Compatible API"), {
6096
6146
  padding: { top: 0, bottom: 0, left: 1, right: 1 },
6097
6147
  borderStyle: "round",
6098
6148
  borderColor: "cyan"
6099
6149
  })
6100
6150
  );
6101
6151
  console.log();
6102
- console.log(chalk10.bold("\u{1F511} API Credentials"));
6103
- console.log(` ${chalk10.dim("BASE_URL:")} ${chalk10.white(service.getBaseUrl())}`);
6152
+ console.log(chalk11.bold("\u{1F511} API Credentials"));
6153
+ console.log(` ${chalk11.dim("BASE_URL:")} ${chalk11.white(service.getBaseUrl())}`);
6104
6154
  console.log(
6105
- ` ${chalk10.dim("API_KEY:")} ${options.full ? chalk10.green(service.getApiKey()) : chalk10.yellow(maskKey2(service.getApiKey()))}`
6155
+ ` ${chalk11.dim("API_KEY:")} ${options.full ? chalk11.green(service.getApiKey()) : chalk11.yellow(maskKey2(service.getApiKey()))}`
6106
6156
  );
6107
6157
  console.log();
6108
6158
  try {
@@ -6111,52 +6161,52 @@ async function handleOpenAiKeysCommand(options) {
6111
6161
  service.getLimits()
6112
6162
  ]);
6113
6163
  const allowedModels = models.filter((m) => m.allowed);
6114
- console.log(chalk10.bold("\u{1F4E6} Available Models"));
6164
+ console.log(chalk11.bold("\u{1F4E6} Available Models"));
6115
6165
  if (allowedModels.length === 0) {
6116
- console.log(chalk10.dim(" Kh\xF4ng c\xF3 models kh\u1EA3 d\u1EE5ng"));
6166
+ console.log(chalk11.dim(" Kh\xF4ng c\xF3 models kh\u1EA3 d\u1EE5ng"));
6117
6167
  } else {
6118
6168
  for (const model of allowedModels) {
6119
- const usageText = model.dailyLimit !== void 0 && model.usedToday !== void 0 ? chalk10.dim(` (${model.usedToday}/${model.dailyLimit} h\xF4m nay)`) : "";
6120
- console.log(` ${chalk10.green("\u2713")} ${chalk10.white(model.id)}${usageText}`);
6169
+ const usageText = model.dailyLimit !== void 0 && model.usedToday !== void 0 ? chalk11.dim(` (${model.usedToday}/${model.dailyLimit} h\xF4m nay)`) : "";
6170
+ console.log(` ${chalk11.green("\u2713")} ${chalk11.white(model.id)}${usageText}`);
6121
6171
  }
6122
6172
  }
6123
6173
  console.log();
6124
6174
  const defaultModel = allowedModels[0]?.id || "gpt-4o";
6125
- console.log(chalk10.bold("\u{1F4DD} Sample cURL"));
6175
+ console.log(chalk11.bold("\u{1F4DD} Sample cURL"));
6126
6176
  console.log();
6127
6177
  const curlSample = options.full ? service.generateFullCurlSample(defaultModel) : service.generateCurlSample(defaultModel);
6128
6178
  const curlLines = curlSample.split("\n");
6129
6179
  for (const line of curlLines) {
6130
- console.log(chalk10.dim(` ${line}`));
6180
+ console.log(chalk11.dim(` ${line}`));
6131
6181
  }
6132
6182
  console.log();
6133
- console.log(chalk10.bold("\u{1F4A1} C\xE1ch s\u1EED d\u1EE5ng"));
6134
- console.log(chalk10.dim(" - Thay th\u1EBF OpenAI API URL v\xE0 API Key"));
6135
- console.log(chalk10.dim(" - T\u01B0\u01A1ng th\xEDch: OpenAI SDK, LangChain, LlamaIndex, v.v."));
6136
- console.log(chalk10.dim(' - Ch\u1EA1y "jai1 chat" \u0111\u1EC3 chat tr\u1EF1c ti\u1EBFp'));
6183
+ console.log(chalk11.bold("\u{1F4A1} C\xE1ch s\u1EED d\u1EE5ng"));
6184
+ console.log(chalk11.dim(" - Thay th\u1EBF OpenAI API URL v\xE0 API Key"));
6185
+ console.log(chalk11.dim(" - T\u01B0\u01A1ng th\xEDch: OpenAI SDK, LangChain, LlamaIndex, v.v."));
6186
+ console.log(chalk11.dim(' - Ch\u1EA1y "jai1 chat" \u0111\u1EC3 chat tr\u1EF1c ti\u1EBFp'));
6137
6187
  if (!options.full) {
6138
- console.log(chalk10.dim(' - Ch\u1EA1y "jai1 openai-keys --full" \u0111\u1EC3 hi\u1EC3n th\u1ECB API key \u0111\u1EA7y \u0111\u1EE7'));
6188
+ console.log(chalk11.dim(' - Ch\u1EA1y "jai1 openai-keys --full" \u0111\u1EC3 hi\u1EC3n th\u1ECB API key \u0111\u1EA7y \u0111\u1EE7'));
6139
6189
  }
6140
6190
  } catch (error) {
6141
6191
  console.log();
6142
6192
  console.log(
6143
- chalk10.red("\u274C L\u1ED7i khi l\u1EA5y th\xF4ng tin API:"),
6144
- chalk10.dim(error instanceof Error ? error.message : String(error))
6193
+ chalk11.red("\u274C L\u1ED7i khi l\u1EA5y th\xF4ng tin API:"),
6194
+ chalk11.dim(error instanceof Error ? error.message : String(error))
6145
6195
  );
6146
- console.log(chalk10.dim('\n\u{1F4A1} Ki\u1EC3m tra API URL v\xE0 access key v\u1EDBi "jai1 status"'));
6196
+ console.log(chalk11.dim('\n\u{1F4A1} Ki\u1EC3m tra API URL v\xE0 access key v\u1EDBi "jai1 status"'));
6147
6197
  }
6148
6198
  }
6149
6199
  function createOpenAiKeysCommand() {
6150
- const cmd = new Command15("openai-keys").description("Show OpenAI-compatible API credentials and info").option("--full", "Show full API key (unmasked)").action(async (options) => {
6200
+ const cmd = new Command16("openai-keys").description("Show OpenAI-compatible API credentials and info").option("--full", "Show full API key (unmasked)").action(async (options) => {
6151
6201
  await handleOpenAiKeysCommand(options);
6152
6202
  });
6153
6203
  return cmd;
6154
6204
  }
6155
6205
 
6156
6206
  // src/commands/stats.ts
6157
- import { Command as Command16 } from "commander";
6207
+ import { Command as Command17 } from "commander";
6158
6208
  import Table2 from "cli-table3";
6159
- import chalk11 from "chalk";
6209
+ import chalk12 from "chalk";
6160
6210
  async function handleStatsCommand() {
6161
6211
  const configService = new ConfigService();
6162
6212
  const config = await configService.load();
@@ -6166,8 +6216,8 @@ async function handleStatsCommand() {
6166
6216
  );
6167
6217
  }
6168
6218
  const service = new LlmProxyService(config);
6169
- console.log(chalk11.bold("\n\u{1F4CA} Th\u1ED1ng K\xEA S\u1EED D\u1EE5ng LLM"));
6170
- console.log(chalk11.dim("\u2500".repeat(45)));
6219
+ console.log(chalk12.bold("\n\u{1F4CA} Th\u1ED1ng K\xEA S\u1EED D\u1EE5ng LLM"));
6220
+ console.log(chalk12.dim("\u2500".repeat(45)));
6171
6221
  try {
6172
6222
  const [limits, usage7Days, usageToday] = await Promise.all([
6173
6223
  service.getLimits(),
@@ -6177,7 +6227,7 @@ async function handleStatsCommand() {
6177
6227
  const today = (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", {
6178
6228
  timeZone: "Asia/Ho_Chi_Minh"
6179
6229
  });
6180
- console.log(chalk11.cyan("\n\u{1F4C5} Kho\u1EA3ng th\u1EDDi gian: 7 ng\xE0y qua\n"));
6230
+ console.log(chalk12.cyan("\n\u{1F4C5} Kho\u1EA3ng th\u1EDDi gian: 7 ng\xE0y qua\n"));
6181
6231
  const usageByModel = /* @__PURE__ */ new Map();
6182
6232
  let total7DaysRequests = 0;
6183
6233
  usage7Days.data?.forEach((record) => {
@@ -6197,16 +6247,16 @@ async function handleStatsCommand() {
6197
6247
  modelData.today = record.count;
6198
6248
  }
6199
6249
  });
6200
- console.log(chalk11.bold("\u{1F4C8} T\u1ED5ng quan s\u1EED d\u1EE5ng"));
6201
- console.log(` T\u1ED5ng s\u1ED1 y\xEAu c\u1EA7u (7 ng\xE0y): ${chalk11.green(total7DaysRequests)}
6250
+ console.log(chalk12.bold("\u{1F4C8} T\u1ED5ng quan s\u1EED d\u1EE5ng"));
6251
+ console.log(` T\u1ED5ng s\u1ED1 y\xEAu c\u1EA7u (7 ng\xE0y): ${chalk12.green(total7DaysRequests)}
6202
6252
  `);
6203
- console.log(chalk11.bold("\u{1F4E6} Th\u1ED1ng k\xEA theo model\n"));
6253
+ console.log(chalk12.bold("\u{1F4E6} Th\u1ED1ng k\xEA theo model\n"));
6204
6254
  const table = new Table2({
6205
6255
  head: [
6206
- chalk11.bold("Model"),
6207
- chalk11.bold("H\xF4m nay"),
6208
- chalk11.bold("Gi\u1EDBi h\u1EA1n"),
6209
- chalk11.bold("T\u1ED5ng 7 ng\xE0y")
6256
+ chalk12.bold("Model"),
6257
+ chalk12.bold("H\xF4m nay"),
6258
+ chalk12.bold("Gi\u1EDBi h\u1EA1n"),
6259
+ chalk12.bold("T\u1ED5ng 7 ng\xE0y")
6210
6260
  ],
6211
6261
  style: {
6212
6262
  head: ["cyan"],
@@ -6218,7 +6268,7 @@ async function handleStatsCommand() {
6218
6268
  const rateLimits = limits.effectiveRateLimits || {};
6219
6269
  if (allowedModels.length === 0) {
6220
6270
  table.push([
6221
- { colSpan: 4, content: chalk11.yellow("Kh\xF4ng c\xF3 model n\xE0o kh\u1EA3 d\u1EE5ng") }
6271
+ { colSpan: 4, content: chalk12.yellow("Kh\xF4ng c\xF3 model n\xE0o kh\u1EA3 d\u1EE5ng") }
6222
6272
  ]);
6223
6273
  } else {
6224
6274
  allowedModels.forEach((modelId) => {
@@ -6227,36 +6277,36 @@ async function handleStatsCommand() {
6227
6277
  const usagePercent = limit > 0 ? usage.today / limit : 0;
6228
6278
  let todayDisplay = `${usage.today}/${limit}`;
6229
6279
  if (usagePercent >= 0.9) {
6230
- todayDisplay = chalk11.red(todayDisplay);
6280
+ todayDisplay = chalk12.red(todayDisplay);
6231
6281
  } else if (usagePercent >= 0.7) {
6232
- todayDisplay = chalk11.yellow(todayDisplay);
6282
+ todayDisplay = chalk12.yellow(todayDisplay);
6233
6283
  } else {
6234
- todayDisplay = chalk11.green(todayDisplay);
6284
+ todayDisplay = chalk12.green(todayDisplay);
6235
6285
  }
6236
6286
  table.push([modelId, todayDisplay, `${limit}/ng\xE0y`, String(usage.total7Days)]);
6237
6287
  });
6238
6288
  }
6239
6289
  console.log(table.toString());
6240
6290
  console.log(
6241
- chalk11.dim('\n\u{1F4A1} M\u1EB9o: Ch\u1EA1y "jai1 openai-keys" \u0111\u1EC3 xem danh s\xE1ch model kh\u1EA3 d\u1EE5ng')
6291
+ chalk12.dim('\n\u{1F4A1} M\u1EB9o: Ch\u1EA1y "jai1 openai-keys" \u0111\u1EC3 xem danh s\xE1ch model kh\u1EA3 d\u1EE5ng')
6242
6292
  );
6243
6293
  } catch (error) {
6244
6294
  console.error(
6245
- chalk11.red("\n\u274C Kh\xF4ng th\u1EC3 l\u1EA5y th\u1ED1ng k\xEA:"),
6295
+ chalk12.red("\n\u274C Kh\xF4ng th\u1EC3 l\u1EA5y th\u1ED1ng k\xEA:"),
6246
6296
  error instanceof Error ? error.message : String(error)
6247
6297
  );
6248
- console.log(chalk11.dim('\n\u{1F4A1} Ki\u1EC3m tra k\u1EBFt n\u1ED1i API v\u1EDBi "jai1 status"'));
6298
+ console.log(chalk12.dim('\n\u{1F4A1} Ki\u1EC3m tra k\u1EBFt n\u1ED1i API v\u1EDBi "jai1 status"'));
6249
6299
  }
6250
6300
  }
6251
6301
  function createStatsCommand() {
6252
- const cmd = new Command16("stats").description("Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM v\xE0 gi\u1EDBi h\u1EA1n").action(async () => {
6302
+ const cmd = new Command17("stats").description("Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM v\xE0 gi\u1EDBi h\u1EA1n").action(async () => {
6253
6303
  await handleStatsCommand();
6254
6304
  });
6255
6305
  return cmd;
6256
6306
  }
6257
6307
 
6258
6308
  // src/commands/translate.ts
6259
- import { Command as Command17 } from "commander";
6309
+ import { Command as Command18 } from "commander";
6260
6310
 
6261
6311
  // src/services/translation.service.ts
6262
6312
  import { promises as fs12 } from "fs";
@@ -6604,18 +6654,18 @@ async function handleFolderTranslation(service, folderPath, options) {
6604
6654
  }
6605
6655
  }
6606
6656
  function createTranslateCommand() {
6607
- const cmd = new Command17("translate").description("D\u1ECBch v\u0103n b\u1EA3n, file ho\u1EB7c th\u01B0 m\u1EE5c b\u1EB1ng AI").argument("<input>", "Chu\u1ED7i v\u0103n b\u1EA3n, \u0111\u01B0\u1EDDng d\u1EABn file ho\u1EB7c th\u01B0 m\u1EE5c").option("--to <language>", "M\xE3 ng\xF4n ng\u1EEF \u0111\xEDch (m\u1EB7c \u0111\u1ECBnh: vi)", "vi").option("-o, --output <path>", "\u0110\u01B0\u1EDDng d\u1EABn output (file/th\u01B0 m\u1EE5c)").option("--dry-run", "Xem tr\u01B0\u1EDBc kh\xF4ng l\u01B0u file").option("--concurrency <number>", "S\u1ED1 file x\u1EED l\xFD song song (m\u1EB7c \u0111\u1ECBnh: 3)", "3").option("--model <model>", "Model LLM (m\u1EB7c \u0111\u1ECBnh: gpt-5.1-codex-mini)").option("--json", "Xu\u1EA5t k\u1EBFt qu\u1EA3 d\u1EA1ng JSON").action(async (input5, options) => {
6657
+ const cmd = new Command18("translate").description("D\u1ECBch v\u0103n b\u1EA3n, file ho\u1EB7c th\u01B0 m\u1EE5c b\u1EB1ng AI").argument("<input>", "Chu\u1ED7i v\u0103n b\u1EA3n, \u0111\u01B0\u1EDDng d\u1EABn file ho\u1EB7c th\u01B0 m\u1EE5c").option("--to <language>", "M\xE3 ng\xF4n ng\u1EEF \u0111\xEDch (m\u1EB7c \u0111\u1ECBnh: vi)", "vi").option("-o, --output <path>", "\u0110\u01B0\u1EDDng d\u1EABn output (file/th\u01B0 m\u1EE5c)").option("--dry-run", "Xem tr\u01B0\u1EDBc kh\xF4ng l\u01B0u file").option("--concurrency <number>", "S\u1ED1 file x\u1EED l\xFD song song (m\u1EB7c \u0111\u1ECBnh: 3)", "3").option("--model <model>", "Model LLM (m\u1EB7c \u0111\u1ECBnh: gpt-5.1-codex-mini)").option("--json", "Xu\u1EA5t k\u1EBFt qu\u1EA3 d\u1EA1ng JSON").action(async (input5, options) => {
6608
6658
  await handleTranslate(input5, options);
6609
6659
  });
6610
6660
  return cmd;
6611
6661
  }
6612
6662
 
6613
6663
  // src/commands/image/index.ts
6614
- import { Command as Command22 } from "commander";
6615
- import chalk12 from "chalk";
6664
+ import { Command as Command23 } from "commander";
6665
+ import chalk13 from "chalk";
6616
6666
 
6617
6667
  // src/commands/image/gen.ts
6618
- import { Command as Command18 } from "commander";
6668
+ import { Command as Command19 } from "commander";
6619
6669
 
6620
6670
  // src/services/image.service.ts
6621
6671
  var ImageService = class {
@@ -6720,7 +6770,7 @@ var SUPPORTED_SIZES = [
6720
6770
  // 3:4 (portrait)
6721
6771
  ];
6722
6772
  function createImageGenCommand() {
6723
- return new Command18("gen").description("Generate an image from text prompt").argument("<prompt>", "Image description prompt").option("-m, --model <model>", "Model to use", "gemini-3-pro-image-preview").option("-s, --size <size>", `Image size: ${SUPPORTED_SIZES.join(", ")}`, "1024x1024").option("-q, --quality <quality>", "Image quality: standard, hd", "hd").option("--no-display", "Don't display image in terminal").action(async (prompt, options) => {
6773
+ return new Command19("gen").description("Generate an image from text prompt").argument("<prompt>", "Image description prompt").option("-m, --model <model>", "Model to use", "gemini-3-pro-image-preview").option("-s, --size <size>", `Image size: ${SUPPORTED_SIZES.join(", ")}`, "1024x1024").option("-q, --quality <quality>", "Image quality: standard, hd", "hd").option("--no-display", "Don't display image in terminal").action(async (prompt, options) => {
6724
6774
  const configService = new ConfigService();
6725
6775
  const config = await configService.load();
6726
6776
  if (!config) {
@@ -6786,9 +6836,9 @@ function createImageGenCommand() {
6786
6836
  }
6787
6837
 
6788
6838
  // src/commands/image/list.ts
6789
- import { Command as Command19 } from "commander";
6839
+ import { Command as Command20 } from "commander";
6790
6840
  function createImageListCommand() {
6791
- return new Command19("list").description("List generated images").option("-m, --model <model>", "Filter by model").option("-l, --limit <number>", "Number of results", "20").option("-o, --offset <number>", "Offset for pagination", "0").action(async (options) => {
6841
+ return new Command20("list").description("List generated images").option("-m, --model <model>", "Filter by model").option("-l, --limit <number>", "Number of results", "20").option("-o, --offset <number>", "Offset for pagination", "0").action(async (options) => {
6792
6842
  const configService = new ConfigService();
6793
6843
  const config = await configService.load();
6794
6844
  if (!config) {
@@ -6824,9 +6874,9 @@ function createImageListCommand() {
6824
6874
  }
6825
6875
 
6826
6876
  // src/commands/image/info.ts
6827
- import { Command as Command20 } from "commander";
6877
+ import { Command as Command21 } from "commander";
6828
6878
  function createImageInfoCommand() {
6829
- return new Command20("info").description("Get detailed info about an image").argument("<id>", "Image ID").action(async (id) => {
6879
+ return new Command21("info").description("Get detailed info about an image").argument("<id>", "Image ID").action(async (id) => {
6830
6880
  const configService = new ConfigService();
6831
6881
  const config = await configService.load();
6832
6882
  if (!config) {
@@ -6860,10 +6910,10 @@ function createImageInfoCommand() {
6860
6910
  }
6861
6911
 
6862
6912
  // src/commands/image/delete.ts
6863
- import { Command as Command21 } from "commander";
6913
+ import { Command as Command22 } from "commander";
6864
6914
  import { confirm as confirm4 } from "@inquirer/prompts";
6865
6915
  function createImageDeleteCommand() {
6866
- return new Command21("delete").description("Delete a generated image").argument("<id>", "Image ID").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
6916
+ return new Command22("delete").description("Delete a generated image").argument("<id>", "Image ID").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
6867
6917
  const configService = new ConfigService();
6868
6918
  const config = await configService.load();
6869
6919
  if (!config) {
@@ -6887,25 +6937,25 @@ function createImageDeleteCommand() {
6887
6937
 
6888
6938
  // src/commands/image/index.ts
6889
6939
  function showImageHelp() {
6890
- console.log(chalk12.bold.cyan("\u{1F3A8} jai1 image") + chalk12.dim(" - Image generation commands"));
6940
+ console.log(chalk13.bold.cyan("\u{1F3A8} jai1 image") + chalk13.dim(" - Image generation commands"));
6891
6941
  console.log();
6892
- console.log(chalk12.yellow("\u26A0\uFE0F Coming Soon - T\xEDnh n\u0103ng \u0111ang ph\xE1t tri\u1EC3n"));
6942
+ console.log(chalk13.yellow("\u26A0\uFE0F Coming Soon - T\xEDnh n\u0103ng \u0111ang ph\xE1t tri\u1EC3n"));
6893
6943
  console.log();
6894
- console.log(chalk12.bold("C\xE1c l\u1EC7nh:"));
6895
- console.log(` ${chalk12.cyan("gen")} T\u1EA1o \u1EA3nh t\u1EEB prompt`);
6896
- console.log(` ${chalk12.cyan("list")} Li\u1EC7t k\xEA c\xE1c \u1EA3nh \u0111\xE3 t\u1EA1o`);
6897
- console.log(` ${chalk12.cyan("info")} Xem th\xF4ng tin \u1EA3nh`);
6898
- console.log(` ${chalk12.cyan("delete")} X\xF3a \u1EA3nh`);
6944
+ console.log(chalk13.bold("C\xE1c l\u1EC7nh:"));
6945
+ console.log(` ${chalk13.cyan("gen")} T\u1EA1o \u1EA3nh t\u1EEB prompt`);
6946
+ console.log(` ${chalk13.cyan("list")} Li\u1EC7t k\xEA c\xE1c \u1EA3nh \u0111\xE3 t\u1EA1o`);
6947
+ console.log(` ${chalk13.cyan("info")} Xem th\xF4ng tin \u1EA3nh`);
6948
+ console.log(` ${chalk13.cyan("delete")} X\xF3a \u1EA3nh`);
6899
6949
  console.log();
6900
- console.log(chalk12.bold("V\xED d\u1EE5:"));
6901
- console.log(chalk12.dim(' $ jai1 image gen "a cute cat"'));
6902
- console.log(chalk12.dim(" $ jai1 image list"));
6903
- console.log(chalk12.dim(" $ jai1 image info <image-id>"));
6950
+ console.log(chalk13.bold("V\xED d\u1EE5:"));
6951
+ console.log(chalk13.dim(' $ jai1 image gen "a cute cat"'));
6952
+ console.log(chalk13.dim(" $ jai1 image list"));
6953
+ console.log(chalk13.dim(" $ jai1 image info <image-id>"));
6904
6954
  console.log();
6905
- console.log(chalk12.dim('Ch\u1EA1y "jai1 image <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
6955
+ console.log(chalk13.dim('Ch\u1EA1y "jai1 image <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
6906
6956
  }
6907
6957
  function createImageCommand() {
6908
- const cmd = new Command22("image").description("Image generation commands (Coming Soon)").action(() => {
6958
+ const cmd = new Command23("image").description("Image generation commands (Coming Soon)").action(() => {
6909
6959
  showImageHelp();
6910
6960
  });
6911
6961
  cmd.addCommand(createImageGenCommand());
@@ -6916,7 +6966,7 @@ function createImageCommand() {
6916
6966
  }
6917
6967
 
6918
6968
  // src/commands/feedback.ts
6919
- import { Command as Command23 } from "commander";
6969
+ import { Command as Command24 } from "commander";
6920
6970
  import { select as select2, input, confirm as confirm5 } from "@inquirer/prompts";
6921
6971
  import os from "os";
6922
6972
  import { promises as fs13 } from "fs";
@@ -7125,21 +7175,21 @@ async function handleFeedbackCommand(options) {
7125
7175
  }
7126
7176
  }
7127
7177
  function createFeedbackCommand() {
7128
- const cmd = new Command23("feedback").alias("report").description("Submit bug reports, feature requests, or suggestions").option("--type <type>", "Feedback type: bug, feature, suggestion").option("--title <title>", "Feedback title (max 200 chars)").option("--message <message>", "Feedback message (max 4000 chars)").option("--context <json>", "Additional context as JSON").option("--no-context", "Do not include automatic context").option("--json", "Output JSON format").action(async (options) => {
7178
+ const cmd = new Command24("feedback").alias("report").description("Submit bug reports, feature requests, or suggestions").option("--type <type>", "Feedback type: bug, feature, suggestion").option("--title <title>", "Feedback title (max 200 chars)").option("--message <message>", "Feedback message (max 4000 chars)").option("--context <json>", "Additional context as JSON").option("--no-context", "Do not include automatic context").option("--json", "Output JSON format").action(async (options) => {
7129
7179
  await handleFeedbackCommand(options);
7130
7180
  });
7131
7181
  return cmd;
7132
7182
  }
7133
7183
 
7134
7184
  // src/commands/client-info.ts
7135
- import { Command as Command24 } from "commander";
7185
+ import { Command as Command25 } from "commander";
7136
7186
  import { confirm as confirm6 } from "@inquirer/prompts";
7137
7187
  import os2 from "os";
7138
7188
  import { promises as fs14 } from "fs";
7139
7189
  import { basename as basename2, join as join8 } from "path";
7140
7190
  import { version as nodeVersion2 } from "process";
7141
7191
  function createClientInfoCommand() {
7142
- const cmd = new Command24("client-info").description("T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n jai1").option("--json", "Output as JSON").option("--full", "Include component list (top 20)").option("--submit", "Submit client info to Jai1 feedback endpoint").option("--message <text>", "Additional message when submitting").option("--show-paths", "Include full project path").action(async (options) => {
7192
+ const cmd = new Command25("client-info").description("T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n jai1").option("--json", "Output as JSON").option("--full", "Include component list (top 20)").option("--submit", "Submit client info to Jai1 feedback endpoint").option("--message <text>", "Additional message when submitting").option("--show-paths", "Include full project path").action(async (options) => {
7143
7193
  await handleClientInfo(options);
7144
7194
  });
7145
7195
  return cmd;
@@ -7402,15 +7452,15 @@ async function confirmSubmit(summary, jsonMode) {
7402
7452
  }
7403
7453
 
7404
7454
  // src/commands/errors/index.ts
7405
- import { Command as Command28 } from "commander";
7406
- import chalk14 from "chalk";
7455
+ import { Command as Command29 } from "commander";
7456
+ import chalk15 from "chalk";
7407
7457
 
7408
7458
  // src/commands/errors/list.ts
7409
- import { Command as Command25 } from "commander";
7410
- import chalk13 from "chalk";
7459
+ import { Command as Command26 } from "commander";
7460
+ import chalk14 from "chalk";
7411
7461
  import Table3 from "cli-table3";
7412
7462
  function createErrorsListSubcommand() {
7413
- return new Command25("list").description("Danh s\xE1ch error logs").option("--json", "Output JSON format").action(async (options) => {
7463
+ return new Command26("list").description("Danh s\xE1ch error logs").option("--json", "Output JSON format").action(async (options) => {
7414
7464
  const service = new ErrorLogService();
7415
7465
  const paths = await service.list();
7416
7466
  if (paths.length === 0) {
@@ -7444,7 +7494,7 @@ function createErrorsListSubcommand() {
7444
7494
  });
7445
7495
  for (const log of logs) {
7446
7496
  table.push([
7447
- chalk13.cyan(log.id),
7497
+ chalk14.cyan(log.id),
7448
7498
  log.timestamp || "-",
7449
7499
  log.command || "-",
7450
7500
  log.message || "-"
@@ -7455,9 +7505,9 @@ function createErrorsListSubcommand() {
7455
7505
  }
7456
7506
 
7457
7507
  // src/commands/errors/show.ts
7458
- import { Command as Command26 } from "commander";
7508
+ import { Command as Command27 } from "commander";
7459
7509
  function createErrorsShowSubcommand() {
7460
- return new Command26("show").description("Xem chi ti\u1EBFt error log").argument("[id]", "Error log id (default: latest)").option("--json", "Output JSON format").action(async (id, options) => {
7510
+ return new Command27("show").description("Xem chi ti\u1EBFt error log").argument("[id]", "Error log id (default: latest)").option("--json", "Output JSON format").action(async (id, options) => {
7461
7511
  const service = new ErrorLogService();
7462
7512
  const paths = await service.list();
7463
7513
  if (paths.length === 0) {
@@ -7484,10 +7534,10 @@ function createErrorsShowSubcommand() {
7484
7534
  }
7485
7535
 
7486
7536
  // src/commands/errors/clear.ts
7487
- import { Command as Command27 } from "commander";
7537
+ import { Command as Command28 } from "commander";
7488
7538
  import { confirm as confirm7 } from "@inquirer/prompts";
7489
7539
  function createErrorsClearSubcommand() {
7490
- return new Command27("clear").description("Xo\xE1 error logs").option("--all", "Delete all error logs").option("--id <id>", "Delete one error log by id").option("-y, --yes", "Skip confirmation").action(async (options) => {
7540
+ return new Command28("clear").description("Xo\xE1 error logs").option("--all", "Delete all error logs").option("--id <id>", "Delete one error log by id").option("-y, --yes", "Skip confirmation").action(async (options) => {
7491
7541
  const service = new ErrorLogService();
7492
7542
  const paths = await service.list();
7493
7543
  if (paths.length === 0) {
@@ -7523,22 +7573,22 @@ function createErrorsClearSubcommand() {
7523
7573
 
7524
7574
  // src/commands/errors/index.ts
7525
7575
  function showErrorsHelp() {
7526
- console.log(chalk14.bold.cyan("\u{1F9FE} jai1 errors") + chalk14.dim(" - Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9"));
7576
+ console.log(chalk15.bold.cyan("\u{1F9FE} jai1 errors") + chalk15.dim(" - Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9"));
7527
7577
  console.log();
7528
- console.log(chalk14.bold("C\xE1c l\u1EC7nh:"));
7529
- console.log(` ${chalk14.cyan("list")} Danh s\xE1ch error logs`);
7530
- console.log(` ${chalk14.cyan("show")} Xem chi ti\u1EBFt error log`);
7531
- console.log(` ${chalk14.cyan("clear")} Xo\xE1 error logs`);
7578
+ console.log(chalk15.bold("C\xE1c l\u1EC7nh:"));
7579
+ console.log(` ${chalk15.cyan("list")} Danh s\xE1ch error logs`);
7580
+ console.log(` ${chalk15.cyan("show")} Xem chi ti\u1EBFt error log`);
7581
+ console.log(` ${chalk15.cyan("clear")} Xo\xE1 error logs`);
7532
7582
  console.log();
7533
- console.log(chalk14.bold("V\xED d\u1EE5:"));
7534
- console.log(chalk14.dim(" $ jai1 errors list"));
7535
- console.log(chalk14.dim(" $ jai1 errors show <id>"));
7536
- console.log(chalk14.dim(" $ jai1 errors clear --all"));
7583
+ console.log(chalk15.bold("V\xED d\u1EE5:"));
7584
+ console.log(chalk15.dim(" $ jai1 errors list"));
7585
+ console.log(chalk15.dim(" $ jai1 errors show <id>"));
7586
+ console.log(chalk15.dim(" $ jai1 errors clear --all"));
7537
7587
  console.log();
7538
- console.log(chalk14.dim('Ch\u1EA1y "jai1 errors <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
7588
+ console.log(chalk15.dim('Ch\u1EA1y "jai1 errors <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
7539
7589
  }
7540
7590
  function createErrorsCommand() {
7541
- const errorsCommand = new Command28("errors").description("Manage local error logs").action(() => {
7591
+ const errorsCommand = new Command29("errors").description("Manage local error logs").action(() => {
7542
7592
  showErrorsHelp();
7543
7593
  });
7544
7594
  errorsCommand.addCommand(createErrorsListSubcommand());
@@ -7548,11 +7598,11 @@ function createErrorsCommand() {
7548
7598
  }
7549
7599
 
7550
7600
  // src/commands/utils/index.ts
7551
- import { Command as Command42 } from "commander";
7552
- import chalk15 from "chalk";
7601
+ import { Command as Command43 } from "commander";
7602
+ import chalk16 from "chalk";
7553
7603
 
7554
7604
  // src/commands/utils/password.ts
7555
- import { Command as Command29 } from "commander";
7605
+ import { Command as Command30 } from "commander";
7556
7606
 
7557
7607
  // src/services/utils.service.ts
7558
7608
  import crypto2 from "crypto";
@@ -7821,7 +7871,7 @@ async function handlePasswordGeneration(options) {
7821
7871
  }
7822
7872
  }
7823
7873
  function createPasswordCommand() {
7824
- const cmd = new Command29("password").description("Generate secure random password").option("-l, --length <number>", "Password length", "16").option("--no-lowercase", "Exclude lowercase letters").option("--no-uppercase", "Exclude uppercase letters").option("--no-digits", "Exclude digits").option("--no-symbols", "Exclude symbols").option("--symbol-chars <chars>", "Custom symbol characters").option("-c, --count <number>", "Number of passwords to generate", "1").addHelpText("after", `
7874
+ const cmd = new Command30("password").description("Generate secure random password").option("-l, --length <number>", "Password length", "16").option("--no-lowercase", "Exclude lowercase letters").option("--no-uppercase", "Exclude uppercase letters").option("--no-digits", "Exclude digits").option("--no-symbols", "Exclude symbols").option("--symbol-chars <chars>", "Custom symbol characters").option("-c, --count <number>", "Number of passwords to generate", "1").addHelpText("after", `
7825
7875
  Examples:
7826
7876
  $ jai1 utils password
7827
7877
  $ jai1 utils password --length 24
@@ -7839,7 +7889,7 @@ Examples:
7839
7889
  }
7840
7890
 
7841
7891
  // src/commands/utils/uuid.ts
7842
- import { Command as Command30 } from "commander";
7892
+ import { Command as Command31 } from "commander";
7843
7893
  async function handleUuidGeneration(options) {
7844
7894
  const service = new UtilsService();
7845
7895
  try {
@@ -7867,7 +7917,7 @@ async function handleUuidGeneration(options) {
7867
7917
  }
7868
7918
  }
7869
7919
  function createUuidCommand() {
7870
- const cmd = new Command30("uuid").description("Generate UUID v4 identifier").option("-c, --count <number>", "Number of UUIDs to generate", "1").option("--uppercase", "Output in uppercase").option("--no-hyphens", "Remove hyphens from output").addHelpText("after", `
7920
+ const cmd = new Command31("uuid").description("Generate UUID v4 identifier").option("-c, --count <number>", "Number of UUIDs to generate", "1").option("--uppercase", "Output in uppercase").option("--no-hyphens", "Remove hyphens from output").addHelpText("after", `
7871
7921
  Examples:
7872
7922
  $ jai1 utils uuid
7873
7923
  $ jai1 utils uuid --count 10
@@ -7884,7 +7934,7 @@ Examples:
7884
7934
  }
7885
7935
 
7886
7936
  // src/commands/utils/hash.ts
7887
- import { Command as Command31 } from "commander";
7937
+ import { Command as Command32 } from "commander";
7888
7938
  async function handleHashGeneration(input5, options) {
7889
7939
  const service = new UtilsService();
7890
7940
  try {
@@ -7924,7 +7974,7 @@ async function handleHashGeneration(input5, options) {
7924
7974
  }
7925
7975
  }
7926
7976
  function createHashCommand() {
7927
- const cmd = new Command31("hash").description("Generate hash (MD5, SHA, bcrypt)").argument("[input]", "Text to hash").option(
7977
+ const cmd = new Command32("hash").description("Generate hash (MD5, SHA, bcrypt)").argument("[input]", "Text to hash").option(
7928
7978
  "-a, --algorithm <algorithm>",
7929
7979
  "Hash algorithm (md5, sha1, sha256, sha512, bcrypt)",
7930
7980
  "sha256"
@@ -7946,7 +7996,7 @@ Examples:
7946
7996
  }
7947
7997
 
7948
7998
  // src/commands/utils/base64-encode.ts
7949
- import { Command as Command32 } from "commander";
7999
+ import { Command as Command33 } from "commander";
7950
8000
  import { readFile as readFile2 } from "fs/promises";
7951
8001
  async function handleBase64Encode(input5, options) {
7952
8002
  const service = new UtilsService();
@@ -7979,7 +8029,7 @@ async function handleBase64Encode(input5, options) {
7979
8029
  }
7980
8030
  }
7981
8031
  function createBase64EncodeCommand() {
7982
- const cmd = new Command32("base64-encode").description("Encode text or file to Base64").argument("[input]", "Text to encode").option("-f, --file <path>", "Encode file contents").option("--url-safe", "Use URL-safe Base64 encoding").addHelpText("after", `
8032
+ const cmd = new Command33("base64-encode").description("Encode text or file to Base64").argument("[input]", "Text to encode").option("-f, --file <path>", "Encode file contents").option("--url-safe", "Use URL-safe Base64 encoding").addHelpText("after", `
7983
8033
  Examples:
7984
8034
  $ jai1 utils base64-encode "hello world"
7985
8035
  $ jai1 utils base64-encode "hello world" --url-safe
@@ -7992,7 +8042,7 @@ Examples:
7992
8042
  }
7993
8043
 
7994
8044
  // src/commands/utils/base64-decode.ts
7995
- import { Command as Command33 } from "commander";
8045
+ import { Command as Command34 } from "commander";
7996
8046
  import { readFile as readFile3, writeFile } from "fs/promises";
7997
8047
  async function handleBase64Decode(input5, options) {
7998
8048
  const service = new UtilsService();
@@ -8024,7 +8074,7 @@ async function handleBase64Decode(input5, options) {
8024
8074
  }
8025
8075
  }
8026
8076
  function createBase64DecodeCommand() {
8027
- const cmd = new Command33("base64-decode").description("Decode Base64 string").argument("[input]", "Base64 string to decode").option("-f, --file <path>", "Decode from file").option("-o, --output <path>", "Write decoded output to file").addHelpText("after", `
8077
+ const cmd = new Command34("base64-decode").description("Decode Base64 string").argument("[input]", "Base64 string to decode").option("-f, --file <path>", "Decode from file").option("-o, --output <path>", "Write decoded output to file").addHelpText("after", `
8028
8078
  Examples:
8029
8079
  $ jai1 utils base64-decode "aGVsbG8gd29ybGQ="
8030
8080
  $ jai1 utils base64-decode --file ./encoded.txt
@@ -8037,7 +8087,7 @@ Examples:
8037
8087
  }
8038
8088
 
8039
8089
  // src/commands/utils/http.ts
8040
- import { Command as Command34 } from "commander";
8090
+ import { Command as Command35 } from "commander";
8041
8091
  import { readFile as readFile4 } from "fs/promises";
8042
8092
  async function handleHttpRequest(url, options) {
8043
8093
  const service = new UtilsService();
@@ -8103,7 +8153,7 @@ async function handleHttpRequest(url, options) {
8103
8153
  }
8104
8154
  }
8105
8155
  function createHttpCommand() {
8106
- const cmd = new Command34("http").description("Make HTTP request with formatted output").argument("<url>", "Target URL").option("-X, --method <method>", "HTTP method", "GET").option("-H, --header <header...>", "Request headers (repeatable)").option("-d, --data <data>", "Request body (JSON string)").option("--file <path>", "Read body from file").option("--timeout <ms>", "Request timeout in milliseconds", "30000").option("--no-follow", "Do not follow redirects").option("--only-headers", "Show only response headers").option("--only-body", "Show only response body").addHelpText("after", `
8156
+ const cmd = new Command35("http").description("Make HTTP request with formatted output").argument("<url>", "Target URL").option("-X, --method <method>", "HTTP method", "GET").option("-H, --header <header...>", "Request headers (repeatable)").option("-d, --data <data>", "Request body (JSON string)").option("--file <path>", "Read body from file").option("--timeout <ms>", "Request timeout in milliseconds", "30000").option("--no-follow", "Do not follow redirects").option("--only-headers", "Show only response headers").option("--only-body", "Show only response body").addHelpText("after", `
8107
8157
  Examples:
8108
8158
  $ jai1 utils http https://api.example.com/users
8109
8159
  $ jai1 utils http https://api.example.com/users -X POST -d '{"name":"John"}'
@@ -8121,7 +8171,7 @@ Examples:
8121
8171
  }
8122
8172
 
8123
8173
  // src/commands/utils/jwt.ts
8124
- import { Command as Command35 } from "commander";
8174
+ import { Command as Command36 } from "commander";
8125
8175
  async function handleJwtDecode(token) {
8126
8176
  const service = new UtilsService();
8127
8177
  try {
@@ -8160,7 +8210,7 @@ async function handleJwtEncode(options) {
8160
8210
  }
8161
8211
  }
8162
8212
  function createJwtCommand() {
8163
- const jwtCommand = new Command35("jwt").description("Decode and encode JWT tokens");
8213
+ const jwtCommand = new Command36("jwt").description("Decode and encode JWT tokens");
8164
8214
  jwtCommand.command("decode").description("Decode JWT token").argument("<token>", "JWT token to decode").addHelpText("after", `
8165
8215
  Examples:
8166
8216
  $ jai1 utils jwt decode "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
@@ -8181,7 +8231,7 @@ Examples:
8181
8231
  }
8182
8232
 
8183
8233
  // src/commands/utils/unix-time.ts
8184
- import { Command as Command36 } from "commander";
8234
+ import { Command as Command37 } from "commander";
8185
8235
  async function handleUnixTime(input5, options) {
8186
8236
  const service = new UtilsService();
8187
8237
  try {
@@ -8229,7 +8279,7 @@ async function handleUnixTime(input5, options) {
8229
8279
  }
8230
8280
  }
8231
8281
  function createUnixTimeCommand() {
8232
- const cmd = new Command36("unix-time").description("Convert unix timestamps to/from dates").argument("[input]", "Unix timestamp or date string").option("-f, --format <format>", "Output format (iso, local, utc)", "iso").option("--ms", "Use milliseconds instead of seconds").addHelpText("after", `
8282
+ const cmd = new Command37("unix-time").description("Convert unix timestamps to/from dates").argument("[input]", "Unix timestamp or date string").option("-f, --format <format>", "Output format (iso, local, utc)", "iso").option("--ms", "Use milliseconds instead of seconds").addHelpText("after", `
8233
8283
  Examples:
8234
8284
  $ jai1 utils unix-time
8235
8285
  $ jai1 utils unix-time 1702550400
@@ -8244,7 +8294,7 @@ Examples:
8244
8294
  }
8245
8295
 
8246
8296
  // src/commands/utils/timezone.ts
8247
- import { Command as Command37 } from "commander";
8297
+ import { Command as Command38 } from "commander";
8248
8298
  async function handleTimezoneConversion(time, options) {
8249
8299
  const service = new UtilsService();
8250
8300
  try {
@@ -8281,7 +8331,7 @@ async function handleTimezoneConversion(time, options) {
8281
8331
  }
8282
8332
  }
8283
8333
  function createTimezoneCommand() {
8284
- const cmd = new Command37("timezone").description("Convert time between timezones").argument("[time]", 'Time to convert (e.g., "2024-01-15 10:00")').option("--from <timezone>", "Source timezone").option("--to <timezone>", "Target timezone").option("--list", "Show available timezones").addHelpText("after", `
8334
+ const cmd = new Command38("timezone").description("Convert time between timezones").argument("[time]", 'Time to convert (e.g., "2024-01-15 10:00")').option("--from <timezone>", "Source timezone").option("--to <timezone>", "Target timezone").option("--list", "Show available timezones").addHelpText("after", `
8285
8335
  Examples:
8286
8336
  $ jai1 utils timezone --list
8287
8337
  $ jai1 utils timezone "2024-01-15 10:00" --from "America/New_York" --to "Asia/Tokyo"
@@ -8294,7 +8344,7 @@ Examples:
8294
8344
  }
8295
8345
 
8296
8346
  // src/commands/utils/url-encode.ts
8297
- import { Command as Command38 } from "commander";
8347
+ import { Command as Command39 } from "commander";
8298
8348
  async function handleUrlEncode(input5, options) {
8299
8349
  const service = new UtilsService();
8300
8350
  try {
@@ -8315,7 +8365,7 @@ async function handleUrlEncode(input5, options) {
8315
8365
  }
8316
8366
  }
8317
8367
  function createUrlEncodeCommand() {
8318
- const cmd = new Command38("url-encode").description("Encode URL component or full URL").argument("<input>", "Text to encode").option("--full", "Encode full URL (use encodeURI instead of encodeURIComponent)").addHelpText("after", `
8368
+ const cmd = new Command39("url-encode").description("Encode URL component or full URL").argument("<input>", "Text to encode").option("--full", "Encode full URL (use encodeURI instead of encodeURIComponent)").addHelpText("after", `
8319
8369
  Examples:
8320
8370
  $ jai1 utils url-encode "hello world"
8321
8371
  $ jai1 utils url-encode "hello world & test"
@@ -8328,7 +8378,7 @@ Examples:
8328
8378
  }
8329
8379
 
8330
8380
  // src/commands/utils/url-decode.ts
8331
- import { Command as Command39 } from "commander";
8381
+ import { Command as Command40 } from "commander";
8332
8382
  async function handleUrlDecode(input5, options) {
8333
8383
  const service = new UtilsService();
8334
8384
  try {
@@ -8349,7 +8399,7 @@ async function handleUrlDecode(input5, options) {
8349
8399
  }
8350
8400
  }
8351
8401
  function createUrlDecodeCommand() {
8352
- const cmd = new Command39("url-decode").description("Decode URL-encoded string").argument("<input>", "Text to decode").option("--full", "Decode full URL (use decodeURI instead of decodeURIComponent)").addHelpText("after", `
8402
+ const cmd = new Command40("url-decode").description("Decode URL-encoded string").argument("<input>", "Text to decode").option("--full", "Decode full URL (use decodeURI instead of decodeURIComponent)").addHelpText("after", `
8353
8403
  Examples:
8354
8404
  $ jai1 utils url-decode "hello%20world"
8355
8405
  $ jai1 utils url-decode "hello%20world%20%26%20test"
@@ -8362,7 +8412,7 @@ Examples:
8362
8412
  }
8363
8413
 
8364
8414
  // src/commands/utils/cron.ts
8365
- import { Command as Command40 } from "commander";
8415
+ import { Command as Command41 } from "commander";
8366
8416
  import cronstrue from "cronstrue";
8367
8417
  async function handleCronParse(expression) {
8368
8418
  try {
@@ -8405,7 +8455,7 @@ async function handleCronParse(expression) {
8405
8455
  }
8406
8456
  }
8407
8457
  function createCronCommand() {
8408
- const cmd = new Command40("cron").description("Parse and explain cron expression").argument("<expression>", 'Cron expression (e.g., "0 5 * * *")').addHelpText("after", `
8458
+ const cmd = new Command41("cron").description("Parse and explain cron expression").argument("<expression>", 'Cron expression (e.g., "0 5 * * *")').addHelpText("after", `
8409
8459
  Examples:
8410
8460
  $ jai1 utils cron "0 5 * * *"
8411
8461
  $ jai1 utils cron "*/15 * * * *"
@@ -8419,7 +8469,7 @@ Examples:
8419
8469
  }
8420
8470
 
8421
8471
  // src/commands/utils/markdown-preview.ts
8422
- import { Command as Command41 } from "commander";
8472
+ import { Command as Command42 } from "commander";
8423
8473
  import { readFile as readFile5 } from "fs/promises";
8424
8474
  import { marked } from "marked";
8425
8475
  import TerminalRenderer from "marked-terminal";
@@ -8458,7 +8508,7 @@ ${code.trim()}
8458
8508
  }
8459
8509
  }
8460
8510
  function createMarkdownPreviewCommand() {
8461
- const cmd = new Command41("markdown-preview").description("Preview markdown file in terminal").argument("<file>", "Markdown file path").option("--raw", "Show raw markdown instead of rendered").addHelpText("after", `
8511
+ const cmd = new Command42("markdown-preview").description("Preview markdown file in terminal").argument("<file>", "Markdown file path").option("--raw", "Show raw markdown instead of rendered").addHelpText("after", `
8462
8512
  Examples:
8463
8513
  $ jai1 utils markdown-preview README.md
8464
8514
  $ jai1 utils markdown-preview ./docs/guide.md
@@ -9867,43 +9917,43 @@ async function runInteractiveMode() {
9867
9917
 
9868
9918
  // src/commands/utils/index.ts
9869
9919
  function showUtilsHelp() {
9870
- console.log(chalk15.bold.cyan("\u{1F6E0}\uFE0F jai1 utils") + chalk15.dim(" - Developer utilities"));
9920
+ console.log(chalk16.bold.cyan("\u{1F6E0}\uFE0F jai1 utils") + chalk16.dim(" - Developer utilities"));
9871
9921
  console.log();
9872
- console.log(chalk15.bold("M\xE3 h\xF3a & B\u1EA3o m\u1EADt:"));
9873
- console.log(` ${chalk15.cyan("password")} T\u1EA1o m\u1EADt kh\u1EA9u ng\u1EABu nhi\xEAn`);
9874
- console.log(` ${chalk15.cyan("uuid")} T\u1EA1o UUID v4`);
9875
- console.log(` ${chalk15.cyan("hash")} Hash text (MD5/SHA/bcrypt)`);
9876
- console.log(` ${chalk15.cyan("jwt")} Decode/encode JWT tokens`);
9922
+ console.log(chalk16.bold("M\xE3 h\xF3a & B\u1EA3o m\u1EADt:"));
9923
+ console.log(` ${chalk16.cyan("password")} T\u1EA1o m\u1EADt kh\u1EA9u ng\u1EABu nhi\xEAn`);
9924
+ console.log(` ${chalk16.cyan("uuid")} T\u1EA1o UUID v4`);
9925
+ console.log(` ${chalk16.cyan("hash")} Hash text (MD5/SHA/bcrypt)`);
9926
+ console.log(` ${chalk16.cyan("jwt")} Decode/encode JWT tokens`);
9877
9927
  console.log();
9878
- console.log(chalk15.bold("Encoding:"));
9879
- console.log(` ${chalk15.cyan("base64-encode")} Encode sang Base64`);
9880
- console.log(` ${chalk15.cyan("base64-decode")} Decode t\u1EEB Base64`);
9881
- console.log(` ${chalk15.cyan("url-encode")} Encode URL components`);
9882
- console.log(` ${chalk15.cyan("url-decode")} Decode URL components`);
9928
+ console.log(chalk16.bold("Encoding:"));
9929
+ console.log(` ${chalk16.cyan("base64-encode")} Encode sang Base64`);
9930
+ console.log(` ${chalk16.cyan("base64-decode")} Decode t\u1EEB Base64`);
9931
+ console.log(` ${chalk16.cyan("url-encode")} Encode URL components`);
9932
+ console.log(` ${chalk16.cyan("url-decode")} Decode URL components`);
9883
9933
  console.log();
9884
- console.log(chalk15.bold("Th\u1EDDi gian:"));
9885
- console.log(` ${chalk15.cyan("unix-time")} Chuy\u1EC3n \u0111\u1ED5i unix timestamp`);
9886
- console.log(` ${chalk15.cyan("timezone")} Chuy\u1EC3n \u0111\u1ED5i m\xFAi gi\u1EDD`);
9887
- console.log(` ${chalk15.cyan("cron")} Parse cron expressions`);
9934
+ console.log(chalk16.bold("Th\u1EDDi gian:"));
9935
+ console.log(` ${chalk16.cyan("unix-time")} Chuy\u1EC3n \u0111\u1ED5i unix timestamp`);
9936
+ console.log(` ${chalk16.cyan("timezone")} Chuy\u1EC3n \u0111\u1ED5i m\xFAi gi\u1EDD`);
9937
+ console.log(` ${chalk16.cyan("cron")} Parse cron expressions`);
9888
9938
  console.log();
9889
- console.log(chalk15.bold("Kh\xE1c:"));
9890
- console.log(` ${chalk15.cyan("http")} G\u1EEDi HTTP requests`);
9891
- console.log(` ${chalk15.cyan("markdown-preview")} Xem tr\u01B0\u1EDBc file markdown`);
9939
+ console.log(chalk16.bold("Kh\xE1c:"));
9940
+ console.log(` ${chalk16.cyan("http")} G\u1EEDi HTTP requests`);
9941
+ console.log(` ${chalk16.cyan("markdown-preview")} Xem tr\u01B0\u1EDBc file markdown`);
9892
9942
  console.log();
9893
- console.log(chalk15.bold("Ch\u1EBF \u0111\u1ED9 Interactive:"));
9894
- console.log(chalk15.dim(" $ jai1 utils -i"));
9895
- console.log(chalk15.dim(" $ jai1 utils --interactive"));
9943
+ console.log(chalk16.bold("Ch\u1EBF \u0111\u1ED9 Interactive:"));
9944
+ console.log(chalk16.dim(" $ jai1 utils -i"));
9945
+ console.log(chalk16.dim(" $ jai1 utils --interactive"));
9896
9946
  console.log();
9897
- console.log(chalk15.bold("V\xED d\u1EE5:"));
9898
- console.log(chalk15.dim(" $ jai1 utils password --length 24"));
9899
- console.log(chalk15.dim(" $ jai1 utils uuid --count 5"));
9900
- console.log(chalk15.dim(' $ jai1 utils hash "text" --algorithm sha256'));
9901
- console.log(chalk15.dim(" $ jai1 utils http https://api.example.com"));
9947
+ console.log(chalk16.bold("V\xED d\u1EE5:"));
9948
+ console.log(chalk16.dim(" $ jai1 utils password --length 24"));
9949
+ console.log(chalk16.dim(" $ jai1 utils uuid --count 5"));
9950
+ console.log(chalk16.dim(' $ jai1 utils hash "text" --algorithm sha256'));
9951
+ console.log(chalk16.dim(" $ jai1 utils http https://api.example.com"));
9902
9952
  console.log();
9903
- console.log(chalk15.dim('Ch\u1EA1y "jai1 utils <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
9953
+ console.log(chalk16.dim('Ch\u1EA1y "jai1 utils <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
9904
9954
  }
9905
9955
  function createUtilsCommand() {
9906
- const utilsCommand = new Command42("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode");
9956
+ const utilsCommand = new Command43("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode");
9907
9957
  utilsCommand.addCommand(createPasswordCommand());
9908
9958
  utilsCommand.addCommand(createUuidCommand());
9909
9959
  utilsCommand.addCommand(createHashCommand());
@@ -9928,12 +9978,12 @@ function createUtilsCommand() {
9928
9978
  }
9929
9979
 
9930
9980
  // src/commands/deps/index.ts
9931
- import { Command as Command45 } from "commander";
9932
- import chalk18 from "chalk";
9981
+ import { Command as Command46 } from "commander";
9982
+ import chalk19 from "chalk";
9933
9983
 
9934
9984
  // src/commands/deps/check.ts
9935
- import { Command as Command43 } from "commander";
9936
- import chalk16 from "chalk";
9985
+ import { Command as Command44 } from "commander";
9986
+ import chalk17 from "chalk";
9937
9987
  import Table4 from "cli-table3";
9938
9988
  import ora from "ora";
9939
9989
 
@@ -10528,7 +10578,7 @@ var DepsPythonService = class {
10528
10578
 
10529
10579
  // src/commands/deps/check.ts
10530
10580
  function createDepsCheckCommand() {
10531
- const checkCommand = new Command43("check").description("Ki\u1EC3m tra c\xE1c packages c\u1EA7n upgrade").action(async () => {
10581
+ const checkCommand = new Command44("check").description("Ki\u1EC3m tra c\xE1c packages c\u1EA7n upgrade").action(async () => {
10532
10582
  const cwd = process.cwd();
10533
10583
  const detector = new DepsDetectorService();
10534
10584
  const spinner = ora("\u0110ang ph\xE1t hi\u1EC7n lo\u1EA1i project...").start();
@@ -10536,7 +10586,7 @@ function createDepsCheckCommand() {
10536
10586
  if (projects.length === 0) {
10537
10587
  spinner.fail("Kh\xF4ng t\xECm th\u1EA5y project n\xE0o \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3");
10538
10588
  console.log();
10539
- console.log(chalk16.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
10589
+ console.log(chalk17.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
10540
10590
  process.exit(1);
10541
10591
  }
10542
10592
  spinner.succeed(`Ph\xE1t hi\u1EC7n ${projects.length} project:`);
@@ -10550,7 +10600,7 @@ function createDepsCheckCommand() {
10550
10600
  await checkEcosystem(project.ecosystem, project.manager, cwd);
10551
10601
  }
10552
10602
  console.log();
10553
- console.log(chalk16.dim('\u{1F4A1} Ch\u1EA1y "jai1 deps upgrade" \u0111\u1EC3 n\xE2ng c\u1EA5p packages.'));
10603
+ console.log(chalk17.dim('\u{1F4A1} Ch\u1EA1y "jai1 deps upgrade" \u0111\u1EC3 n\xE2ng c\u1EA5p packages.'));
10554
10604
  });
10555
10605
  return checkCommand;
10556
10606
  }
@@ -10583,7 +10633,7 @@ async function checkEcosystem(ecosystem, manager, cwd) {
10583
10633
  });
10584
10634
  } catch (error) {
10585
10635
  spinner.fail(`L\u1ED7i ki\u1EC3m tra ${label}`);
10586
- console.log(chalk16.red(error.message));
10636
+ console.log(chalk17.red(error.message));
10587
10637
  console.log();
10588
10638
  return;
10589
10639
  }
@@ -10596,10 +10646,10 @@ async function checkEcosystem(ecosystem, manager, cwd) {
10596
10646
  console.log();
10597
10647
  const table = new Table4({
10598
10648
  head: [
10599
- chalk16.cyan("Package"),
10600
- chalk16.cyan("Hi\u1EC7n t\u1EA1i"),
10601
- chalk16.cyan("M\u1EDBi nh\u1EA5t"),
10602
- chalk16.cyan("Lo\u1EA1i")
10649
+ chalk17.cyan("Package"),
10650
+ chalk17.cyan("Hi\u1EC7n t\u1EA1i"),
10651
+ chalk17.cyan("M\u1EDBi nh\u1EA5t"),
10652
+ chalk17.cyan("Lo\u1EA1i")
10603
10653
  ],
10604
10654
  style: {
10605
10655
  head: [],
@@ -10610,9 +10660,9 @@ async function checkEcosystem(ecosystem, manager, cwd) {
10610
10660
  const upgradeIcon = pkg.upgradeType === "major" ? "\u{1F534}" : pkg.upgradeType === "minor" ? "\u{1F7E1}" : "\u{1F7E2}";
10611
10661
  table.push([
10612
10662
  `${upgradeIcon} ${pkg.name}`,
10613
- chalk16.dim(pkg.current),
10614
- chalk16.green(pkg.latest),
10615
- pkg.type === "dev" ? chalk16.dim("dev") : "dep"
10663
+ chalk17.dim(pkg.current),
10664
+ chalk17.green(pkg.latest),
10665
+ pkg.type === "dev" ? chalk17.dim("dev") : "dep"
10616
10666
  ]);
10617
10667
  }
10618
10668
  console.log(table.toString());
@@ -10620,26 +10670,26 @@ async function checkEcosystem(ecosystem, manager, cwd) {
10620
10670
  if (result.isLaravel) {
10621
10671
  const blockedPackages = result.packages.filter((p) => p.blockedReason);
10622
10672
  if (blockedPackages.length > 0) {
10623
- console.log(chalk16.yellow("\u26A0\uFE0F Laravel major version upgrades blocked (nguy hi\u1EC3m):"));
10673
+ console.log(chalk17.yellow("\u26A0\uFE0F Laravel major version upgrades blocked (nguy hi\u1EC3m):"));
10624
10674
  for (const pkg of blockedPackages) {
10625
- console.log(chalk16.dim(` - ${pkg.name}: ${pkg.current} \u2192 ${pkg.latest}`));
10675
+ console.log(chalk17.dim(` - ${pkg.name}: ${pkg.current} \u2192 ${pkg.latest}`));
10626
10676
  }
10627
10677
  console.log();
10628
- console.log(chalk16.dim("\u{1F4A1} \u0110\u1EC3 n\xE2ng c\u1EA5p Laravel major version, ch\u1EA1y th\u1EE7 c\xF4ng:"));
10629
- console.log(chalk16.dim(` composer require ${blockedPackages[0].name}:^${blockedPackages[0].latest}`));
10678
+ console.log(chalk17.dim("\u{1F4A1} \u0110\u1EC3 n\xE2ng c\u1EA5p Laravel major version, ch\u1EA1y th\u1EE7 c\xF4ng:"));
10679
+ console.log(chalk17.dim(` composer require ${blockedPackages[0].name}:^${blockedPackages[0].latest}`));
10630
10680
  console.log();
10631
10681
  }
10632
10682
  }
10633
10683
  }
10634
10684
 
10635
10685
  // src/commands/deps/upgrade.ts
10636
- import { Command as Command44 } from "commander";
10686
+ import { Command as Command45 } from "commander";
10637
10687
  import { checkbox as checkbox3, confirm as confirm8 } from "@inquirer/prompts";
10638
- import chalk17 from "chalk";
10688
+ import chalk18 from "chalk";
10639
10689
  import ora2 from "ora";
10640
10690
  import Table5 from "cli-table3";
10641
10691
  function createDepsUpgradeCommand() {
10642
- return new Command44("upgrade").description("Upgrade packages l\xEAn version m\u1EDBi nh\u1EA5t").option("--all", "Upgrade t\u1EA5t c\u1EA3 kh\xF4ng c\u1EA7n ch\u1ECDn").action(async (options) => {
10692
+ return new Command45("upgrade").description("Upgrade packages l\xEAn version m\u1EDBi nh\u1EA5t").option("--all", "Upgrade t\u1EA5t c\u1EA3 kh\xF4ng c\u1EA7n ch\u1ECDn").action(async (options) => {
10643
10693
  await handleDepsUpgrade(options);
10644
10694
  });
10645
10695
  }
@@ -10652,7 +10702,7 @@ async function handleDepsUpgrade(options) {
10652
10702
  if (projects.length === 0) {
10653
10703
  spinner.fail("Kh\xF4ng t\xECm th\u1EA5y project n\xE0o \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3");
10654
10704
  console.log();
10655
- console.log(chalk17.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
10705
+ console.log(chalk18.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
10656
10706
  process.exit(1);
10657
10707
  }
10658
10708
  spinner.succeed(`Ph\xE1t hi\u1EC7n ${projects.length} project:`);
@@ -10666,9 +10716,9 @@ async function handleDepsUpgrade(options) {
10666
10716
  await upgradeEcosystem(project, cwd, options);
10667
10717
  }
10668
10718
  console.log();
10669
- console.log(chalk17.green("\u2705 Ho\xE0n th\xE0nh!"));
10719
+ console.log(chalk18.green("\u2705 Ho\xE0n th\xE0nh!"));
10670
10720
  } catch (error) {
10671
- console.error(chalk17.red(`
10721
+ console.error(chalk18.red(`
10672
10722
  \u274C ${error.message}
10673
10723
  `));
10674
10724
  process.exit(1);
@@ -10677,10 +10727,10 @@ async function handleDepsUpgrade(options) {
10677
10727
  async function upgradeEcosystem(project, cwd, options) {
10678
10728
  const service = getService(project.ecosystem);
10679
10729
  const label = `${getEcosystemIcon(project.ecosystem)} ${getEcosystemLabel(project.ecosystem)}`;
10680
- console.log(chalk17.bold.cyan(`
10730
+ console.log(chalk18.bold.cyan(`
10681
10731
  ${"\u2501".repeat(80)}`));
10682
- console.log(chalk17.bold.cyan(`${label}`));
10683
- console.log(chalk17.bold.cyan("\u2501".repeat(80)));
10732
+ console.log(chalk18.bold.cyan(`${label}`));
10733
+ console.log(chalk18.bold.cyan("\u2501".repeat(80)));
10684
10734
  console.log();
10685
10735
  const spinner = ora2("\u0110ang ki\u1EC3m tra packages...").start();
10686
10736
  let packages;
@@ -10691,7 +10741,7 @@ ${"\u2501".repeat(80)}`));
10691
10741
  packages = result.packages;
10692
10742
  } catch (error) {
10693
10743
  spinner.fail("L\u1ED7i ki\u1EC3m tra packages");
10694
- console.log(chalk17.red(error.message));
10744
+ console.log(chalk18.red(error.message));
10695
10745
  return;
10696
10746
  }
10697
10747
  if (packages.length === 0) {
@@ -10704,7 +10754,7 @@ ${"\u2501".repeat(80)}`));
10704
10754
  let selectedPackages;
10705
10755
  if (options.all) {
10706
10756
  selectedPackages = packages;
10707
- console.log(chalk17.cyan(`\u{1F4CB} \u0110\xE3 ch\u1ECDn t\u1EA5t c\u1EA3 ${selectedPackages.length} packages
10757
+ console.log(chalk18.cyan(`\u{1F4CB} \u0110\xE3 ch\u1ECDn t\u1EA5t c\u1EA3 ${selectedPackages.length} packages
10708
10758
  `));
10709
10759
  } else {
10710
10760
  try {
@@ -10722,12 +10772,12 @@ ${"\u2501".repeat(80)}`));
10722
10772
  theme: checkboxTheme
10723
10773
  });
10724
10774
  if (selected.length === 0) {
10725
- console.log(chalk17.yellow("\u23F8\uFE0F Kh\xF4ng c\xF3 packages n\xE0o \u0111\u01B0\u1EE3c ch\u1ECDn\n"));
10775
+ console.log(chalk18.yellow("\u23F8\uFE0F Kh\xF4ng c\xF3 packages n\xE0o \u0111\u01B0\u1EE3c ch\u1ECDn\n"));
10726
10776
  return;
10727
10777
  }
10728
10778
  selectedPackages = packages.filter((p) => selected.includes(p.name));
10729
10779
  } catch {
10730
- console.log(chalk17.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
10780
+ console.log(chalk18.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
10731
10781
  return;
10732
10782
  }
10733
10783
  }
@@ -10738,35 +10788,35 @@ ${"\u2501".repeat(80)}`));
10738
10788
  default: true
10739
10789
  });
10740
10790
  } catch {
10741
- console.log(chalk17.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
10791
+ console.log(chalk18.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
10742
10792
  return;
10743
10793
  }
10744
10794
  if (!shouldProceed) {
10745
- console.log(chalk17.yellow("\u23F8\uFE0F Upgrade \u0111\xE3 h\u1EE7y\n"));
10795
+ console.log(chalk18.yellow("\u23F8\uFE0F Upgrade \u0111\xE3 h\u1EE7y\n"));
10746
10796
  return;
10747
10797
  }
10748
10798
  console.log();
10749
- console.log(chalk17.cyan(`\u{1F527} Package manager: ${project.manager}`));
10750
- console.log(chalk17.cyan("\u{1F4E5} \u0110ang upgrade...\n"));
10799
+ console.log(chalk18.cyan(`\u{1F527} Package manager: ${project.manager}`));
10800
+ console.log(chalk18.cyan("\u{1F4E5} \u0110ang upgrade...\n"));
10751
10801
  const commands = service.getUpgradeCommands(selectedPackages);
10752
10802
  try {
10753
10803
  if (commands.deps) {
10754
- console.log(chalk17.dim(`$ ${commands.deps}
10804
+ console.log(chalk18.dim(`$ ${commands.deps}
10755
10805
  `));
10756
10806
  }
10757
10807
  if (commands.devDeps) {
10758
- console.log(chalk17.dim(`$ ${commands.devDeps}
10808
+ console.log(chalk18.dim(`$ ${commands.devDeps}
10759
10809
  `));
10760
10810
  }
10761
10811
  await service.upgrade(cwd, { packages: selectedPackages });
10762
- console.log(chalk17.green(`
10812
+ console.log(chalk18.green(`
10763
10813
  \u2705 \u0110\xE3 upgrade ${selectedPackages.length} packages th\xE0nh c\xF4ng!`));
10764
10814
  } catch (error) {
10765
- console.error(chalk17.red("\n\u274C L\u1ED7i khi upgrade:"));
10766
- console.error(chalk17.red(error.message));
10767
- console.log(chalk17.yellow("\n\u{1F4A1} B\u1EA1n c\xF3 th\u1EC3 th\u1EED upgrade th\u1EE7 c\xF4ng:"));
10768
- if (commands.deps) console.log(chalk17.cyan(` ${commands.deps}`));
10769
- if (commands.devDeps) console.log(chalk17.cyan(` ${commands.devDeps}`));
10815
+ console.error(chalk18.red("\n\u274C L\u1ED7i khi upgrade:"));
10816
+ console.error(chalk18.red(error.message));
10817
+ console.log(chalk18.yellow("\n\u{1F4A1} B\u1EA1n c\xF3 th\u1EC3 th\u1EED upgrade th\u1EE7 c\xF4ng:"));
10818
+ if (commands.deps) console.log(chalk18.cyan(` ${commands.deps}`));
10819
+ if (commands.devDeps) console.log(chalk18.cyan(` ${commands.devDeps}`));
10770
10820
  console.log();
10771
10821
  throw error;
10772
10822
  }
@@ -10774,10 +10824,10 @@ ${"\u2501".repeat(80)}`));
10774
10824
  function displayUpgradeTable(packages) {
10775
10825
  const table = new Table5({
10776
10826
  head: [
10777
- chalk17.cyan("Package"),
10778
- chalk17.cyan("Hi\u1EC7n t\u1EA1i"),
10779
- chalk17.cyan("M\u1EDBi nh\u1EA5t"),
10780
- chalk17.cyan("Lo\u1EA1i")
10827
+ chalk18.cyan("Package"),
10828
+ chalk18.cyan("Hi\u1EC7n t\u1EA1i"),
10829
+ chalk18.cyan("M\u1EDBi nh\u1EA5t"),
10830
+ chalk18.cyan("Lo\u1EA1i")
10781
10831
  ],
10782
10832
  style: {
10783
10833
  head: [],
@@ -10788,9 +10838,9 @@ function displayUpgradeTable(packages) {
10788
10838
  const upgradeIcon = pkg.upgradeType === "major" ? "\u{1F534}" : pkg.upgradeType === "minor" ? "\u{1F7E1}" : "\u{1F7E2}";
10789
10839
  table.push([
10790
10840
  `${upgradeIcon} ${pkg.name}`,
10791
- chalk17.dim(pkg.current),
10792
- chalk17.green(pkg.latest),
10793
- pkg.type === "dev" ? chalk17.dim("dev") : "dep"
10841
+ chalk18.dim(pkg.current),
10842
+ chalk18.green(pkg.latest),
10843
+ pkg.type === "dev" ? chalk18.dim("dev") : "dep"
10794
10844
  ]);
10795
10845
  }
10796
10846
  console.log(table.toString());
@@ -10833,26 +10883,26 @@ function getEcosystemLabel(ecosystem) {
10833
10883
 
10834
10884
  // src/commands/deps/index.ts
10835
10885
  function showDepsHelp() {
10836
- console.log(chalk18.bold.cyan("\u{1F4E6} jai1 deps") + chalk18.dim(" - Qu\u1EA3n l\xFD dependencies trong project"));
10886
+ console.log(chalk19.bold.cyan("\u{1F4E6} jai1 deps") + chalk19.dim(" - Qu\u1EA3n l\xFD dependencies trong project"));
10837
10887
  console.log();
10838
- console.log(chalk18.bold("C\xE1c l\u1EC7nh:"));
10839
- console.log(` ${chalk18.cyan("check")} Ki\u1EC3m tra c\xE1c packages c\u1EA7n upgrade`);
10840
- console.log(` ${chalk18.cyan("upgrade")} N\xE2ng c\u1EA5p dependencies l\xEAn phi\xEAn b\u1EA3n m\u1EDBi nh\u1EA5t`);
10888
+ console.log(chalk19.bold("C\xE1c l\u1EC7nh:"));
10889
+ console.log(` ${chalk19.cyan("check")} Ki\u1EC3m tra c\xE1c packages c\u1EA7n upgrade`);
10890
+ console.log(` ${chalk19.cyan("upgrade")} N\xE2ng c\u1EA5p dependencies l\xEAn phi\xEAn b\u1EA3n m\u1EDBi nh\u1EA5t`);
10841
10891
  console.log();
10842
- console.log(chalk18.bold("H\u1ED7 tr\u1EE3:"));
10843
- console.log(chalk18.dim(" \u2022 Node.js (npm, pnpm, yarn, bun)"));
10844
- console.log(chalk18.dim(" \u2022 PHP/Composer (v\u1EDBi b\u1EA3o v\u1EC7 Laravel major version)"));
10845
- console.log(chalk18.dim(" \u2022 Python (pip, pipenv)"));
10892
+ console.log(chalk19.bold("H\u1ED7 tr\u1EE3:"));
10893
+ console.log(chalk19.dim(" \u2022 Node.js (npm, pnpm, yarn, bun)"));
10894
+ console.log(chalk19.dim(" \u2022 PHP/Composer (v\u1EDBi b\u1EA3o v\u1EC7 Laravel major version)"));
10895
+ console.log(chalk19.dim(" \u2022 Python (pip, pipenv)"));
10846
10896
  console.log();
10847
- console.log(chalk18.bold("V\xED d\u1EE5:"));
10848
- console.log(chalk18.dim(" $ jai1 deps check"));
10849
- console.log(chalk18.dim(" $ jai1 deps upgrade"));
10850
- console.log(chalk18.dim(" $ jai1 deps upgrade --all"));
10897
+ console.log(chalk19.bold("V\xED d\u1EE5:"));
10898
+ console.log(chalk19.dim(" $ jai1 deps check"));
10899
+ console.log(chalk19.dim(" $ jai1 deps upgrade"));
10900
+ console.log(chalk19.dim(" $ jai1 deps upgrade --all"));
10851
10901
  console.log();
10852
- console.log(chalk18.dim('Ch\u1EA1y "jai1 deps <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
10902
+ console.log(chalk19.dim('Ch\u1EA1y "jai1 deps <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
10853
10903
  }
10854
10904
  function createDepsCommand() {
10855
- const depsCommand = new Command45("deps").description("Qu\u1EA3n l\xFD dependencies trong project").action(() => {
10905
+ const depsCommand = new Command46("deps").description("Qu\u1EA3n l\xFD dependencies trong project").action(() => {
10856
10906
  showDepsHelp();
10857
10907
  });
10858
10908
  depsCommand.addCommand(createDepsCheckCommand());
@@ -10861,17 +10911,17 @@ function createDepsCommand() {
10861
10911
  }
10862
10912
 
10863
10913
  // src/commands/tasks/index.ts
10864
- import { Command as Command56 } from "commander";
10914
+ import { Command as Command57 } from "commander";
10865
10915
 
10866
10916
  // src/commands/tasks/add.ts
10867
- import { Command as Command46 } from "commander";
10868
- import chalk19 from "chalk";
10917
+ import { Command as Command47 } from "commander";
10918
+ import chalk20 from "chalk";
10869
10919
  function createTaskAddCommand() {
10870
- return new Command46("add").description("Add a new task").argument("<title>", "Task title").option("-p, --priority <n>", "Priority: 0=critical, 1=high, 2=medium, 3=low", "2").option("-P, --parent <parent>", "Parent: feature/xxx, plan/xxx, bug/xxx").option("-t, --tags <tags>", "Comma-separated tags").option("-j, --json", "Output JSON").action(async (title, options) => {
10920
+ return new Command47("add").description("Add a new task").argument("<title>", "Task title").option("-p, --priority <n>", "Priority: 0=critical, 1=high, 2=medium, 3=low", "2").option("-P, --parent <parent>", "Parent: feature/xxx, plan/xxx, bug/xxx").option("-t, --tags <tags>", "Comma-separated tags").option("-j, --json", "Output JSON").action(async (title, options) => {
10871
10921
  const service = new TaskService();
10872
10922
  const priority = Number(options.priority ?? 2);
10873
10923
  if (priority < 0 || priority > 3) {
10874
- console.error(chalk19.red("\u274C Priority must be 0-3"));
10924
+ console.error(chalk20.red("\u274C Priority must be 0-3"));
10875
10925
  process.exit(1);
10876
10926
  }
10877
10927
  const tags = options.tags ? options.tags.split(",").map((t) => t.trim()) : [];
@@ -10887,23 +10937,23 @@ function createTaskAddCommand() {
10887
10937
  }
10888
10938
  const icon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
10889
10939
  const label = PRIORITY_LABELS[task.priority] || "Medium";
10890
- console.log(chalk19.green(`\u2705 Task added: ${chalk19.bold(task.id)}`));
10891
- console.log(` ${chalk19.dim("Title:")} ${task.title}`);
10892
- console.log(` ${chalk19.dim("Priority:")} ${icon} ${label}`);
10940
+ console.log(chalk20.green(`\u2705 Task added: ${chalk20.bold(task.id)}`));
10941
+ console.log(` ${chalk20.dim("Title:")} ${task.title}`);
10942
+ console.log(` ${chalk20.dim("Priority:")} ${icon} ${label}`);
10893
10943
  if (task.parent) {
10894
- console.log(` ${chalk19.dim("Parent:")} ${task.parent}`);
10944
+ console.log(` ${chalk20.dim("Parent:")} ${task.parent}`);
10895
10945
  }
10896
10946
  if (task.tags.length > 0) {
10897
- console.log(` ${chalk19.dim("Tags:")} ${task.tags.join(", ")}`);
10947
+ console.log(` ${chalk20.dim("Tags:")} ${task.tags.join(", ")}`);
10898
10948
  }
10899
10949
  });
10900
10950
  }
10901
10951
 
10902
10952
  // src/commands/tasks/list.ts
10903
- import { Command as Command47 } from "commander";
10904
- import chalk20 from "chalk";
10953
+ import { Command as Command48 } from "commander";
10954
+ import chalk21 from "chalk";
10905
10955
  function createTaskListCommand() {
10906
- return new Command47("list").alias("ls").description("List tasks").option("-s, --status <status>", "Filter by status: todo, in_progress, done, cancelled").option("-P, --parent <parent>", "Filter by parent: feature/xxx, plan/xxx").option("-j, --json", "Output JSON").action(async (options) => {
10956
+ return new Command48("list").alias("ls").description("List tasks").option("-s, --status <status>", "Filter by status: todo, in_progress, done, cancelled").option("-P, --parent <parent>", "Filter by parent: feature/xxx, plan/xxx").option("-j, --json", "Output JSON").action(async (options) => {
10907
10957
  await handleTaskList(options);
10908
10958
  });
10909
10959
  }
@@ -10922,12 +10972,12 @@ async function handleTaskList(options) {
10922
10972
  return;
10923
10973
  }
10924
10974
  if (tasks.length === 0) {
10925
- console.log(chalk20.dim("No tasks found."));
10975
+ console.log(chalk21.dim("No tasks found."));
10926
10976
  return;
10927
10977
  }
10928
10978
  const doneIds = new Set(allTasks.filter((t) => t.status === "done").map((t) => t.id));
10929
10979
  const header = options.parent ? `\u{1F4CB} ${options.parent} (${tasks.length} tasks)` : `\u{1F4CB} All tasks (${tasks.length})`;
10930
- console.log(chalk20.bold(header));
10980
+ console.log(chalk21.bold(header));
10931
10981
  console.log();
10932
10982
  for (const task of tasks) {
10933
10983
  printTaskLine(task, doneIds);
@@ -10937,25 +10987,25 @@ function printTaskLine(task, doneIds) {
10937
10987
  const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
10938
10988
  const statusIcon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
10939
10989
  const priorityIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
10940
- let line = ` ${statusIcon} ${chalk20.dim(task.id)} P${task.priority}${priorityIcon} ${task.title}`;
10990
+ let line = ` ${statusIcon} ${chalk21.dim(task.id)} P${task.priority}${priorityIcon} ${task.title}`;
10941
10991
  if (task.status === "in_progress" && task.assigned_to) {
10942
- line += chalk20.cyan(` @${task.assigned_to}`);
10992
+ line += chalk21.cyan(` @${task.assigned_to}`);
10943
10993
  }
10944
10994
  if (isBlocked) {
10945
10995
  const blockedBy = task.depends_on.filter((id) => !doneIds.has(id));
10946
- line += chalk20.red(` (blocked: ${blockedBy.join(", ")})`);
10996
+ line += chalk21.red(` (blocked: ${blockedBy.join(", ")})`);
10947
10997
  }
10948
10998
  if (task.parent) {
10949
- line += chalk20.dim(` [${task.parent}]`);
10999
+ line += chalk21.dim(` [${task.parent}]`);
10950
11000
  }
10951
11001
  console.log(line);
10952
11002
  }
10953
11003
 
10954
11004
  // src/commands/tasks/ready.ts
10955
- import { Command as Command48 } from "commander";
10956
- import chalk21 from "chalk";
11005
+ import { Command as Command49 } from "commander";
11006
+ import chalk22 from "chalk";
10957
11007
  function createTaskReadyCommand() {
10958
- return new Command48("ready").description("Show tasks ready to pick (not blocked, not assigned)").option("-P, --parent <parent>", "Filter by parent").option("-j, --json", "Output JSON").action(async (options) => {
11008
+ return new Command49("ready").description("Show tasks ready to pick (not blocked, not assigned)").option("-P, --parent <parent>", "Filter by parent").option("-j, --json", "Output JSON").action(async (options) => {
10959
11009
  const service = new TaskService();
10960
11010
  const tasks = await service.getReady(options.parent);
10961
11011
  if (options.json) {
@@ -10963,61 +11013,75 @@ function createTaskReadyCommand() {
10963
11013
  return;
10964
11014
  }
10965
11015
  if (tasks.length === 0) {
10966
- console.log(chalk21.dim("No tasks ready to pick."));
10967
- console.log(chalk21.dim("\u{1F4A1} Check blocked tasks: jai1 t list -s todo"));
11016
+ console.log(chalk22.dim("No tasks ready to pick."));
11017
+ console.log(chalk22.dim("\u{1F4A1} Check blocked tasks: jai1 t list -s todo"));
10968
11018
  return;
10969
11019
  }
10970
- console.log(chalk21.bold(`\u{1F4CB} Ready to pick (${tasks.length} tasks):`));
11020
+ console.log(chalk22.bold(`\u{1F4CB} Ready to pick (${tasks.length} tasks):`));
10971
11021
  console.log();
10972
11022
  for (const task of tasks) {
10973
11023
  const icon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
10974
- let line = ` P${task.priority}${icon} ${chalk21.dim(task.id)} ${task.title}`;
11024
+ let line = ` P${task.priority}${icon} ${chalk22.dim(task.id)} ${task.title}`;
10975
11025
  if (task.parent) {
10976
- line += chalk21.dim(` [${task.parent}]`);
11026
+ line += chalk22.dim(` [${task.parent}]`);
10977
11027
  }
10978
11028
  console.log(line);
10979
11029
  }
10980
11030
  console.log();
10981
- console.log(chalk21.dim("\u{1F4A1} Run: jai1 t pick"));
11031
+ console.log(chalk22.dim("\u{1F4A1} Run: jai1 t pick"));
10982
11032
  });
10983
11033
  }
10984
11034
 
10985
11035
  // src/commands/tasks/update.ts
10986
- import { Command as Command49 } from "commander";
10987
- import chalk22 from "chalk";
11036
+ import { Command as Command50 } from "commander";
11037
+ import chalk23 from "chalk";
10988
11038
  var VALID_STATUSES = ["todo", "in_progress", "done", "cancelled"];
10989
11039
  function createTaskUpdateCommand() {
10990
- return new Command49("update").description("Update task status").argument("<id>", "Task ID (e.g. T-001)").requiredOption("-s, --status <status>", "New status: todo, in_progress, done, cancelled").option("-j, --json", "Output JSON").action(async (id, options) => {
10991
- if (!VALID_STATUSES.includes(options.status)) {
10992
- console.error(chalk22.red(`\u274C Invalid status. Must be: ${VALID_STATUSES.join(", ")}`));
11040
+ return new Command50("update").description("Update task status and/or notes").argument("<id>", "Task ID (e.g. T-001)").option("-s, --status <status>", "New status: todo, in_progress, done, cancelled").option("-n, --notes <notes>", 'Task notes (e.g. "files: a.ts, b.ts")').option("-j, --json", "Output JSON").action(async (id, options) => {
11041
+ if (!options.status && !options.notes) {
11042
+ console.error(chalk23.red("\u274C At least one of --status or --notes is required"));
11043
+ process.exit(1);
11044
+ }
11045
+ if (options.status && !VALID_STATUSES.includes(options.status)) {
11046
+ console.error(chalk23.red(`\u274C Invalid status. Must be: ${VALID_STATUSES.join(", ")}`));
10993
11047
  process.exit(1);
10994
11048
  }
10995
11049
  const service = new TaskService();
10996
11050
  try {
10997
- const task = await service.update(id, { status: options.status });
11051
+ const changes = {};
11052
+ if (options.status) changes.status = options.status;
11053
+ if (options.notes) changes.notes = options.notes;
11054
+ const task = await service.update(id, changes);
10998
11055
  if (options.json) {
10999
11056
  console.log(JSON.stringify(task, null, 2));
11000
11057
  return;
11001
11058
  }
11002
- const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
11003
- console.log(chalk22.green(`\u2705 ${task.id} \u2192 ${icon} ${task.status}`));
11059
+ const parts = [];
11060
+ if (options.status) {
11061
+ const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
11062
+ parts.push(`${icon} ${task.status}`);
11063
+ }
11064
+ if (options.notes) {
11065
+ parts.push(`\u{1F4DD} notes updated`);
11066
+ }
11067
+ console.log(chalk23.green(`\u2705 ${task.id} \u2192 ${parts.join(" | ")}`));
11004
11068
  } catch (error) {
11005
- console.error(chalk22.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11069
+ console.error(chalk23.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11006
11070
  process.exit(1);
11007
11071
  }
11008
11072
  });
11009
11073
  }
11010
11074
 
11011
11075
  // src/commands/tasks/show.ts
11012
- import { Command as Command50 } from "commander";
11013
- import chalk23 from "chalk";
11076
+ import { Command as Command51 } from "commander";
11077
+ import chalk24 from "chalk";
11014
11078
  function createTaskShowCommand() {
11015
- return new Command50("show").description("Show task detail or all tasks under a parent").argument("<query>", "Task ID (T-001) or parent (feature/xxx)").option("-j, --json", "Output JSON").action(async (query, options) => {
11079
+ return new Command51("show").description("Show task detail or all tasks under a parent").argument("<query>", "Task ID (T-001) or parent (feature/xxx)").option("-j, --json", "Output JSON").action(async (query, options) => {
11016
11080
  const service = new TaskService();
11017
11081
  if (query.startsWith("T-")) {
11018
11082
  const task = await service.findById(query);
11019
11083
  if (!task) {
11020
- console.error(chalk23.red(`\u274C Task ${query} not found`));
11084
+ console.error(chalk24.red(`\u274C Task ${query} not found`));
11021
11085
  process.exit(1);
11022
11086
  }
11023
11087
  if (options.json) {
@@ -11028,34 +11092,34 @@ function createTaskShowCommand() {
11028
11092
  const statusIcon = blocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
11029
11093
  const priIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
11030
11094
  const priLabel = PRIORITY_LABELS[task.priority] || "Medium";
11031
- console.log(chalk23.bold(`
11095
+ console.log(chalk24.bold(`
11032
11096
  \u{1F4CC} ${task.id}: ${task.title}
11033
11097
  `));
11034
- console.log(` ${chalk23.dim("Status:")} ${statusIcon} ${task.status}${blocked ? chalk23.red(" (BLOCKED)") : ""}`);
11035
- console.log(` ${chalk23.dim("Priority:")} ${priIcon} P${task.priority} ${priLabel}`);
11098
+ console.log(` ${chalk24.dim("Status:")} ${statusIcon} ${task.status}${blocked ? chalk24.red(" (BLOCKED)") : ""}`);
11099
+ console.log(` ${chalk24.dim("Priority:")} ${priIcon} P${task.priority} ${priLabel}`);
11036
11100
  if (task.parent) {
11037
- console.log(` ${chalk23.dim("Parent:")} ${task.parent}`);
11101
+ console.log(` ${chalk24.dim("Parent:")} ${task.parent}`);
11038
11102
  }
11039
11103
  if (task.assigned_to) {
11040
- console.log(` ${chalk23.dim("Assigned:")} @${task.assigned_to} (${task.claimed_at})`);
11104
+ console.log(` ${chalk24.dim("Assigned:")} @${task.assigned_to} (${task.claimed_at})`);
11041
11105
  }
11042
11106
  if (task.depends_on.length > 0) {
11043
- console.log(` ${chalk23.dim("Depends on:")} ${task.depends_on.join(", ")}`);
11107
+ console.log(` ${chalk24.dim("Depends on:")} ${task.depends_on.join(", ")}`);
11044
11108
  if (blocked) {
11045
- console.log(` ${chalk23.dim("Blocked by:")} ${chalk23.red(blockedBy.join(", "))}`);
11109
+ console.log(` ${chalk24.dim("Blocked by:")} ${chalk24.red(blockedBy.join(", "))}`);
11046
11110
  }
11047
11111
  }
11048
11112
  if (task.tags.length > 0) {
11049
- console.log(` ${chalk23.dim("Tags:")} ${task.tags.join(", ")}`);
11113
+ console.log(` ${chalk24.dim("Tags:")} ${task.tags.join(", ")}`);
11050
11114
  }
11051
11115
  if (task.branch) {
11052
- console.log(` ${chalk23.dim("Branch:")} ${task.branch}`);
11116
+ console.log(` ${chalk24.dim("Branch:")} ${task.branch}`);
11053
11117
  }
11054
11118
  if (task.notes) {
11055
- console.log(` ${chalk23.dim("Notes:")} ${task.notes}`);
11119
+ console.log(` ${chalk24.dim("Notes:")} ${task.notes}`);
11056
11120
  }
11057
- console.log(` ${chalk23.dim("Created:")} ${task.created}`);
11058
- console.log(` ${chalk23.dim("Updated:")} ${task.updated}`);
11121
+ console.log(` ${chalk24.dim("Created:")} ${task.created}`);
11122
+ console.log(` ${chalk24.dim("Updated:")} ${task.updated}`);
11059
11123
  console.log();
11060
11124
  } else {
11061
11125
  const tasks = await service.filter({ parent: query });
@@ -11064,10 +11128,10 @@ function createTaskShowCommand() {
11064
11128
  return;
11065
11129
  }
11066
11130
  if (tasks.length === 0) {
11067
- console.log(chalk23.dim(`No tasks for parent: ${query}`));
11131
+ console.log(chalk24.dim(`No tasks for parent: ${query}`));
11068
11132
  return;
11069
11133
  }
11070
- console.log(chalk23.bold(`
11134
+ console.log(chalk24.bold(`
11071
11135
  \u{1F4CB} ${query} (${tasks.length} tasks)
11072
11136
  `));
11073
11137
  const allTasks = await service.readAll();
@@ -11075,11 +11139,11 @@ function createTaskShowCommand() {
11075
11139
  for (const task of tasks) {
11076
11140
  const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
11077
11141
  const icon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
11078
- let line = ` ${icon} ${chalk23.dim(task.id)} P${task.priority} ${task.title}`;
11079
- if (task.assigned_to) line += chalk23.cyan(` @${task.assigned_to}`);
11142
+ let line = ` ${icon} ${chalk24.dim(task.id)} P${task.priority} ${task.title}`;
11143
+ if (task.assigned_to) line += chalk24.cyan(` @${task.assigned_to}`);
11080
11144
  if (isBlocked) {
11081
11145
  const bb = task.depends_on.filter((id) => !doneIds.has(id));
11082
- line += chalk23.red(` (blocked: ${bb.join(", ")})`);
11146
+ line += chalk24.red(` (blocked: ${bb.join(", ")})`);
11083
11147
  }
11084
11148
  console.log(line);
11085
11149
  }
@@ -11089,11 +11153,11 @@ function createTaskShowCommand() {
11089
11153
  }
11090
11154
 
11091
11155
  // src/commands/tasks/pick.ts
11092
- import { Command as Command51 } from "commander";
11093
- import chalk24 from "chalk";
11156
+ import { Command as Command52 } from "commander";
11157
+ import chalk25 from "chalk";
11094
11158
  import { confirm as confirm9 } from "@inquirer/prompts";
11095
11159
  function createTaskPickCommand() {
11096
- return new Command51("pick").description("Claim the next available task").option("-j, --json", "Output JSON").action(async (options) => {
11160
+ return new Command52("pick").description("Claim the next available task").option("-j, --json", "Output JSON").action(async (options) => {
11097
11161
  const service = new TaskService();
11098
11162
  const ready = await service.getReady();
11099
11163
  if (ready.length === 0) {
@@ -11101,8 +11165,8 @@ function createTaskPickCommand() {
11101
11165
  console.log(JSON.stringify({ picked: null, message: "No tasks ready" }));
11102
11166
  return;
11103
11167
  }
11104
- console.log(chalk24.dim("No tasks ready to pick."));
11105
- console.log(chalk24.dim('\u{1F4A1} Add tasks first: jai1 t add "..."'));
11168
+ console.log(chalk25.dim("No tasks ready to pick."));
11169
+ console.log(chalk25.dim('\u{1F4A1} Add tasks first: jai1 t add "..."'));
11106
11170
  return;
11107
11171
  }
11108
11172
  const top = ready[0];
@@ -11112,13 +11176,13 @@ function createTaskPickCommand() {
11112
11176
  console.log(JSON.stringify(picked2, null, 2));
11113
11177
  return;
11114
11178
  }
11115
- console.log(chalk24.bold("\n\u{1F4CC} Next available task:"));
11116
- console.log(` ${chalk24.bold(top.id)} P${top.priority}${icon} ${top.title}`);
11179
+ console.log(chalk25.bold("\n\u{1F4CC} Next available task:"));
11180
+ console.log(` ${chalk25.bold(top.id)} P${top.priority}${icon} ${top.title}`);
11117
11181
  if (top.parent) {
11118
- console.log(` ${chalk24.dim("Parent:")} ${top.parent}`);
11182
+ console.log(` ${chalk25.dim("Parent:")} ${top.parent}`);
11119
11183
  }
11120
11184
  if (ready.length > 1) {
11121
- console.log(chalk24.dim(`
11185
+ console.log(chalk25.dim(`
11122
11186
  +${ready.length - 1} more tasks ready`));
11123
11187
  }
11124
11188
  const proceed = await confirm9({
@@ -11126,20 +11190,20 @@ function createTaskPickCommand() {
11126
11190
  default: true
11127
11191
  });
11128
11192
  if (!proceed) {
11129
- console.log(chalk24.dim("\nCancelled."));
11193
+ console.log(chalk25.dim("\nCancelled."));
11130
11194
  return;
11131
11195
  }
11132
11196
  const picked = await service.pick(top.id);
11133
- console.log(chalk24.green(`
11197
+ console.log(chalk25.green(`
11134
11198
  \u2705 ${picked.id} assigned to @${picked.assigned_to}, status \u2192 in_progress`));
11135
11199
  });
11136
11200
  }
11137
11201
 
11138
11202
  // src/commands/tasks/done.ts
11139
- import { Command as Command52 } from "commander";
11140
- import chalk25 from "chalk";
11203
+ import { Command as Command53 } from "commander";
11204
+ import chalk26 from "chalk";
11141
11205
  function createTaskDoneCommand() {
11142
- return new Command52("done").description("Mark task as done").argument("<id>", "Task ID (e.g. T-001)").option("-j, --json", "Output JSON").action(async (id, options) => {
11206
+ return new Command53("done").description("Mark task as done").argument("<id>", "Task ID (e.g. T-001)").option("-j, --json", "Output JSON").action(async (id, options) => {
11143
11207
  const service = new TaskService();
11144
11208
  try {
11145
11209
  const task = await service.markDone(id);
@@ -11147,19 +11211,19 @@ function createTaskDoneCommand() {
11147
11211
  console.log(JSON.stringify(task, null, 2));
11148
11212
  return;
11149
11213
  }
11150
- console.log(chalk25.green(`\u2705 ${task.id}: ${task.title} \u2192 done`));
11214
+ console.log(chalk26.green(`\u2705 ${task.id}: ${task.title} \u2192 done`));
11151
11215
  } catch (error) {
11152
- console.error(chalk25.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11216
+ console.error(chalk26.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11153
11217
  process.exit(1);
11154
11218
  }
11155
11219
  });
11156
11220
  }
11157
11221
 
11158
11222
  // src/commands/tasks/dep.ts
11159
- import { Command as Command53 } from "commander";
11160
- import chalk26 from "chalk";
11223
+ import { Command as Command54 } from "commander";
11224
+ import chalk27 from "chalk";
11161
11225
  function createTaskDepCommand() {
11162
- return new Command53("dep").description("Add dependency: child depends on parent").argument("<childId>", "Child task ID (the one that waits)").argument("<parentId>", "Parent task ID (must be done first)").option("-j, --json", "Output JSON").action(async (childId, parentId, options) => {
11226
+ return new Command54("dep").description("Add dependency: child depends on parent").argument("<childId>", "Child task ID (the one that waits)").argument("<parentId>", "Parent task ID (must be done first)").option("-j, --json", "Output JSON").action(async (childId, parentId, options) => {
11163
11227
  const service = new TaskService();
11164
11228
  try {
11165
11229
  const task = await service.addDependency(childId, parentId);
@@ -11167,156 +11231,156 @@ function createTaskDepCommand() {
11167
11231
  console.log(JSON.stringify(task, null, 2));
11168
11232
  return;
11169
11233
  }
11170
- console.log(chalk26.green(`\u2705 ${childId} now depends on ${parentId}`));
11171
- console.log(chalk26.dim(` ${task.title} \u2192 waits for ${parentId}`));
11234
+ console.log(chalk27.green(`\u2705 ${childId} now depends on ${parentId}`));
11235
+ console.log(chalk27.dim(` ${task.title} \u2192 waits for ${parentId}`));
11172
11236
  } catch (error) {
11173
- console.error(chalk26.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11237
+ console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11174
11238
  process.exit(1);
11175
11239
  }
11176
11240
  });
11177
11241
  }
11178
11242
 
11179
11243
  // src/commands/tasks/sync.ts
11180
- import { Command as Command54 } from "commander";
11181
- import chalk27 from "chalk";
11244
+ import { Command as Command55 } from "commander";
11245
+ import chalk28 from "chalk";
11182
11246
  function createTaskSyncCommand() {
11183
- return new Command54("sync").description("Sync tasks with git (commit & push only tasks file)").option("--pull", "Pull and merge tasks from origin/main").option("--push", "Commit and push tasks file").action(async (options) => {
11247
+ return new Command55("sync").description("Sync tasks with git (commit & push only tasks file)").option("--pull", "Pull and merge tasks from origin/main").option("--push", "Commit and push tasks file").action(async (options) => {
11184
11248
  const service = new TaskService();
11185
11249
  if (options.pull) {
11186
- console.log(chalk27.dim("\u23F3 Pulling tasks from origin/main..."));
11250
+ console.log(chalk28.dim("\u23F3 Pulling tasks from origin/main..."));
11187
11251
  try {
11188
11252
  const result = await service.syncPull();
11189
- console.log(chalk27.green(`\u2705 Sync pull complete: ${result.merged} tasks merged`));
11253
+ console.log(chalk28.green(`\u2705 Sync pull complete: ${result.merged} tasks merged`));
11190
11254
  } catch (error) {
11191
- console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11255
+ console.error(chalk28.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11192
11256
  process.exit(1);
11193
11257
  }
11194
11258
  return;
11195
11259
  }
11196
- console.log(chalk27.dim("\u23F3 Syncing tasks to git..."));
11260
+ console.log(chalk28.dim("\u23F3 Syncing tasks to git..."));
11197
11261
  try {
11198
11262
  await service.syncPush();
11199
- console.log(chalk27.green("\u2705 Tasks synced to git"));
11263
+ console.log(chalk28.green("\u2705 Tasks synced to git"));
11200
11264
  } catch (error) {
11201
- console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11265
+ console.error(chalk28.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
11202
11266
  process.exit(1);
11203
11267
  }
11204
11268
  });
11205
11269
  }
11206
11270
 
11207
11271
  // src/commands/tasks/guide.ts
11208
- import { Command as Command55 } from "commander";
11209
- import chalk28 from "chalk";
11272
+ import { Command as Command56 } from "commander";
11273
+ import chalk29 from "chalk";
11210
11274
  var GUIDE_TEXT = `
11211
- ${chalk28.cyan.bold("\u{1F4D6} Jai1 Task Management Guide")}
11212
-
11213
- ${chalk28.bold("\u2501\u2501\u2501 STATUSES \u2501\u2501\u2501")}
11214
- ${chalk28.dim("todo")} \u{1F4CB} Ch\u01B0a b\u1EAFt \u0111\u1EA7u
11215
- ${chalk28.dim("in_progress")} \u{1F535} \u0110ang l\xE0m (bao g\u1ED3m review)
11216
- ${chalk28.dim("done")} \u2705 Ho\xE0n th\xE0nh
11217
- ${chalk28.dim("cancelled")} \u26AB Hu\u1EF7
11218
- ${chalk28.dim("(blocked)")} \u{1F534} Computed: depends_on ch\u01B0a done
11219
-
11220
- ${chalk28.bold("\u2501\u2501\u2501 PRIORITY \u2501\u2501\u2501")}
11221
- ${chalk28.dim("0")} = \u{1F525} Critical \u2014 Prod down, security, block c\u1EA3 team
11222
- ${chalk28.dim("1")} = \u{1F534} High \u2014 Feature ch\xEDnh, deadline g\u1EA7n
11223
- ${chalk28.dim("2")} = \u{1F7E1} Medium \u2014 B\xECnh th\u01B0\u1EDDng (default)
11224
- ${chalk28.dim("3")} = \u{1F7E2} Low \u2014 Nice-to-have, docs, refactor
11225
-
11226
- ${chalk28.bold("\u2501\u2501\u2501 QUICK START \u2501\u2501\u2501")}
11227
- ${chalk28.cyan("jai1 t add")} "Fix login bug" -p 1 -P bug/login
11228
- ${chalk28.cyan("jai1 t ready")} Show tasks s\u1EB5n s\xE0ng
11229
- ${chalk28.cyan("jai1 t pick")} Claim & start working
11230
- ${chalk28.cyan("jai1 t done")} T-003 Mark complete
11231
-
11232
- ${chalk28.bold("\u2501\u2501\u2501 DAILY WORKFLOW \u2501\u2501\u2501")}
11233
- ${chalk28.cyan("jai1 t sync --pull")} Pull latest tasks
11234
- ${chalk28.cyan("jai1 t summary")} Dashboard t\u1ED5ng quan
11235
- ${chalk28.cyan("jai1 t ready")} Xem tasks s\u1EB5n s\xE0ng
11236
- ${chalk28.cyan("jai1 t pick")} Claim task m\u1EDBi
11237
- ${chalk28.cyan("jai1 t done")} T-xxx Ho\xE0n th\xE0nh task
11238
- ${chalk28.cyan("jai1 t sync --push")} Push l\xEAn git
11239
-
11240
- ${chalk28.bold("\u2501\u2501\u2501 ADDING TASKS \u2501\u2501\u2501")}
11241
- ${chalk28.yellow("\u26A0 Lu\xF4n ki\u1EC3m tra duplicate tr\u01B0\u1EDBc khi add:")}
11242
- ${chalk28.cyan("jai1 t list -P")} feature/xxx
11243
-
11244
- ${chalk28.dim("Add cho feature:")}
11245
- ${chalk28.cyan("jai1 t add")} "Setup DB schema" -p 1 -P feature/xxx
11246
- ${chalk28.cyan("jai1 t add")} "Create API" -p 1 -P feature/xxx
11247
- ${chalk28.cyan("jai1 t add")} "Build UI" -p 2 -P feature/xxx
11248
-
11249
- ${chalk28.dim("Add cho plan:")}
11250
- ${chalk28.cyan("jai1 t add")} "Refactor middleware" -p 2 -P plan/xxx
11251
-
11252
- ${chalk28.dim("Add standalone:")}
11253
- ${chalk28.cyan("jai1 t add")} "Fix README typo" -p 3
11254
-
11255
- ${chalk28.dim("Add bug fix:")}
11256
- ${chalk28.cyan("jai1 t add")} "Fix login redirect" -p 1 -P bug/xxx
11257
-
11258
- ${chalk28.bold("\u2501\u2501\u2501 DEPENDENCY \u2501\u2501\u2501")}
11259
- ${chalk28.dim("Task dependency:")}
11260
- ${chalk28.cyan("jai1 t dep")} T-002 T-001 T-002 ch\u1EDD T-001 done
11261
- ${chalk28.cyan("jai1 t dep")} T-003 T-002 T-003 ch\u1EDD T-002 done
11262
-
11263
- ${chalk28.dim("Feature-level dependency:")}
11264
- ${chalk28.dim("# N\u1EBFu feature/auth ph\u1EE5 thu\u1ED9c feature/user-model:")}
11265
- ${chalk28.cyan("jai1 t add")} "[DEP] Wait for feature/user-model" -p 1 -P feature/auth
11266
- ${chalk28.dim("# R\u1ED3i dep n\xF3 v\u1EDBi tasks cu\u1ED1i c\u1EE7a user-model")}
11267
-
11268
- ${chalk28.dim("View deps:")}
11269
- ${chalk28.cyan("jai1 t show")} T-002 Hi\u1EC7n depends_on
11270
-
11271
- ${chalk28.bold("\u2501\u2501\u2501 TEAM COLLABORATION \u2501\u2501\u2501")}
11272
- ${chalk28.yellow("\u26A0 Assignment ch\u1EC9 qua pick \u2014 kh\xF4ng set th\u1EE7 c\xF4ng.")}
11273
- ${chalk28.dim("Khi b\u1EA1n pick \u2192 team th\u1EA5y task \u0111\xE3 c\xF3 ng\u01B0\u1EDDi nh\u1EADn.")}
11274
-
11275
- ${chalk28.dim("Sync morning:")} ${chalk28.cyan("jai1 t sync --pull")}
11276
- ${chalk28.dim("Sync evening:")} ${chalk28.cyan("jai1 t sync --push")}
11277
-
11278
- ${chalk28.bold("\u2501\u2501\u2501 FOR AI AGENTS (Workflow Integration) \u2501\u2501\u2501")}
11279
- ${chalk28.dim("Khi t\u1EA1o tasks t\u1EEB feature/plan:")}
11280
- 1. ${chalk28.cyan("jai1 t list -P")} <parent> Check existing (tr\xE1nh duplicate)
11281
- 2. ${chalk28.cyan("jai1 t add")} "..." -p <0-3> -P <parent> Add t\u1EEBng task
11282
- 3. ${chalk28.cyan("jai1 t dep")} <child> <parent> Set dependencies
11283
- 4. ${chalk28.cyan("jai1 t done")} <id> Mark complete
11284
-
11285
- ${chalk28.dim("Khi implement task ti\u1EBFp theo:")}
11286
- 1. ${chalk28.cyan("jai1 t pick")} (ho\u1EB7c ${chalk28.cyan("jai1 t ready -P")} <parent>)
11275
+ ${chalk29.cyan.bold("\u{1F4D6} Jai1 Task Management Guide")}
11276
+
11277
+ ${chalk29.bold("\u2501\u2501\u2501 STATUSES \u2501\u2501\u2501")}
11278
+ ${chalk29.dim("todo")} \u{1F4CB} Ch\u01B0a b\u1EAFt \u0111\u1EA7u
11279
+ ${chalk29.dim("in_progress")} \u{1F535} \u0110ang l\xE0m (bao g\u1ED3m review)
11280
+ ${chalk29.dim("done")} \u2705 Ho\xE0n th\xE0nh
11281
+ ${chalk29.dim("cancelled")} \u26AB Hu\u1EF7
11282
+ ${chalk29.dim("(blocked)")} \u{1F534} Computed: depends_on ch\u01B0a done
11283
+
11284
+ ${chalk29.bold("\u2501\u2501\u2501 PRIORITY \u2501\u2501\u2501")}
11285
+ ${chalk29.dim("0")} = \u{1F525} Critical \u2014 Prod down, security, block c\u1EA3 team
11286
+ ${chalk29.dim("1")} = \u{1F534} High \u2014 Feature ch\xEDnh, deadline g\u1EA7n
11287
+ ${chalk29.dim("2")} = \u{1F7E1} Medium \u2014 B\xECnh th\u01B0\u1EDDng (default)
11288
+ ${chalk29.dim("3")} = \u{1F7E2} Low \u2014 Nice-to-have, docs, refactor
11289
+
11290
+ ${chalk29.bold("\u2501\u2501\u2501 QUICK START \u2501\u2501\u2501")}
11291
+ ${chalk29.cyan("jai1 t add")} "Fix login bug" -p 1 -P bug/login
11292
+ ${chalk29.cyan("jai1 t ready")} Show tasks s\u1EB5n s\xE0ng
11293
+ ${chalk29.cyan("jai1 t pick")} Claim & start working
11294
+ ${chalk29.cyan("jai1 t done")} T-003 Mark complete
11295
+
11296
+ ${chalk29.bold("\u2501\u2501\u2501 DAILY WORKFLOW \u2501\u2501\u2501")}
11297
+ ${chalk29.cyan("jai1 t sync --pull")} Pull latest tasks
11298
+ ${chalk29.cyan("jai1 t summary")} Dashboard t\u1ED5ng quan
11299
+ ${chalk29.cyan("jai1 t ready")} Xem tasks s\u1EB5n s\xE0ng
11300
+ ${chalk29.cyan("jai1 t pick")} Claim task m\u1EDBi
11301
+ ${chalk29.cyan("jai1 t done")} T-xxx Ho\xE0n th\xE0nh task
11302
+ ${chalk29.cyan("jai1 t sync --push")} Push l\xEAn git
11303
+
11304
+ ${chalk29.bold("\u2501\u2501\u2501 ADDING TASKS \u2501\u2501\u2501")}
11305
+ ${chalk29.yellow("\u26A0 Lu\xF4n ki\u1EC3m tra duplicate tr\u01B0\u1EDBc khi add:")}
11306
+ ${chalk29.cyan("jai1 t list -P")} feature/xxx
11307
+
11308
+ ${chalk29.dim("Add cho feature:")}
11309
+ ${chalk29.cyan("jai1 t add")} "Setup DB schema" -p 1 -P feature/xxx
11310
+ ${chalk29.cyan("jai1 t add")} "Create API" -p 1 -P feature/xxx
11311
+ ${chalk29.cyan("jai1 t add")} "Build UI" -p 2 -P feature/xxx
11312
+
11313
+ ${chalk29.dim("Add cho plan:")}
11314
+ ${chalk29.cyan("jai1 t add")} "Refactor middleware" -p 2 -P plan/xxx
11315
+
11316
+ ${chalk29.dim("Add standalone:")}
11317
+ ${chalk29.cyan("jai1 t add")} "Fix README typo" -p 3
11318
+
11319
+ ${chalk29.dim("Add bug fix:")}
11320
+ ${chalk29.cyan("jai1 t add")} "Fix login redirect" -p 1 -P bug/xxx
11321
+
11322
+ ${chalk29.bold("\u2501\u2501\u2501 DEPENDENCY \u2501\u2501\u2501")}
11323
+ ${chalk29.dim("Task dependency:")}
11324
+ ${chalk29.cyan("jai1 t dep")} T-002 T-001 T-002 ch\u1EDD T-001 done
11325
+ ${chalk29.cyan("jai1 t dep")} T-003 T-002 T-003 ch\u1EDD T-002 done
11326
+
11327
+ ${chalk29.dim("Feature-level dependency:")}
11328
+ ${chalk29.dim("# N\u1EBFu feature/auth ph\u1EE5 thu\u1ED9c feature/user-model:")}
11329
+ ${chalk29.cyan("jai1 t add")} "[DEP] Wait for feature/user-model" -p 1 -P feature/auth
11330
+ ${chalk29.dim("# R\u1ED3i dep n\xF3 v\u1EDBi tasks cu\u1ED1i c\u1EE7a user-model")}
11331
+
11332
+ ${chalk29.dim("View deps:")}
11333
+ ${chalk29.cyan("jai1 t show")} T-002 Hi\u1EC7n depends_on
11334
+
11335
+ ${chalk29.bold("\u2501\u2501\u2501 TEAM COLLABORATION \u2501\u2501\u2501")}
11336
+ ${chalk29.yellow("\u26A0 Assignment ch\u1EC9 qua pick \u2014 kh\xF4ng set th\u1EE7 c\xF4ng.")}
11337
+ ${chalk29.dim("Khi b\u1EA1n pick \u2192 team th\u1EA5y task \u0111\xE3 c\xF3 ng\u01B0\u1EDDi nh\u1EADn.")}
11338
+
11339
+ ${chalk29.dim("Sync morning:")} ${chalk29.cyan("jai1 t sync --pull")}
11340
+ ${chalk29.dim("Sync evening:")} ${chalk29.cyan("jai1 t sync --push")}
11341
+
11342
+ ${chalk29.bold("\u2501\u2501\u2501 FOR AI AGENTS (Workflow Integration) \u2501\u2501\u2501")}
11343
+ ${chalk29.dim("Khi t\u1EA1o tasks t\u1EEB feature/plan:")}
11344
+ 1. ${chalk29.cyan("jai1 t list -P")} <parent> Check existing (tr\xE1nh duplicate)
11345
+ 2. ${chalk29.cyan("jai1 t add")} "..." -p <0-3> -P <parent> Add t\u1EEBng task
11346
+ 3. ${chalk29.cyan("jai1 t dep")} <child> <parent> Set dependencies
11347
+ 4. ${chalk29.cyan("jai1 t done")} <id> Mark complete
11348
+
11349
+ ${chalk29.dim("Khi implement task ti\u1EBFp theo:")}
11350
+ 1. ${chalk29.cyan("jai1 t pick")} (ho\u1EB7c ${chalk29.cyan("jai1 t ready -P")} <parent>)
11287
11351
  2. Implement task
11288
- 3. ${chalk28.cyan("jai1 t done")} <id>
11352
+ 3. ${chalk29.cyan("jai1 t done")} <id>
11289
11353
 
11290
- ${chalk28.dim("Status transitions:")}
11354
+ ${chalk29.dim("Status transitions:")}
11291
11355
  add \u2192 todo (default)
11292
11356
  pick \u2192 in_progress (auto assign)
11293
11357
  done \u2192 done
11294
11358
  update -s \u2192 any valid status
11295
11359
 
11296
- ${chalk28.bold("\u2501\u2501\u2501 ALL COMMANDS \u2501\u2501\u2501")}
11297
- ${chalk28.cyan("jai1 t list")} [-s status] [-P parent] [-j]
11298
- ${chalk28.cyan("jai1 t ready")} [-P parent] [-j]
11299
- ${chalk28.cyan("jai1 t add")} <title> [-p 0-3] [-P parent] [-t tags] [-j]
11300
- ${chalk28.cyan("jai1 t update")} <id> -s <status> [-j]
11301
- ${chalk28.cyan("jai1 t show")} <id|parent> [-j]
11302
- ${chalk28.cyan("jai1 t pick")} [-j]
11303
- ${chalk28.cyan("jai1 t done")} <id> [-j]
11304
- ${chalk28.cyan("jai1 t dep")} <childId> <parentId> [-j]
11305
- ${chalk28.cyan("jai1 t sync")} [--pull] [--push]
11306
- ${chalk28.cyan("jai1 t summary")} [-j]
11307
- ${chalk28.cyan("jai1 t guide")}
11308
-
11309
- ${chalk28.dim("-j / --json available on all commands (except guide, sync)")}
11360
+ ${chalk29.bold("\u2501\u2501\u2501 ALL COMMANDS \u2501\u2501\u2501")}
11361
+ ${chalk29.cyan("jai1 t list")} [-s status] [-P parent] [-j]
11362
+ ${chalk29.cyan("jai1 t ready")} [-P parent] [-j]
11363
+ ${chalk29.cyan("jai1 t add")} <title> [-p 0-3] [-P parent] [-t tags] [-j]
11364
+ ${chalk29.cyan("jai1 t update")} <id> [-s <status>] [-n <notes>] [-j]
11365
+ ${chalk29.cyan("jai1 t show")} <id|parent> [-j]
11366
+ ${chalk29.cyan("jai1 t pick")} [-j]
11367
+ ${chalk29.cyan("jai1 t done")} <id> [-j]
11368
+ ${chalk29.cyan("jai1 t dep")} <childId> <parentId> [-j]
11369
+ ${chalk29.cyan("jai1 t sync")} [--pull] [--push]
11370
+ ${chalk29.cyan("jai1 t summary")} [-j]
11371
+ ${chalk29.cyan("jai1 t guide")}
11372
+
11373
+ ${chalk29.dim("-j / --json available on all commands (except guide, sync)")}
11310
11374
  `;
11311
11375
  function createTaskGuideCommand() {
11312
- return new Command55("guide").description("Show full task management guide").action(() => {
11376
+ return new Command56("guide").description("Show full task management guide").action(() => {
11313
11377
  console.log(GUIDE_TEXT);
11314
11378
  });
11315
11379
  }
11316
11380
 
11317
11381
  // src/commands/tasks/index.ts
11318
11382
  function createTasksCommand() {
11319
- const cmd = new Command56("tasks").alias("t").description("Task management \u2014 track, assign, and manage development tasks").hook("preAction", (thisCommand, actionCommand) => {
11383
+ const cmd = new Command57("tasks").alias("t").description("Task management \u2014 track, assign, and manage development tasks").hook("preAction", (thisCommand, actionCommand) => {
11320
11384
  if (actionCommand.name() !== "guide") {
11321
11385
  TaskService.ensureJai1Dir();
11322
11386
  }
@@ -11340,12 +11404,12 @@ function createTasksCommand() {
11340
11404
  }
11341
11405
 
11342
11406
  // src/commands/kit/index.ts
11343
- import { Command as Command60 } from "commander";
11344
- import chalk30 from "chalk";
11407
+ import { Command as Command61 } from "commander";
11408
+ import chalk31 from "chalk";
11345
11409
 
11346
11410
  // src/commands/kit/list.ts
11347
- import { Command as Command57 } from "commander";
11348
- import chalk29 from "chalk";
11411
+ import { Command as Command58 } from "commander";
11412
+ import chalk30 from "chalk";
11349
11413
  import Table6 from "cli-table3";
11350
11414
 
11351
11415
  // src/services/starter-kit.service.ts
@@ -11413,13 +11477,13 @@ var StarterKitService = class {
11413
11477
 
11414
11478
  // src/commands/kit/list.ts
11415
11479
  function createKitListCommand() {
11416
- return new Command57("list").description("List available starter kits").option("-c, --category <category>", "Filter by category (backend, frontend, fullstack)").option("-s, --search <term>", "Search kits by name or description").action(async (options) => {
11480
+ return new Command58("list").description("List available starter kits").option("-c, --category <category>", "Filter by category (backend, frontend, fullstack)").option("-s, --search <term>", "Search kits by name or description").action(async (options) => {
11417
11481
  const configService = new ConfigService();
11418
11482
  const config = await configService.load();
11419
11483
  if (!config) {
11420
11484
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
11421
11485
  }
11422
- console.log(chalk29.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
11486
+ console.log(chalk30.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
11423
11487
  console.log();
11424
11488
  const kitService = new StarterKitService();
11425
11489
  const kits = await kitService.list(config, {
@@ -11427,9 +11491,9 @@ function createKitListCommand() {
11427
11491
  search: options.search
11428
11492
  });
11429
11493
  if (kits.length === 0) {
11430
- console.log(chalk29.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
11494
+ console.log(chalk30.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
11431
11495
  if (options.category || options.search) {
11432
- console.log(chalk29.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
11496
+ console.log(chalk30.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
11433
11497
  }
11434
11498
  return;
11435
11499
  }
@@ -11453,35 +11517,35 @@ function createKitListCommand() {
11453
11517
  const categoryKits = byCategory[category];
11454
11518
  const categoryIcon = category === "frontend" ? "\u{1F3A8}" : category === "backend" ? "\u2699\uFE0F" : category === "fullstack" ? "\u{1F680}" : "\u{1F4E6}";
11455
11519
  console.log(
11456
- chalk29.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
11520
+ chalk30.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
11457
11521
  );
11458
11522
  const table = new Table6({
11459
11523
  head: [
11460
- chalk29.cyan("Slug"),
11461
- chalk29.cyan("M\xF4 t\u1EA3"),
11462
- chalk29.cyan("Version")
11524
+ chalk30.cyan("Slug"),
11525
+ chalk30.cyan("M\xF4 t\u1EA3"),
11526
+ chalk30.cyan("Version")
11463
11527
  ],
11464
11528
  style: { head: [], border: ["gray"] }
11465
11529
  });
11466
11530
  for (const kit of categoryKits) {
11467
11531
  table.push([
11468
- chalk29.white(kit.slug),
11469
- chalk29.dim(kit.description.slice(0, 50)),
11470
- chalk29.green(`v${kit.version}`)
11532
+ chalk30.white(kit.slug),
11533
+ chalk30.dim(kit.description.slice(0, 50)),
11534
+ chalk30.green(`v${kit.version}`)
11471
11535
  ]);
11472
11536
  }
11473
11537
  console.log(table.toString());
11474
11538
  console.log();
11475
11539
  }
11476
- console.log(chalk29.dim(`T\u1ED5ng c\u1ED9ng: ${kits.length} starter kit(s)`));
11477
- console.log(chalk29.dim('\n\u{1F4A1} Ch\u1EA1y "jai1 kit create <slug>" \u0111\u1EC3 t\u1EA1o project m\u1EDBi'));
11540
+ console.log(chalk30.dim(`T\u1ED5ng c\u1ED9ng: ${kits.length} starter kit(s)`));
11541
+ console.log(chalk30.dim('\n\u{1F4A1} Ch\u1EA1y "jai1 kit create <slug>" \u0111\u1EC3 t\u1EA1o project m\u1EDBi'));
11478
11542
  });
11479
11543
  }
11480
11544
 
11481
11545
  // src/commands/kit/info.ts
11482
- import { Command as Command58 } from "commander";
11546
+ import { Command as Command59 } from "commander";
11483
11547
  function createKitInfoCommand() {
11484
- return new Command58("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
11548
+ return new Command59("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
11485
11549
  const configService = new ConfigService();
11486
11550
  const config = await configService.load();
11487
11551
  if (!config) {
@@ -11530,7 +11594,7 @@ Post-Init Commands:`);
11530
11594
  }
11531
11595
 
11532
11596
  // src/commands/kit/create.ts
11533
- import { Command as Command59 } from "commander";
11597
+ import { Command as Command60 } from "commander";
11534
11598
  import { promises as fs21 } from "fs";
11535
11599
  import { join as join11 } from "path";
11536
11600
  import { select as select3, input as input2, checkbox as checkbox4 } from "@inquirer/prompts";
@@ -11575,7 +11639,7 @@ var HookExecutor = class {
11575
11639
 
11576
11640
  // src/commands/kit/create.ts
11577
11641
  function createKitCreateCommand() {
11578
- return new Command59("create").description("Create a new project from a starter kit").argument("<slug>", "Starter kit slug").argument("[directory]", "Project directory (default: ./<slug>)").option("-y, --yes", "Auto mode - use defaults, no prompts").option("--name <name>", "Project name").option("--skip-install", "Skip dependency installation").option("--skip-git", "Skip git initialization").option("--skip-framework", "Skip framework apply").option("--skip-ide", "Skip IDE sync").action(async (slug, directory, options) => {
11642
+ return new Command60("create").description("Create a new project from a starter kit").argument("<slug>", "Starter kit slug").argument("[directory]", "Project directory (default: ./<slug>)").option("-y, --yes", "Auto mode - use defaults, no prompts").option("--name <name>", "Project name").option("--skip-install", "Skip dependency installation").option("--skip-git", "Skip git initialization").option("--skip-framework", "Skip framework apply").option("--skip-ide", "Skip IDE sync").action(async (slug, directory, options) => {
11579
11643
  const configService = new ConfigService();
11580
11644
  const config = await configService.load();
11581
11645
  if (!config) {
@@ -11754,23 +11818,23 @@ async function getAllFiles(dir) {
11754
11818
 
11755
11819
  // src/commands/kit/index.ts
11756
11820
  function showKitHelp() {
11757
- console.log(chalk30.bold.cyan("\u{1F4E6} jai1 kit") + chalk30.dim(" - Qu\u1EA3n l\xFD starter kits"));
11821
+ console.log(chalk31.bold.cyan("\u{1F4E6} jai1 kit") + chalk31.dim(" - Qu\u1EA3n l\xFD starter kits"));
11758
11822
  console.log();
11759
- console.log(chalk30.bold("C\xE1c l\u1EC7nh:"));
11760
- console.log(` ${chalk30.cyan("list")} Li\u1EC7t k\xEA c\xE1c starter kits c\xF3 s\u1EB5n`);
11761
- console.log(` ${chalk30.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t starter kit`);
11762
- console.log(` ${chalk30.cyan("create")} T\u1EA1o project m\u1EDBi t\u1EEB starter kit`);
11823
+ console.log(chalk31.bold("C\xE1c l\u1EC7nh:"));
11824
+ console.log(` ${chalk31.cyan("list")} Li\u1EC7t k\xEA c\xE1c starter kits c\xF3 s\u1EB5n`);
11825
+ console.log(` ${chalk31.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t starter kit`);
11826
+ console.log(` ${chalk31.cyan("create")} T\u1EA1o project m\u1EDBi t\u1EEB starter kit`);
11763
11827
  console.log();
11764
- console.log(chalk30.bold("V\xED d\u1EE5:"));
11765
- console.log(chalk30.dim(" $ jai1 kit list"));
11766
- console.log(chalk30.dim(" $ jai1 kit list --category frontend"));
11767
- console.log(chalk30.dim(" $ jai1 kit info next-tw4-shadcn"));
11768
- console.log(chalk30.dim(" $ jai1 kit create next-tw4-shadcn my-project"));
11828
+ console.log(chalk31.bold("V\xED d\u1EE5:"));
11829
+ console.log(chalk31.dim(" $ jai1 kit list"));
11830
+ console.log(chalk31.dim(" $ jai1 kit list --category frontend"));
11831
+ console.log(chalk31.dim(" $ jai1 kit info next-tw4-shadcn"));
11832
+ console.log(chalk31.dim(" $ jai1 kit create next-tw4-shadcn my-project"));
11769
11833
  console.log();
11770
- console.log(chalk30.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
11834
+ console.log(chalk31.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
11771
11835
  }
11772
11836
  function createKitCommand() {
11773
- const cmd = new Command60("kit").description("Manage starter kits for new projects").action(() => {
11837
+ const cmd = new Command61("kit").description("Manage starter kits for new projects").action(() => {
11774
11838
  showKitHelp();
11775
11839
  });
11776
11840
  cmd.addCommand(createKitListCommand());
@@ -11780,21 +11844,21 @@ function createKitCommand() {
11780
11844
  }
11781
11845
 
11782
11846
  // src/commands/rules/index.ts
11783
- import { Command as Command67 } from "commander";
11784
- import chalk32 from "chalk";
11847
+ import { Command as Command68 } from "commander";
11848
+ import chalk33 from "chalk";
11785
11849
 
11786
11850
  // src/commands/rules/list.ts
11787
- import { Command as Command61 } from "commander";
11788
- import chalk31 from "chalk";
11851
+ import { Command as Command62 } from "commander";
11852
+ import chalk32 from "chalk";
11789
11853
  import Table7 from "cli-table3";
11790
11854
  function createRulesListCommand() {
11791
- return new Command61("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
11855
+ return new Command62("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
11792
11856
  const configService = new ConfigService();
11793
11857
  const config = await configService.load();
11794
11858
  if (!config) {
11795
11859
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
11796
11860
  }
11797
- console.log(chalk31.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
11861
+ console.log(chalk32.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
11798
11862
  console.log();
11799
11863
  try {
11800
11864
  const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
@@ -11811,23 +11875,23 @@ function createRulesListCommand() {
11811
11875
  return;
11812
11876
  }
11813
11877
  if (data.total === 0) {
11814
- console.log(chalk31.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
11878
+ console.log(chalk32.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
11815
11879
  return;
11816
11880
  }
11817
11881
  console.log(
11818
- chalk31.green(`\u2713 T\xECm th\u1EA5y ${chalk31.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
11882
+ chalk32.green(`\u2713 T\xECm th\u1EA5y ${chalk32.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
11819
11883
  );
11820
11884
  console.log();
11821
11885
  for (const preset of data.presets) {
11822
- console.log(chalk31.bold.cyan(`\u{1F4E6} ${preset.slug}`));
11886
+ console.log(chalk32.bold.cyan(`\u{1F4E6} ${preset.slug}`));
11823
11887
  const table = new Table7({
11824
11888
  style: { head: [], border: ["gray"], compact: true },
11825
11889
  colWidths: [15, 55]
11826
11890
  });
11827
11891
  table.push(
11828
- [chalk31.dim("T\xEAn"), chalk31.white(preset.name)],
11829
- [chalk31.dim("M\xF4 t\u1EA3"), chalk31.white(preset.description)],
11830
- [chalk31.dim("Version"), chalk31.green(`v${preset.version}`)]
11892
+ [chalk32.dim("T\xEAn"), chalk32.white(preset.name)],
11893
+ [chalk32.dim("M\xF4 t\u1EA3"), chalk32.white(preset.description)],
11894
+ [chalk32.dim("Version"), chalk32.green(`v${preset.version}`)]
11831
11895
  );
11832
11896
  const stackParts = [];
11833
11897
  if (preset.stack.frontend) stackParts.push(preset.stack.frontend);
@@ -11835,16 +11899,16 @@ function createRulesListCommand() {
11835
11899
  if (preset.stack.css) stackParts.push(preset.stack.css);
11836
11900
  if (preset.stack.database) stackParts.push(preset.stack.database);
11837
11901
  if (stackParts.length > 0) {
11838
- table.push([chalk31.dim("Stack"), chalk31.yellow(stackParts.join(" + "))]);
11902
+ table.push([chalk32.dim("Stack"), chalk32.yellow(stackParts.join(" + "))]);
11839
11903
  }
11840
11904
  table.push(
11841
- [chalk31.dim("Tags"), chalk31.dim(preset.tags.join(", ") || "-")],
11842
- [chalk31.dim("Downloads"), chalk31.white(preset.downloads.toString())]
11905
+ [chalk32.dim("Tags"), chalk32.dim(preset.tags.join(", ") || "-")],
11906
+ [chalk32.dim("Downloads"), chalk32.white(preset.downloads.toString())]
11843
11907
  );
11844
11908
  console.log(table.toString());
11845
11909
  console.log();
11846
11910
  }
11847
- console.log(chalk31.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
11911
+ console.log(chalk32.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
11848
11912
  } catch (error) {
11849
11913
  throw new Error(
11850
11914
  `L\u1ED7i khi t\u1EA3i presets: ${error instanceof Error ? error.message : String(error)}`
@@ -11854,7 +11918,7 @@ function createRulesListCommand() {
11854
11918
  }
11855
11919
 
11856
11920
  // src/commands/rules/init.ts
11857
- import { Command as Command62 } from "commander";
11921
+ import { Command as Command63 } from "commander";
11858
11922
  import { promises as fs23 } from "fs";
11859
11923
  import { join as join13 } from "path";
11860
11924
  import { select as select4, confirm as confirm10 } from "@inquirer/prompts";
@@ -11979,7 +12043,7 @@ var ProjectConfigService = class {
11979
12043
 
11980
12044
  // src/commands/rules/init.ts
11981
12045
  function createRulesInitCommand() {
11982
- return new Command62("init").description("Apply rule preset to project").option("--preset <slug>", "Preset slug to apply").option("--output <format>", "Output format: cursor, agents-md, both (default: cursor)", "cursor").option("-y, --yes", "Skip confirmations").action(async (options) => {
12046
+ return new Command63("init").description("Apply rule preset to project").option("--preset <slug>", "Preset slug to apply").option("--output <format>", "Output format: cursor, agents-md, both (default: cursor)", "cursor").option("-y, --yes", "Skip confirmations").action(async (options) => {
11983
12047
  const configService = new ConfigService();
11984
12048
  const config = await configService.load();
11985
12049
  if (!config) {
@@ -12111,7 +12175,7 @@ async function applyAgentsMdFormat(bundle) {
12111
12175
  }
12112
12176
 
12113
12177
  // src/commands/rules/apply.ts
12114
- import { Command as Command63 } from "commander";
12178
+ import { Command as Command64 } from "commander";
12115
12179
  import { promises as fs25 } from "fs";
12116
12180
  import { join as join15 } from "path";
12117
12181
  import { search, confirm as confirm11, checkbox as checkbox5 } from "@inquirer/prompts";
@@ -12625,7 +12689,7 @@ Restoring backup from ${metadata.timestamp}...`);
12625
12689
 
12626
12690
  // src/commands/rules/apply.ts
12627
12691
  function createRulesApplyCommand() {
12628
- return new Command63("apply").description("Apply rule preset to project with multi-IDE support").argument("[preset]", "Preset slug to apply (optional)").option("--ides <ides>", 'Comma-separated list of IDE formats (cursor,windsurf,antigravity,claude,agentsmd,gemini) or "all"').option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
12692
+ return new Command64("apply").description("Apply rule preset to project with multi-IDE support").argument("[preset]", "Preset slug to apply (optional)").option("--ides <ides>", 'Comma-separated list of IDE formats (cursor,windsurf,antigravity,claude,agentsmd,gemini) or "all"').option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
12629
12693
  const configService = new ConfigService();
12630
12694
  const config = await configService.load();
12631
12695
  if (!config) {
@@ -12920,11 +12984,11 @@ function createRulesApplyCommand() {
12920
12984
  }
12921
12985
 
12922
12986
  // src/commands/rules/restore.ts
12923
- import { Command as Command64 } from "commander";
12987
+ import { Command as Command65 } from "commander";
12924
12988
  import { join as join16 } from "path";
12925
12989
  import { select as select5, confirm as confirm12 } from "@inquirer/prompts";
12926
12990
  function createRulesRestoreCommand() {
12927
- return new Command64("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
12991
+ return new Command65("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
12928
12992
  const backupService = new BackupService();
12929
12993
  const backups = await backupService.listBackups();
12930
12994
  if (backups.length === 0) {
@@ -12993,12 +13057,12 @@ function formatTimestamp(timestamp) {
12993
13057
  }
12994
13058
 
12995
13059
  // src/commands/rules/sync.ts
12996
- import { Command as Command65 } from "commander";
13060
+ import { Command as Command66 } from "commander";
12997
13061
  import { promises as fs26 } from "fs";
12998
13062
  import { join as join17 } from "path";
12999
13063
  import { checkbox as checkbox6, confirm as confirm13, Separator } from "@inquirer/prompts";
13000
13064
  function createRulesSyncCommand() {
13001
- return new Command65("sync").description("Regenerate rule outputs for all configured IDEs").option("--ides <ides>", "Comma-separated list of IDEs to sync (default: all configured)").option("--detect", "Auto-detect active IDEs instead of using config").option("-y, --yes", "Skip confirmations").action(async (options) => {
13065
+ return new Command66("sync").description("Regenerate rule outputs for all configured IDEs").option("--ides <ides>", "Comma-separated list of IDEs to sync (default: all configured)").option("--detect", "Auto-detect active IDEs instead of using config").option("-y, --yes", "Skip confirmations").action(async (options) => {
13002
13066
  const rulePresetDir = join17(process.cwd(), ".jai1", "rule-preset");
13003
13067
  const presetJsonPath = join17(rulePresetDir, "preset.json");
13004
13068
  let presetExists = false;
@@ -13216,11 +13280,11 @@ function buildIdeChoices(currentIdes, detected, suggestions) {
13216
13280
  }
13217
13281
 
13218
13282
  // src/commands/rules/info.ts
13219
- import { Command as Command66 } from "commander";
13283
+ import { Command as Command67 } from "commander";
13220
13284
  import { promises as fs27 } from "fs";
13221
13285
  import { join as join18 } from "path";
13222
13286
  function createRulesInfoCommand() {
13223
- return new Command66("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
13287
+ return new Command67("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
13224
13288
  const projectConfigService = new ProjectConfigService();
13225
13289
  const rulesConfig = await projectConfigService.loadRules();
13226
13290
  if (!rulesConfig) {
@@ -13323,26 +13387,26 @@ async function checkIdeFilesExist(ideId, format) {
13323
13387
 
13324
13388
  // src/commands/rules/index.ts
13325
13389
  function showRulesHelp() {
13326
- console.log(chalk32.bold.cyan("\u{1F4CB} jai1 rules") + chalk32.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
13390
+ console.log(chalk33.bold.cyan("\u{1F4CB} jai1 rules") + chalk33.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
13327
13391
  console.log();
13328
- console.log(chalk32.bold("C\xE1c l\u1EC7nh:"));
13329
- console.log(` ${chalk32.cyan("list")} Li\u1EC7t k\xEA c\xE1c presets c\xF3 s\u1EB5n`);
13330
- console.log(` ${chalk32.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t preset`);
13331
- console.log(` ${chalk32.cyan("init")} Kh\u1EDFi t\u1EA1o rules t\u1EEB preset`);
13332
- console.log(` ${chalk32.cyan("apply")} \xC1p d\u1EE5ng preset v\xE0o project`);
13333
- console.log(` ${chalk32.cyan("sync")} \u0110\u1ED3ng b\u1ED9 rules sang c\xE1c \u0111\u1ECBnh d\u1EA1ng IDE`);
13334
- console.log(` ${chalk32.cyan("restore")} Kh\xF4i ph\u1EE5c rules t\u1EEB backup`);
13392
+ console.log(chalk33.bold("C\xE1c l\u1EC7nh:"));
13393
+ console.log(` ${chalk33.cyan("list")} Li\u1EC7t k\xEA c\xE1c presets c\xF3 s\u1EB5n`);
13394
+ console.log(` ${chalk33.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t preset`);
13395
+ console.log(` ${chalk33.cyan("init")} Kh\u1EDFi t\u1EA1o rules t\u1EEB preset`);
13396
+ console.log(` ${chalk33.cyan("apply")} \xC1p d\u1EE5ng preset v\xE0o project`);
13397
+ console.log(` ${chalk33.cyan("sync")} \u0110\u1ED3ng b\u1ED9 rules sang c\xE1c \u0111\u1ECBnh d\u1EA1ng IDE`);
13398
+ console.log(` ${chalk33.cyan("restore")} Kh\xF4i ph\u1EE5c rules t\u1EEB backup`);
13335
13399
  console.log();
13336
- console.log(chalk32.bold("V\xED d\u1EE5:"));
13337
- console.log(chalk32.dim(" $ jai1 rules list"));
13338
- console.log(chalk32.dim(" $ jai1 rules info react-typescript"));
13339
- console.log(chalk32.dim(" $ jai1 rules init --preset=react-typescript"));
13340
- console.log(chalk32.dim(" $ jai1 rules apply react-typescript"));
13400
+ console.log(chalk33.bold("V\xED d\u1EE5:"));
13401
+ console.log(chalk33.dim(" $ jai1 rules list"));
13402
+ console.log(chalk33.dim(" $ jai1 rules info react-typescript"));
13403
+ console.log(chalk33.dim(" $ jai1 rules init --preset=react-typescript"));
13404
+ console.log(chalk33.dim(" $ jai1 rules apply react-typescript"));
13341
13405
  console.log();
13342
- console.log(chalk32.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
13406
+ console.log(chalk33.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
13343
13407
  }
13344
13408
  function createRulesCommand() {
13345
- const rulesCommand = new Command67("rules").description("Manage rule presets for AI agents").action(() => {
13409
+ const rulesCommand = new Command68("rules").description("Manage rule presets for AI agents").action(() => {
13346
13410
  showRulesHelp();
13347
13411
  });
13348
13412
  rulesCommand.addCommand(createRulesListCommand());
@@ -13355,7 +13419,7 @@ function createRulesCommand() {
13355
13419
  }
13356
13420
 
13357
13421
  // src/commands/upgrade.ts
13358
- import { Command as Command68 } from "commander";
13422
+ import { Command as Command69 } from "commander";
13359
13423
  import { confirm as confirm14 } from "@inquirer/prompts";
13360
13424
  import { execSync as execSync4 } from "child_process";
13361
13425
  var colors2 = {
@@ -13367,7 +13431,7 @@ var colors2 = {
13367
13431
  bold: "\x1B[1m"
13368
13432
  };
13369
13433
  function createUpgradeCommand() {
13370
- return new Command68("upgrade").description("Upgrade CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
13434
+ return new Command69("upgrade").description("Upgrade CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
13371
13435
  await handleUpgrade(options);
13372
13436
  });
13373
13437
  }
@@ -13515,11 +13579,11 @@ function getInstallCommand(packageManager2) {
13515
13579
  }
13516
13580
 
13517
13581
  // src/commands/clean.ts
13518
- import { Command as Command69 } from "commander";
13582
+ import { Command as Command70 } from "commander";
13519
13583
  import { confirm as confirm15, select as select6 } from "@inquirer/prompts";
13520
13584
  import { join as join19 } from "path";
13521
13585
  function createCleanCommand() {
13522
- return new Command69("clean").description("Clean up backups, cache, and temporary files").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--all", "Clean all (backups + cache)").action(async (options) => {
13586
+ return new Command70("clean").description("Clean up backups, cache, and temporary files").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--all", "Clean all (backups + cache)").action(async (options) => {
13523
13587
  await handleClean(options);
13524
13588
  });
13525
13589
  }
@@ -13633,7 +13697,7 @@ async function cleanTarget(target, skipConfirm) {
13633
13697
  }
13634
13698
 
13635
13699
  // src/commands/redmine/check.ts
13636
- import { Command as Command70 } from "commander";
13700
+ import { Command as Command71 } from "commander";
13637
13701
 
13638
13702
  // src/services/redmine-config.service.ts
13639
13703
  import { readFile as readFile7 } from "fs/promises";
@@ -13940,7 +14004,7 @@ async function checkConnectivity(config) {
13940
14004
 
13941
14005
  // src/commands/redmine/check.ts
13942
14006
  function createRedmineCheckCommand() {
13943
- const cmd = new Command70("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
14007
+ const cmd = new Command71("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
13944
14008
  await handleRedmineCheck(options);
13945
14009
  });
13946
14010
  return cmd;
@@ -13968,7 +14032,7 @@ async function handleRedmineCheck(options) {
13968
14032
  }
13969
14033
 
13970
14034
  // src/commands/redmine/sync-issue.ts
13971
- import { Command as Command71 } from "commander";
14035
+ import { Command as Command72 } from "commander";
13972
14036
 
13973
14037
  // src/sync-issue.ts
13974
14038
  import { resolve as resolve3, relative } from "path";
@@ -14352,7 +14416,7 @@ function extractIssueIdFromUrl(url) {
14352
14416
 
14353
14417
  // src/commands/redmine/sync-issue.ts
14354
14418
  function createSyncIssueCommand() {
14355
- const cmd = new Command71("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
14419
+ const cmd = new Command72("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
14356
14420
  await handleSyncIssue(options);
14357
14421
  });
14358
14422
  return cmd;
@@ -14396,7 +14460,7 @@ async function handleSyncIssue(options) {
14396
14460
  }
14397
14461
 
14398
14462
  // src/commands/redmine/sync-project.ts
14399
- import { Command as Command72 } from "commander";
14463
+ import { Command as Command73 } from "commander";
14400
14464
 
14401
14465
  // src/sync-project.ts
14402
14466
  async function syncProject(config, options = {}) {
@@ -14466,7 +14530,7 @@ async function syncProject(config, options = {}) {
14466
14530
 
14467
14531
  // src/commands/redmine/sync-project.ts
14468
14532
  function createSyncProjectCommand() {
14469
- const cmd = new Command72("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
14533
+ const cmd = new Command73("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
14470
14534
  await handleSyncProject(options);
14471
14535
  });
14472
14536
  return cmd;
@@ -14521,12 +14585,12 @@ async function handleSyncProject(options) {
14521
14585
  }
14522
14586
 
14523
14587
  // src/commands/framework/info.ts
14524
- import { Command as Command73 } from "commander";
14588
+ import { Command as Command74 } from "commander";
14525
14589
  import { promises as fs28 } from "fs";
14526
14590
  import { join as join20 } from "path";
14527
14591
  import { homedir as homedir6 } from "os";
14528
14592
  function createInfoCommand() {
14529
- const cmd = new Command73("info").description("Show client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
14593
+ const cmd = new Command74("info").description("Show client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
14530
14594
  await handleInfo(options);
14531
14595
  });
14532
14596
  return cmd;
@@ -14582,7 +14646,7 @@ async function getProjectStatus2() {
14582
14646
  }
14583
14647
 
14584
14648
  // src/commands/self-update.ts
14585
- import { Command as Command74 } from "commander";
14649
+ import { Command as Command75 } from "commander";
14586
14650
  import { confirm as confirm16 } from "@inquirer/prompts";
14587
14651
  import { execSync as execSync5 } from "child_process";
14588
14652
  var colors3 = {
@@ -14594,7 +14658,7 @@ var colors3 = {
14594
14658
  bold: "\x1B[1m"
14595
14659
  };
14596
14660
  function createSelfUpdateCommand() {
14597
- return new Command74("self-update").description("Update CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
14661
+ return new Command75("self-update").description("Update CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
14598
14662
  await handleSelfUpdate(options);
14599
14663
  });
14600
14664
  }
@@ -14734,10 +14798,10 @@ function getInstallCommand2(packageManager2) {
14734
14798
  }
14735
14799
 
14736
14800
  // src/commands/clear-backups.ts
14737
- import { Command as Command75 } from "commander";
14801
+ import { Command as Command76 } from "commander";
14738
14802
  import { confirm as confirm17 } from "@inquirer/prompts";
14739
14803
  function createClearBackupsCommand() {
14740
- return new Command75("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
14804
+ return new Command76("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
14741
14805
  const service = new ComponentsService();
14742
14806
  const backups = await service.listBackups(process.cwd());
14743
14807
  if (backups.length === 0) {
@@ -14762,7 +14826,7 @@ function createClearBackupsCommand() {
14762
14826
  }
14763
14827
 
14764
14828
  // src/commands/vscode/index.ts
14765
- import { Command as Command76 } from "commander";
14829
+ import { Command as Command77 } from "commander";
14766
14830
  import { checkbox as checkbox7, confirm as confirm18, select as select7 } from "@inquirer/prompts";
14767
14831
  import fs29 from "fs/promises";
14768
14832
  import path12 from "path";
@@ -14902,7 +14966,7 @@ var PERFORMANCE_GROUPS2 = {
14902
14966
  }
14903
14967
  };
14904
14968
  function createVSCodeCommand() {
14905
- const vscodeCommand = new Command76("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
14969
+ const vscodeCommand = new Command77("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
14906
14970
  vscodeCommand.action(async () => {
14907
14971
  await interactiveMode2();
14908
14972
  });
@@ -15073,10 +15137,10 @@ async function resetSettings2(groupKeys) {
15073
15137
  }
15074
15138
 
15075
15139
  // src/commands/migrate-ide.ts
15076
- import { Command as Command77 } from "commander";
15140
+ import { Command as Command78 } from "commander";
15077
15141
  import { checkbox as checkbox8, confirm as confirm19 } from "@inquirer/prompts";
15078
15142
  function createMigrateIdeCommand() {
15079
- const cmd = new Command77("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (Cursor, Windsurf, Claude Code, etc.)").option("--ide <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").action(async (options) => {
15143
+ const cmd = new Command78("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (Cursor, Windsurf, Claude Code, etc.)").option("--ide <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").action(async (options) => {
15080
15144
  await runMigrateIde(options);
15081
15145
  });
15082
15146
  return cmd;
@@ -15185,62 +15249,63 @@ async function runMigrateIde(options) {
15185
15249
 
15186
15250
  // src/utils/help-formatter.ts
15187
15251
  import boxen4 from "boxen";
15188
- import chalk33 from "chalk";
15252
+ import chalk34 from "chalk";
15189
15253
  import gradient from "gradient-string";
15190
15254
  import figlet from "figlet";
15191
15255
  function showCustomHelp(version) {
15192
15256
  const title = figlet.textSync("JAI1", { font: "Small" });
15193
15257
  console.log(gradient.pastel(title));
15194
15258
  console.log(
15195
- boxen4(chalk33.cyan(`Agentic Coding CLI v${version}`), {
15259
+ boxen4(chalk34.cyan(`Agentic Coding CLI v${version}`), {
15196
15260
  padding: { left: 1, right: 1, top: 0, bottom: 0 },
15197
15261
  borderStyle: "round",
15198
15262
  borderColor: "cyan"
15199
15263
  })
15200
15264
  );
15201
- console.log(chalk33.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
15265
+ console.log(chalk34.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
15202
15266
  console.log(" auth X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client");
15203
15267
  console.log(" status Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh");
15204
15268
  console.log(" client-info T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n");
15205
15269
  console.log(" errors Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9");
15206
15270
  console.log(" guide H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh");
15271
+ console.log(" quickstart B\u1EAFt \u0111\u1EA7u t\u1EEB \u0111\xE2u? (theo t\xECnh hu\u1ED1ng)");
15207
15272
  console.log(" doctor Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i");
15208
- console.log(chalk33.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
15273
+ console.log(chalk34.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
15209
15274
  console.log(" apply C\xE0i \u0111\u1EB7t components (interactive)");
15210
15275
  console.log(" update C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i");
15211
15276
  console.log(" check Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server");
15212
- console.log(chalk33.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
15277
+ console.log(chalk34.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
15213
15278
  console.log(" ide L\u1EC7nh c\u1EA5u h\xECnh IDE");
15214
15279
  console.log(" chat Chat AI v\u1EDBi Jai1 LLM Proxy");
15215
15280
  console.log(" openai-keys Th\xF4ng tin API credentials");
15216
- console.log(chalk33.bold("\n\u{1F916} AI Tools"));
15281
+ console.log(chalk34.bold("\n\u{1F916} AI Tools"));
15217
15282
  console.log(" translate D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI");
15218
15283
  console.log(" image T\u1EA1o \u1EA3nh (Coming Soon)");
15219
15284
  console.log(" stats Th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM");
15220
15285
  console.log(" feedback G\u1EEDi b\xE1o c\xE1o/\u0111\u1EC1 xu\u1EA5t");
15221
- console.log(chalk33.bold("\n\u{1F4C1} Project"));
15286
+ console.log(chalk34.bold("\n\u{1F4C1} Project"));
15222
15287
  console.log(" kit Qu\u1EA3n l\xFD starter kits");
15223
15288
  console.log(" rules Qu\u1EA3n l\xFD rule presets");
15224
15289
  console.log(" deps Qu\u1EA3n l\xFD dependencies");
15225
15290
  console.log(" redmine Redmine context sync");
15226
- console.log(chalk33.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
15291
+ console.log(chalk34.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
15227
15292
  console.log(" upgrade C\u1EADp nh\u1EADt CLI client");
15228
15293
  console.log(" clean D\u1ECDn d\u1EB9p cache/backup");
15229
15294
  console.log(" utils Developer utilities");
15230
15295
  const name = getCliName();
15231
- console.log(chalk33.dim(`
15296
+ console.log(chalk34.dim(`
15232
15297
  S\u1EED d\u1EE5ng: ${name} [l\u1EC7nh] --help \u0111\u1EC3 xem chi ti\u1EBFt`));
15233
15298
  }
15234
15299
  function showUnknownCommand(commandName) {
15235
- console.error(chalk33.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
15300
+ console.error(chalk34.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
15236
15301
  const name = getCliName();
15237
- console.error(chalk33.dim(`
15302
+ console.error(chalk34.dim(`
15238
15303
  G\u1EE3i \xFD: Ch\u1EA1y ${name} --help \u0111\u1EC3 xem danh s\xE1ch l\u1EC7nh`));
15239
15304
  }
15240
15305
 
15241
15306
  // src/cli.ts
15242
15307
  checkNodeVersion();
15243
- var program = new Command78();
15308
+ var program = new Command79();
15244
15309
  if (process.argv.includes("-v") || process.argv.includes("--version")) {
15245
15310
  console.log(package_default.version);
15246
15311
  if (!process.argv.includes("--skip-update-check")) {
@@ -15263,6 +15328,7 @@ program.addCommand(createUpdateCommand());
15263
15328
  program.addCommand(createCheckCommand());
15264
15329
  program.addCommand(createIdeCommand());
15265
15330
  program.addCommand(createGuideCommand());
15331
+ program.addCommand(createQuickstartCommand());
15266
15332
  program.addCommand(createDoctorCommand());
15267
15333
  program.addCommand(createChatCommand());
15268
15334
  program.addCommand(createOpenAiKeysCommand());
@@ -15279,9 +15345,9 @@ program.addCommand(createKitCommand());
15279
15345
  program.addCommand(createRulesCommand());
15280
15346
  program.addCommand(createUpgradeCommand());
15281
15347
  program.addCommand(createCleanCommand());
15282
- var redmineCommand = new Command78("redmine").description("Redmine context sync commands");
15348
+ var redmineCommand = new Command79("redmine").description("Redmine context sync commands");
15283
15349
  redmineCommand.addCommand(createRedmineCheckCommand());
15284
- var syncCommand = new Command78("sync").description("Sync Redmine issues to markdown files");
15350
+ var syncCommand = new Command79("sync").description("Sync Redmine issues to markdown files");
15285
15351
  syncCommand.addCommand(createSyncIssueCommand());
15286
15352
  syncCommand.addCommand(createSyncProjectCommand());
15287
15353
  redmineCommand.addCommand(syncCommand);