@haaaiawd/anws 1.0.0
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/README.md +96 -0
- package/bin/cli.js +76 -0
- package/lib/copy.js +38 -0
- package/lib/index.js +8 -0
- package/lib/init.js +139 -0
- package/lib/manifest.js +53 -0
- package/lib/output.js +74 -0
- package/lib/update.js +85 -0
- package/package.json +36 -0
- package/templates/.agent/rules/agents.md +90 -0
- package/templates/.agent/skills/build-inspector/SKILL.md +83 -0
- package/templates/.agent/skills/complexity-guard/SKILL.md +71 -0
- package/templates/.agent/skills/complexity-guard/references/anti_patterns.md +21 -0
- package/templates/.agent/skills/concept-modeler/SKILL.md +112 -0
- package/templates/.agent/skills/concept-modeler/prompts/GLOSSARY_PROMPT.md +40 -0
- package/templates/.agent/skills/concept-modeler/references/ENTITY_EXTRACTION_PROMPT.md +299 -0
- package/templates/.agent/skills/concept-modeler/scripts/glossary_gen.py +66 -0
- package/templates/.agent/skills/git-forensics/SKILL.md +74 -0
- package/templates/.agent/skills/git-forensics/references/ANALYSIS_METHODOLOGY.md +193 -0
- package/templates/.agent/skills/git-forensics/scripts/git_forensics.py +615 -0
- package/templates/.agent/skills/git-forensics/scripts/git_hotspots.py +118 -0
- package/templates/.agent/skills/report-template/SKILL.md +88 -0
- package/templates/.agent/skills/report-template/references/REPORT_TEMPLATE.md +100 -0
- package/templates/.agent/skills/runtime-inspector/SKILL.md +93 -0
- package/templates/.agent/skills/spec-writer/SKILL.md +58 -0
- package/templates/.agent/skills/spec-writer/references/prd_template.md +174 -0
- package/templates/.agent/skills/system-architect/SKILL.md +620 -0
- package/templates/.agent/skills/system-architect/references/rfc_template.md +59 -0
- package/templates/.agent/skills/system-designer/SKILL.md +439 -0
- package/templates/.agent/skills/system-designer/references/system-design-template.md +533 -0
- package/templates/.agent/skills/task-planner/SKILL.md +474 -0
- package/templates/.agent/skills/task-planner/references/TASK_TEMPLATE.md +133 -0
- package/templates/.agent/skills/tech-evaluator/SKILL.md +135 -0
- package/templates/.agent/skills/tech-evaluator/references/ADR_TEMPLATE.md +68 -0
- package/templates/.agent/workflows/blueprint.md +185 -0
- package/templates/.agent/workflows/challenge.md +467 -0
- package/templates/.agent/workflows/change.md +294 -0
- package/templates/.agent/workflows/craft.md +626 -0
- package/templates/.agent/workflows/design-system.md +497 -0
- package/templates/.agent/workflows/explore.md +307 -0
- package/templates/.agent/workflows/forge.md +354 -0
- package/templates/.agent/workflows/genesis.md +265 -0
- package/templates/.agent/workflows/scout.md +130 -0
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# anws
|
|
2
|
+
|
|
3
|
+
**Antigravity Workflow System** — 一条命令,将 AI 协作工作流体系注入任意项目。
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
npm install -g @haaaiawd/anws
|
|
7
|
+
anws init
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 安装
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g @haaaiawd/anws
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
需要 **Node.js ≥ 18**。
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 命令
|
|
23
|
+
|
|
24
|
+
### `anws init`
|
|
25
|
+
|
|
26
|
+
将 `.agent/` 工作流体系复制到当前项目目录。
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cd my-project
|
|
30
|
+
anws init
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- **首次初始化**:直接写入所有文件,不覆盖任何已有文件。
|
|
34
|
+
- **检测到冲突**:显示已存在的托管文件数量,询问是否覆盖(默认 **N**)。
|
|
35
|
+
确认后只会覆盖 `anws` 管理的文件,你的自定义文件不受影响。
|
|
36
|
+
- **非 TTY 环境(如 CI)**:检测到冲突时自动跳过,不挂起进程。
|
|
37
|
+
|
|
38
|
+
### `anws update`
|
|
39
|
+
|
|
40
|
+
将当前项目的 `.agent/` 托管文件更新到最新版本。
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
anws update
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- 仅覆盖 `anws` 管理的文件,用户自定义文件完全保留。
|
|
47
|
+
- 交互式确认(默认 **N**),防止误操作。
|
|
48
|
+
|
|
49
|
+
### 选项
|
|
50
|
+
|
|
51
|
+
| 选项 | 说明 |
|
|
52
|
+
|------|------|
|
|
53
|
+
| `-v`, `--version` | 打印版本号 |
|
|
54
|
+
| `-h`, `--help` | 显示帮助信息 |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 无 npm 安装方式
|
|
59
|
+
|
|
60
|
+
如果你不想全局安装,也可以直接克隆仓库手动获取模板:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# 克隆仓库
|
|
64
|
+
git clone https://github.com/YOYZHANG/Antigravity-Workflow-System.git
|
|
65
|
+
|
|
66
|
+
# 将 templates/.agent/ 复制到你的项目
|
|
67
|
+
cp -r Antigravity-Workflow-System/src/anws/templates/.agent/ my-project/
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 完成初始化后
|
|
73
|
+
|
|
74
|
+
1. 阅读 `.agent/rules/agents.md` — 了解系统的核心法则
|
|
75
|
+
2. 在你的 AI 助手中执行 `/genesis` — 启动新项目的架构设计流程
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 冲突处理机制
|
|
80
|
+
|
|
81
|
+
`anws` 维护一份静态的**托管文件清单**(34 个文件),只有清单内的文件才会被覆盖,清单外的文件永远不会被修改。
|
|
82
|
+
|
|
83
|
+
这意味着你可以安全地在 `.agent/` 目录中添加自定义工作流或技能,`anws update` 不会碰它们。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 系统要求
|
|
88
|
+
|
|
89
|
+
- Node.js **≥ 18.0.0**
|
|
90
|
+
- 无运行时依赖
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { parseArgs } = require('node:util');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const { error, info, logo } = require('../lib/output');
|
|
7
|
+
|
|
8
|
+
// ─── 版本号从 package.json 读取 ─────────────────────────────────────────────
|
|
9
|
+
const { version } = require(path.join(__dirname, '..', 'package.json'));
|
|
10
|
+
|
|
11
|
+
// ─── 帮助文本 ─────────────────────────────────────────────────────────────────
|
|
12
|
+
const HELP = `
|
|
13
|
+
v${version} — Antigravity Workflow System
|
|
14
|
+
|
|
15
|
+
USAGE
|
|
16
|
+
anws <command> [options]
|
|
17
|
+
|
|
18
|
+
COMMANDS
|
|
19
|
+
init Copy .agent/ workflow system into the current project
|
|
20
|
+
update Update managed .agent/ files to the latest version
|
|
21
|
+
|
|
22
|
+
OPTIONS
|
|
23
|
+
-v, --version Print version number
|
|
24
|
+
-h, --help Show this help message
|
|
25
|
+
|
|
26
|
+
EXAMPLES
|
|
27
|
+
anws init # Set up workflow system in current directory
|
|
28
|
+
anws update # Update existing workflow files to latest
|
|
29
|
+
`.trimStart();
|
|
30
|
+
|
|
31
|
+
// ─── 参数解析 ─────────────────────────────────────────────────────────────────
|
|
32
|
+
const { values, positionals } = parseArgs({
|
|
33
|
+
args: process.argv.slice(2),
|
|
34
|
+
options: {
|
|
35
|
+
version: { type: 'boolean', short: 'v', default: false },
|
|
36
|
+
help: { type: 'boolean', short: 'h', default: false },
|
|
37
|
+
},
|
|
38
|
+
strict: false,
|
|
39
|
+
allowPositionals: true,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ─── 命令路由 ─────────────────────────────────────────────────────────────────
|
|
43
|
+
async function main() {
|
|
44
|
+
if (values.version) {
|
|
45
|
+
console.log(version);
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (values.help || positionals.length === 0) {
|
|
50
|
+
logo();
|
|
51
|
+
process.stdout.write(HELP);
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const command = positionals[0];
|
|
56
|
+
|
|
57
|
+
switch (command) {
|
|
58
|
+
case 'init':
|
|
59
|
+
await require('../lib/init')();
|
|
60
|
+
break;
|
|
61
|
+
|
|
62
|
+
case 'update':
|
|
63
|
+
await require('../lib/update')();
|
|
64
|
+
break;
|
|
65
|
+
|
|
66
|
+
default:
|
|
67
|
+
error(`Unknown command: "${command}"`);
|
|
68
|
+
info('Run `anws --help` to see available commands.');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
main().catch((err) => {
|
|
74
|
+
error(`Unexpected error: ${err.message}`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
});
|
package/lib/copy.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 递归复制目录,返回已写入的文件路径数组(相对于 destDir)。
|
|
8
|
+
*
|
|
9
|
+
* @param {string} srcDir 源目录绝对路径
|
|
10
|
+
* @param {string} destDir 目标目录绝对路径(不存在时自动创建)
|
|
11
|
+
* @returns {Promise<string[]>} 已写入文件的绝对路径列表
|
|
12
|
+
*/
|
|
13
|
+
async function copyDir(srcDir, destDir) {
|
|
14
|
+
const written = [];
|
|
15
|
+
|
|
16
|
+
async function walk(src, dest) {
|
|
17
|
+
await fs.mkdir(dest, { recursive: true });
|
|
18
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
19
|
+
|
|
20
|
+
for (const entry of entries) {
|
|
21
|
+
const srcPath = path.join(src, entry.name);
|
|
22
|
+
const destPath = path.join(dest, entry.name);
|
|
23
|
+
|
|
24
|
+
if (entry.isDirectory()) {
|
|
25
|
+
await walk(srcPath, destPath);
|
|
26
|
+
} else if (entry.isFile()) {
|
|
27
|
+
await fs.copyFile(srcPath, destPath);
|
|
28
|
+
written.push(destPath);
|
|
29
|
+
}
|
|
30
|
+
// 忽略 symlink 等特殊文件类型
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await walk(srcDir, destDir);
|
|
35
|
+
return written;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = { copyDir };
|
package/lib/index.js
ADDED
package/lib/init.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { copyDir } = require('./copy');
|
|
6
|
+
const { MANAGED_FILES } = require('./manifest');
|
|
7
|
+
const { success, warn, info, fileLine, blank, logo } = require('./output');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* anws init — 将工作流系统写入当前项目
|
|
11
|
+
*/
|
|
12
|
+
async function init() {
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const srcRoot = path.join(__dirname, '..', 'templates', '.agent');
|
|
15
|
+
const destRoot = path.join(cwd, '.agent');
|
|
16
|
+
|
|
17
|
+
// ── 冲突检测(T1.2.3 在此处插入冲突分支)──────────────────────────────────
|
|
18
|
+
const conflicting = await findConflicts(cwd);
|
|
19
|
+
if (conflicting.length > 0) {
|
|
20
|
+
const confirmed = await askOverwrite(conflicting.length);
|
|
21
|
+
if (!confirmed) {
|
|
22
|
+
blank();
|
|
23
|
+
info('Aborted. No files were changed.');
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
// 仅覆盖托管文件(用户自有文件不受影响)
|
|
27
|
+
await overwriteManaged(srcRoot, cwd);
|
|
28
|
+
printSummary(conflicting, cwd, 'updated');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// ── 无冲突:直接复制 ─────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
logo();
|
|
34
|
+
info('Initializing Antigravity Workflow System...');
|
|
35
|
+
blank();
|
|
36
|
+
|
|
37
|
+
const written = await copyDir(srcRoot, destRoot);
|
|
38
|
+
|
|
39
|
+
// 打印文件列表
|
|
40
|
+
for (const absPath of written) {
|
|
41
|
+
const rel = path.relative(cwd, absPath).replace(/\\/g, '/');
|
|
42
|
+
fileLine(rel);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
blank();
|
|
46
|
+
success(`Done! ${written.length} files written to .agent/`);
|
|
47
|
+
printNextSteps();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ─── 辅助函数 ──────────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 找出 cwd 中已存在的托管文件列表。
|
|
54
|
+
* @returns {Promise<string[]>} 已存在的托管文件相对路径数组
|
|
55
|
+
*/
|
|
56
|
+
async function findConflicts(cwd) {
|
|
57
|
+
const conflicts = [];
|
|
58
|
+
for (const rel of MANAGED_FILES) {
|
|
59
|
+
const abs = path.join(cwd, rel);
|
|
60
|
+
const exists = await fs.access(abs).then(() => true).catch(() => false);
|
|
61
|
+
if (exists) conflicts.push(rel);
|
|
62
|
+
}
|
|
63
|
+
return conflicts;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 交互式询问用户是否覆盖(默认 N)。
|
|
68
|
+
* 非 TTY 环境(如 CI)自动返回 false。
|
|
69
|
+
* @returns {Promise<boolean>}
|
|
70
|
+
*/
|
|
71
|
+
async function askOverwrite(count) {
|
|
72
|
+
// 非 TTY 环境:默认不覆盖,防止 CI 挂起
|
|
73
|
+
if (!process.stdin.isTTY) {
|
|
74
|
+
warn(`${count} managed file(s) already exist. Non-TTY: skipping overwrite.`);
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const readline = require('node:readline');
|
|
79
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
80
|
+
|
|
81
|
+
return new Promise((resolve) => {
|
|
82
|
+
rl.question(
|
|
83
|
+
`\n\u26a0 ${count} managed file(s) already exist. Overwrite? [y/N] `,
|
|
84
|
+
(answer) => {
|
|
85
|
+
rl.close();
|
|
86
|
+
resolve(answer.trim().toLowerCase() === 'y');
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 仅覆盖 MANAGED_FILES 清单内的文件,用户自有文件不受影响。
|
|
94
|
+
*/
|
|
95
|
+
async function overwriteManaged(srcRoot, cwd) {
|
|
96
|
+
// srcRoot 是 templates/.agent/
|
|
97
|
+
const srcBase = path.dirname(srcRoot); // templates/
|
|
98
|
+
for (const rel of MANAGED_FILES) {
|
|
99
|
+
// rel 格式: '.agent/skills/...'
|
|
100
|
+
const srcPath = path.join(srcBase, rel);
|
|
101
|
+
const destPath = path.join(cwd, rel);
|
|
102
|
+
|
|
103
|
+
// 确保目标目录存在
|
|
104
|
+
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
105
|
+
|
|
106
|
+
// 只复制 templates 中存在的文件(安全检查)
|
|
107
|
+
const srcExists = await fs.access(srcPath).then(() => true).catch(() => false);
|
|
108
|
+
if (srcExists) {
|
|
109
|
+
await fs.copyFile(srcPath, destPath);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 打印操作摘要(更新场景)。
|
|
116
|
+
*/
|
|
117
|
+
function printSummary(files, cwd, action) {
|
|
118
|
+
const verb = action === 'updated' ? 'Updating' : 'Writing';
|
|
119
|
+
blank();
|
|
120
|
+
info(`${verb} files...`);
|
|
121
|
+
blank();
|
|
122
|
+
for (const rel of files) {
|
|
123
|
+
fileLine(rel.replace(/\\/g, '/'));
|
|
124
|
+
}
|
|
125
|
+
blank();
|
|
126
|
+
success(`Done! ${files.length} file(s) ${action}.`);
|
|
127
|
+
if (action === 'updated') {
|
|
128
|
+
info('Managed files have been updated to the latest version.');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function printNextSteps() {
|
|
133
|
+
blank();
|
|
134
|
+
info('Next steps:');
|
|
135
|
+
info(' 1. Read .agent/rules/agents.md to understand the system');
|
|
136
|
+
info(' 2. Run /genesis in your AI assistant to start a new project');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = init;
|
package/lib/manifest.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MANAGED_FILES — anws 托管文件清单
|
|
5
|
+
*
|
|
6
|
+
* 此数组列出 anws 包负责管理的所有文件路径(相对于目标项目根目录)。
|
|
7
|
+
*
|
|
8
|
+
* 冲突检测规则:
|
|
9
|
+
* - 仅当目标项目中存在此清单内的文件时,才触发覆盖确认
|
|
10
|
+
* - 清单之外的用户文件,在任何情况下均不会被触碰
|
|
11
|
+
*
|
|
12
|
+
* 维护规则(重要):
|
|
13
|
+
* - 每次向 templates/.agent/ 新增文件时,必须同步更新此数组
|
|
14
|
+
* - 文件路径格式:'.agent/relative/path'(Unix 风格斜杠)
|
|
15
|
+
*/
|
|
16
|
+
const MANAGED_FILES = [
|
|
17
|
+
'.agent/rules/agents.md',
|
|
18
|
+
'.agent/skills/build-inspector/SKILL.md',
|
|
19
|
+
'.agent/skills/complexity-guard/references/anti_patterns.md',
|
|
20
|
+
'.agent/skills/complexity-guard/SKILL.md',
|
|
21
|
+
'.agent/skills/concept-modeler/prompts/GLOSSARY_PROMPT.md',
|
|
22
|
+
'.agent/skills/concept-modeler/references/ENTITY_EXTRACTION_PROMPT.md',
|
|
23
|
+
'.agent/skills/concept-modeler/scripts/glossary_gen.py',
|
|
24
|
+
'.agent/skills/concept-modeler/SKILL.md',
|
|
25
|
+
'.agent/skills/git-forensics/references/ANALYSIS_METHODOLOGY.md',
|
|
26
|
+
'.agent/skills/git-forensics/scripts/git_forensics.py',
|
|
27
|
+
'.agent/skills/git-forensics/scripts/git_hotspots.py',
|
|
28
|
+
'.agent/skills/git-forensics/SKILL.md',
|
|
29
|
+
'.agent/skills/report-template/references/REPORT_TEMPLATE.md',
|
|
30
|
+
'.agent/skills/report-template/SKILL.md',
|
|
31
|
+
'.agent/skills/runtime-inspector/SKILL.md',
|
|
32
|
+
'.agent/skills/spec-writer/references/prd_template.md',
|
|
33
|
+
'.agent/skills/spec-writer/SKILL.md',
|
|
34
|
+
'.agent/skills/system-architect/references/rfc_template.md',
|
|
35
|
+
'.agent/skills/system-architect/SKILL.md',
|
|
36
|
+
'.agent/skills/system-designer/references/system-design-template.md',
|
|
37
|
+
'.agent/skills/system-designer/SKILL.md',
|
|
38
|
+
'.agent/skills/task-planner/references/TASK_TEMPLATE.md',
|
|
39
|
+
'.agent/skills/task-planner/SKILL.md',
|
|
40
|
+
'.agent/skills/tech-evaluator/references/ADR_TEMPLATE.md',
|
|
41
|
+
'.agent/skills/tech-evaluator/SKILL.md',
|
|
42
|
+
'.agent/workflows/blueprint.md',
|
|
43
|
+
'.agent/workflows/challenge.md',
|
|
44
|
+
'.agent/workflows/change.md',
|
|
45
|
+
'.agent/workflows/craft.md',
|
|
46
|
+
'.agent/workflows/design-system.md',
|
|
47
|
+
'.agent/workflows/explore.md',
|
|
48
|
+
'.agent/workflows/forge.md',
|
|
49
|
+
'.agent/workflows/genesis.md',
|
|
50
|
+
'.agent/workflows/scout.md',
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
module.exports = { MANAGED_FILES };
|
package/lib/output.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* lib/output.js — 统一终端输出工具
|
|
5
|
+
*
|
|
6
|
+
* 特性:
|
|
7
|
+
* - ✔ / ⚠ / ✖ Unicode 前缀区分成功/警告/错误
|
|
8
|
+
* - 自动 ANSI 颜色(TTY 环境)
|
|
9
|
+
* - 非 TTY 或 NO_COLOR=1 时自动降级为无颜色输出
|
|
10
|
+
* - 不依赖任何第三方库
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// ─── 颜色检测 ─────────────────────────────────────────────────────────────────
|
|
14
|
+
const useColor =
|
|
15
|
+
!!process.stdout.isTTY &&
|
|
16
|
+
!process.env.NO_COLOR &&
|
|
17
|
+
process.env.TERM !== 'dumb';
|
|
18
|
+
|
|
19
|
+
// ─── ANSI 转义码 ──────────────────────────────────────────────────────────────
|
|
20
|
+
const c = {
|
|
21
|
+
green: useColor ? '\x1b[32m' : '',
|
|
22
|
+
yellow: useColor ? '\x1b[33m' : '',
|
|
23
|
+
red: useColor ? '\x1b[31m' : '',
|
|
24
|
+
dim: useColor ? '\x1b[2m' : '',
|
|
25
|
+
reset: useColor ? '\x1b[0m' : '',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// ─── 公共输出函数 ─────────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
/** 成功消息(绿色 ✔)*/
|
|
31
|
+
function success(msg) {
|
|
32
|
+
console.log(`${c.green}\u2714${c.reset} ${msg}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** 警告/提示消息(黄色 ⚠)*/
|
|
36
|
+
function warn(msg) {
|
|
37
|
+
console.log(`${c.yellow}\u26a0${c.reset} ${msg}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** 错误消息(红色 ✖,写入 stderr)*/
|
|
41
|
+
function error(msg) {
|
|
42
|
+
console.error(`${c.red}\u2716${c.reset} ${msg}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 普通信息行(缩进两格)*/
|
|
46
|
+
function info(msg) {
|
|
47
|
+
console.log(` ${msg}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** 文件路径行(dimmed 样式)*/
|
|
51
|
+
function fileLine(relativePath) {
|
|
52
|
+
console.log(` ${c.dim}${relativePath}${c.reset}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** 空行 */
|
|
56
|
+
function blank() {
|
|
57
|
+
console.log('');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** 打印 ASCII Logo */
|
|
61
|
+
function logo() {
|
|
62
|
+
const art = `
|
|
63
|
+
___ _ ___ _______
|
|
64
|
+
/ | / | / / | /| / / ___/
|
|
65
|
+
/ /| | / |/ /| |/ |/ /\\__ \\
|
|
66
|
+
/ ___ |/ /| / | /| /___/ /
|
|
67
|
+
/_/ |_/_/ |_/ |__/|__//____/
|
|
68
|
+
`;
|
|
69
|
+
const cyan = useColor ? '\x1b[36m' : '';
|
|
70
|
+
const reset = useColor ? '\x1b[0m' : '';
|
|
71
|
+
console.log(`${cyan}${art}${reset}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = { success, warn, error, info, fileLine, blank, logo, c };
|
package/lib/update.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { MANAGED_FILES } = require('./manifest');
|
|
6
|
+
const { success, warn, error, info, fileLine, blank, logo } = require('./output');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* anws update — 将当前项目的托管文件更新到最新版本
|
|
10
|
+
*/
|
|
11
|
+
async function update() {
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const agentDir = path.join(cwd, '.agent');
|
|
14
|
+
|
|
15
|
+
// 检查 .agent/ 是否存在
|
|
16
|
+
const agentExists = await fs.access(agentDir).then(() => true).catch(() => false);
|
|
17
|
+
if (!agentExists) {
|
|
18
|
+
logo();
|
|
19
|
+
error('No .agent/ found in current directory.');
|
|
20
|
+
info('Run `anws init` first to set up the workflow system.');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 询问确认
|
|
25
|
+
const confirmed = await askUpdate();
|
|
26
|
+
if (!confirmed) {
|
|
27
|
+
blank();
|
|
28
|
+
info('Aborted. No files were changed.');
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
logo();
|
|
33
|
+
// 仅覆盖托管文件
|
|
34
|
+
const srcRoot = path.join(__dirname, '..', 'templates', '.agent');
|
|
35
|
+
const updated = [];
|
|
36
|
+
|
|
37
|
+
for (const rel of MANAGED_FILES) {
|
|
38
|
+
const srcPath = path.join(path.dirname(srcRoot), rel); // templates/.agent/...
|
|
39
|
+
const destPath = path.join(cwd, rel);
|
|
40
|
+
|
|
41
|
+
const srcExists = await fs.access(srcPath).then(() => true).catch(() => false);
|
|
42
|
+
if (!srcExists) continue;
|
|
43
|
+
|
|
44
|
+
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
45
|
+
await fs.copyFile(srcPath, destPath);
|
|
46
|
+
updated.push(rel);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 打印摘要
|
|
50
|
+
blank();
|
|
51
|
+
info('Updated files:');
|
|
52
|
+
blank();
|
|
53
|
+
for (const rel of updated) {
|
|
54
|
+
fileLine(rel.replace(/\\/g, '/'));
|
|
55
|
+
}
|
|
56
|
+
blank();
|
|
57
|
+
success(`Done! ${updated.length} file(s) updated.`);
|
|
58
|
+
info('Managed files have been updated to the latest version.');
|
|
59
|
+
info('Your custom files in .agent/ were not touched.');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 交互式确认更新操作(默认 N)。
|
|
64
|
+
*/
|
|
65
|
+
async function askUpdate() {
|
|
66
|
+
if (!process.stdin.isTTY) {
|
|
67
|
+
warn('Non-TTY environment detected. Skipping update to avoid accidental overwrites.');
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const readline = require('node:readline');
|
|
72
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
73
|
+
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
|
+
rl.question(
|
|
76
|
+
'\n\u26a0 This will overwrite all managed .agent/ files. Continue? [y/N] ',
|
|
77
|
+
(answer) => {
|
|
78
|
+
rl.close();
|
|
79
|
+
resolve(answer.trim().toLowerCase() === 'y');
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = update;
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@haaaiawd/anws",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Antigravity Workflow System CLI — one command to install AI collaboration workflows into your project",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"workflow",
|
|
8
|
+
"agent",
|
|
9
|
+
"cli",
|
|
10
|
+
"developer-tools"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/your-org/antigravity-workflow-system",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/your-org/antigravity-workflow-system.git"
|
|
16
|
+
},
|
|
17
|
+
"author": "haaaiawd <1134180104@qq.com>",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"anws": "bin/cli.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin/",
|
|
27
|
+
"lib/",
|
|
28
|
+
"templates/",
|
|
29
|
+
"README.md"
|
|
30
|
+
],
|
|
31
|
+
"main": "./lib/index.js",
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test": "node --test test/**/*.test.js"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {}
|
|
36
|
+
}
|