@tengx5383/aitool-sync-cli 0.1.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/.claude/settings.local.json +8 -0
- package/README.md +203 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +87 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +24 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +89 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +105 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +22 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/pull.d.ts +6 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +52 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +6 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +60 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/remove.d.ts +2 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +20 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +46 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/config-file.d.ts +22 -0
- package/dist/config/config-file.d.ts.map +1 -0
- package/dist/config/config-file.js +86 -0
- package/dist/config/config-file.js.map +1 -0
- package/dist/config/schema.d.ts +101 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +24 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/backup.d.ts +8 -0
- package/dist/core/backup.d.ts.map +1 -0
- package/dist/core/backup.js +50 -0
- package/dist/core/backup.js.map +1 -0
- package/dist/core/checksum.d.ts +14 -0
- package/dist/core/checksum.d.ts.map +1 -0
- package/dist/core/checksum.js +23 -0
- package/dist/core/checksum.js.map +1 -0
- package/dist/core/exclusions.d.ts +8 -0
- package/dist/core/exclusions.d.ts.map +1 -0
- package/dist/core/exclusions.js +29 -0
- package/dist/core/exclusions.js.map +1 -0
- package/dist/core/file-collector.d.ts +16 -0
- package/dist/core/file-collector.d.ts.map +1 -0
- package/dist/core/file-collector.js +104 -0
- package/dist/core/file-collector.js.map +1 -0
- package/dist/core/manifest.d.ts +18 -0
- package/dist/core/manifest.d.ts.map +1 -0
- package/dist/core/manifest.js +42 -0
- package/dist/core/manifest.js.map +1 -0
- package/dist/core/path-expander.d.ts +6 -0
- package/dist/core/path-expander.d.ts.map +1 -0
- package/dist/core/path-expander.js +25 -0
- package/dist/core/path-expander.js.map +1 -0
- package/dist/core/sync-engine.d.ts +24 -0
- package/dist/core/sync-engine.d.ts.map +1 -0
- package/dist/core/sync-engine.js +206 -0
- package/dist/core/sync-engine.js.map +1 -0
- package/dist/core/sync-package.d.ts +12 -0
- package/dist/core/sync-package.d.ts.map +1 -0
- package/dist/core/sync-package.js +95 -0
- package/dist/core/sync-package.js.map +1 -0
- package/dist/crypto/encryptor.d.ts +15 -0
- package/dist/crypto/encryptor.d.ts.map +1 -0
- package/dist/crypto/encryptor.js +77 -0
- package/dist/crypto/encryptor.js.map +1 -0
- package/dist/crypto/key-resolver.d.ts +28 -0
- package/dist/crypto/key-resolver.d.ts.map +1 -0
- package/dist/crypto/key-resolver.js +62 -0
- package/dist/crypto/key-resolver.js.map +1 -0
- package/dist/gist/client.d.ts +18 -0
- package/dist/gist/client.d.ts.map +1 -0
- package/dist/gist/client.js +58 -0
- package/dist/gist/client.js.map +1 -0
- package/dist/gist/mock-client.d.ts +19 -0
- package/dist/gist/mock-client.d.ts.map +1 -0
- package/dist/gist/mock-client.js +61 -0
- package/dist/gist/mock-client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/presets/claude-code.d.ts +3 -0
- package/dist/presets/claude-code.d.ts.map +1 -0
- package/dist/presets/claude-code.js +27 -0
- package/dist/presets/claude-code.js.map +1 -0
- package/dist/presets/hermes.d.ts +3 -0
- package/dist/presets/hermes.d.ts.map +1 -0
- package/dist/presets/hermes.js +27 -0
- package/dist/presets/hermes.js.map +1 -0
- package/dist/presets/index.d.ts +15 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +42 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/openclaw.d.ts +3 -0
- package/dist/presets/openclaw.d.ts.map +1 -0
- package/dist/presets/openclaw.js +27 -0
- package/dist/presets/openclaw.js.map +1 -0
- package/dist/types/config.d.ts +45 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/gist.d.ts +25 -0
- package/dist/types/gist.d.ts.map +1 -0
- package/dist/types/gist.js +2 -0
- package/dist/types/gist.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/sync.d.ts +78 -0
- package/dist/types/sync.d.ts.map +1 -0
- package/dist/types/sync.js +2 -0
- package/dist/types/sync.js.map +1 -0
- package/dist/utils/diff.d.ts +7 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +99 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/env.d.ts +13 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +29 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +39 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/table.d.ts +5 -0
- package/dist/utils/table.d.ts.map +1 -0
- package/dist/utils/table.js +59 -0
- package/dist/utils/table.js.map +1 -0
- package/package.json +41 -0
- package/tests/integration/encryption-flow.test.ts +142 -0
- package/tests/integration/init-flow.test.ts +69 -0
- package/tests/integration/push-pull-flow.test.ts +183 -0
- package/tests/integration/status-flow.test.ts +149 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(node -e \"const p = require\\('./package-lock.json'\\); p.name = '@tengx5383/aitool-sync-cli'; p.packages[''].name = '@tengx5383/aitool-sync-cli'; require\\('fs'\\).writeFileSync\\('package-lock.json', JSON.stringify\\(p, null, 2\\) + '\\\\n'\\)\")",
|
|
5
|
+
"Bash(npm run *)"
|
|
6
|
+
]
|
|
7
|
+
}
|
|
8
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# aitool-sync
|
|
2
|
+
|
|
3
|
+
跨设备同步 AI 智能体工具配置(Claude Code、Hermes、OpenClaw),通过 GitHub Gist API 实现。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g aitool-sync
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
或者本地开发运行:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone <repo>
|
|
15
|
+
cd AIToolSynchronizer
|
|
16
|
+
npm install
|
|
17
|
+
npm run build
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 快速开始
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# 1. 设置 GitHub Token
|
|
24
|
+
export GITHUB_TOKEN=ghp_xxxxxxxx
|
|
25
|
+
|
|
26
|
+
# 2. 初始化配置(自动检测已安装的工具)
|
|
27
|
+
aitool-sync init
|
|
28
|
+
|
|
29
|
+
# 3. 推送配置到 Gist
|
|
30
|
+
aitool-sync push
|
|
31
|
+
|
|
32
|
+
# 4. 在另一台设备上拉取配置
|
|
33
|
+
aitool-sync pull
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 命令说明
|
|
37
|
+
|
|
38
|
+
| 命令 | 说明 |
|
|
39
|
+
|------|------|
|
|
40
|
+
| `aitool-sync init` | 创建 `.aitoolsync.json` 配置文件,自动检测已安装的工具预设 |
|
|
41
|
+
| `aitool-sync status` | 查看本地与远程的差异 |
|
|
42
|
+
| `aitool-sync push` | 将本地配置上传到 Gist |
|
|
43
|
+
| `aitool-sync pull` | 从 Gist 下载配置到本地 |
|
|
44
|
+
| `aitool-sync push --force` | 强制推送(忽略冲突) |
|
|
45
|
+
| `aitool-sync pull --force` | 强制拉取(忽略冲突) |
|
|
46
|
+
| `aitool-sync add <名称> <路径>` | 添加一个同步路径 |
|
|
47
|
+
| `aitool-sync remove <名称>` | 移除一个同步路径 |
|
|
48
|
+
| `aitool-sync list` | 查看所有已跟踪的路径 |
|
|
49
|
+
| `aitool-sync doctor` | 诊断配置和连接状态 |
|
|
50
|
+
|
|
51
|
+
## 配置文件
|
|
52
|
+
|
|
53
|
+
所有配置保存在 `.aitoolsync.json` 中。示例:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"version": 1,
|
|
58
|
+
"gistId": "abc123def456...",
|
|
59
|
+
"syncPaths": [
|
|
60
|
+
{ "name": "claude-code-settings", "path": "~/.claude/settings.json", "enabled": true },
|
|
61
|
+
{ "name": "claude-code-mcp", "path": "~/.claude/mcp.json", "enabled": true }
|
|
62
|
+
],
|
|
63
|
+
"exclusions": [
|
|
64
|
+
{ "pattern": "**/node_modules/**" },
|
|
65
|
+
{ "pattern": "**/.git/**" }
|
|
66
|
+
],
|
|
67
|
+
"encryption": [
|
|
68
|
+
{ "pattern": "**/token*" },
|
|
69
|
+
{ "pattern": "**/credentials*" }
|
|
70
|
+
],
|
|
71
|
+
"lastKnownManifest": null,
|
|
72
|
+
"lastPushAt": null,
|
|
73
|
+
"lastPullAt": null
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### syncPaths
|
|
78
|
+
|
|
79
|
+
要同步的文件或目录路径,支持 `~` 和 `$HOME` 展开。每个条目包含:
|
|
80
|
+
- `name`: 显示名称
|
|
81
|
+
- `path`: 文件或目录路径
|
|
82
|
+
- `enabled`: 是否启用同步
|
|
83
|
+
|
|
84
|
+
### exclusions
|
|
85
|
+
|
|
86
|
+
排除规则,使用 glob 模式匹配文件路径。以 `!` 开头的模式表示强制包含。
|
|
87
|
+
|
|
88
|
+
### encryption
|
|
89
|
+
|
|
90
|
+
加密规则,使用 glob 模式匹配需要加密的文件。启用加密需要设置 `AITOOLSYNC_PASSWORD` 环境变量。
|
|
91
|
+
|
|
92
|
+
## 文件加密
|
|
93
|
+
|
|
94
|
+
匹配加密模式的文件会在上传前使用 AES-256-GCM 加密:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# 设置加密密码
|
|
98
|
+
export AITOOLSYNC_PASSWORD=my-secret-password
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
加密文件在 Gist 中存储为密文,只有在拉取时提供正确密码才能解密恢复。
|
|
102
|
+
|
|
103
|
+
## 支持的 AI 工具预设
|
|
104
|
+
|
|
105
|
+
| 工具 | 预设 ID | 同步内容 |
|
|
106
|
+
|------|---------|----------|
|
|
107
|
+
| Claude Code | `claude-code` | `~/.claude/settings.json`, `mcp.json`, `claude.json` |
|
|
108
|
+
| Hermes | `hermes` | `~/.hermes/config.yaml`, `tools/`, `prompts/` |
|
|
109
|
+
| OpenClaw | `openclaw` | `~/.openclaw/config.json`, `tools/`, `profiles/` |
|
|
110
|
+
|
|
111
|
+
初始化时会自动检测已安装的工具并应用对应预设。
|
|
112
|
+
|
|
113
|
+
## 环境变量
|
|
114
|
+
|
|
115
|
+
| 变量 | 说明 |
|
|
116
|
+
|------|------|
|
|
117
|
+
| `GITHUB_TOKEN` | GitHub 个人访问令牌(push/pull 必需) |
|
|
118
|
+
| `AITOOLSYNC_PASSWORD` | 加密密码(可选,设置后启用文件加密) |
|
|
119
|
+
|
|
120
|
+
## 工作流程
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
本地文件系统 GitHub Gist
|
|
124
|
+
──────────── ───────────
|
|
125
|
+
~/.claude/ push ──→ aitool-sync-package.json
|
|
126
|
+
~/.hermes/ ←── pull (包含所有文件的
|
|
127
|
+
~/.openclaw/ 包和清单)
|
|
128
|
+
自定义路径
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 三方合并冲突检测
|
|
132
|
+
|
|
133
|
+
系统保存上次成功同步时的远程清单(`lastKnownManifest`),通过比较本地、远程和上次已知状态来判断冲突:
|
|
134
|
+
|
|
135
|
+
- **仅本地变更** → 安全推送/拉取
|
|
136
|
+
- **仅远程变更** → 安全推送/拉取
|
|
137
|
+
- **双方均变更** → 冲突,需使用 `--force` 覆盖
|
|
138
|
+
|
|
139
|
+
### 备份保护
|
|
140
|
+
|
|
141
|
+
执行 `pull` 操作前会自动在临时目录创建带时间戳的备份,防止意外覆盖。
|
|
142
|
+
|
|
143
|
+
## 开发
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# 安装依赖
|
|
147
|
+
npm install
|
|
148
|
+
|
|
149
|
+
# 运行测试
|
|
150
|
+
npm test
|
|
151
|
+
|
|
152
|
+
# 开发模式运行
|
|
153
|
+
npx tsx src/index.ts <command>
|
|
154
|
+
|
|
155
|
+
# 构建
|
|
156
|
+
npm run build
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 项目结构
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
src/
|
|
163
|
+
├── index.ts # 入口
|
|
164
|
+
├── cli.ts # Commander CLI 设置
|
|
165
|
+
├── commands/ # 命令实现
|
|
166
|
+
│ ├── init.ts # 初始化向导
|
|
167
|
+
│ ├── status.ts # 状态差异
|
|
168
|
+
│ ├── push.ts # 上传
|
|
169
|
+
│ ├── pull.ts # 下载
|
|
170
|
+
│ ├── add.ts # 添加路径
|
|
171
|
+
│ ├── remove.ts # 移除路径
|
|
172
|
+
│ ├── list.ts # 列出路径
|
|
173
|
+
│ └── doctor.ts # 诊断
|
|
174
|
+
├── core/ # 核心同步逻辑
|
|
175
|
+
│ ├── sync-engine.ts # 同步编排器
|
|
176
|
+
│ ├── manifest.ts # 清单管理
|
|
177
|
+
│ ├── checksum.ts # SHA-256 哈希
|
|
178
|
+
│ ├── file-collector.ts # 文件收集
|
|
179
|
+
│ ├── backup.ts # 备份
|
|
180
|
+
│ ├── path-expander.ts # 路径展开
|
|
181
|
+
│ ├── exclusions.ts # 排除规则
|
|
182
|
+
│ └── sync-package.ts # 同步包构建/解析
|
|
183
|
+
├── gist/ # Gist API 客户端
|
|
184
|
+
│ ├── client.ts # Octokit 封装
|
|
185
|
+
│ └── mock-client.ts # 测试用模拟客户端
|
|
186
|
+
├── crypto/ # 加密模块
|
|
187
|
+
│ ├── encryptor.ts # AES-256-GCM
|
|
188
|
+
│ └── key-resolver.ts # 密码解析
|
|
189
|
+
├── config/ # 配置文件
|
|
190
|
+
│ ├── config-file.ts # 读写 .aitoolsync.json
|
|
191
|
+
│ └── schema.ts # Zod 校验
|
|
192
|
+
├── presets/ # 工具预设
|
|
193
|
+
│ ├── index.ts # 注册表和检测
|
|
194
|
+
│ ├── claude-code.ts # Claude Code
|
|
195
|
+
│ ├── hermes.ts # Hermes
|
|
196
|
+
│ └── openclaw.ts # OpenClaw
|
|
197
|
+
├── types/ # 类型定义
|
|
198
|
+
└── utils/ # 工具函数
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { setLogLevel, LogLevel } from './utils/logger.js';
|
|
3
|
+
import { initCommand } from './commands/init.js';
|
|
4
|
+
import { statusCommand } from './commands/status.js';
|
|
5
|
+
import { pushCommand } from './commands/push.js';
|
|
6
|
+
import { pullCommand } from './commands/pull.js';
|
|
7
|
+
import { addCommand } from './commands/add.js';
|
|
8
|
+
import { removeCommand } from './commands/remove.js';
|
|
9
|
+
import { listCommand } from './commands/list.js';
|
|
10
|
+
import { doctorCommand } from './commands/doctor.js';
|
|
11
|
+
const program = new Command();
|
|
12
|
+
program
|
|
13
|
+
.name('aitool-sync')
|
|
14
|
+
.description('Sync AI agent tool configs across devices via GitHub Gist')
|
|
15
|
+
.version('0.1.0')
|
|
16
|
+
.option('--debug', 'Enable debug logging')
|
|
17
|
+
.hook('preAction', (thisCommand) => {
|
|
18
|
+
const opts = thisCommand.opts();
|
|
19
|
+
if (opts.debug) {
|
|
20
|
+
setLogLevel(LogLevel.DEBUG);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
// init
|
|
24
|
+
program
|
|
25
|
+
.command('init')
|
|
26
|
+
.description('Initialize aitool-sync configuration')
|
|
27
|
+
.option('--gist-id <id>', 'Use existing Gist ID instead of creating one')
|
|
28
|
+
.option('--preset <preset>', 'Add a specific preset (claude-code, hermes, openclaw)')
|
|
29
|
+
.action(async (options) => {
|
|
30
|
+
await initCommand(options);
|
|
31
|
+
});
|
|
32
|
+
// status
|
|
33
|
+
program
|
|
34
|
+
.command('status')
|
|
35
|
+
.description('Show differences between local and remote')
|
|
36
|
+
.action(async () => {
|
|
37
|
+
await statusCommand();
|
|
38
|
+
});
|
|
39
|
+
// push
|
|
40
|
+
program
|
|
41
|
+
.command('push')
|
|
42
|
+
.description('Upload local configs to Gist')
|
|
43
|
+
.option('--force', 'Force push despite conflicts')
|
|
44
|
+
.action(async (options) => {
|
|
45
|
+
await pushCommand(options);
|
|
46
|
+
});
|
|
47
|
+
// pull
|
|
48
|
+
program
|
|
49
|
+
.command('pull')
|
|
50
|
+
.description('Download configs from Gist to local')
|
|
51
|
+
.option('--force', 'Force pull despite conflicts')
|
|
52
|
+
.action(async (options) => {
|
|
53
|
+
await pullCommand(options);
|
|
54
|
+
});
|
|
55
|
+
// add
|
|
56
|
+
program
|
|
57
|
+
.command('add')
|
|
58
|
+
.description('Add a path to the sync configuration')
|
|
59
|
+
.argument('<name>', 'Display name for this path')
|
|
60
|
+
.argument('<path>', 'File or directory path to sync')
|
|
61
|
+
.action(async (name, pathArg) => {
|
|
62
|
+
await addCommand(name, pathArg);
|
|
63
|
+
});
|
|
64
|
+
// remove
|
|
65
|
+
program
|
|
66
|
+
.command('remove')
|
|
67
|
+
.description('Remove a path from the sync configuration')
|
|
68
|
+
.argument('<name>', 'Name of the path to remove')
|
|
69
|
+
.action(async (name) => {
|
|
70
|
+
await removeCommand(name);
|
|
71
|
+
});
|
|
72
|
+
// list
|
|
73
|
+
program
|
|
74
|
+
.command('list')
|
|
75
|
+
.description('List all tracked sync paths')
|
|
76
|
+
.action(async () => {
|
|
77
|
+
await listCommand();
|
|
78
|
+
});
|
|
79
|
+
// doctor
|
|
80
|
+
program
|
|
81
|
+
.command('doctor')
|
|
82
|
+
.description('Diagnose configuration and connectivity issues')
|
|
83
|
+
.action(async () => {
|
|
84
|
+
await doctorCommand();
|
|
85
|
+
});
|
|
86
|
+
program.parse(process.argv);
|
|
87
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB7E"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { readConfig, writeConfig } from '../config/config-file.js';
|
|
2
|
+
import { success, error, warn } from '../utils/logger.js';
|
|
3
|
+
export async function addCommand(name, rawPath) {
|
|
4
|
+
const config = readConfig();
|
|
5
|
+
if (!config) {
|
|
6
|
+
error('No configuration found. Run `aitool-sync init` first.');
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
// Check for duplicate name
|
|
10
|
+
const existing = config.syncPaths.find((p) => p.name === name);
|
|
11
|
+
if (existing) {
|
|
12
|
+
warn(`Path with name "${name}" already exists: ${existing.path}`);
|
|
13
|
+
warn('Use `aitool-sync remove` first if you want to replace it.');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
config.syncPaths.push({
|
|
17
|
+
name,
|
|
18
|
+
path: rawPath,
|
|
19
|
+
enabled: true,
|
|
20
|
+
});
|
|
21
|
+
writeConfig(config);
|
|
22
|
+
success(`Added "${name}" -> ${rawPath}`);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,OAAe;IAC5D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC/D,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC,mBAAmB,IAAI,qBAAqB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,2DAA2D,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;QACpB,IAAI;QACJ,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,OAAO,CAAC,UAAU,IAAI,QAAQ,OAAO,EAAE,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAQA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAmFnD"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { readConfig } from '../config/config-file.js';
|
|
3
|
+
import { resolveGithubToken, getEncryptionPassword } from '../utils/env.js';
|
|
4
|
+
import { detectInstalledPresets, getAllPresets } from '../presets/index.js';
|
|
5
|
+
import { expandPath } from '../core/path-expander.js';
|
|
6
|
+
import { GistClient } from '../gist/client.js';
|
|
7
|
+
import { info, success, warn, error } from '../utils/logger.js';
|
|
8
|
+
export async function doctorCommand() {
|
|
9
|
+
console.log('🔍 aitool-sync Doctor');
|
|
10
|
+
console.log('====================\n');
|
|
11
|
+
// 1. Check config
|
|
12
|
+
const config = readConfig();
|
|
13
|
+
if (config) {
|
|
14
|
+
success('Config file: found (.aitoolsync.json)');
|
|
15
|
+
info(` Version: ${config.version}`);
|
|
16
|
+
info(` Gist ID: ${config.gistId || '(not set)'}`);
|
|
17
|
+
info(` Sync paths: ${config.syncPaths.length}`);
|
|
18
|
+
info(` Exclusions: ${config.exclusions.length}`);
|
|
19
|
+
info(` Encryption rules: ${config.encryption.length}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
error('Config file: not found');
|
|
23
|
+
warn(' Run `aitool-sync init` to create one.');
|
|
24
|
+
}
|
|
25
|
+
// 2. Check environment
|
|
26
|
+
console.log('');
|
|
27
|
+
const token = resolveGithubToken(config);
|
|
28
|
+
if (token) {
|
|
29
|
+
const source = config?.githubToken ? 'config' : 'environment';
|
|
30
|
+
success(`GitHub token: set (from ${source}, ${token.slice(0, 4)}...)`);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
warn('GitHub token: not set');
|
|
34
|
+
warn(' Run `aitool-sync init` to configure it, or set GITHUB_TOKEN environment variable.');
|
|
35
|
+
}
|
|
36
|
+
const password = getEncryptionPassword();
|
|
37
|
+
if (password) {
|
|
38
|
+
success('AITOOLSYNC_PASSWORD: set');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
info('AITOOLSYNC_PASSWORD: not set (encryption disabled)');
|
|
42
|
+
}
|
|
43
|
+
// 3. Check connectivity
|
|
44
|
+
if (token) {
|
|
45
|
+
console.log('');
|
|
46
|
+
info('Checking GitHub API connectivity...');
|
|
47
|
+
try {
|
|
48
|
+
const client = new GistClient(token);
|
|
49
|
+
// A simple API call to verify the token works
|
|
50
|
+
const gist = await client.createGist('aitool-sync-doctor-check', {
|
|
51
|
+
'doctor-check.txt': { content: 'connectivity test' },
|
|
52
|
+
});
|
|
53
|
+
await client.deleteGist(gist.gistId);
|
|
54
|
+
success('GitHub API: connected');
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
error(`GitHub API: unreachable (${e.message})`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 4. Check paths
|
|
61
|
+
if (config && config.syncPaths.length > 0) {
|
|
62
|
+
console.log('');
|
|
63
|
+
info('Checking sync paths...');
|
|
64
|
+
for (const p of config.syncPaths) {
|
|
65
|
+
const expanded = expandPath(p.path);
|
|
66
|
+
const exists = fs.existsSync(expanded);
|
|
67
|
+
const icon = exists ? '✓' : '✗';
|
|
68
|
+
const color = exists ? success : warn;
|
|
69
|
+
color(` ${icon} ${p.name}: ${p.path}`);
|
|
70
|
+
if (!exists) {
|
|
71
|
+
warn(` Expanded path not found: ${expanded}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// 5. Check presets
|
|
76
|
+
console.log('');
|
|
77
|
+
info('Available presets:');
|
|
78
|
+
const allPresets = getAllPresets();
|
|
79
|
+
const installed = detectInstalledPresets();
|
|
80
|
+
for (const preset of allPresets) {
|
|
81
|
+
const isInstalled = installed.some((p) => p.id === preset.id);
|
|
82
|
+
const icon = isInstalled ? '✓' : ' ';
|
|
83
|
+
const label = isInstalled ? success : info;
|
|
84
|
+
label(` ${icon} ${preset.id}: ${preset.description}`);
|
|
85
|
+
}
|
|
86
|
+
console.log('');
|
|
87
|
+
info('Doctor check complete.');
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AASA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAsFrE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import { readConfig, createDefaultConfig, writeConfig } from '../config/config-file.js';
|
|
3
|
+
import { detectInstalledPresets, getPreset, getAllPresets } from '../presets/index.js';
|
|
4
|
+
import { info, success, warn, error } from '../utils/logger.js';
|
|
5
|
+
import { getGithubToken } from '../utils/env.js';
|
|
6
|
+
export async function initCommand(options) {
|
|
7
|
+
// Check for existing config
|
|
8
|
+
const existing = readConfig();
|
|
9
|
+
if (existing) {
|
|
10
|
+
warn('Configuration already exists (.aitool-sync.json found).');
|
|
11
|
+
warn('To re-initialize, delete the config file and run init again.');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const config = createDefaultConfig();
|
|
15
|
+
// Apply presets
|
|
16
|
+
if (options.preset) {
|
|
17
|
+
const presetId = options.preset;
|
|
18
|
+
const preset = getPreset(presetId);
|
|
19
|
+
if (!preset) {
|
|
20
|
+
error(`Unknown preset: ${presetId}`);
|
|
21
|
+
error(`Available presets: ${getAllPresets().map((p) => p.id).join(', ')}`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
applyPreset(config, preset);
|
|
25
|
+
success(`Applied preset: ${preset.name}`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Auto-detect installed presets
|
|
29
|
+
const installed = detectInstalledPresets();
|
|
30
|
+
if (installed.length > 0) {
|
|
31
|
+
info(`Detected ${installed.length} tool(s): ${installed.map((p) => p.name).join(', ')}`);
|
|
32
|
+
for (const preset of installed) {
|
|
33
|
+
applyPreset(config, preset);
|
|
34
|
+
}
|
|
35
|
+
success('Auto-detected and applied presets.');
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
info('No supported tools detected. You can add paths manually with `aitool-sync add`.');
|
|
39
|
+
info(`Supported presets: ${getAllPresets().map((p) => p.id).join(', ')}`);
|
|
40
|
+
info('Use --preset <name> to apply a specific preset.');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Gist setup
|
|
44
|
+
if (options.gistId) {
|
|
45
|
+
config.gistId = options.gistId;
|
|
46
|
+
info(`Using existing Gist: ${options.gistId}`);
|
|
47
|
+
}
|
|
48
|
+
// GitHub token setup
|
|
49
|
+
const existingToken = getGithubToken();
|
|
50
|
+
if (!existingToken) {
|
|
51
|
+
info('');
|
|
52
|
+
info('A GitHub personal access token is required for push/pull operations.');
|
|
53
|
+
info('Create one at: https://github.com/settings/tokens (need "gist" scope).');
|
|
54
|
+
const answer = await inquirer.prompt([
|
|
55
|
+
{
|
|
56
|
+
type: 'password',
|
|
57
|
+
name: 'githubToken',
|
|
58
|
+
message: 'Enter GitHub token (leave blank to skip, you can set GITHUB_TOKEN env var later):',
|
|
59
|
+
mask: '*',
|
|
60
|
+
},
|
|
61
|
+
]);
|
|
62
|
+
if (answer.githubToken.trim()) {
|
|
63
|
+
config.githubToken = answer.githubToken.trim();
|
|
64
|
+
success('GitHub token saved to config.');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
info('Token skipped. Set GITHUB_TOKEN environment variable before running push/pull.');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Token already in env, store it in config too for portability
|
|
72
|
+
config.githubToken = existingToken;
|
|
73
|
+
info('GitHub token found from GITHUB_TOKEN environment variable and saved to config.');
|
|
74
|
+
}
|
|
75
|
+
// Write config
|
|
76
|
+
writeConfig(config);
|
|
77
|
+
success('Configuration created: .aitool-sync.json');
|
|
78
|
+
if (!config.gistId) {
|
|
79
|
+
info('');
|
|
80
|
+
info('Next steps:');
|
|
81
|
+
if (!config.githubToken) {
|
|
82
|
+
info(' 1. Set GITHUB_TOKEN in your environment or re-run init to configure it');
|
|
83
|
+
info(' 2. Run `aitool-sync push` to create a Gist and upload your configs');
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
info(' 1. Run `aitool-sync push` to create a Gist and upload your configs');
|
|
87
|
+
}
|
|
88
|
+
info(' (A Gist will be created automatically on first push)');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function applyPreset(config, preset) {
|
|
92
|
+
for (const p of preset.defaultPaths) {
|
|
93
|
+
const exists = config.syncPaths.some((sp) => sp.name === p.name);
|
|
94
|
+
if (!exists) {
|
|
95
|
+
config.syncPaths.push({ ...p });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
for (const e of preset.defaultExclusions) {
|
|
99
|
+
const exists = config.exclusions.some((ex) => ex.pattern === e.pattern);
|
|
100
|
+
if (!exists) {
|
|
101
|
+
config.exclusions.push({ ...e });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBjD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { readConfig } from '../config/config-file.js';
|
|
2
|
+
import { renderPathList } from '../utils/table.js';
|
|
3
|
+
import { error } from '../utils/logger.js';
|
|
4
|
+
export async function listCommand() {
|
|
5
|
+
const config = readConfig();
|
|
6
|
+
if (!config) {
|
|
7
|
+
error('No configuration found. Run `aitool-sync init` first.');
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (config.syncPaths.length === 0) {
|
|
11
|
+
console.log('No paths configured. Use `aitool-sync add <name> <path>` to add one.');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
console.log(`Gist ID: ${config.gistId || '(not set)'}`);
|
|
15
|
+
console.log(`Last push: ${config.lastPushAt || 'never'}`);
|
|
16
|
+
console.log(`Last pull: ${config.lastPullAt || 'never'}`);
|
|
17
|
+
console.log(`Encryption rules: ${config.encryption.length > 0 ? config.encryption.map((r) => r.pattern).join(', ') : '(none)'}`);
|
|
18
|
+
console.log('');
|
|
19
|
+
console.log('Tracked paths:');
|
|
20
|
+
renderPathList(config.syncPaths);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;QACpF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,IAAI,OAAO,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,IAAI,OAAO,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC9B,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAQA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDrE"}
|