wangchuan 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/.wangchuan/config.example.json +43 -0
- package/README.md +210 -0
- package/dist/bin/wangchuan.d.ts +9 -0
- package/dist/bin/wangchuan.d.ts.map +1 -0
- package/dist/bin/wangchuan.js +93 -0
- package/dist/bin/wangchuan.js.map +1 -0
- package/dist/src/commands/diff.d.ts +9 -0
- package/dist/src/commands/diff.d.ts.map +1 -0
- package/dist/src/commands/diff.js +96 -0
- package/dist/src/commands/diff.js.map +1 -0
- package/dist/src/commands/init.d.ts +6 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +49 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/list.d.ts +9 -0
- package/dist/src/commands/list.d.ts.map +1 -0
- package/dist/src/commands/list.js +45 -0
- package/dist/src/commands/list.js.map +1 -0
- package/dist/src/commands/pull.d.ts +6 -0
- package/dist/src/commands/pull.d.ts.map +1 -0
- package/dist/src/commands/pull.js +53 -0
- package/dist/src/commands/pull.js.map +1 -0
- package/dist/src/commands/push.d.ts +9 -0
- package/dist/src/commands/push.d.ts.map +1 -0
- package/dist/src/commands/push.js +72 -0
- package/dist/src/commands/push.js.map +1 -0
- package/dist/src/commands/status.d.ts +6 -0
- package/dist/src/commands/status.d.ts.map +1 -0
- package/dist/src/commands/status.js +86 -0
- package/dist/src/commands/status.js.map +1 -0
- package/dist/src/core/config.d.ts +27 -0
- package/dist/src/core/config.d.ts.map +1 -0
- package/dist/src/core/config.js +110 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/crypto.d.ts +24 -0
- package/dist/src/core/crypto.d.ts.map +1 -0
- package/dist/src/core/crypto.js +89 -0
- package/dist/src/core/crypto.js.map +1 -0
- package/dist/src/core/git.d.ts +18 -0
- package/dist/src/core/git.d.ts.map +1 -0
- package/dist/src/core/git.js +79 -0
- package/dist/src/core/git.js.map +1 -0
- package/dist/src/core/sync.d.ts +27 -0
- package/dist/src/core/sync.d.ts.map +1 -0
- package/dist/src/core/sync.js +253 -0
- package/dist/src/core/sync.js.map +1 -0
- package/dist/src/types.d.ts +95 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +5 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/linediff.d.ts +22 -0
- package/dist/src/utils/linediff.d.ts.map +1 -0
- package/dist/src/utils/linediff.js +80 -0
- package/dist/src/utils/linediff.js.map +1 -0
- package/dist/src/utils/logger.d.ts +13 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +34 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/prompt.d.ts +14 -0
- package/dist/src/utils/prompt.d.ts.map +1 -0
- package/dist/src/utils/prompt.js +37 -0
- package/dist/src/utils/prompt.js.map +1 -0
- package/dist/src/utils/validator.d.ts +17 -0
- package/dist/src/utils/validator.d.ts.map +1 -0
- package/dist/src/utils/validator.js +33 -0
- package/dist/src/utils/validator.js.map +1 -0
- package/dist/test/crypto.test.d.ts +5 -0
- package/dist/test/crypto.test.d.ts.map +1 -0
- package/dist/test/crypto.test.js +93 -0
- package/dist/test/crypto.test.js.map +1 -0
- package/package.json +56 -0
- package/skill/SKILL.md +67 -0
- package/skill/wangchuan-skill.sh +54 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "忘川配置示例 — 复制为 ~/.wangchuan/config.json 并修改",
|
|
3
|
+
"repo": "git@github.com:SUpermin6u/wangchuan.git",
|
|
4
|
+
"branch": "main",
|
|
5
|
+
"localRepoPath": "~/.wangchuan/repo",
|
|
6
|
+
"keyPath": "~/.wangchuan/master.key",
|
|
7
|
+
"hostname": "",
|
|
8
|
+
"profiles": {
|
|
9
|
+
"default": {
|
|
10
|
+
"openclaw": {
|
|
11
|
+
"enabled": true,
|
|
12
|
+
"workspacePath": "~/.openclaw/workspace",
|
|
13
|
+
"syncFiles": [
|
|
14
|
+
{ "src": "MEMORY.md", "encrypt": true },
|
|
15
|
+
{ "src": "AGENTS.md", "encrypt": false },
|
|
16
|
+
{ "src": "SOUL.md", "encrypt": false },
|
|
17
|
+
{ "src": "USER.md", "encrypt": true },
|
|
18
|
+
{ "src": "TOOLS.md", "encrypt": false },
|
|
19
|
+
{ "src": "config/mcporter.json", "encrypt": true }
|
|
20
|
+
],
|
|
21
|
+
"syncDirs": [
|
|
22
|
+
{ "src": "skills/", "encrypt": false }
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"claude": {
|
|
26
|
+
"enabled": false,
|
|
27
|
+
"workspacePath": "~/.claude",
|
|
28
|
+
"syncFiles": [
|
|
29
|
+
{ "src": ".claude.json", "encrypt": true }
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"gemini": {
|
|
33
|
+
"enabled": false,
|
|
34
|
+
"workspacePath": "~/.gemini",
|
|
35
|
+
"syncFiles": [
|
|
36
|
+
{ "src": "settings.internal.json", "encrypt": true },
|
|
37
|
+
{ "src": "projects.json", "encrypt": false },
|
|
38
|
+
{ "src": "trustedFolders.json", "encrypt": false }
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# 忘川 · Wangchuan
|
|
2
|
+
|
|
3
|
+
> 忘川是中国神话中冥界的遗忘之河,亡魂渡河饮水即忘前世一切记忆。
|
|
4
|
+
> 而 **Wangchuan** 让你的 AI 配置在环境切换时永不遗失。
|
|
5
|
+
|
|
6
|
+
AI 记忆同步系统,支持 OpenClaw / Claude / Gemini 多种智能体记忆的加密备份与跨环境迁移。
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 功能特性
|
|
11
|
+
|
|
12
|
+
| 命令 | 描述 |
|
|
13
|
+
|------|------|
|
|
14
|
+
| `init` | 初始化系统、生成 AES-256-GCM 密钥、克隆私有仓库 |
|
|
15
|
+
| `pull` | 从私有仓库拉取并解密配置,还原到本地工作区(支持冲突交互) |
|
|
16
|
+
| `push` | 将本地配置加密推送到私有仓库 |
|
|
17
|
+
| `status` | 查看仓库状态、工作区差异与文件清单 |
|
|
18
|
+
| `diff` | 逐文件显示本地与仓库的行级差异(自动解密) |
|
|
19
|
+
| `list` | 列出所有托管文件,显示本地/仓库存在状态 |
|
|
20
|
+
|
|
21
|
+
- **AES-256-GCM** 加密:密钥本地存储,永不提交 Git
|
|
22
|
+
- 全局 `--agent` 过滤:只操作指定智能体(`openclaw` / `claude` / `gemini`)
|
|
23
|
+
- 推送前自动扫描明文 token/apiKey
|
|
24
|
+
- 拉取冲突时交互式选择:覆盖 / 跳过 / 全部覆盖 / 全部跳过
|
|
25
|
+
- 失败自动回滚,不污染仓库历史
|
|
26
|
+
- 支持 OpenClaw Skill 封装,对话直接调用
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 安装
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/SUpermin6u/wangchuan.git ~/wangchuan
|
|
34
|
+
cd ~/wangchuan
|
|
35
|
+
npm install
|
|
36
|
+
npm run build # 编译 TypeScript
|
|
37
|
+
npm link # 全局注册 wangchuan 命令(可选)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 快速开始
|
|
43
|
+
|
|
44
|
+
### 1. 初始化
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
wangchuan init --repo git@github.com:yourname/your-brain.git
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
执行后:
|
|
51
|
+
- 生成 `~/.wangchuan/config.json`(系统配置)
|
|
52
|
+
- 生成 `~/.wangchuan/master.key`(主密钥,**请妥善保管**)
|
|
53
|
+
- 克隆仓库到 `~/.wangchuan/repo`
|
|
54
|
+
|
|
55
|
+
### 2. 推送本地配置
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
wangchuan push --message "初始化配置"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. 在新环境拉取配置
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 先把 master.key 复制到新环境的 ~/.wangchuan/master.key
|
|
65
|
+
wangchuan init --repo git@github.com:yourname/your-brain.git
|
|
66
|
+
wangchuan pull
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 4. 查看同步状态
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
wangchuan status
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 5. 只操作指定智能体
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
wangchuan push --agent openclaw -m "更新 OpenClaw 记忆"
|
|
79
|
+
wangchuan pull --agent claude
|
|
80
|
+
wangchuan diff --agent gemini
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 支持同步的配置
|
|
86
|
+
|
|
87
|
+
每个智能体的 `workspacePath` 均可在 `~/.wangchuan/config.json` 中自定义。
|
|
88
|
+
|
|
89
|
+
### OpenClaw(默认开启)
|
|
90
|
+
|
|
91
|
+
| 文件 | 加密 |
|
|
92
|
+
|------|------|
|
|
93
|
+
| `MEMORY.md` | ✔ 加密 |
|
|
94
|
+
| `AGENTS.md` | 明文 |
|
|
95
|
+
| `SOUL.md` | 明文 |
|
|
96
|
+
| `USER.md` | ✔ 加密 |
|
|
97
|
+
| `TOOLS.md` | 明文 |
|
|
98
|
+
| `config/mcporter.json` | ✔ 加密 |
|
|
99
|
+
| `skills/` (目录) | 明文 |
|
|
100
|
+
|
|
101
|
+
默认路径:`~/.openclaw/workspace/`
|
|
102
|
+
|
|
103
|
+
### Claude(可选,在配置中开启)
|
|
104
|
+
|
|
105
|
+
| 文件 | 加密 |
|
|
106
|
+
|------|------|
|
|
107
|
+
| `.claude.json` | ✔ 加密 |
|
|
108
|
+
|
|
109
|
+
默认路径:`~/.claude/`
|
|
110
|
+
|
|
111
|
+
### Gemini(可选,在配置中开启)
|
|
112
|
+
|
|
113
|
+
| 文件 | 加密 |
|
|
114
|
+
|------|------|
|
|
115
|
+
| `settings.internal.json` | ✔ 加密 |
|
|
116
|
+
| `projects.json` | 明文 |
|
|
117
|
+
| `trustedFolders.json` | 明文 |
|
|
118
|
+
|
|
119
|
+
默认路径:`~/.gemini/`
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 配置文件
|
|
124
|
+
|
|
125
|
+
配置位于 `~/.wangchuan/config.json`,示例见 [.wangchuan/config.example.json](.wangchuan/config.example.json)。
|
|
126
|
+
|
|
127
|
+
```jsonc
|
|
128
|
+
{
|
|
129
|
+
"repo": "git@github.com:yourname/your-brain.git",
|
|
130
|
+
"branch": "main",
|
|
131
|
+
"localRepoPath": "~/.wangchuan/repo",
|
|
132
|
+
"keyPath": "~/.wangchuan/master.key",
|
|
133
|
+
"profiles": {
|
|
134
|
+
"default": {
|
|
135
|
+
"openclaw": { "enabled": true, "workspacePath": "~/.openclaw/workspace", ... },
|
|
136
|
+
"claude": { "enabled": false, "workspacePath": "~/.claude", ... },
|
|
137
|
+
"gemini": { "enabled": false, "workspacePath": "~/.gemini", ... }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 加密说明
|
|
146
|
+
|
|
147
|
+
- 算法:**AES-256-GCM**(认证加密,防篡改)
|
|
148
|
+
- 密钥:`~/.wangchuan/master.key`(32 字节,十六进制存储)
|
|
149
|
+
- 密文格式:`IV(12B) + AuthTag(16B) + CipherText`,Base64 编码后存储为 `.enc` 文件
|
|
150
|
+
- **⚠️ master.key 丢失将无法解密历史配置,请做好备份**
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## OpenClaw Skill
|
|
155
|
+
|
|
156
|
+
将 `skill/` 目录注册为 OpenClaw Skill 后,即可在对话中直接说:
|
|
157
|
+
|
|
158
|
+
> "帮我拉取最新的 AI 配置"
|
|
159
|
+
> "把修改推送一下,备注:更新项目记忆"
|
|
160
|
+
> "查看忘川状态"
|
|
161
|
+
> "列出所有托管文件"
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 安全规范
|
|
166
|
+
|
|
167
|
+
1. `master.key` 已加入 `.gitignore`,不会意外提交
|
|
168
|
+
2. 推送前自动扫描明文 token(`api_key`, `sk-xxx`, `password` 等)
|
|
169
|
+
3. 若需迁移密钥,用加密方式传输(不要通过明文邮件/IM)
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 目录结构
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
wangchuan/
|
|
177
|
+
├── bin/wangchuan.ts CLI 入口
|
|
178
|
+
├── src/
|
|
179
|
+
│ ├── core/
|
|
180
|
+
│ │ ├── sync.ts 同步引擎
|
|
181
|
+
│ │ ├── crypto.ts AES-256-GCM 加解密
|
|
182
|
+
│ │ ├── git.ts simple-git 封装
|
|
183
|
+
│ │ └── config.ts 配置管理
|
|
184
|
+
│ ├── commands/
|
|
185
|
+
│ │ ├── init.ts init 命令
|
|
186
|
+
│ │ ├── pull.ts pull 命令
|
|
187
|
+
│ │ ├── push.ts push 命令
|
|
188
|
+
│ │ ├── status.ts status 命令
|
|
189
|
+
│ │ ├── diff.ts diff 命令
|
|
190
|
+
│ │ └── list.ts list 命令
|
|
191
|
+
│ ├── utils/
|
|
192
|
+
│ │ ├── logger.ts 日志工具
|
|
193
|
+
│ │ ├── validator.ts 参数校验
|
|
194
|
+
│ │ ├── linediff.ts LCS 行级差异算法
|
|
195
|
+
│ │ └── prompt.ts 交互式冲突提示
|
|
196
|
+
│ └── types.ts 全局类型定义
|
|
197
|
+
├── skill/
|
|
198
|
+
│ ├── SKILL.md OpenClaw Skill 说明
|
|
199
|
+
│ └── wangchuan-skill.sh Skill 脚本
|
|
200
|
+
├── test/
|
|
201
|
+
│ └── crypto.test.ts 加密模块测试
|
|
202
|
+
└── .wangchuan/
|
|
203
|
+
└── config.example.json 配置示例
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wangchuan.d.ts","sourceRoot":"","sources":["../../bin/wangchuan.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* wangchuan.ts — CLI 入口
|
|
4
|
+
*
|
|
5
|
+
* 用法:
|
|
6
|
+
* wangchuan <command> [--agent openclaw|claude|gemini] [flags]
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import { cmdInit } from '../src/commands/init.js';
|
|
10
|
+
import { cmdPull } from '../src/commands/pull.js';
|
|
11
|
+
import { cmdPush } from '../src/commands/push.js';
|
|
12
|
+
import { cmdStatus } from '../src/commands/status.js';
|
|
13
|
+
import { cmdDiff } from '../src/commands/diff.js';
|
|
14
|
+
import { cmdList } from '../src/commands/list.js';
|
|
15
|
+
import { logger } from '../src/utils/logger.js';
|
|
16
|
+
const AGENT_CHOICES = ['openclaw', 'claude', 'gemini'];
|
|
17
|
+
/** 校验 --agent 值合法性 */
|
|
18
|
+
function parseAgent(val) {
|
|
19
|
+
if (!AGENT_CHOICES.includes(val)) {
|
|
20
|
+
throw new Error(`--agent 必须是 openclaw | claude | gemini,收到: ${val}`);
|
|
21
|
+
}
|
|
22
|
+
return val;
|
|
23
|
+
}
|
|
24
|
+
const program = new Command();
|
|
25
|
+
program
|
|
26
|
+
.name('wangchuan')
|
|
27
|
+
.description('忘川 · AI 记忆同步系统')
|
|
28
|
+
.version('1.0.0');
|
|
29
|
+
// ── init ────────────────────────────────────────────────────────
|
|
30
|
+
program
|
|
31
|
+
.command('init')
|
|
32
|
+
.description('初始化忘川,配置仓库并生成密钥')
|
|
33
|
+
.requiredOption('-r, --repo <url>', 'Git 仓库地址 (SSH 或 HTTPS)')
|
|
34
|
+
.option('--force', '强制重新初始化(覆盖现有配置)', false)
|
|
35
|
+
.action(async (opts) => {
|
|
36
|
+
await run(() => cmdInit(opts));
|
|
37
|
+
});
|
|
38
|
+
// ── pull ────────────────────────────────────────────────────────
|
|
39
|
+
program
|
|
40
|
+
.command('pull')
|
|
41
|
+
.description('从远端仓库拉取并还原配置到本地工作区')
|
|
42
|
+
.option('-a, --agent <name>', '只操作指定智能体 (openclaw|claude|gemini)', parseAgent)
|
|
43
|
+
.action(async (opts) => {
|
|
44
|
+
await run(() => cmdPull(opts));
|
|
45
|
+
});
|
|
46
|
+
// ── push ────────────────────────────────────────────────────────
|
|
47
|
+
program
|
|
48
|
+
.command('push')
|
|
49
|
+
.description('将本地工作区配置加密后推送到远端仓库')
|
|
50
|
+
.option('-m, --message <msg>', '自定义提交信息')
|
|
51
|
+
.option('-a, --agent <name>', '只操作指定智能体 (openclaw|claude|gemini)', parseAgent)
|
|
52
|
+
.action(async (opts) => {
|
|
53
|
+
await run(() => cmdPush(opts));
|
|
54
|
+
});
|
|
55
|
+
// ── status ──────────────────────────────────────────────────────
|
|
56
|
+
program
|
|
57
|
+
.command('status')
|
|
58
|
+
.description('查看当前同步状态和工作区差异')
|
|
59
|
+
.option('-a, --agent <name>', '只操作指定智能体 (openclaw|claude|gemini)', parseAgent)
|
|
60
|
+
.action(async (opts) => {
|
|
61
|
+
await run(() => cmdStatus(opts));
|
|
62
|
+
});
|
|
63
|
+
// ── diff ────────────────────────────────────────────────────────
|
|
64
|
+
program
|
|
65
|
+
.command('diff')
|
|
66
|
+
.description('显示本地与仓库的行级文件差异')
|
|
67
|
+
.option('-a, --agent <name>', '只显示指定智能体 (openclaw|claude|gemini)', parseAgent)
|
|
68
|
+
.action(async (opts) => {
|
|
69
|
+
await run(() => cmdDiff(opts));
|
|
70
|
+
});
|
|
71
|
+
// ── list ────────────────────────────────────────────────────────
|
|
72
|
+
program
|
|
73
|
+
.command('list')
|
|
74
|
+
.description('列出所有受管配置项及其本地/仓库存在状态')
|
|
75
|
+
.option('-a, --agent <name>', '只列出指定智能体 (openclaw|claude|gemini)', parseAgent)
|
|
76
|
+
.action(async (opts) => {
|
|
77
|
+
await run(() => cmdList(opts));
|
|
78
|
+
});
|
|
79
|
+
// ── 错误兜底 ────────────────────────────────────────────────────
|
|
80
|
+
async function run(fn) {
|
|
81
|
+
try {
|
|
82
|
+
await fn();
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
logger.error(err.message);
|
|
86
|
+
if (process.env['WANGCHUAN_LOG_LEVEL'] === 'debug') {
|
|
87
|
+
console.error(err.stack);
|
|
88
|
+
}
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
program.parse(process.argv);
|
|
93
|
+
//# sourceMappingURL=wangchuan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wangchuan.js","sourceRoot":"","sources":["../../bin/wangchuan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* diff.ts — wangchuan diff 命令
|
|
3
|
+
*
|
|
4
|
+
* 对每个有变化的文件展示行级 unified diff。
|
|
5
|
+
* 加密文件先解密后再比较内容,明文文件直接比较。
|
|
6
|
+
*/
|
|
7
|
+
import type { DiffCommandOptions } from '../types.js';
|
|
8
|
+
export declare function cmdDiff({ agent }?: DiffCommandOptions): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/commands/diff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,wBAAsB,OAAO,CAAC,EAAE,KAAK,EAAE,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqF/E"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* diff.ts — wangchuan diff 命令
|
|
3
|
+
*
|
|
4
|
+
* 对每个有变化的文件展示行级 unified diff。
|
|
5
|
+
* 加密文件先解密后再比较内容,明文文件直接比较。
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { config } from '../core/config.js';
|
|
10
|
+
import { syncEngine } from '../core/sync.js';
|
|
11
|
+
import { cryptoEngine } from '../core/crypto.js';
|
|
12
|
+
import { validator } from '../utils/validator.js';
|
|
13
|
+
import { logger } from '../utils/logger.js';
|
|
14
|
+
import { diffText } from '../utils/linediff.js';
|
|
15
|
+
import chalk from 'chalk';
|
|
16
|
+
export async function cmdDiff({ agent } = {}) {
|
|
17
|
+
logger.banner('忘川 · 文件差异');
|
|
18
|
+
const cfg = config.load();
|
|
19
|
+
validator.requireInit(cfg);
|
|
20
|
+
const repoPath = syncEngine.expandHome(cfg.localRepoPath);
|
|
21
|
+
const keyPath = syncEngine.expandHome(cfg.keyPath);
|
|
22
|
+
const entries = syncEngine.buildFileEntries(cfg, undefined, agent);
|
|
23
|
+
if (agent)
|
|
24
|
+
logger.info(`过滤智能体: ${chalk.cyan(agent)}\n`);
|
|
25
|
+
let totalChanged = 0;
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const srcExists = fs.existsSync(entry.srcAbs);
|
|
28
|
+
const repoAbs = path.join(repoPath, entry.repoRel);
|
|
29
|
+
const repoExists = fs.existsSync(repoAbs);
|
|
30
|
+
// ── 仅一侧存在 ──────────────────────────────────────────
|
|
31
|
+
if (srcExists && !repoExists) {
|
|
32
|
+
console.log(chalk.bold.green(`+++ ${entry.repoRel}`) + chalk.gray(' (新增,仓库中不存在)'));
|
|
33
|
+
const lines = fs.readFileSync(entry.srcAbs, 'utf-8').split('\n');
|
|
34
|
+
lines.forEach(l => console.log(chalk.green(`+ ${l}`)));
|
|
35
|
+
console.log();
|
|
36
|
+
totalChanged++;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (!srcExists && repoExists) {
|
|
40
|
+
console.log(chalk.bold.red(`--- ${entry.repoRel}`) + chalk.gray(' (本地缺失)'));
|
|
41
|
+
console.log();
|
|
42
|
+
totalChanged++;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (!srcExists && !repoExists)
|
|
46
|
+
continue;
|
|
47
|
+
// ── 两侧均存在,读取内容 ──────────────────────────────────
|
|
48
|
+
const localText = fs.readFileSync(entry.srcAbs, 'utf-8');
|
|
49
|
+
let repoText;
|
|
50
|
+
if (entry.encrypt) {
|
|
51
|
+
try {
|
|
52
|
+
repoText = cryptoEngine.decryptString(fs.readFileSync(repoAbs, 'utf-8').trim(), keyPath);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
console.log(chalk.yellow(`~ ${entry.repoRel}`) + chalk.gray(' [加密文件,无法解密比较]'));
|
|
56
|
+
console.log();
|
|
57
|
+
totalChanged++;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
repoText = fs.readFileSync(repoAbs, 'utf-8');
|
|
63
|
+
}
|
|
64
|
+
const diffLines = diffText(repoText, localText);
|
|
65
|
+
if (diffLines.length === 0)
|
|
66
|
+
continue; // 内容相同,跳过
|
|
67
|
+
const encLabel = entry.encrypt ? chalk.gray(' [enc]') : '';
|
|
68
|
+
console.log(chalk.bold(`~~~ ${entry.repoRel}`) + encLabel);
|
|
69
|
+
console.log(chalk.gray(' --- 仓库版本'));
|
|
70
|
+
console.log(chalk.gray(' +++ 本地版本'));
|
|
71
|
+
console.log();
|
|
72
|
+
for (const line of diffLines) {
|
|
73
|
+
if (line.content === '...') {
|
|
74
|
+
console.log(chalk.gray(' ...'));
|
|
75
|
+
}
|
|
76
|
+
else if (line.type === 'added') {
|
|
77
|
+
console.log(chalk.green(`+ ${line.content}`));
|
|
78
|
+
}
|
|
79
|
+
else if (line.type === 'removed') {
|
|
80
|
+
console.log(chalk.red(`- ${line.content}`));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.log(chalk.gray(` ${line.content}`));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
console.log();
|
|
87
|
+
totalChanged++;
|
|
88
|
+
}
|
|
89
|
+
if (totalChanged === 0) {
|
|
90
|
+
logger.ok('所有文件与仓库一致,无差异');
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
logger.info(`共 ${totalChanged} 个文件有差异`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/commands/diff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAY,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAQ,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAS,uBAAuB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAY,oBAAoB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAU,sBAAsB,CAAC;AAEpD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,KAAK,KAAyB,EAAE;IAC9D,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAE3B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC1B,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE3B,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAI,UAAU,CAAC,gBAAgB,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAEpE,IAAI,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAExD,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAI,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAE1C,sDAAsD;QACtD,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;YACpF,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,EAAE,CAAC;YACd,YAAY,EAAE,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,CAAC,SAAS,IAAI,UAAU,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAC7E,OAAO,CAAC,GAAG,EAAE,CAAC;YACd,YAAY,EAAE,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU;YAAE,SAAS;QAExC,mDAAmD;QACnD,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzD,IAAM,QAAgB,CAAC;QAEvB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,QAAQ,GAAG,YAAY,CAAC,aAAa,CACnC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EACxC,OAAO,CACR,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;gBAChF,OAAO,CAAC,GAAG,EAAE,CAAC;gBACd,YAAY,EAAE,CAAC;gBACf,SAAS;YACX,CAAC;QACH,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAChD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS,CAAE,UAAU;QAEjD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,EAAE,CAAC;QAEd,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YACrC,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAClD,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,KAAK,YAAY,SAAS,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGhE,wBAAsB,OAAO,CAAC,EAAE,IAAI,EAAE,KAAa,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CA2C5F"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* init.ts — wangchuan init 命令
|
|
3
|
+
*/
|
|
4
|
+
import { config } from '../core/config.js';
|
|
5
|
+
import { cryptoEngine } from '../core/crypto.js';
|
|
6
|
+
import { gitEngine } from '../core/git.js';
|
|
7
|
+
import { validator } from '../utils/validator.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import ora from 'ora';
|
|
10
|
+
export async function cmdInit({ repo, force = false }) {
|
|
11
|
+
logger.banner('忘川初始化');
|
|
12
|
+
if (!validator.isGitUrl(repo)) {
|
|
13
|
+
throw new Error(`无效的 Git 地址: ${repo}`);
|
|
14
|
+
}
|
|
15
|
+
const existing = config.load();
|
|
16
|
+
if (existing !== null && !force) {
|
|
17
|
+
logger.warn(`忘川已初始化 (仓库: ${existing.repo})`);
|
|
18
|
+
logger.info('如需重新初始化,请使用 --force 参数');
|
|
19
|
+
return existing;
|
|
20
|
+
}
|
|
21
|
+
// ── 写配置 ──────────────────────────────────────────────────
|
|
22
|
+
let spinner = ora('写入配置 …').start();
|
|
23
|
+
const cfg = await config.initialize(repo);
|
|
24
|
+
spinner.succeed(`配置已写入: ${config.paths.config}`);
|
|
25
|
+
// ── 生成密钥 ────────────────────────────────────────────────
|
|
26
|
+
if (!cryptoEngine.hasKey(cfg.keyPath)) {
|
|
27
|
+
spinner = ora('生成 AES-256-GCM 主密钥 …').start();
|
|
28
|
+
cryptoEngine.generateKey(cfg.keyPath);
|
|
29
|
+
spinner.succeed(`主密钥已生成: ${cfg.keyPath}`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
logger.info(`主密钥已存在,跳过生成: ${cfg.keyPath}`);
|
|
33
|
+
}
|
|
34
|
+
// ── 克隆/拉取仓库 ────────────────────────────────────────────
|
|
35
|
+
spinner = ora(`克隆仓库: ${repo} …`).start();
|
|
36
|
+
try {
|
|
37
|
+
await gitEngine.cloneOrFetch(repo, cfg.localRepoPath, cfg.branch);
|
|
38
|
+
spinner.succeed(`仓库已就绪: ${cfg.localRepoPath}`);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
spinner.fail('克隆仓库失败');
|
|
42
|
+
throw new Error(`Git 操作失败: ${err.message}`);
|
|
43
|
+
}
|
|
44
|
+
logger.ok('\n忘川初始化完成!');
|
|
45
|
+
logger.step('下一步: wangchuan pull (同步远端配置到本地)');
|
|
46
|
+
logger.step(' wangchuan push (推送本地配置到远端)');
|
|
47
|
+
return cfg;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAY,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAS,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAS,uBAAuB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAY,oBAAoB,CAAC;AAElD,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,KAAK,EAAe;IAChE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,eAAe,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACtC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,4DAA4D;IAC5D,IAAI,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,CAAC,OAAO,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAEjD,2DAA2D;IAC3D,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,OAAO,GAAG,GAAG,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;QAC9C,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,0DAA0D;IAC1D,OAAO,GAAG,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAClE,OAAO,CAAC,OAAO,CAAC,UAAU,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,aAAc,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;IACxB,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAChD,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAEnD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* list.ts — wangchuan list 命令
|
|
3
|
+
*
|
|
4
|
+
* 瞬间列出所有受管配置文件,不做任何 git/IO 操作。
|
|
5
|
+
* 支持 --agent 过滤,按智能体分组展示。
|
|
6
|
+
*/
|
|
7
|
+
import type { ListOptions } from '../types.js';
|
|
8
|
+
export declare function cmdList({ agent }?: ListOptions): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,aAAa,CAAC;AAS1D,wBAAsB,OAAO,CAAC,EAAE,KAAK,EAAE,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCxE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* list.ts — wangchuan list 命令
|
|
3
|
+
*
|
|
4
|
+
* 瞬间列出所有受管配置文件,不做任何 git/IO 操作。
|
|
5
|
+
* 支持 --agent 过滤,按智能体分组展示。
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import { config } from '../core/config.js';
|
|
9
|
+
import { syncEngine } from '../core/sync.js';
|
|
10
|
+
import { validator } from '../utils/validator.js';
|
|
11
|
+
import { logger } from '../utils/logger.js';
|
|
12
|
+
import chalk from 'chalk';
|
|
13
|
+
const AGENT_LABELS = {
|
|
14
|
+
openclaw: 'OpenClaw',
|
|
15
|
+
claude: 'Claude',
|
|
16
|
+
gemini: 'Gemini',
|
|
17
|
+
};
|
|
18
|
+
export async function cmdList({ agent } = {}) {
|
|
19
|
+
logger.banner('忘川 · 配置清单');
|
|
20
|
+
const cfg = config.load();
|
|
21
|
+
validator.requireInit(cfg);
|
|
22
|
+
const repoPath = syncEngine.expandHome(cfg.localRepoPath);
|
|
23
|
+
const allAgents = agent ? [agent] : ['openclaw', 'claude', 'gemini'];
|
|
24
|
+
let totalFiles = 0;
|
|
25
|
+
for (const ag of allAgents) {
|
|
26
|
+
const entries = syncEngine.buildFileEntries(cfg, undefined, ag);
|
|
27
|
+
if (entries.length === 0)
|
|
28
|
+
continue;
|
|
29
|
+
console.log(chalk.bold.cyan(` ▸ ${AGENT_LABELS[ag]}`));
|
|
30
|
+
for (const e of entries) {
|
|
31
|
+
const localExists = fs.existsSync(e.srcAbs);
|
|
32
|
+
const repoExists = fs.existsSync(`${repoPath}/${e.repoRel}`);
|
|
33
|
+
const localMark = localExists ? chalk.green('✔') : chalk.red('✖');
|
|
34
|
+
const repoMark = repoExists ? chalk.green('✔') : chalk.gray('·');
|
|
35
|
+
const encLabel = e.encrypt ? chalk.magenta('[enc]') : ' ';
|
|
36
|
+
console.log(` ${localMark} 本地 ${repoMark} 仓库 ${encLabel} ${chalk.white(e.repoRel)}`);
|
|
37
|
+
console.log(chalk.gray(` └─ ${e.srcAbs}`));
|
|
38
|
+
}
|
|
39
|
+
console.log();
|
|
40
|
+
totalFiles += entries.length;
|
|
41
|
+
}
|
|
42
|
+
console.log(chalk.gray(` 共 ${totalFiles} 个配置文件`));
|
|
43
|
+
console.log(chalk.gray(` ✔ = 存在 · = 仓库中尚无(未推送) [enc] = 加密存储`));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,EAAE,MAAU,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAO,uBAAuB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAU,oBAAoB,CAAC;AAEhD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,YAAY,GAA8B;IAC9C,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAI,QAAQ;IAClB,MAAM,EAAI,QAAQ;CACnB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,KAAK,KAAkB,EAAE;IACvD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAE3B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC1B,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE3B,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAgB,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAElF,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,UAAU,CAAC,gBAAgB,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAChE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAExD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,WAAW,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC5C,MAAM,UAAU,GAAI,EAAE,CAAC,UAAU,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAE9D,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClE,MAAM,QAAQ,GAAI,UAAU,CAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnE,MAAM,QAAQ,GAAI,CAAC,CAAC,OAAO,CAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAEjE,OAAO,CAAC,GAAG,CACT,OAAO,SAAS,QAAQ,QAAQ,QAAQ,QAAQ,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAC9E,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,UAAU,QAAQ,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/commands/pull.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI9D,wBAAsB,OAAO,CAAC,EAAE,KAAK,EAAE,GAAE,WAAgB,GAAG,OAAO,CAAC,aAAa,CAAC,CA8CjF"}
|