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