@jvittechs/j 1.0.24 → 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 +571 -519
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -42,7 +42,7 @@ function checkNodeVersion() {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/cli.ts
|
|
45
|
-
import { Command as
|
|
45
|
+
import { Command as Command79 } from "commander";
|
|
46
46
|
|
|
47
47
|
// src/errors/index.ts
|
|
48
48
|
var Jai1Error = class extends Error {
|
|
@@ -169,7 +169,7 @@ import { basename as basename4 } from "path";
|
|
|
169
169
|
// package.json
|
|
170
170
|
var package_default = {
|
|
171
171
|
name: "@jvittechs/j",
|
|
172
|
-
version: "1.0.
|
|
172
|
+
version: "1.0.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,37 +11013,37 @@ 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
|
|
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) => {
|
|
10991
11041
|
if (!options.status && !options.notes) {
|
|
10992
|
-
console.error(
|
|
11042
|
+
console.error(chalk23.red("\u274C At least one of --status or --notes is required"));
|
|
10993
11043
|
process.exit(1);
|
|
10994
11044
|
}
|
|
10995
11045
|
if (options.status && !VALID_STATUSES.includes(options.status)) {
|
|
10996
|
-
console.error(
|
|
11046
|
+
console.error(chalk23.red(`\u274C Invalid status. Must be: ${VALID_STATUSES.join(", ")}`));
|
|
10997
11047
|
process.exit(1);
|
|
10998
11048
|
}
|
|
10999
11049
|
const service = new TaskService();
|
|
@@ -11014,24 +11064,24 @@ function createTaskUpdateCommand() {
|
|
|
11014
11064
|
if (options.notes) {
|
|
11015
11065
|
parts.push(`\u{1F4DD} notes updated`);
|
|
11016
11066
|
}
|
|
11017
|
-
console.log(
|
|
11067
|
+
console.log(chalk23.green(`\u2705 ${task.id} \u2192 ${parts.join(" | ")}`));
|
|
11018
11068
|
} catch (error) {
|
|
11019
|
-
console.error(
|
|
11069
|
+
console.error(chalk23.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11020
11070
|
process.exit(1);
|
|
11021
11071
|
}
|
|
11022
11072
|
});
|
|
11023
11073
|
}
|
|
11024
11074
|
|
|
11025
11075
|
// src/commands/tasks/show.ts
|
|
11026
|
-
import { Command as
|
|
11027
|
-
import
|
|
11076
|
+
import { Command as Command51 } from "commander";
|
|
11077
|
+
import chalk24 from "chalk";
|
|
11028
11078
|
function createTaskShowCommand() {
|
|
11029
|
-
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) => {
|
|
11030
11080
|
const service = new TaskService();
|
|
11031
11081
|
if (query.startsWith("T-")) {
|
|
11032
11082
|
const task = await service.findById(query);
|
|
11033
11083
|
if (!task) {
|
|
11034
|
-
console.error(
|
|
11084
|
+
console.error(chalk24.red(`\u274C Task ${query} not found`));
|
|
11035
11085
|
process.exit(1);
|
|
11036
11086
|
}
|
|
11037
11087
|
if (options.json) {
|
|
@@ -11042,34 +11092,34 @@ function createTaskShowCommand() {
|
|
|
11042
11092
|
const statusIcon = blocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11043
11093
|
const priIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11044
11094
|
const priLabel = PRIORITY_LABELS[task.priority] || "Medium";
|
|
11045
|
-
console.log(
|
|
11095
|
+
console.log(chalk24.bold(`
|
|
11046
11096
|
\u{1F4CC} ${task.id}: ${task.title}
|
|
11047
11097
|
`));
|
|
11048
|
-
console.log(` ${
|
|
11049
|
-
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}`);
|
|
11050
11100
|
if (task.parent) {
|
|
11051
|
-
console.log(` ${
|
|
11101
|
+
console.log(` ${chalk24.dim("Parent:")} ${task.parent}`);
|
|
11052
11102
|
}
|
|
11053
11103
|
if (task.assigned_to) {
|
|
11054
|
-
console.log(` ${
|
|
11104
|
+
console.log(` ${chalk24.dim("Assigned:")} @${task.assigned_to} (${task.claimed_at})`);
|
|
11055
11105
|
}
|
|
11056
11106
|
if (task.depends_on.length > 0) {
|
|
11057
|
-
console.log(` ${
|
|
11107
|
+
console.log(` ${chalk24.dim("Depends on:")} ${task.depends_on.join(", ")}`);
|
|
11058
11108
|
if (blocked) {
|
|
11059
|
-
console.log(` ${
|
|
11109
|
+
console.log(` ${chalk24.dim("Blocked by:")} ${chalk24.red(blockedBy.join(", "))}`);
|
|
11060
11110
|
}
|
|
11061
11111
|
}
|
|
11062
11112
|
if (task.tags.length > 0) {
|
|
11063
|
-
console.log(` ${
|
|
11113
|
+
console.log(` ${chalk24.dim("Tags:")} ${task.tags.join(", ")}`);
|
|
11064
11114
|
}
|
|
11065
11115
|
if (task.branch) {
|
|
11066
|
-
console.log(` ${
|
|
11116
|
+
console.log(` ${chalk24.dim("Branch:")} ${task.branch}`);
|
|
11067
11117
|
}
|
|
11068
11118
|
if (task.notes) {
|
|
11069
|
-
console.log(` ${
|
|
11119
|
+
console.log(` ${chalk24.dim("Notes:")} ${task.notes}`);
|
|
11070
11120
|
}
|
|
11071
|
-
console.log(` ${
|
|
11072
|
-
console.log(` ${
|
|
11121
|
+
console.log(` ${chalk24.dim("Created:")} ${task.created}`);
|
|
11122
|
+
console.log(` ${chalk24.dim("Updated:")} ${task.updated}`);
|
|
11073
11123
|
console.log();
|
|
11074
11124
|
} else {
|
|
11075
11125
|
const tasks = await service.filter({ parent: query });
|
|
@@ -11078,10 +11128,10 @@ function createTaskShowCommand() {
|
|
|
11078
11128
|
return;
|
|
11079
11129
|
}
|
|
11080
11130
|
if (tasks.length === 0) {
|
|
11081
|
-
console.log(
|
|
11131
|
+
console.log(chalk24.dim(`No tasks for parent: ${query}`));
|
|
11082
11132
|
return;
|
|
11083
11133
|
}
|
|
11084
|
-
console.log(
|
|
11134
|
+
console.log(chalk24.bold(`
|
|
11085
11135
|
\u{1F4CB} ${query} (${tasks.length} tasks)
|
|
11086
11136
|
`));
|
|
11087
11137
|
const allTasks = await service.readAll();
|
|
@@ -11089,11 +11139,11 @@ function createTaskShowCommand() {
|
|
|
11089
11139
|
for (const task of tasks) {
|
|
11090
11140
|
const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
|
|
11091
11141
|
const icon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11092
|
-
let line = ` ${icon} ${
|
|
11093
|
-
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}`);
|
|
11094
11144
|
if (isBlocked) {
|
|
11095
11145
|
const bb = task.depends_on.filter((id) => !doneIds.has(id));
|
|
11096
|
-
line +=
|
|
11146
|
+
line += chalk24.red(` (blocked: ${bb.join(", ")})`);
|
|
11097
11147
|
}
|
|
11098
11148
|
console.log(line);
|
|
11099
11149
|
}
|
|
@@ -11103,11 +11153,11 @@ function createTaskShowCommand() {
|
|
|
11103
11153
|
}
|
|
11104
11154
|
|
|
11105
11155
|
// src/commands/tasks/pick.ts
|
|
11106
|
-
import { Command as
|
|
11107
|
-
import
|
|
11156
|
+
import { Command as Command52 } from "commander";
|
|
11157
|
+
import chalk25 from "chalk";
|
|
11108
11158
|
import { confirm as confirm9 } from "@inquirer/prompts";
|
|
11109
11159
|
function createTaskPickCommand() {
|
|
11110
|
-
return new
|
|
11160
|
+
return new Command52("pick").description("Claim the next available task").option("-j, --json", "Output JSON").action(async (options) => {
|
|
11111
11161
|
const service = new TaskService();
|
|
11112
11162
|
const ready = await service.getReady();
|
|
11113
11163
|
if (ready.length === 0) {
|
|
@@ -11115,8 +11165,8 @@ function createTaskPickCommand() {
|
|
|
11115
11165
|
console.log(JSON.stringify({ picked: null, message: "No tasks ready" }));
|
|
11116
11166
|
return;
|
|
11117
11167
|
}
|
|
11118
|
-
console.log(
|
|
11119
|
-
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 "..."'));
|
|
11120
11170
|
return;
|
|
11121
11171
|
}
|
|
11122
11172
|
const top = ready[0];
|
|
@@ -11126,13 +11176,13 @@ function createTaskPickCommand() {
|
|
|
11126
11176
|
console.log(JSON.stringify(picked2, null, 2));
|
|
11127
11177
|
return;
|
|
11128
11178
|
}
|
|
11129
|
-
console.log(
|
|
11130
|
-
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}`);
|
|
11131
11181
|
if (top.parent) {
|
|
11132
|
-
console.log(` ${
|
|
11182
|
+
console.log(` ${chalk25.dim("Parent:")} ${top.parent}`);
|
|
11133
11183
|
}
|
|
11134
11184
|
if (ready.length > 1) {
|
|
11135
|
-
console.log(
|
|
11185
|
+
console.log(chalk25.dim(`
|
|
11136
11186
|
+${ready.length - 1} more tasks ready`));
|
|
11137
11187
|
}
|
|
11138
11188
|
const proceed = await confirm9({
|
|
@@ -11140,20 +11190,20 @@ function createTaskPickCommand() {
|
|
|
11140
11190
|
default: true
|
|
11141
11191
|
});
|
|
11142
11192
|
if (!proceed) {
|
|
11143
|
-
console.log(
|
|
11193
|
+
console.log(chalk25.dim("\nCancelled."));
|
|
11144
11194
|
return;
|
|
11145
11195
|
}
|
|
11146
11196
|
const picked = await service.pick(top.id);
|
|
11147
|
-
console.log(
|
|
11197
|
+
console.log(chalk25.green(`
|
|
11148
11198
|
\u2705 ${picked.id} assigned to @${picked.assigned_to}, status \u2192 in_progress`));
|
|
11149
11199
|
});
|
|
11150
11200
|
}
|
|
11151
11201
|
|
|
11152
11202
|
// src/commands/tasks/done.ts
|
|
11153
|
-
import { Command as
|
|
11154
|
-
import
|
|
11203
|
+
import { Command as Command53 } from "commander";
|
|
11204
|
+
import chalk26 from "chalk";
|
|
11155
11205
|
function createTaskDoneCommand() {
|
|
11156
|
-
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) => {
|
|
11157
11207
|
const service = new TaskService();
|
|
11158
11208
|
try {
|
|
11159
11209
|
const task = await service.markDone(id);
|
|
@@ -11161,19 +11211,19 @@ function createTaskDoneCommand() {
|
|
|
11161
11211
|
console.log(JSON.stringify(task, null, 2));
|
|
11162
11212
|
return;
|
|
11163
11213
|
}
|
|
11164
|
-
console.log(
|
|
11214
|
+
console.log(chalk26.green(`\u2705 ${task.id}: ${task.title} \u2192 done`));
|
|
11165
11215
|
} catch (error) {
|
|
11166
|
-
console.error(
|
|
11216
|
+
console.error(chalk26.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11167
11217
|
process.exit(1);
|
|
11168
11218
|
}
|
|
11169
11219
|
});
|
|
11170
11220
|
}
|
|
11171
11221
|
|
|
11172
11222
|
// src/commands/tasks/dep.ts
|
|
11173
|
-
import { Command as
|
|
11174
|
-
import
|
|
11223
|
+
import { Command as Command54 } from "commander";
|
|
11224
|
+
import chalk27 from "chalk";
|
|
11175
11225
|
function createTaskDepCommand() {
|
|
11176
|
-
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) => {
|
|
11177
11227
|
const service = new TaskService();
|
|
11178
11228
|
try {
|
|
11179
11229
|
const task = await service.addDependency(childId, parentId);
|
|
@@ -11181,156 +11231,156 @@ function createTaskDepCommand() {
|
|
|
11181
11231
|
console.log(JSON.stringify(task, null, 2));
|
|
11182
11232
|
return;
|
|
11183
11233
|
}
|
|
11184
|
-
console.log(
|
|
11185
|
-
console.log(
|
|
11234
|
+
console.log(chalk27.green(`\u2705 ${childId} now depends on ${parentId}`));
|
|
11235
|
+
console.log(chalk27.dim(` ${task.title} \u2192 waits for ${parentId}`));
|
|
11186
11236
|
} catch (error) {
|
|
11187
|
-
console.error(
|
|
11237
|
+
console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11188
11238
|
process.exit(1);
|
|
11189
11239
|
}
|
|
11190
11240
|
});
|
|
11191
11241
|
}
|
|
11192
11242
|
|
|
11193
11243
|
// src/commands/tasks/sync.ts
|
|
11194
|
-
import { Command as
|
|
11195
|
-
import
|
|
11244
|
+
import { Command as Command55 } from "commander";
|
|
11245
|
+
import chalk28 from "chalk";
|
|
11196
11246
|
function createTaskSyncCommand() {
|
|
11197
|
-
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) => {
|
|
11198
11248
|
const service = new TaskService();
|
|
11199
11249
|
if (options.pull) {
|
|
11200
|
-
console.log(
|
|
11250
|
+
console.log(chalk28.dim("\u23F3 Pulling tasks from origin/main..."));
|
|
11201
11251
|
try {
|
|
11202
11252
|
const result = await service.syncPull();
|
|
11203
|
-
console.log(
|
|
11253
|
+
console.log(chalk28.green(`\u2705 Sync pull complete: ${result.merged} tasks merged`));
|
|
11204
11254
|
} catch (error) {
|
|
11205
|
-
console.error(
|
|
11255
|
+
console.error(chalk28.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11206
11256
|
process.exit(1);
|
|
11207
11257
|
}
|
|
11208
11258
|
return;
|
|
11209
11259
|
}
|
|
11210
|
-
console.log(
|
|
11260
|
+
console.log(chalk28.dim("\u23F3 Syncing tasks to git..."));
|
|
11211
11261
|
try {
|
|
11212
11262
|
await service.syncPush();
|
|
11213
|
-
console.log(
|
|
11263
|
+
console.log(chalk28.green("\u2705 Tasks synced to git"));
|
|
11214
11264
|
} catch (error) {
|
|
11215
|
-
console.error(
|
|
11265
|
+
console.error(chalk28.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11216
11266
|
process.exit(1);
|
|
11217
11267
|
}
|
|
11218
11268
|
});
|
|
11219
11269
|
}
|
|
11220
11270
|
|
|
11221
11271
|
// src/commands/tasks/guide.ts
|
|
11222
|
-
import { Command as
|
|
11223
|
-
import
|
|
11272
|
+
import { Command as Command56 } from "commander";
|
|
11273
|
+
import chalk29 from "chalk";
|
|
11224
11274
|
var GUIDE_TEXT = `
|
|
11225
|
-
${
|
|
11226
|
-
|
|
11227
|
-
${
|
|
11228
|
-
${
|
|
11229
|
-
${
|
|
11230
|
-
${
|
|
11231
|
-
${
|
|
11232
|
-
${
|
|
11233
|
-
|
|
11234
|
-
${
|
|
11235
|
-
${
|
|
11236
|
-
${
|
|
11237
|
-
${
|
|
11238
|
-
${
|
|
11239
|
-
|
|
11240
|
-
${
|
|
11241
|
-
${
|
|
11242
|
-
${
|
|
11243
|
-
${
|
|
11244
|
-
${
|
|
11245
|
-
|
|
11246
|
-
${
|
|
11247
|
-
${
|
|
11248
|
-
${
|
|
11249
|
-
${
|
|
11250
|
-
${
|
|
11251
|
-
${
|
|
11252
|
-
${
|
|
11253
|
-
|
|
11254
|
-
${
|
|
11255
|
-
${
|
|
11256
|
-
${
|
|
11257
|
-
|
|
11258
|
-
${
|
|
11259
|
-
${
|
|
11260
|
-
${
|
|
11261
|
-
${
|
|
11262
|
-
|
|
11263
|
-
${
|
|
11264
|
-
${
|
|
11265
|
-
|
|
11266
|
-
${
|
|
11267
|
-
${
|
|
11268
|
-
|
|
11269
|
-
${
|
|
11270
|
-
${
|
|
11271
|
-
|
|
11272
|
-
${
|
|
11273
|
-
${
|
|
11274
|
-
${
|
|
11275
|
-
${
|
|
11276
|
-
|
|
11277
|
-
${
|
|
11278
|
-
${
|
|
11279
|
-
${
|
|
11280
|
-
${
|
|
11281
|
-
|
|
11282
|
-
${
|
|
11283
|
-
${
|
|
11284
|
-
|
|
11285
|
-
${
|
|
11286
|
-
${
|
|
11287
|
-
${
|
|
11288
|
-
|
|
11289
|
-
${
|
|
11290
|
-
${
|
|
11291
|
-
|
|
11292
|
-
${
|
|
11293
|
-
${
|
|
11294
|
-
1. ${
|
|
11295
|
-
2. ${
|
|
11296
|
-
3. ${
|
|
11297
|
-
4. ${
|
|
11298
|
-
|
|
11299
|
-
${
|
|
11300
|
-
1. ${
|
|
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>)
|
|
11301
11351
|
2. Implement task
|
|
11302
|
-
3. ${
|
|
11352
|
+
3. ${chalk29.cyan("jai1 t done")} <id>
|
|
11303
11353
|
|
|
11304
|
-
${
|
|
11354
|
+
${chalk29.dim("Status transitions:")}
|
|
11305
11355
|
add \u2192 todo (default)
|
|
11306
11356
|
pick \u2192 in_progress (auto assign)
|
|
11307
11357
|
done \u2192 done
|
|
11308
11358
|
update -s \u2192 any valid status
|
|
11309
11359
|
|
|
11310
|
-
${
|
|
11311
|
-
${
|
|
11312
|
-
${
|
|
11313
|
-
${
|
|
11314
|
-
${
|
|
11315
|
-
${
|
|
11316
|
-
${
|
|
11317
|
-
${
|
|
11318
|
-
${
|
|
11319
|
-
${
|
|
11320
|
-
${
|
|
11321
|
-
${
|
|
11322
|
-
|
|
11323
|
-
${
|
|
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)")}
|
|
11324
11374
|
`;
|
|
11325
11375
|
function createTaskGuideCommand() {
|
|
11326
|
-
return new
|
|
11376
|
+
return new Command56("guide").description("Show full task management guide").action(() => {
|
|
11327
11377
|
console.log(GUIDE_TEXT);
|
|
11328
11378
|
});
|
|
11329
11379
|
}
|
|
11330
11380
|
|
|
11331
11381
|
// src/commands/tasks/index.ts
|
|
11332
11382
|
function createTasksCommand() {
|
|
11333
|
-
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) => {
|
|
11334
11384
|
if (actionCommand.name() !== "guide") {
|
|
11335
11385
|
TaskService.ensureJai1Dir();
|
|
11336
11386
|
}
|
|
@@ -11354,12 +11404,12 @@ function createTasksCommand() {
|
|
|
11354
11404
|
}
|
|
11355
11405
|
|
|
11356
11406
|
// src/commands/kit/index.ts
|
|
11357
|
-
import { Command as
|
|
11358
|
-
import
|
|
11407
|
+
import { Command as Command61 } from "commander";
|
|
11408
|
+
import chalk31 from "chalk";
|
|
11359
11409
|
|
|
11360
11410
|
// src/commands/kit/list.ts
|
|
11361
|
-
import { Command as
|
|
11362
|
-
import
|
|
11411
|
+
import { Command as Command58 } from "commander";
|
|
11412
|
+
import chalk30 from "chalk";
|
|
11363
11413
|
import Table6 from "cli-table3";
|
|
11364
11414
|
|
|
11365
11415
|
// src/services/starter-kit.service.ts
|
|
@@ -11427,13 +11477,13 @@ var StarterKitService = class {
|
|
|
11427
11477
|
|
|
11428
11478
|
// src/commands/kit/list.ts
|
|
11429
11479
|
function createKitListCommand() {
|
|
11430
|
-
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) => {
|
|
11431
11481
|
const configService = new ConfigService();
|
|
11432
11482
|
const config = await configService.load();
|
|
11433
11483
|
if (!config) {
|
|
11434
11484
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
11435
11485
|
}
|
|
11436
|
-
console.log(
|
|
11486
|
+
console.log(chalk30.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
|
|
11437
11487
|
console.log();
|
|
11438
11488
|
const kitService = new StarterKitService();
|
|
11439
11489
|
const kits = await kitService.list(config, {
|
|
@@ -11441,9 +11491,9 @@ function createKitListCommand() {
|
|
|
11441
11491
|
search: options.search
|
|
11442
11492
|
});
|
|
11443
11493
|
if (kits.length === 0) {
|
|
11444
|
-
console.log(
|
|
11494
|
+
console.log(chalk30.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
|
|
11445
11495
|
if (options.category || options.search) {
|
|
11446
|
-
console.log(
|
|
11496
|
+
console.log(chalk30.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
|
|
11447
11497
|
}
|
|
11448
11498
|
return;
|
|
11449
11499
|
}
|
|
@@ -11467,35 +11517,35 @@ function createKitListCommand() {
|
|
|
11467
11517
|
const categoryKits = byCategory[category];
|
|
11468
11518
|
const categoryIcon = category === "frontend" ? "\u{1F3A8}" : category === "backend" ? "\u2699\uFE0F" : category === "fullstack" ? "\u{1F680}" : "\u{1F4E6}";
|
|
11469
11519
|
console.log(
|
|
11470
|
-
|
|
11520
|
+
chalk30.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
|
|
11471
11521
|
);
|
|
11472
11522
|
const table = new Table6({
|
|
11473
11523
|
head: [
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11524
|
+
chalk30.cyan("Slug"),
|
|
11525
|
+
chalk30.cyan("M\xF4 t\u1EA3"),
|
|
11526
|
+
chalk30.cyan("Version")
|
|
11477
11527
|
],
|
|
11478
11528
|
style: { head: [], border: ["gray"] }
|
|
11479
11529
|
});
|
|
11480
11530
|
for (const kit of categoryKits) {
|
|
11481
11531
|
table.push([
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11532
|
+
chalk30.white(kit.slug),
|
|
11533
|
+
chalk30.dim(kit.description.slice(0, 50)),
|
|
11534
|
+
chalk30.green(`v${kit.version}`)
|
|
11485
11535
|
]);
|
|
11486
11536
|
}
|
|
11487
11537
|
console.log(table.toString());
|
|
11488
11538
|
console.log();
|
|
11489
11539
|
}
|
|
11490
|
-
console.log(
|
|
11491
|
-
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'));
|
|
11492
11542
|
});
|
|
11493
11543
|
}
|
|
11494
11544
|
|
|
11495
11545
|
// src/commands/kit/info.ts
|
|
11496
|
-
import { Command as
|
|
11546
|
+
import { Command as Command59 } from "commander";
|
|
11497
11547
|
function createKitInfoCommand() {
|
|
11498
|
-
return new
|
|
11548
|
+
return new Command59("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
|
|
11499
11549
|
const configService = new ConfigService();
|
|
11500
11550
|
const config = await configService.load();
|
|
11501
11551
|
if (!config) {
|
|
@@ -11544,7 +11594,7 @@ Post-Init Commands:`);
|
|
|
11544
11594
|
}
|
|
11545
11595
|
|
|
11546
11596
|
// src/commands/kit/create.ts
|
|
11547
|
-
import { Command as
|
|
11597
|
+
import { Command as Command60 } from "commander";
|
|
11548
11598
|
import { promises as fs21 } from "fs";
|
|
11549
11599
|
import { join as join11 } from "path";
|
|
11550
11600
|
import { select as select3, input as input2, checkbox as checkbox4 } from "@inquirer/prompts";
|
|
@@ -11589,7 +11639,7 @@ var HookExecutor = class {
|
|
|
11589
11639
|
|
|
11590
11640
|
// src/commands/kit/create.ts
|
|
11591
11641
|
function createKitCreateCommand() {
|
|
11592
|
-
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) => {
|
|
11593
11643
|
const configService = new ConfigService();
|
|
11594
11644
|
const config = await configService.load();
|
|
11595
11645
|
if (!config) {
|
|
@@ -11768,23 +11818,23 @@ async function getAllFiles(dir) {
|
|
|
11768
11818
|
|
|
11769
11819
|
// src/commands/kit/index.ts
|
|
11770
11820
|
function showKitHelp() {
|
|
11771
|
-
console.log(
|
|
11821
|
+
console.log(chalk31.bold.cyan("\u{1F4E6} jai1 kit") + chalk31.dim(" - Qu\u1EA3n l\xFD starter kits"));
|
|
11772
11822
|
console.log();
|
|
11773
|
-
console.log(
|
|
11774
|
-
console.log(` ${
|
|
11775
|
-
console.log(` ${
|
|
11776
|
-
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`);
|
|
11777
11827
|
console.log();
|
|
11778
|
-
console.log(
|
|
11779
|
-
console.log(
|
|
11780
|
-
console.log(
|
|
11781
|
-
console.log(
|
|
11782
|
-
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"));
|
|
11783
11833
|
console.log();
|
|
11784
|
-
console.log(
|
|
11834
|
+
console.log(chalk31.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11785
11835
|
}
|
|
11786
11836
|
function createKitCommand() {
|
|
11787
|
-
const cmd = new
|
|
11837
|
+
const cmd = new Command61("kit").description("Manage starter kits for new projects").action(() => {
|
|
11788
11838
|
showKitHelp();
|
|
11789
11839
|
});
|
|
11790
11840
|
cmd.addCommand(createKitListCommand());
|
|
@@ -11794,21 +11844,21 @@ function createKitCommand() {
|
|
|
11794
11844
|
}
|
|
11795
11845
|
|
|
11796
11846
|
// src/commands/rules/index.ts
|
|
11797
|
-
import { Command as
|
|
11798
|
-
import
|
|
11847
|
+
import { Command as Command68 } from "commander";
|
|
11848
|
+
import chalk33 from "chalk";
|
|
11799
11849
|
|
|
11800
11850
|
// src/commands/rules/list.ts
|
|
11801
|
-
import { Command as
|
|
11802
|
-
import
|
|
11851
|
+
import { Command as Command62 } from "commander";
|
|
11852
|
+
import chalk32 from "chalk";
|
|
11803
11853
|
import Table7 from "cli-table3";
|
|
11804
11854
|
function createRulesListCommand() {
|
|
11805
|
-
return new
|
|
11855
|
+
return new Command62("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
|
|
11806
11856
|
const configService = new ConfigService();
|
|
11807
11857
|
const config = await configService.load();
|
|
11808
11858
|
if (!config) {
|
|
11809
11859
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
11810
11860
|
}
|
|
11811
|
-
console.log(
|
|
11861
|
+
console.log(chalk32.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
|
|
11812
11862
|
console.log();
|
|
11813
11863
|
try {
|
|
11814
11864
|
const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
|
|
@@ -11825,23 +11875,23 @@ function createRulesListCommand() {
|
|
|
11825
11875
|
return;
|
|
11826
11876
|
}
|
|
11827
11877
|
if (data.total === 0) {
|
|
11828
|
-
console.log(
|
|
11878
|
+
console.log(chalk32.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
|
|
11829
11879
|
return;
|
|
11830
11880
|
}
|
|
11831
11881
|
console.log(
|
|
11832
|
-
|
|
11882
|
+
chalk32.green(`\u2713 T\xECm th\u1EA5y ${chalk32.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
|
|
11833
11883
|
);
|
|
11834
11884
|
console.log();
|
|
11835
11885
|
for (const preset of data.presets) {
|
|
11836
|
-
console.log(
|
|
11886
|
+
console.log(chalk32.bold.cyan(`\u{1F4E6} ${preset.slug}`));
|
|
11837
11887
|
const table = new Table7({
|
|
11838
11888
|
style: { head: [], border: ["gray"], compact: true },
|
|
11839
11889
|
colWidths: [15, 55]
|
|
11840
11890
|
});
|
|
11841
11891
|
table.push(
|
|
11842
|
-
[
|
|
11843
|
-
[
|
|
11844
|
-
[
|
|
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}`)]
|
|
11845
11895
|
);
|
|
11846
11896
|
const stackParts = [];
|
|
11847
11897
|
if (preset.stack.frontend) stackParts.push(preset.stack.frontend);
|
|
@@ -11849,16 +11899,16 @@ function createRulesListCommand() {
|
|
|
11849
11899
|
if (preset.stack.css) stackParts.push(preset.stack.css);
|
|
11850
11900
|
if (preset.stack.database) stackParts.push(preset.stack.database);
|
|
11851
11901
|
if (stackParts.length > 0) {
|
|
11852
|
-
table.push([
|
|
11902
|
+
table.push([chalk32.dim("Stack"), chalk32.yellow(stackParts.join(" + "))]);
|
|
11853
11903
|
}
|
|
11854
11904
|
table.push(
|
|
11855
|
-
[
|
|
11856
|
-
[
|
|
11905
|
+
[chalk32.dim("Tags"), chalk32.dim(preset.tags.join(", ") || "-")],
|
|
11906
|
+
[chalk32.dim("Downloads"), chalk32.white(preset.downloads.toString())]
|
|
11857
11907
|
);
|
|
11858
11908
|
console.log(table.toString());
|
|
11859
11909
|
console.log();
|
|
11860
11910
|
}
|
|
11861
|
-
console.log(
|
|
11911
|
+
console.log(chalk32.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
|
|
11862
11912
|
} catch (error) {
|
|
11863
11913
|
throw new Error(
|
|
11864
11914
|
`L\u1ED7i khi t\u1EA3i presets: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -11868,7 +11918,7 @@ function createRulesListCommand() {
|
|
|
11868
11918
|
}
|
|
11869
11919
|
|
|
11870
11920
|
// src/commands/rules/init.ts
|
|
11871
|
-
import { Command as
|
|
11921
|
+
import { Command as Command63 } from "commander";
|
|
11872
11922
|
import { promises as fs23 } from "fs";
|
|
11873
11923
|
import { join as join13 } from "path";
|
|
11874
11924
|
import { select as select4, confirm as confirm10 } from "@inquirer/prompts";
|
|
@@ -11993,7 +12043,7 @@ var ProjectConfigService = class {
|
|
|
11993
12043
|
|
|
11994
12044
|
// src/commands/rules/init.ts
|
|
11995
12045
|
function createRulesInitCommand() {
|
|
11996
|
-
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) => {
|
|
11997
12047
|
const configService = new ConfigService();
|
|
11998
12048
|
const config = await configService.load();
|
|
11999
12049
|
if (!config) {
|
|
@@ -12125,7 +12175,7 @@ async function applyAgentsMdFormat(bundle) {
|
|
|
12125
12175
|
}
|
|
12126
12176
|
|
|
12127
12177
|
// src/commands/rules/apply.ts
|
|
12128
|
-
import { Command as
|
|
12178
|
+
import { Command as Command64 } from "commander";
|
|
12129
12179
|
import { promises as fs25 } from "fs";
|
|
12130
12180
|
import { join as join15 } from "path";
|
|
12131
12181
|
import { search, confirm as confirm11, checkbox as checkbox5 } from "@inquirer/prompts";
|
|
@@ -12639,7 +12689,7 @@ Restoring backup from ${metadata.timestamp}...`);
|
|
|
12639
12689
|
|
|
12640
12690
|
// src/commands/rules/apply.ts
|
|
12641
12691
|
function createRulesApplyCommand() {
|
|
12642
|
-
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) => {
|
|
12643
12693
|
const configService = new ConfigService();
|
|
12644
12694
|
const config = await configService.load();
|
|
12645
12695
|
if (!config) {
|
|
@@ -12934,11 +12984,11 @@ function createRulesApplyCommand() {
|
|
|
12934
12984
|
}
|
|
12935
12985
|
|
|
12936
12986
|
// src/commands/rules/restore.ts
|
|
12937
|
-
import { Command as
|
|
12987
|
+
import { Command as Command65 } from "commander";
|
|
12938
12988
|
import { join as join16 } from "path";
|
|
12939
12989
|
import { select as select5, confirm as confirm12 } from "@inquirer/prompts";
|
|
12940
12990
|
function createRulesRestoreCommand() {
|
|
12941
|
-
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) => {
|
|
12942
12992
|
const backupService = new BackupService();
|
|
12943
12993
|
const backups = await backupService.listBackups();
|
|
12944
12994
|
if (backups.length === 0) {
|
|
@@ -13007,12 +13057,12 @@ function formatTimestamp(timestamp) {
|
|
|
13007
13057
|
}
|
|
13008
13058
|
|
|
13009
13059
|
// src/commands/rules/sync.ts
|
|
13010
|
-
import { Command as
|
|
13060
|
+
import { Command as Command66 } from "commander";
|
|
13011
13061
|
import { promises as fs26 } from "fs";
|
|
13012
13062
|
import { join as join17 } from "path";
|
|
13013
13063
|
import { checkbox as checkbox6, confirm as confirm13, Separator } from "@inquirer/prompts";
|
|
13014
13064
|
function createRulesSyncCommand() {
|
|
13015
|
-
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) => {
|
|
13016
13066
|
const rulePresetDir = join17(process.cwd(), ".jai1", "rule-preset");
|
|
13017
13067
|
const presetJsonPath = join17(rulePresetDir, "preset.json");
|
|
13018
13068
|
let presetExists = false;
|
|
@@ -13230,11 +13280,11 @@ function buildIdeChoices(currentIdes, detected, suggestions) {
|
|
|
13230
13280
|
}
|
|
13231
13281
|
|
|
13232
13282
|
// src/commands/rules/info.ts
|
|
13233
|
-
import { Command as
|
|
13283
|
+
import { Command as Command67 } from "commander";
|
|
13234
13284
|
import { promises as fs27 } from "fs";
|
|
13235
13285
|
import { join as join18 } from "path";
|
|
13236
13286
|
function createRulesInfoCommand() {
|
|
13237
|
-
return new
|
|
13287
|
+
return new Command67("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
|
|
13238
13288
|
const projectConfigService = new ProjectConfigService();
|
|
13239
13289
|
const rulesConfig = await projectConfigService.loadRules();
|
|
13240
13290
|
if (!rulesConfig) {
|
|
@@ -13337,26 +13387,26 @@ async function checkIdeFilesExist(ideId, format) {
|
|
|
13337
13387
|
|
|
13338
13388
|
// src/commands/rules/index.ts
|
|
13339
13389
|
function showRulesHelp() {
|
|
13340
|
-
console.log(
|
|
13390
|
+
console.log(chalk33.bold.cyan("\u{1F4CB} jai1 rules") + chalk33.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
|
|
13341
13391
|
console.log();
|
|
13342
|
-
console.log(
|
|
13343
|
-
console.log(` ${
|
|
13344
|
-
console.log(` ${
|
|
13345
|
-
console.log(` ${
|
|
13346
|
-
console.log(` ${
|
|
13347
|
-
console.log(` ${
|
|
13348
|
-
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`);
|
|
13349
13399
|
console.log();
|
|
13350
|
-
console.log(
|
|
13351
|
-
console.log(
|
|
13352
|
-
console.log(
|
|
13353
|
-
console.log(
|
|
13354
|
-
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"));
|
|
13355
13405
|
console.log();
|
|
13356
|
-
console.log(
|
|
13406
|
+
console.log(chalk33.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
13357
13407
|
}
|
|
13358
13408
|
function createRulesCommand() {
|
|
13359
|
-
const rulesCommand = new
|
|
13409
|
+
const rulesCommand = new Command68("rules").description("Manage rule presets for AI agents").action(() => {
|
|
13360
13410
|
showRulesHelp();
|
|
13361
13411
|
});
|
|
13362
13412
|
rulesCommand.addCommand(createRulesListCommand());
|
|
@@ -13369,7 +13419,7 @@ function createRulesCommand() {
|
|
|
13369
13419
|
}
|
|
13370
13420
|
|
|
13371
13421
|
// src/commands/upgrade.ts
|
|
13372
|
-
import { Command as
|
|
13422
|
+
import { Command as Command69 } from "commander";
|
|
13373
13423
|
import { confirm as confirm14 } from "@inquirer/prompts";
|
|
13374
13424
|
import { execSync as execSync4 } from "child_process";
|
|
13375
13425
|
var colors2 = {
|
|
@@ -13381,7 +13431,7 @@ var colors2 = {
|
|
|
13381
13431
|
bold: "\x1B[1m"
|
|
13382
13432
|
};
|
|
13383
13433
|
function createUpgradeCommand() {
|
|
13384
|
-
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) => {
|
|
13385
13435
|
await handleUpgrade(options);
|
|
13386
13436
|
});
|
|
13387
13437
|
}
|
|
@@ -13529,11 +13579,11 @@ function getInstallCommand(packageManager2) {
|
|
|
13529
13579
|
}
|
|
13530
13580
|
|
|
13531
13581
|
// src/commands/clean.ts
|
|
13532
|
-
import { Command as
|
|
13582
|
+
import { Command as Command70 } from "commander";
|
|
13533
13583
|
import { confirm as confirm15, select as select6 } from "@inquirer/prompts";
|
|
13534
13584
|
import { join as join19 } from "path";
|
|
13535
13585
|
function createCleanCommand() {
|
|
13536
|
-
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) => {
|
|
13537
13587
|
await handleClean(options);
|
|
13538
13588
|
});
|
|
13539
13589
|
}
|
|
@@ -13647,7 +13697,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
13647
13697
|
}
|
|
13648
13698
|
|
|
13649
13699
|
// src/commands/redmine/check.ts
|
|
13650
|
-
import { Command as
|
|
13700
|
+
import { Command as Command71 } from "commander";
|
|
13651
13701
|
|
|
13652
13702
|
// src/services/redmine-config.service.ts
|
|
13653
13703
|
import { readFile as readFile7 } from "fs/promises";
|
|
@@ -13954,7 +14004,7 @@ async function checkConnectivity(config) {
|
|
|
13954
14004
|
|
|
13955
14005
|
// src/commands/redmine/check.ts
|
|
13956
14006
|
function createRedmineCheckCommand() {
|
|
13957
|
-
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) => {
|
|
13958
14008
|
await handleRedmineCheck(options);
|
|
13959
14009
|
});
|
|
13960
14010
|
return cmd;
|
|
@@ -13982,7 +14032,7 @@ async function handleRedmineCheck(options) {
|
|
|
13982
14032
|
}
|
|
13983
14033
|
|
|
13984
14034
|
// src/commands/redmine/sync-issue.ts
|
|
13985
|
-
import { Command as
|
|
14035
|
+
import { Command as Command72 } from "commander";
|
|
13986
14036
|
|
|
13987
14037
|
// src/sync-issue.ts
|
|
13988
14038
|
import { resolve as resolve3, relative } from "path";
|
|
@@ -14366,7 +14416,7 @@ function extractIssueIdFromUrl(url) {
|
|
|
14366
14416
|
|
|
14367
14417
|
// src/commands/redmine/sync-issue.ts
|
|
14368
14418
|
function createSyncIssueCommand() {
|
|
14369
|
-
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) => {
|
|
14370
14420
|
await handleSyncIssue(options);
|
|
14371
14421
|
});
|
|
14372
14422
|
return cmd;
|
|
@@ -14410,7 +14460,7 @@ async function handleSyncIssue(options) {
|
|
|
14410
14460
|
}
|
|
14411
14461
|
|
|
14412
14462
|
// src/commands/redmine/sync-project.ts
|
|
14413
|
-
import { Command as
|
|
14463
|
+
import { Command as Command73 } from "commander";
|
|
14414
14464
|
|
|
14415
14465
|
// src/sync-project.ts
|
|
14416
14466
|
async function syncProject(config, options = {}) {
|
|
@@ -14480,7 +14530,7 @@ async function syncProject(config, options = {}) {
|
|
|
14480
14530
|
|
|
14481
14531
|
// src/commands/redmine/sync-project.ts
|
|
14482
14532
|
function createSyncProjectCommand() {
|
|
14483
|
-
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) => {
|
|
14484
14534
|
await handleSyncProject(options);
|
|
14485
14535
|
});
|
|
14486
14536
|
return cmd;
|
|
@@ -14535,12 +14585,12 @@ async function handleSyncProject(options) {
|
|
|
14535
14585
|
}
|
|
14536
14586
|
|
|
14537
14587
|
// src/commands/framework/info.ts
|
|
14538
|
-
import { Command as
|
|
14588
|
+
import { Command as Command74 } from "commander";
|
|
14539
14589
|
import { promises as fs28 } from "fs";
|
|
14540
14590
|
import { join as join20 } from "path";
|
|
14541
14591
|
import { homedir as homedir6 } from "os";
|
|
14542
14592
|
function createInfoCommand() {
|
|
14543
|
-
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) => {
|
|
14544
14594
|
await handleInfo(options);
|
|
14545
14595
|
});
|
|
14546
14596
|
return cmd;
|
|
@@ -14596,7 +14646,7 @@ async function getProjectStatus2() {
|
|
|
14596
14646
|
}
|
|
14597
14647
|
|
|
14598
14648
|
// src/commands/self-update.ts
|
|
14599
|
-
import { Command as
|
|
14649
|
+
import { Command as Command75 } from "commander";
|
|
14600
14650
|
import { confirm as confirm16 } from "@inquirer/prompts";
|
|
14601
14651
|
import { execSync as execSync5 } from "child_process";
|
|
14602
14652
|
var colors3 = {
|
|
@@ -14608,7 +14658,7 @@ var colors3 = {
|
|
|
14608
14658
|
bold: "\x1B[1m"
|
|
14609
14659
|
};
|
|
14610
14660
|
function createSelfUpdateCommand() {
|
|
14611
|
-
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) => {
|
|
14612
14662
|
await handleSelfUpdate(options);
|
|
14613
14663
|
});
|
|
14614
14664
|
}
|
|
@@ -14748,10 +14798,10 @@ function getInstallCommand2(packageManager2) {
|
|
|
14748
14798
|
}
|
|
14749
14799
|
|
|
14750
14800
|
// src/commands/clear-backups.ts
|
|
14751
|
-
import { Command as
|
|
14801
|
+
import { Command as Command76 } from "commander";
|
|
14752
14802
|
import { confirm as confirm17 } from "@inquirer/prompts";
|
|
14753
14803
|
function createClearBackupsCommand() {
|
|
14754
|
-
return new
|
|
14804
|
+
return new Command76("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
14755
14805
|
const service = new ComponentsService();
|
|
14756
14806
|
const backups = await service.listBackups(process.cwd());
|
|
14757
14807
|
if (backups.length === 0) {
|
|
@@ -14776,7 +14826,7 @@ function createClearBackupsCommand() {
|
|
|
14776
14826
|
}
|
|
14777
14827
|
|
|
14778
14828
|
// src/commands/vscode/index.ts
|
|
14779
|
-
import { Command as
|
|
14829
|
+
import { Command as Command77 } from "commander";
|
|
14780
14830
|
import { checkbox as checkbox7, confirm as confirm18, select as select7 } from "@inquirer/prompts";
|
|
14781
14831
|
import fs29 from "fs/promises";
|
|
14782
14832
|
import path12 from "path";
|
|
@@ -14916,7 +14966,7 @@ var PERFORMANCE_GROUPS2 = {
|
|
|
14916
14966
|
}
|
|
14917
14967
|
};
|
|
14918
14968
|
function createVSCodeCommand() {
|
|
14919
|
-
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");
|
|
14920
14970
|
vscodeCommand.action(async () => {
|
|
14921
14971
|
await interactiveMode2();
|
|
14922
14972
|
});
|
|
@@ -15087,10 +15137,10 @@ async function resetSettings2(groupKeys) {
|
|
|
15087
15137
|
}
|
|
15088
15138
|
|
|
15089
15139
|
// src/commands/migrate-ide.ts
|
|
15090
|
-
import { Command as
|
|
15140
|
+
import { Command as Command78 } from "commander";
|
|
15091
15141
|
import { checkbox as checkbox8, confirm as confirm19 } from "@inquirer/prompts";
|
|
15092
15142
|
function createMigrateIdeCommand() {
|
|
15093
|
-
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) => {
|
|
15094
15144
|
await runMigrateIde(options);
|
|
15095
15145
|
});
|
|
15096
15146
|
return cmd;
|
|
@@ -15199,62 +15249,63 @@ async function runMigrateIde(options) {
|
|
|
15199
15249
|
|
|
15200
15250
|
// src/utils/help-formatter.ts
|
|
15201
15251
|
import boxen4 from "boxen";
|
|
15202
|
-
import
|
|
15252
|
+
import chalk34 from "chalk";
|
|
15203
15253
|
import gradient from "gradient-string";
|
|
15204
15254
|
import figlet from "figlet";
|
|
15205
15255
|
function showCustomHelp(version) {
|
|
15206
15256
|
const title = figlet.textSync("JAI1", { font: "Small" });
|
|
15207
15257
|
console.log(gradient.pastel(title));
|
|
15208
15258
|
console.log(
|
|
15209
|
-
boxen4(
|
|
15259
|
+
boxen4(chalk34.cyan(`Agentic Coding CLI v${version}`), {
|
|
15210
15260
|
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
15211
15261
|
borderStyle: "round",
|
|
15212
15262
|
borderColor: "cyan"
|
|
15213
15263
|
})
|
|
15214
15264
|
);
|
|
15215
|
-
console.log(
|
|
15265
|
+
console.log(chalk34.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
|
|
15216
15266
|
console.log(" auth X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client");
|
|
15217
15267
|
console.log(" status Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh");
|
|
15218
15268
|
console.log(" client-info T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n");
|
|
15219
15269
|
console.log(" errors Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9");
|
|
15220
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)");
|
|
15221
15272
|
console.log(" doctor Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i");
|
|
15222
|
-
console.log(
|
|
15273
|
+
console.log(chalk34.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
|
|
15223
15274
|
console.log(" apply C\xE0i \u0111\u1EB7t components (interactive)");
|
|
15224
15275
|
console.log(" update C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i");
|
|
15225
15276
|
console.log(" check Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server");
|
|
15226
|
-
console.log(
|
|
15277
|
+
console.log(chalk34.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
|
|
15227
15278
|
console.log(" ide L\u1EC7nh c\u1EA5u h\xECnh IDE");
|
|
15228
15279
|
console.log(" chat Chat AI v\u1EDBi Jai1 LLM Proxy");
|
|
15229
15280
|
console.log(" openai-keys Th\xF4ng tin API credentials");
|
|
15230
|
-
console.log(
|
|
15281
|
+
console.log(chalk34.bold("\n\u{1F916} AI Tools"));
|
|
15231
15282
|
console.log(" translate D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI");
|
|
15232
15283
|
console.log(" image T\u1EA1o \u1EA3nh (Coming Soon)");
|
|
15233
15284
|
console.log(" stats Th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM");
|
|
15234
15285
|
console.log(" feedback G\u1EEDi b\xE1o c\xE1o/\u0111\u1EC1 xu\u1EA5t");
|
|
15235
|
-
console.log(
|
|
15286
|
+
console.log(chalk34.bold("\n\u{1F4C1} Project"));
|
|
15236
15287
|
console.log(" kit Qu\u1EA3n l\xFD starter kits");
|
|
15237
15288
|
console.log(" rules Qu\u1EA3n l\xFD rule presets");
|
|
15238
15289
|
console.log(" deps Qu\u1EA3n l\xFD dependencies");
|
|
15239
15290
|
console.log(" redmine Redmine context sync");
|
|
15240
|
-
console.log(
|
|
15291
|
+
console.log(chalk34.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
|
|
15241
15292
|
console.log(" upgrade C\u1EADp nh\u1EADt CLI client");
|
|
15242
15293
|
console.log(" clean D\u1ECDn d\u1EB9p cache/backup");
|
|
15243
15294
|
console.log(" utils Developer utilities");
|
|
15244
15295
|
const name = getCliName();
|
|
15245
|
-
console.log(
|
|
15296
|
+
console.log(chalk34.dim(`
|
|
15246
15297
|
S\u1EED d\u1EE5ng: ${name} [l\u1EC7nh] --help \u0111\u1EC3 xem chi ti\u1EBFt`));
|
|
15247
15298
|
}
|
|
15248
15299
|
function showUnknownCommand(commandName) {
|
|
15249
|
-
console.error(
|
|
15300
|
+
console.error(chalk34.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
|
|
15250
15301
|
const name = getCliName();
|
|
15251
|
-
console.error(
|
|
15302
|
+
console.error(chalk34.dim(`
|
|
15252
15303
|
G\u1EE3i \xFD: Ch\u1EA1y ${name} --help \u0111\u1EC3 xem danh s\xE1ch l\u1EC7nh`));
|
|
15253
15304
|
}
|
|
15254
15305
|
|
|
15255
15306
|
// src/cli.ts
|
|
15256
15307
|
checkNodeVersion();
|
|
15257
|
-
var program = new
|
|
15308
|
+
var program = new Command79();
|
|
15258
15309
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
15259
15310
|
console.log(package_default.version);
|
|
15260
15311
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -15277,6 +15328,7 @@ program.addCommand(createUpdateCommand());
|
|
|
15277
15328
|
program.addCommand(createCheckCommand());
|
|
15278
15329
|
program.addCommand(createIdeCommand());
|
|
15279
15330
|
program.addCommand(createGuideCommand());
|
|
15331
|
+
program.addCommand(createQuickstartCommand());
|
|
15280
15332
|
program.addCommand(createDoctorCommand());
|
|
15281
15333
|
program.addCommand(createChatCommand());
|
|
15282
15334
|
program.addCommand(createOpenAiKeysCommand());
|
|
@@ -15293,9 +15345,9 @@ program.addCommand(createKitCommand());
|
|
|
15293
15345
|
program.addCommand(createRulesCommand());
|
|
15294
15346
|
program.addCommand(createUpgradeCommand());
|
|
15295
15347
|
program.addCommand(createCleanCommand());
|
|
15296
|
-
var redmineCommand = new
|
|
15348
|
+
var redmineCommand = new Command79("redmine").description("Redmine context sync commands");
|
|
15297
15349
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
15298
|
-
var syncCommand = new
|
|
15350
|
+
var syncCommand = new Command79("sync").description("Sync Redmine issues to markdown files");
|
|
15299
15351
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
15300
15352
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
15301
15353
|
redmineCommand.addCommand(syncCommand);
|