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