@nalvietnam/avatar-cli 1.0.1 → 1.1.1
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/bin/avatar.js +0 -0
- package/bin/postinstall.js +13 -0
- package/dist/hooks/post-merge.sh.tpl +24 -0
- package/dist/hooks/pre-push.sh.tpl +33 -0
- package/dist/index.js +855 -180
- package/dist/index.js.map +1 -1
- package/dist/lib/print-welcome-screen.js +117 -0
- package/dist/lib/print-welcome-screen.js.map +1 -0
- package/dist/templates/CLAUDE.md.tpl +40 -0
- package/dist/templates/gitignore/generic.txt +20 -0
- package/dist/templates/gitignore/go.txt +16 -0
- package/dist/templates/gitignore/java.txt +23 -0
- package/dist/templates/gitignore/node.txt +21 -0
- package/dist/templates/gitignore/python.txt +26 -0
- package/dist/templates/gitignore/ruby.txt +16 -0
- package/dist/templates/gitignore/rust.txt +5 -0
- package/dist/templates/gitignore.tpl +4 -0
- package/dist/templates/project/architecture.md.tpl +27 -0
- package/dist/templates/project/conventions.md.tpl +27 -0
- package/dist/templates/project/domain.md.tpl +23 -0
- package/dist/templates/project/gotchas.md.tpl +28 -0
- package/dist/templates/project/tech-stack.md.tpl +32 -0
- package/dist/templates/settings.json.tpl +32 -0
- package/package.json +3 -2
- package/src/templates/gitignore/generic.txt +20 -0
- package/src/templates/gitignore/go.txt +16 -0
- package/src/templates/gitignore/java.txt +23 -0
- package/src/templates/gitignore/node.txt +21 -0
- package/src/templates/gitignore/python.txt +26 -0
- package/src/templates/gitignore/ruby.txt +16 -0
- package/src/templates/gitignore/rust.txt +5 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// @nalvietnam/avatar-cli — built with tsup
|
|
2
|
+
|
|
3
|
+
// src/lib/print-welcome-screen.ts
|
|
4
|
+
import boxen from "boxen";
|
|
5
|
+
|
|
6
|
+
// src/lib/avatar-ascii-banner.ts
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
var BANNER_LINES = [
|
|
9
|
+
" \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
10
|
+
"\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557",
|
|
11
|
+
"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
|
|
12
|
+
"\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557",
|
|
13
|
+
"\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
14
|
+
"\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D"
|
|
15
|
+
];
|
|
16
|
+
var GRADIENT_STOPS = [
|
|
17
|
+
[217, 79, 30],
|
|
18
|
+
// cam-cháy (#d94f1e)
|
|
19
|
+
[200, 70, 80],
|
|
20
|
+
// cam-hồng
|
|
21
|
+
[170, 70, 140],
|
|
22
|
+
// hồng-tím
|
|
23
|
+
[125, 88, 217]
|
|
24
|
+
// tím (#7d58d9)
|
|
25
|
+
];
|
|
26
|
+
function lerpChannel(a, b, t) {
|
|
27
|
+
return Math.round(a + (b - a) * t);
|
|
28
|
+
}
|
|
29
|
+
function gradientAt(t) {
|
|
30
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
31
|
+
const scaled = clamped * (GRADIENT_STOPS.length - 1);
|
|
32
|
+
const lo = Math.floor(scaled);
|
|
33
|
+
const hi = Math.min(GRADIENT_STOPS.length - 1, lo + 1);
|
|
34
|
+
const localT = scaled - lo;
|
|
35
|
+
const a = GRADIENT_STOPS[lo];
|
|
36
|
+
const b = GRADIENT_STOPS[hi];
|
|
37
|
+
return [
|
|
38
|
+
lerpChannel(a[0], b[0], localT),
|
|
39
|
+
lerpChannel(a[1], b[1], localT),
|
|
40
|
+
lerpChannel(a[2], b[2], localT)
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
function renderAvatarBanner(opts) {
|
|
44
|
+
const isTty = process.stdout.isTTY ?? false;
|
|
45
|
+
const supportsColor = isTty && chalk.level > 0;
|
|
46
|
+
if (!supportsColor) {
|
|
47
|
+
return [...BANNER_LINES, ...opts?.tagline ? ["", opts.tagline] : []].join("\n");
|
|
48
|
+
}
|
|
49
|
+
const colored = BANNER_LINES.map((line, idx) => {
|
|
50
|
+
const t = BANNER_LINES.length === 1 ? 0 : idx / (BANNER_LINES.length - 1);
|
|
51
|
+
const [r, g, b] = gradientAt(t);
|
|
52
|
+
return chalk.rgb(r, g, b).bold(line);
|
|
53
|
+
});
|
|
54
|
+
if (opts?.tagline) {
|
|
55
|
+
colored.push("");
|
|
56
|
+
colored.push(chalk.dim(opts.tagline));
|
|
57
|
+
}
|
|
58
|
+
return colored.join("\n");
|
|
59
|
+
}
|
|
60
|
+
function printAvatarBanner(opts) {
|
|
61
|
+
process.stdout.write(`
|
|
62
|
+
${renderAvatarBanner(opts)}
|
|
63
|
+
|
|
64
|
+
`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/lib/terminal-logger.ts
|
|
68
|
+
import chalk2 from "chalk";
|
|
69
|
+
import ora from "ora";
|
|
70
|
+
|
|
71
|
+
// src/lib/print-welcome-screen.ts
|
|
72
|
+
var COMMANDS = [
|
|
73
|
+
{ name: "login", desc: "\u0110\u0103ng nh\u1EADp Google SSO (@nal.vn)" },
|
|
74
|
+
{ name: "init", desc: "Kh\u1EDFi t\u1EA1o Avatar \u2014 3 flow t\u1EF1 nh\u1EADn di\u1EC7n" },
|
|
75
|
+
{ name: "sync", desc: "Pull team-ai-pack m\u1EDBi nh\u1EA5t" },
|
|
76
|
+
{ name: "scan", desc: "Project scanner + knowledge proposal" },
|
|
77
|
+
{ name: "review", desc: "Duy\u1EC7t pending proposals" },
|
|
78
|
+
{ name: "status", desc: "Snapshot project, pack, pending, backup" },
|
|
79
|
+
{ name: "doctor", desc: "Ch\u1EA9n \u0111o\xE1n c\xE0i \u0111\u1EB7t Avatar" },
|
|
80
|
+
{ name: "restore", desc: "Kh\xF4i ph\u1EE5c .claude/pack/ t\u1EEB backup" },
|
|
81
|
+
{ name: "commit", desc: "Commit src/ ho\u1EB7c Avatar state (client mode)" },
|
|
82
|
+
{ name: "tools", desc: "Qu\u1EA3n l\xFD system tools + MCP servers" },
|
|
83
|
+
{ name: "secrets", desc: "Qu\u1EA3n l\xFD secrets trong OS keychain" },
|
|
84
|
+
{ name: "uninstall", desc: "G\u1EE1 Avatar kh\u1ECFi project + backup" },
|
|
85
|
+
{ name: "help", desc: "Hi\u1EC3n th\u1ECB help cho t\u1EEBng l\u1EC7nh" }
|
|
86
|
+
];
|
|
87
|
+
var CLI_VERSION = "1.1.1";
|
|
88
|
+
function printWelcomeScreen() {
|
|
89
|
+
printAvatarBanner({ tagline: `v${CLI_VERSION} \xB7 AI harness CLI for NAL Vietnam` });
|
|
90
|
+
const maxNameWidth = Math.max(...COMMANDS.map((c) => c.name.length));
|
|
91
|
+
const commandLines = COMMANDS.map((c) => {
|
|
92
|
+
const padded = c.name.padEnd(maxNameWidth);
|
|
93
|
+
return ` ${chalk2.cyan(padded)} ${chalk2.dim(c.desc)}`;
|
|
94
|
+
}).join("\n");
|
|
95
|
+
const nextSteps = [
|
|
96
|
+
"",
|
|
97
|
+
chalk2.bold("13 l\u1EC7nh s\u1EB5n s\xE0ng:"),
|
|
98
|
+
"",
|
|
99
|
+
commandLines,
|
|
100
|
+
"",
|
|
101
|
+
chalk2.bold("Next steps:"),
|
|
102
|
+
"",
|
|
103
|
+
` ${chalk2.green("1.")} ${chalk2.cyan("avatar login")} \u0110\u0103ng nh\u1EADp SSO`,
|
|
104
|
+
` ${chalk2.green("2.")} ${chalk2.cyan("avatar init")} Kh\u1EDFi t\u1EA1o d\u1EF1 \xE1n`,
|
|
105
|
+
` ${chalk2.green("?.")} ${chalk2.cyan("avatar <command> --help")} Xem chi ti\u1EBFt l\u1EC7nh`,
|
|
106
|
+
"",
|
|
107
|
+
chalk2.dim("Docs: https://www.npmjs.com/package/@nalvietnam/avatar-cli")
|
|
108
|
+
].join("\n");
|
|
109
|
+
process.stdout.write(
|
|
110
|
+
`${boxen(nextSteps, { padding: 1, borderStyle: "round", borderColor: "magenta" })}
|
|
111
|
+
`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
export {
|
|
115
|
+
printWelcomeScreen
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=print-welcome-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/print-welcome-screen.ts","../../src/lib/avatar-ascii-banner.ts","../../src/lib/terminal-logger.ts"],"sourcesContent":["// Welcome screen in ra sau `npm install -g` (qua postinstall hook) hoặc khi\n// user gọi `avatar welcome` thủ công. Mục đích: cho user thấy banner + 13\n// commands + next step gợi ý ngay sau khi cài.\nimport boxen from \"boxen\";\nimport { printAvatarBanner } from \"./avatar-ascii-banner.js\";\nimport { chalk } from \"./terminal-logger.js\";\n\ninterface CommandSummary {\n name: string;\n desc: string;\n}\n\n// Danh sách 13 commands user-facing (mcp-run là hidden, bỏ qua).\nconst COMMANDS: CommandSummary[] = [\n { name: \"login\", desc: \"Đăng nhập Google SSO (@nal.vn)\" },\n { name: \"init\", desc: \"Khởi tạo Avatar — 3 flow tự nhận diện\" },\n { name: \"sync\", desc: \"Pull team-ai-pack mới nhất\" },\n { name: \"scan\", desc: \"Project scanner + knowledge proposal\" },\n { name: \"review\", desc: \"Duyệt pending proposals\" },\n { name: \"status\", desc: \"Snapshot project, pack, pending, backup\" },\n { name: \"doctor\", desc: \"Chẩn đoán cài đặt Avatar\" },\n { name: \"restore\", desc: \"Khôi phục .claude/pack/ từ backup\" },\n { name: \"commit\", desc: \"Commit src/ hoặc Avatar state (client mode)\" },\n { name: \"tools\", desc: \"Quản lý system tools + MCP servers\" },\n { name: \"secrets\", desc: \"Quản lý secrets trong OS keychain\" },\n { name: \"uninstall\", desc: \"Gỡ Avatar khỏi project + backup\" },\n { name: \"help\", desc: \"Hiển thị help cho từng lệnh\" },\n];\n\nconst CLI_VERSION = \"1.1.1\";\n\nexport function printWelcomeScreen(): void {\n printAvatarBanner({ tagline: `v${CLI_VERSION} · AI harness CLI for NAL Vietnam` });\n\n // Tính độ rộng max của tên command để align cột.\n const maxNameWidth = Math.max(...COMMANDS.map((c) => c.name.length));\n\n const commandLines = COMMANDS.map((c) => {\n const padded = c.name.padEnd(maxNameWidth);\n return ` ${chalk.cyan(padded)} ${chalk.dim(c.desc)}`;\n }).join(\"\\n\");\n\n const nextSteps = [\n \"\",\n chalk.bold(\"13 lệnh sẵn sàng:\"),\n \"\",\n commandLines,\n \"\",\n chalk.bold(\"Next steps:\"),\n \"\",\n ` ${chalk.green(\"1.\")} ${chalk.cyan(\"avatar login\")} Đăng nhập SSO`,\n ` ${chalk.green(\"2.\")} ${chalk.cyan(\"avatar init\")} Khởi tạo dự án`,\n ` ${chalk.green(\"?.\")} ${chalk.cyan(\"avatar <command> --help\")} Xem chi tiết lệnh`,\n \"\",\n chalk.dim(\"Docs: https://www.npmjs.com/package/@nalvietnam/avatar-cli\"),\n ].join(\"\\n\");\n\n process.stdout.write(\n `${boxen(nextSteps, { padding: 1, borderStyle: \"round\", borderColor: \"magenta\" })}\\n`,\n );\n}\n\n// Caller (bin/postinstall.js) chịu trách nhiệm gọi printWelcomeScreen() —\n// không auto-execute ở đây để tránh in trùng khi module được import từ postinstall.\n","// Avatar ASCII banner — gradient màu cam → tím để in ở các entry point chính:\n// `avatar --version`, `avatar init`, `avatar login`.\n//\n// Style: ANSI Shadow block characters (Unicode box-drawing).\n// Tự fallback sang plain text khi không phải TTY (CI, pipe ra file).\nimport chalk from \"chalk\";\n\n// 6 dòng chính của logo, mỗi dòng giữ độ rộng đồng nhất 50 ký tự để gradient đẹp.\nconst BANNER_LINES: readonly string[] = [\n \" █████╗ ██╗ ██╗ █████╗ ████████╗ █████╗ ██████╗ \",\n \"██╔══██╗██║ ██║██╔══██╗╚══██╔══╝██╔══██╗██╔══██╗\",\n \"███████║██║ ██║███████║ ██║ ███████║██████╔╝\",\n \"██╔══██║╚██╗ ██╔╝██╔══██║ ██║ ██╔══██║██╔══██╗\",\n \"██║ ██║ ╚████╔╝ ██║ ██║ ██║ ██║ ██║██║ ██║\",\n \"╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\",\n] as const;\n\n// Gradient stops cam → tím (RGB triples). Mỗi dòng nội suy theo % chiều cao.\nconst GRADIENT_STOPS: ReadonlyArray<readonly [number, number, number]> = [\n [217, 79, 30], // cam-cháy (#d94f1e)\n [200, 70, 80], // cam-hồng\n [170, 70, 140], // hồng-tím\n [125, 88, 217], // tím (#7d58d9)\n];\n\n// Nội suy tuyến tính 1 kênh màu giữa 2 stop.\nfunction lerpChannel(a: number, b: number, t: number): number {\n return Math.round(a + (b - a) * t);\n}\n\n// Lấy màu RGB tại vị trí [0,1] trên gradient.\nfunction gradientAt(t: number): readonly [number, number, number] {\n const clamped = Math.max(0, Math.min(1, t));\n const scaled = clamped * (GRADIENT_STOPS.length - 1);\n const lo = Math.floor(scaled);\n const hi = Math.min(GRADIENT_STOPS.length - 1, lo + 1);\n const localT = scaled - lo;\n const a = GRADIENT_STOPS[lo];\n const b = GRADIENT_STOPS[hi];\n return [\n lerpChannel(a[0], b[0], localT),\n lerpChannel(a[1], b[1], localT),\n lerpChannel(a[2], b[2], localT),\n ];\n}\n\n// Build banner string đã tô màu sẵn. Trả empty khi terminal không hỗ trợ màu.\nexport function renderAvatarBanner(opts?: { tagline?: string }): string {\n const isTty = process.stdout.isTTY ?? false;\n const supportsColor = isTty && chalk.level > 0;\n\n // Plain fallback cho CI hoặc pipe.\n if (!supportsColor) {\n return [...BANNER_LINES, ...(opts?.tagline ? [\"\", opts.tagline] : [])].join(\"\\n\");\n }\n\n const colored = BANNER_LINES.map((line, idx) => {\n const t = BANNER_LINES.length === 1 ? 0 : idx / (BANNER_LINES.length - 1);\n const [r, g, b] = gradientAt(t);\n return chalk.rgb(r, g, b).bold(line);\n });\n\n if (opts?.tagline) {\n colored.push(\"\");\n colored.push(chalk.dim(opts.tagline));\n }\n\n return colored.join(\"\\n\");\n}\n\n// Tiện ích: in banner ra stdout với newline phía trước/sau cho thoáng.\nexport function printAvatarBanner(opts?: { tagline?: string }): void {\n process.stdout.write(`\\n${renderAvatarBanner(opts)}\\n\\n`);\n}\n","// Terminal logging helpers — chalk for color, ora for spinners.\n// All Avatar CLI output should funnel through here for consistent UX.\nimport chalk from \"chalk\";\nimport ora, { type Ora } from \"ora\";\n\ntype LogFn = (message: string) => void;\n\nexport const log: {\n info: LogFn;\n success: LogFn;\n warn: LogFn;\n error: LogFn;\n dim: LogFn;\n plain: LogFn;\n} = {\n info: (m) => process.stdout.write(`${chalk.blue(\"ℹ\")} ${m}\\n`),\n success: (m) => process.stdout.write(`${chalk.green(\"✓\")} ${m}\\n`),\n warn: (m) => process.stdout.write(`${chalk.yellow(\"⚠\")} ${m}\\n`),\n error: (m) => process.stderr.write(`${chalk.red(\"✗\")} ${m}\\n`),\n dim: (m) => process.stdout.write(`${chalk.dim(m)}\\n`),\n plain: (m) => process.stdout.write(`${m}\\n`),\n};\n\n// Spinner wrapper — handles non-TTY by degrading to plain output.\nexport function spinner(text: string): Ora {\n return ora({\n text,\n spinner: \"dots\",\n isEnabled: process.stdout.isTTY ?? false,\n }).start();\n}\n\n// Chalk re-export so commands don't all import chalk separately.\nexport { chalk };\n"],"mappings":"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","names":["chalk","chalk"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
{{projectDescription}}
|
|
4
|
+
|
|
5
|
+
## Context cho Claude Code
|
|
6
|
+
|
|
7
|
+
File này là entry point. Claude Code đọc file này và resolve các @-imports bên dưới
|
|
8
|
+
để có toàn bộ context dự án. KHÔNG sửa file này thủ công; chạy `avatar scan`
|
|
9
|
+
và `avatar review` để cập nhật.
|
|
10
|
+
|
|
11
|
+
### Knowledge nền tảng (từ team-ai-pack)
|
|
12
|
+
|
|
13
|
+
@.claude/pack/knowledge/org/coding-standards.md
|
|
14
|
+
@.claude/pack/knowledge/org/git-workflow.md
|
|
15
|
+
@.claude/pack/knowledge/org/security-policy.md
|
|
16
|
+
|
|
17
|
+
### Knowledge dự án này (auto-scan)
|
|
18
|
+
|
|
19
|
+
@.claude/project/tech-stack.md
|
|
20
|
+
@.claude/project/conventions.md
|
|
21
|
+
@.claude/project/architecture.md
|
|
22
|
+
@.claude/project/domain.md
|
|
23
|
+
@.claude/project/gotchas.md
|
|
24
|
+
|
|
25
|
+
### Hướng dẫn cho Claude
|
|
26
|
+
|
|
27
|
+
- Tuân thủ convention trong @.claude/project/conventions.md trước, sau đó tới
|
|
28
|
+
@.claude/pack/knowledge/org/coding-standards.md.
|
|
29
|
+
- Khi tạo file mới, đặt theo pattern trong @.claude/project/architecture.md.
|
|
30
|
+
- Khi gặp gotcha mới, đề xuất ghi vào @.claude/project/gotchas.md.
|
|
31
|
+
- Câu hỏi quy trình: đọc @.claude/pack/knowledge/playbooks/
|
|
32
|
+
- Quyết định kiến trúc lớn: tham khảo @.claude/pack/knowledge/decisions/
|
|
33
|
+
|
|
34
|
+
### Project metadata
|
|
35
|
+
|
|
36
|
+
- Team owner: {{teamOwner}}
|
|
37
|
+
- Avatar version: {{avatarVersion}}
|
|
38
|
+
- Pack version: {{packVersion}}
|
|
39
|
+
- Last scan: {{lastScan}}
|
|
40
|
+
- Mode: {{mode}}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Node
|
|
2
|
+
node_modules/
|
|
3
|
+
npm-debug.log*
|
|
4
|
+
yarn-debug.log*
|
|
5
|
+
yarn-error.log*
|
|
6
|
+
pnpm-debug.log*
|
|
7
|
+
.pnpm-store/
|
|
8
|
+
|
|
9
|
+
# Build outputs
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
out/
|
|
13
|
+
.next/
|
|
14
|
+
.nuxt/
|
|
15
|
+
.turbo/
|
|
16
|
+
coverage/
|
|
17
|
+
|
|
18
|
+
# Cache
|
|
19
|
+
.cache/
|
|
20
|
+
.parcel-cache/
|
|
21
|
+
.eslintcache
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# Virtual envs
|
|
8
|
+
venv/
|
|
9
|
+
.venv/
|
|
10
|
+
env/
|
|
11
|
+
.env/
|
|
12
|
+
ENV/
|
|
13
|
+
|
|
14
|
+
# Build
|
|
15
|
+
build/
|
|
16
|
+
dist/
|
|
17
|
+
*.egg-info/
|
|
18
|
+
.eggs/
|
|
19
|
+
|
|
20
|
+
# Test/coverage
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
.tox/
|
|
25
|
+
.mypy_cache/
|
|
26
|
+
.ruff_cache/
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Architecture — {{projectName}}
|
|
2
|
+
|
|
3
|
+
> File này do `avatar scan` cập nhật. KHÔNG sửa thủ công.
|
|
4
|
+
|
|
5
|
+
## Tổng quan kiến trúc
|
|
6
|
+
|
|
7
|
+
{{architectureOverview}}
|
|
8
|
+
|
|
9
|
+
## Layer / Module chính
|
|
10
|
+
|
|
11
|
+
{{moduleLayout}}
|
|
12
|
+
|
|
13
|
+
## Data flow
|
|
14
|
+
|
|
15
|
+
{{dataFlow}}
|
|
16
|
+
|
|
17
|
+
## External integration
|
|
18
|
+
|
|
19
|
+
{{externalIntegrations}}
|
|
20
|
+
|
|
21
|
+
## Deployment topology
|
|
22
|
+
|
|
23
|
+
{{deploymentTopology}}
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
*Generated: {{lastScan}} · Avatar v{{avatarVersion}}*
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Conventions — {{projectName}}
|
|
2
|
+
|
|
3
|
+
> File này do `avatar scan` cập nhật. KHÔNG sửa thủ công.
|
|
4
|
+
|
|
5
|
+
## Code style
|
|
6
|
+
|
|
7
|
+
{{codeStyle}}
|
|
8
|
+
|
|
9
|
+
## Naming convention
|
|
10
|
+
|
|
11
|
+
{{namingConvention}}
|
|
12
|
+
|
|
13
|
+
## Folder structure
|
|
14
|
+
|
|
15
|
+
{{folderStructure}}
|
|
16
|
+
|
|
17
|
+
## Commit message
|
|
18
|
+
|
|
19
|
+
{{commitConvention}}
|
|
20
|
+
|
|
21
|
+
## Linter / Formatter
|
|
22
|
+
|
|
23
|
+
{{linterConfig}}
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
*Generated: {{lastScan}} · Avatar v{{avatarVersion}}*
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Domain — {{projectName}}
|
|
2
|
+
|
|
3
|
+
> File này do `avatar scan` cập nhật. KHÔNG sửa thủ công.
|
|
4
|
+
|
|
5
|
+
## Mô tả domain
|
|
6
|
+
|
|
7
|
+
{{domainDescription}}
|
|
8
|
+
|
|
9
|
+
## Khái niệm chính
|
|
10
|
+
|
|
11
|
+
{{coreEntities}}
|
|
12
|
+
|
|
13
|
+
## Use case chính
|
|
14
|
+
|
|
15
|
+
{{primaryUseCases}}
|
|
16
|
+
|
|
17
|
+
## Glossary
|
|
18
|
+
|
|
19
|
+
{{domainGlossary}}
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
*Generated: {{lastScan}} · Avatar v{{avatarVersion}}*
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Gotchas — {{projectName}}
|
|
2
|
+
|
|
3
|
+
> File tự đầy theo thời gian qua skill `knowledge-capture`. Bẫy quan trọng,
|
|
4
|
+
> bài học kinh nghiệm sẽ tích lũy ở đây.
|
|
5
|
+
|
|
6
|
+
## Cấu trúc một mục gotcha
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
### [Tag] Tên ngắn gọn
|
|
10
|
+
|
|
11
|
+
**Triệu chứng:** Lỗi gì xuất hiện.
|
|
12
|
+
|
|
13
|
+
**Nguyên nhân:** Vì sao xảy ra.
|
|
14
|
+
|
|
15
|
+
**Cách tránh:** Làm thế nào để không lặp lại.
|
|
16
|
+
|
|
17
|
+
**Tham khảo:** Link PR, issue, commit.
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Bẫy đã ghi nhận
|
|
23
|
+
|
|
24
|
+
*(Chưa có gotcha nào — Avatar sẽ tự bổ sung khi gặp pattern lặp lại trong session.)*
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
*Last updated: {{lastScan}} · Avatar v{{avatarVersion}}*
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Tech stack — {{projectName}}
|
|
2
|
+
|
|
3
|
+
> File này do `avatar scan` cập nhật. KHÔNG sửa thủ công. Đề xuất thay đổi
|
|
4
|
+
> qua `avatar review`.
|
|
5
|
+
|
|
6
|
+
## Ngôn ngữ chính
|
|
7
|
+
|
|
8
|
+
{{primaryLanguage}}
|
|
9
|
+
|
|
10
|
+
## Framework / Library
|
|
11
|
+
|
|
12
|
+
{{frameworks}}
|
|
13
|
+
|
|
14
|
+
## Database
|
|
15
|
+
|
|
16
|
+
{{databases}}
|
|
17
|
+
|
|
18
|
+
## Test stack
|
|
19
|
+
|
|
20
|
+
{{testStack}}
|
|
21
|
+
|
|
22
|
+
## Build & deploy
|
|
23
|
+
|
|
24
|
+
{{buildStack}}
|
|
25
|
+
|
|
26
|
+
## Phiên bản công cụ
|
|
27
|
+
|
|
28
|
+
{{toolVersions}}
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
*Generated: {{lastScan}} · Avatar v{{avatarVersion}}*
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"allowedTools": [
|
|
3
|
+
"Bash(npm:*)",
|
|
4
|
+
"Bash(pnpm:*)",
|
|
5
|
+
"Bash(git:*)",
|
|
6
|
+
"Bash(node:*)",
|
|
7
|
+
"Edit",
|
|
8
|
+
"Read",
|
|
9
|
+
"Write",
|
|
10
|
+
"Glob",
|
|
11
|
+
"Grep"
|
|
12
|
+
],
|
|
13
|
+
"hooks": {
|
|
14
|
+
"PostToolUse": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "Edit|Write",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "avatar internal post-edit",
|
|
21
|
+
"timeout": 5
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"env": {
|
|
28
|
+
"AVATAR_PROJECT": "{{projectName}}",
|
|
29
|
+
"AVATAR_OWNER": "{{teamOwner}}",
|
|
30
|
+
"AVATAR_MODE": "{{mode}}"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nalvietnam/avatar-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "AI harness CLI for NAL Vietnam engineering",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"test:all": "npm run build && vitest run --passWithNoTests",
|
|
26
26
|
"lint": "biome check src test",
|
|
27
27
|
"format": "biome format --write src test",
|
|
28
|
-
"prepublishOnly": "npm run build && npm run test:all"
|
|
28
|
+
"prepublishOnly": "npm run build && npm run test:all",
|
|
29
|
+
"postinstall": "node ./bin/postinstall.js"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
32
|
"@inquirer/prompts": "^8.4.3",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Node
|
|
2
|
+
node_modules/
|
|
3
|
+
npm-debug.log*
|
|
4
|
+
yarn-debug.log*
|
|
5
|
+
yarn-error.log*
|
|
6
|
+
pnpm-debug.log*
|
|
7
|
+
.pnpm-store/
|
|
8
|
+
|
|
9
|
+
# Build outputs
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
out/
|
|
13
|
+
.next/
|
|
14
|
+
.nuxt/
|
|
15
|
+
.turbo/
|
|
16
|
+
coverage/
|
|
17
|
+
|
|
18
|
+
# Cache
|
|
19
|
+
.cache/
|
|
20
|
+
.parcel-cache/
|
|
21
|
+
.eslintcache
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# Virtual envs
|
|
8
|
+
venv/
|
|
9
|
+
.venv/
|
|
10
|
+
env/
|
|
11
|
+
.env/
|
|
12
|
+
ENV/
|
|
13
|
+
|
|
14
|
+
# Build
|
|
15
|
+
build/
|
|
16
|
+
dist/
|
|
17
|
+
*.egg-info/
|
|
18
|
+
.eggs/
|
|
19
|
+
|
|
20
|
+
# Test/coverage
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
.tox/
|
|
25
|
+
.mypy_cache/
|
|
26
|
+
.ruff_cache/
|