@singbox-iac/cli 0.1.4 → 0.1.6
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-en.md +62 -11
- package/README.md +62 -11
- package/assets/rule-set/geoip-cn.srs +0 -0
- package/assets/rule-set/geosite-anthropic.srs +0 -0
- package/assets/rule-set/geosite-cn.srs +0 -0
- package/assets/rule-set/geosite-cursor.srs +0 -0
- package/assets/rule-set/geosite-figma.srs +0 -0
- package/assets/rule-set/geosite-github-copilot.srs +0 -0
- package/assets/rule-set/geosite-github.srs +0 -0
- package/assets/rule-set/geosite-google-deepmind.srs +0 -0
- package/assets/rule-set/geosite-google-gemini.srs +0 -0
- package/assets/rule-set/geosite-google.srs +0 -0
- package/dist/cli/command-helpers.js +1 -1
- package/dist/cli/command-helpers.js.map +1 -1
- package/dist/cli/commands/author.d.ts +28 -0
- package/dist/cli/commands/author.js +119 -121
- package/dist/cli/commands/author.js.map +1 -1
- package/dist/cli/commands/build.js +8 -35
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/go.d.ts +2 -0
- package/dist/cli/commands/go.js +38 -0
- package/dist/cli/commands/go.js.map +1 -0
- package/dist/cli/commands/proxifier.d.ts +2 -0
- package/dist/cli/commands/proxifier.js +61 -0
- package/dist/cli/commands/proxifier.js.map +1 -0
- package/dist/cli/commands/quickstart.d.ts +2 -0
- package/dist/cli/commands/quickstart.js +54 -0
- package/dist/cli/commands/quickstart.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +30 -0
- package/dist/cli/commands/setup.js +277 -233
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/update.js +16 -2
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/use.d.ts +2 -0
- package/dist/cli/commands/use.js +45 -0
- package/dist/cli/commands/use.js.map +1 -0
- package/dist/cli/index.js +43 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/modules/compiler/index.js +15 -10
- package/dist/modules/compiler/index.js.map +1 -1
- package/dist/modules/fetcher/index.d.ts +1 -0
- package/dist/modules/fetcher/index.js +66 -19
- package/dist/modules/fetcher/index.js.map +1 -1
- package/dist/modules/manager/index.d.ts +1 -0
- package/dist/modules/manager/index.js +15 -0
- package/dist/modules/manager/index.js.map +1 -1
- package/dist/modules/natural-language/index.js +3 -2
- package/dist/modules/natural-language/index.js.map +1 -1
- package/dist/modules/proxifier/index.d.ts +27 -0
- package/dist/modules/proxifier/index.js +184 -0
- package/dist/modules/proxifier/index.js.map +1 -0
- package/dist/modules/rule-set-sync/index.d.ts +10 -0
- package/dist/modules/rule-set-sync/index.js +72 -12
- package/dist/modules/rule-set-sync/index.js.map +1 -1
- package/dist/modules/update/index.d.ts +1 -0
- package/dist/modules/update/index.js +4 -1
- package/dist/modules/update/index.js.map +1 -1
- package/dist/modules/verification/index.d.ts +15 -0
- package/dist/modules/verification/index.js +89 -44
- package/dist/modules/verification/index.js.map +1 -1
- package/docs/proxifier-onboarding.md +65 -0
- package/docs/runtime-on-macos.md +24 -7
- package/examples/builder.config.yaml +8 -27
- package/package.json +11 -2
package/README-en.md
CHANGED
|
@@ -62,7 +62,7 @@ The system has three layers:
|
|
|
62
62
|
|
|
63
63
|
```mermaid
|
|
64
64
|
flowchart TD
|
|
65
|
-
A["User provides subscription URL + one sentence"] --> B["setup"]
|
|
65
|
+
A["User provides subscription URL + one sentence"] --> B["quickstart / setup --ready"]
|
|
66
66
|
B --> C["Detect local environment<br/>macOS / sing-box / Chrome / AI CLI"]
|
|
67
67
|
C --> D["Generate rules from intent"]
|
|
68
68
|
D --> E["Sync local rule sets"]
|
|
@@ -158,24 +158,42 @@ singbox-iac --help
|
|
|
158
158
|
|
|
159
159
|
## Quick Start
|
|
160
160
|
|
|
161
|
+
### Most users only need 3 commands
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
singbox-iac go '<subscription-url>' '<one-sentence intent>'
|
|
165
|
+
singbox-iac use '<new routing sentence>'
|
|
166
|
+
singbox-iac update
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- `go`: first-time onboarding in one command
|
|
170
|
+
- `use`: change policy later with one sentence and re-apply it
|
|
171
|
+
- `update`: refresh the subscription and apply the latest config
|
|
172
|
+
|
|
173
|
+
Everything else can be treated as advanced commands for debugging or fine-grained control.
|
|
174
|
+
|
|
161
175
|
### One-step onboarding
|
|
162
176
|
|
|
163
177
|
```bash
|
|
164
|
-
singbox-iac
|
|
178
|
+
singbox-iac quickstart \
|
|
165
179
|
--subscription-url 'your subscription URL' \
|
|
166
180
|
--prompt 'GitHub and developer sites go through Hong Kong, Antigravity process traffic goes through the US, Gemini goes through Singapore, update every 30 minutes'
|
|
167
181
|
```
|
|
168
182
|
|
|
169
|
-
`
|
|
183
|
+
`quickstart` will:
|
|
170
184
|
|
|
171
185
|
- create `~/.config/singbox-iac/builder.config.yaml`
|
|
172
186
|
- create `~/.config/singbox-iac/rules/custom.rules.yaml`
|
|
187
|
+
- create `~/.config/singbox-iac/proxifier/` helper files
|
|
173
188
|
- check local environment readiness
|
|
174
|
-
-
|
|
189
|
+
- use bundled default `.srs` rule sets and only sync extras when needed
|
|
175
190
|
- turn one sentence into routing rules
|
|
176
191
|
- build `~/.config/singbox-iac/generated/config.staging.json`
|
|
192
|
+
- verify critical routes
|
|
193
|
+
- publish the live config
|
|
194
|
+
- install the recurring schedule
|
|
177
195
|
|
|
178
|
-
|
|
196
|
+
If you want the more explicit onboarding command, you can still use:
|
|
179
197
|
|
|
180
198
|
```bash
|
|
181
199
|
singbox-iac setup \
|
|
@@ -184,11 +202,10 @@ singbox-iac setup \
|
|
|
184
202
|
--ready
|
|
185
203
|
```
|
|
186
204
|
|
|
187
|
-
|
|
205
|
+
The difference is simple:
|
|
188
206
|
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
- recurring schedule installation
|
|
207
|
+
- `quickstart` is the shortest opinionated first-run path
|
|
208
|
+
- `setup --ready` is better if you still want to control run/browser/Proxifier flags yourself
|
|
192
209
|
|
|
193
210
|
### Manual foreground run
|
|
194
211
|
|
|
@@ -204,7 +221,7 @@ Default local listeners:
|
|
|
204
221
|
### Day-to-day usage
|
|
205
222
|
|
|
206
223
|
```bash
|
|
207
|
-
singbox-iac update
|
|
224
|
+
singbox-iac update
|
|
208
225
|
```
|
|
209
226
|
|
|
210
227
|
That command performs:
|
|
@@ -213,7 +230,7 @@ That command performs:
|
|
|
213
230
|
- build
|
|
214
231
|
- verify
|
|
215
232
|
- apply
|
|
216
|
-
-
|
|
233
|
+
- reload automatically when a `sing-box` process is already running
|
|
217
234
|
|
|
218
235
|
### Background schedule
|
|
219
236
|
|
|
@@ -223,6 +240,12 @@ singbox-iac schedule install
|
|
|
223
240
|
|
|
224
241
|
## Natural-Language Authoring
|
|
225
242
|
|
|
243
|
+
If you only want to change the routing sentence and apply it immediately, use the shorter command:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
singbox-iac use 'GitHub and developer sites go through Hong Kong, Gemini goes through Singapore'
|
|
247
|
+
```
|
|
248
|
+
|
|
226
249
|
For common cases, you do not need to learn raw `sing-box` JSON or even the DSL.
|
|
227
250
|
|
|
228
251
|
Examples:
|
|
@@ -245,6 +268,30 @@ The authoring layer supports:
|
|
|
245
268
|
- preview before writing
|
|
246
269
|
- closed-loop update after rule generation
|
|
247
270
|
|
|
271
|
+
## Proxifier Onboarding
|
|
272
|
+
|
|
273
|
+
If your AI IDE, language server, or desktop app does not respect the normal system proxy path, use the generated Proxifier helper directory:
|
|
274
|
+
|
|
275
|
+
```text
|
|
276
|
+
~/.config/singbox-iac/proxifier/
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
It contains:
|
|
280
|
+
|
|
281
|
+
- `README.md`
|
|
282
|
+
- `proxy-endpoint.txt`
|
|
283
|
+
- `custom-processes.txt`
|
|
284
|
+
- `bundles/antigravity.txt`
|
|
285
|
+
- `bundles/cursor.txt`
|
|
286
|
+
- `bundles/developer-ai-cli.txt`
|
|
287
|
+
- `all-processes.txt`
|
|
288
|
+
|
|
289
|
+
If you only want to regenerate the Proxifier helper files:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
singbox-iac proxifier scaffold --prompt 'Antigravity process traffic goes through the US and Cursor also uses a dedicated ingress'
|
|
293
|
+
```
|
|
294
|
+
|
|
248
295
|
## How It Works With sing-box
|
|
249
296
|
|
|
250
297
|
This project does not replace the `sing-box` core binary. It generates and manages `sing-box` configuration.
|
|
@@ -282,6 +329,7 @@ The project does not automatically upload subscription URLs to any remote servic
|
|
|
282
329
|
```bash
|
|
283
330
|
singbox-iac init
|
|
284
331
|
singbox-iac setup
|
|
332
|
+
singbox-iac quickstart
|
|
285
333
|
singbox-iac author
|
|
286
334
|
singbox-iac build
|
|
287
335
|
singbox-iac check
|
|
@@ -290,6 +338,8 @@ singbox-iac run
|
|
|
290
338
|
singbox-iac verify
|
|
291
339
|
singbox-iac update
|
|
292
340
|
singbox-iac doctor
|
|
341
|
+
singbox-iac proxifier bundles
|
|
342
|
+
singbox-iac proxifier scaffold
|
|
293
343
|
singbox-iac schedule install
|
|
294
344
|
singbox-iac schedule remove
|
|
295
345
|
singbox-iac templates list
|
|
@@ -300,6 +350,7 @@ singbox-iac templates list
|
|
|
300
350
|
- [rules-dsl.md](./docs/rules-dsl.md)
|
|
301
351
|
- [rule-templates.md](./docs/rule-templates.md)
|
|
302
352
|
- [natural-language-authoring.md](./docs/natural-language-authoring.md)
|
|
353
|
+
- [proxifier-onboarding.md](./docs/proxifier-onboarding.md)
|
|
303
354
|
- [runtime-on-macos.md](./docs/runtime-on-macos.md)
|
|
304
355
|
- [openspec/project.md](./openspec/project.md)
|
|
305
356
|
|
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ flowchart LR
|
|
|
62
62
|
|
|
63
63
|
```mermaid
|
|
64
64
|
flowchart TD
|
|
65
|
-
A["用户提供订阅地址 + 一句话需求"] --> B["setup"]
|
|
65
|
+
A["用户提供订阅地址 + 一句话需求"] --> B["quickstart / setup --ready"]
|
|
66
66
|
B --> C["检测本地环境<br/>macOS / sing-box / Chrome / AI CLI"]
|
|
67
67
|
C --> D["根据意图生成规则"]
|
|
68
68
|
D --> E["同步本地 rule set"]
|
|
@@ -158,24 +158,42 @@ singbox-iac --help
|
|
|
158
158
|
|
|
159
159
|
## 快速开始
|
|
160
160
|
|
|
161
|
+
### 大多数用户只需要 3 个命令
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
singbox-iac go '<订阅地址>' '<一句话需求>'
|
|
165
|
+
singbox-iac use '<新的需求描述>'
|
|
166
|
+
singbox-iac update
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- `go`:第一次安装时使用,一条命令完成初始化、验证、发布和定时任务准备
|
|
170
|
+
- `use`:以后需求变化时使用,一句话改策略并重新应用
|
|
171
|
+
- `update`:日常更新订阅并自动在运行中的 `sing-box` 上生效
|
|
172
|
+
|
|
173
|
+
其余命令都可以理解为高级命令,主要用于调试、排障或更细粒度控制。
|
|
174
|
+
|
|
161
175
|
### 一步完成初始化
|
|
162
176
|
|
|
163
177
|
```bash
|
|
164
|
-
singbox-iac
|
|
178
|
+
singbox-iac quickstart \
|
|
165
179
|
--subscription-url '你的机场订阅地址' \
|
|
166
180
|
--prompt 'GitHub 这类开发类走香港,Antigravity 进程级走美国,Gemini 走新加坡,每30分钟自动更新'
|
|
167
181
|
```
|
|
168
182
|
|
|
169
|
-
`
|
|
183
|
+
`quickstart` 会自动:
|
|
170
184
|
|
|
171
185
|
- 生成 `~/.config/singbox-iac/builder.config.yaml`
|
|
172
186
|
- 生成 `~/.config/singbox-iac/rules/custom.rules.yaml`
|
|
187
|
+
- 生成 `~/.config/singbox-iac/proxifier/` 辅助文件
|
|
173
188
|
- 检查本地环境
|
|
174
|
-
-
|
|
189
|
+
- 使用包内内置的默认 `.srs` 规则集,并在需要时补充同步
|
|
175
190
|
- 把一句自然语言转成路由规则
|
|
176
191
|
- 构建 `~/.config/singbox-iac/generated/config.staging.json`
|
|
192
|
+
- 验证关键路由
|
|
193
|
+
- 发布 live config
|
|
194
|
+
- 安装定时更新
|
|
177
195
|
|
|
178
|
-
|
|
196
|
+
如果你希望保留更细的步骤控制,也可以继续用:
|
|
179
197
|
|
|
180
198
|
```bash
|
|
181
199
|
singbox-iac setup \
|
|
@@ -184,11 +202,10 @@ singbox-iac setup \
|
|
|
184
202
|
--ready
|
|
185
203
|
```
|
|
186
204
|
|
|
187
|
-
|
|
205
|
+
`setup --ready` 和 `quickstart` 的主要区别是:
|
|
188
206
|
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
- 安装定时更新
|
|
207
|
+
- `quickstart` 更偏默认的一键上手
|
|
208
|
+
- `setup --ready` 更适合你还想自己决定是否运行、是否开浏览器、是否写 Proxifier 辅助目录
|
|
192
209
|
|
|
193
210
|
### 前台运行测试
|
|
194
211
|
|
|
@@ -204,7 +221,7 @@ singbox-iac run
|
|
|
204
221
|
### 日常使用
|
|
205
222
|
|
|
206
223
|
```bash
|
|
207
|
-
singbox-iac update
|
|
224
|
+
singbox-iac update
|
|
208
225
|
```
|
|
209
226
|
|
|
210
227
|
这条命令会执行:
|
|
@@ -213,7 +230,7 @@ singbox-iac update --reload
|
|
|
213
230
|
- build
|
|
214
231
|
- verify
|
|
215
232
|
- apply
|
|
216
|
-
-
|
|
233
|
+
- 如果检测到 `sing-box` 正在运行,则自动 reload
|
|
217
234
|
|
|
218
235
|
### 定时更新
|
|
219
236
|
|
|
@@ -223,6 +240,12 @@ singbox-iac schedule install
|
|
|
223
240
|
|
|
224
241
|
## 自然语言规则编写
|
|
225
242
|
|
|
243
|
+
如果你只想“改一句话需求并立即生效”,推荐直接用更短的命令:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
singbox-iac use 'GitHub 这类开发类都走香港,Gemini 走新加坡'
|
|
247
|
+
```
|
|
248
|
+
|
|
226
249
|
对于大多数场景,不需要手写 `sing-box` JSON,也不需要理解 DSL。
|
|
227
250
|
|
|
228
251
|
示例:
|
|
@@ -245,6 +268,30 @@ singbox-iac author \
|
|
|
245
268
|
- 写入前先 preview
|
|
246
269
|
- 生成规则后直接闭环 update
|
|
247
270
|
|
|
271
|
+
## Proxifier 上手
|
|
272
|
+
|
|
273
|
+
如果你的 AI IDE、language server 或桌面应用不走系统代理,可以直接使用自动生成的 Proxifier 辅助目录:
|
|
274
|
+
|
|
275
|
+
```text
|
|
276
|
+
~/.config/singbox-iac/proxifier/
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
其中会包含:
|
|
280
|
+
|
|
281
|
+
- `README.md`
|
|
282
|
+
- `proxy-endpoint.txt`
|
|
283
|
+
- `custom-processes.txt`
|
|
284
|
+
- `bundles/antigravity.txt`
|
|
285
|
+
- `bundles/cursor.txt`
|
|
286
|
+
- `bundles/developer-ai-cli.txt`
|
|
287
|
+
- `all-processes.txt`
|
|
288
|
+
|
|
289
|
+
如果你只想重新生成这部分,不需要重跑全部 onboarding:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
singbox-iac proxifier scaffold --prompt 'Antigravity 进程级走美国,Cursor 也走独立入口'
|
|
293
|
+
```
|
|
294
|
+
|
|
248
295
|
## 它和 sing-box 是怎么配合的
|
|
249
296
|
|
|
250
297
|
它不会替代 `sing-box` 内核本身,而是负责生成和维护 `sing-box` 配置。
|
|
@@ -282,6 +329,7 @@ singbox-iac author \
|
|
|
282
329
|
```bash
|
|
283
330
|
singbox-iac init
|
|
284
331
|
singbox-iac setup
|
|
332
|
+
singbox-iac quickstart
|
|
285
333
|
singbox-iac author
|
|
286
334
|
singbox-iac build
|
|
287
335
|
singbox-iac check
|
|
@@ -290,6 +338,8 @@ singbox-iac run
|
|
|
290
338
|
singbox-iac verify
|
|
291
339
|
singbox-iac update
|
|
292
340
|
singbox-iac doctor
|
|
341
|
+
singbox-iac proxifier bundles
|
|
342
|
+
singbox-iac proxifier scaffold
|
|
293
343
|
singbox-iac schedule install
|
|
294
344
|
singbox-iac schedule remove
|
|
295
345
|
singbox-iac templates list
|
|
@@ -300,6 +350,7 @@ singbox-iac templates list
|
|
|
300
350
|
- [rules-dsl.md](./docs/rules-dsl.md)
|
|
301
351
|
- [rule-templates.md](./docs/rule-templates.md)
|
|
302
352
|
- [natural-language-authoring.md](./docs/natural-language-authoring.md)
|
|
353
|
+
- [proxifier-onboarding.md](./docs/proxifier-onboarding.md)
|
|
303
354
|
- [runtime-on-macos.md](./docs/runtime-on-macos.md)
|
|
304
355
|
- [openspec/project.md](./openspec/project.md)
|
|
305
356
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -42,9 +42,9 @@ async function fileExists(filePath) {
|
|
|
42
42
|
}
|
|
43
43
|
function getDefaultConfigCandidates() {
|
|
44
44
|
return [
|
|
45
|
+
getDefaultConfigPath(),
|
|
45
46
|
path.resolve(process.cwd(), "builder.config.local.yaml"),
|
|
46
47
|
path.resolve(process.cwd(), "builder.config.yaml"),
|
|
47
|
-
getDefaultConfigPath(),
|
|
48
48
|
];
|
|
49
49
|
}
|
|
50
50
|
export function resolvePackageRoot(moduleUrl) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-helpers.js","sourceRoot":"","sources":["../../src/cli/command-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAOtD,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAA6B;IAE7B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,qBAAqB,EAAE,CAAC;IACjD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,UAAU,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,KAAK,MAAM,QAAQ,IAAI,0BAA0B,EAAE,EAAE,CAAC;QACpD,IAAI,MAAM,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B;IACjC,OAAO;QACL,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,2BAA2B,CAAC;QACxD,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"command-helpers.js","sourceRoot":"","sources":["../../src/cli/command-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAOtD,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAA6B;IAE7B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,qBAAqB,EAAE,CAAC;IACjD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,UAAU,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,KAAK,MAAM,QAAQ,IAAI,0BAA0B,EAAE,EAAE,CAAC;QACpD,IAAI,MAAM,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B;IACjC,OAAO;QACL,oBAAoB,EAAE;QACtB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,2BAA2B,CAAC;QACxD,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,qBAAqB,CAAC;KACnD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,SAAiB;IACpD,MAAM,iBAAiB,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,QAAQ,SAAS,EAAE,CAAC,CAAC;AAClF,CAAC"}
|
|
@@ -1,2 +1,30 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
export declare function registerAuthorCommand(program: Command): void;
|
|
3
|
+
export declare function runAuthorFlow(options: AuthorCommandOptions): Promise<void>;
|
|
4
|
+
interface AuthorCommandOptions {
|
|
5
|
+
readonly prompt: string;
|
|
6
|
+
readonly config?: string;
|
|
7
|
+
readonly provider?: "deterministic" | "auto" | "claude" | "exec";
|
|
8
|
+
readonly authorTimeoutMs?: string;
|
|
9
|
+
readonly execCommand?: string;
|
|
10
|
+
readonly execArg: string[];
|
|
11
|
+
readonly rulesOut?: string;
|
|
12
|
+
readonly subscriptionUrl?: string;
|
|
13
|
+
readonly subscriptionFile?: string;
|
|
14
|
+
readonly preview?: boolean;
|
|
15
|
+
readonly skipBuild?: boolean;
|
|
16
|
+
readonly update?: boolean;
|
|
17
|
+
readonly skipVerify?: boolean;
|
|
18
|
+
readonly reload?: boolean;
|
|
19
|
+
readonly livePath?: string;
|
|
20
|
+
readonly backupPath?: string;
|
|
21
|
+
readonly singBoxBin?: string;
|
|
22
|
+
readonly chromeBin?: string;
|
|
23
|
+
readonly installSchedule?: boolean;
|
|
24
|
+
readonly label: string;
|
|
25
|
+
readonly launchAgentsDir?: string;
|
|
26
|
+
readonly logsDir?: string;
|
|
27
|
+
readonly forceSchedule?: boolean;
|
|
28
|
+
readonly load?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -9,7 +9,7 @@ import { findDefaultConfigPath, resolveBuilderConfig, resolveCliEntrypoint, } fr
|
|
|
9
9
|
export function registerAuthorCommand(program) {
|
|
10
10
|
program
|
|
11
11
|
.command("author")
|
|
12
|
-
.description("
|
|
12
|
+
.description("Advanced rule authoring from a natural-language prompt.")
|
|
13
13
|
.requiredOption("-p, --prompt <text>", "natural-language routing prompt")
|
|
14
14
|
.option("-c, --config <path>", "path to builder config YAML")
|
|
15
15
|
.option("--provider <provider>", "authoring provider: deterministic, auto, claude, exec")
|
|
@@ -35,89 +35,45 @@ export function registerAuthorCommand(program) {
|
|
|
35
35
|
.option("-f, --force-schedule", "replace an existing LaunchAgent file when installing")
|
|
36
36
|
.option("--no-load", "write the LaunchAgent without calling launchctl bootstrap")
|
|
37
37
|
.action(async (options) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
await runAuthorFlow(options);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
export async function runAuthorFlow(options) {
|
|
42
|
+
const [builderConfig, configPath] = await Promise.all([
|
|
43
|
+
resolveBuilderConfig(options),
|
|
44
|
+
options.config ? Promise.resolve(resolvePath(options.config)) : findDefaultConfigPath(),
|
|
45
|
+
]);
|
|
46
|
+
if (!builderConfig || !configPath) {
|
|
47
|
+
throw new Error("author requires a builder config. Pass --config or run init first.");
|
|
48
|
+
}
|
|
49
|
+
if (options.update && options.skipBuild) {
|
|
50
|
+
throw new Error("author cannot use --update together with --skip-build.");
|
|
51
|
+
}
|
|
52
|
+
const planResult = await generateAuthoringPlan({
|
|
53
|
+
prompt: options.prompt,
|
|
54
|
+
config: builderConfig,
|
|
55
|
+
...(options.provider ? { provider: options.provider } : {}),
|
|
56
|
+
...(options.authorTimeoutMs ? { timeoutMs: Number.parseInt(options.authorTimeoutMs, 10) } : {}),
|
|
57
|
+
...(options.execCommand ? { execCommand: options.execCommand } : {}),
|
|
58
|
+
...(options.execArg.length > 0 ? { execArgs: options.execArg } : {}),
|
|
59
|
+
});
|
|
60
|
+
const plan = planResult.plan;
|
|
61
|
+
const rulesPath = options.rulesOut
|
|
62
|
+
? resolvePath(options.rulesOut)
|
|
63
|
+
: builderConfig.rules.userRulesFile;
|
|
64
|
+
const effectiveConfig = applyPlanToBuilderConfig(builderConfig, {
|
|
65
|
+
rulesPath,
|
|
66
|
+
plan,
|
|
67
|
+
});
|
|
68
|
+
if (options.preview) {
|
|
69
|
+
const preview = await generateAuthoringPreview({
|
|
70
|
+
configPath,
|
|
50
71
|
config: builderConfig,
|
|
51
|
-
...(options.provider ? { provider: options.provider } : {}),
|
|
52
|
-
...(options.authorTimeoutMs
|
|
53
|
-
? { timeoutMs: Number.parseInt(options.authorTimeoutMs, 10) }
|
|
54
|
-
: {}),
|
|
55
|
-
...(options.execCommand ? { execCommand: options.execCommand } : {}),
|
|
56
|
-
...(options.execArg.length > 0 ? { execArgs: options.execArg } : {}),
|
|
57
|
-
});
|
|
58
|
-
const plan = planResult.plan;
|
|
59
|
-
const rulesPath = options.rulesOut
|
|
60
|
-
? resolvePath(options.rulesOut)
|
|
61
|
-
: builderConfig.rules.userRulesFile;
|
|
62
|
-
const effectiveConfig = applyPlanToBuilderConfig(builderConfig, {
|
|
63
|
-
rulesPath,
|
|
64
72
|
plan,
|
|
65
|
-
});
|
|
66
|
-
if (options.preview) {
|
|
67
|
-
const preview = await generateAuthoringPreview({
|
|
68
|
-
configPath,
|
|
69
|
-
config: builderConfig,
|
|
70
|
-
plan,
|
|
71
|
-
rulesPath,
|
|
72
|
-
...(options.subscriptionFile ? { subscriptionFile: options.subscriptionFile } : {}),
|
|
73
|
-
...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
|
|
74
|
-
buildStaging: !options.skipBuild,
|
|
75
|
-
});
|
|
76
|
-
const lines = [
|
|
77
|
-
`Config: ${configPath}`,
|
|
78
|
-
`Rules: ${rulesPath}`,
|
|
79
|
-
`Provider requested: ${planResult.providerRequested}`,
|
|
80
|
-
`Provider used: ${planResult.providerUsed}`,
|
|
81
|
-
`Templates: ${plan.templateIds.length > 0 ? plan.templateIds.join(", ") : "(none)"}`,
|
|
82
|
-
`Generated rules: ${plan.beforeBuiltins.length + plan.afterBuiltins.length}`,
|
|
83
|
-
"Preview mode: no files were written.",
|
|
84
|
-
];
|
|
85
|
-
if (plan.notes.length > 0) {
|
|
86
|
-
lines.push(`Notes: ${plan.notes.length}`);
|
|
87
|
-
lines.push(...plan.notes.map((note) => `- ${note}`));
|
|
88
|
-
}
|
|
89
|
-
if (options.installSchedule) {
|
|
90
|
-
lines.push("Schedule install: requested, but skipped in preview mode.");
|
|
91
|
-
}
|
|
92
|
-
if (options.update) {
|
|
93
|
-
lines.push("Live update: requested, but skipped in preview mode.");
|
|
94
|
-
}
|
|
95
|
-
lines.push("");
|
|
96
|
-
lines.push("Rules diff:");
|
|
97
|
-
lines.push(preview.rulesDiff.diff);
|
|
98
|
-
lines.push("");
|
|
99
|
-
lines.push("Builder config diff:");
|
|
100
|
-
lines.push(preview.configDiff.diff);
|
|
101
|
-
if (preview.stagingDiff) {
|
|
102
|
-
lines.push("");
|
|
103
|
-
lines.push("Staging config diff:");
|
|
104
|
-
lines.push(preview.stagingDiff.diff);
|
|
105
|
-
}
|
|
106
|
-
process.stdout.write(`${lines.join("\n")}\n`);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
await writeGeneratedRules({
|
|
110
|
-
filePath: rulesPath,
|
|
111
|
-
plan,
|
|
112
|
-
});
|
|
113
|
-
await updateBuilderAuthoring({
|
|
114
|
-
configPath,
|
|
115
73
|
rulesPath,
|
|
116
|
-
...(
|
|
117
|
-
...(
|
|
118
|
-
|
|
119
|
-
? { verificationOverrides: plan.verificationOverrides }
|
|
120
|
-
: {}),
|
|
74
|
+
...(options.subscriptionFile ? { subscriptionFile: options.subscriptionFile } : {}),
|
|
75
|
+
...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
|
|
76
|
+
buildStaging: !options.skipBuild,
|
|
121
77
|
});
|
|
122
78
|
const lines = [
|
|
123
79
|
`Config: ${configPath}`,
|
|
@@ -126,58 +82,100 @@ export function registerAuthorCommand(program) {
|
|
|
126
82
|
`Provider used: ${planResult.providerUsed}`,
|
|
127
83
|
`Templates: ${plan.templateIds.length > 0 ? plan.templateIds.join(", ") : "(none)"}`,
|
|
128
84
|
`Generated rules: ${plan.beforeBuiltins.length + plan.afterBuiltins.length}`,
|
|
85
|
+
"Preview mode: no files were written.",
|
|
129
86
|
];
|
|
130
87
|
if (plan.notes.length > 0) {
|
|
131
88
|
lines.push(`Notes: ${plan.notes.length}`);
|
|
132
89
|
lines.push(...plan.notes.map((note) => `- ${note}`));
|
|
133
90
|
}
|
|
134
91
|
if (options.installSchedule) {
|
|
135
|
-
|
|
136
|
-
const schedule = await installLaunchdSchedule({
|
|
137
|
-
configPath,
|
|
138
|
-
intervalMinutes,
|
|
139
|
-
cliEntrypoint: resolveCliEntrypoint(import.meta.url),
|
|
140
|
-
label: options.label,
|
|
141
|
-
...(options.launchAgentsDir
|
|
142
|
-
? { launchAgentsDir: resolvePath(options.launchAgentsDir) }
|
|
143
|
-
: {}),
|
|
144
|
-
...(options.logsDir ? { logsDir: resolvePath(options.logsDir) } : {}),
|
|
145
|
-
force: options.forceSchedule === true,
|
|
146
|
-
load: options.load !== false,
|
|
147
|
-
});
|
|
148
|
-
lines.push(`LaunchAgent: ${schedule.plistPath}`);
|
|
92
|
+
lines.push("Schedule install: requested, but skipped in preview mode.");
|
|
149
93
|
}
|
|
150
94
|
if (options.update) {
|
|
151
|
-
|
|
152
|
-
config: effectiveConfig,
|
|
153
|
-
...(options.subscriptionFile ? { subscriptionFile: options.subscriptionFile } : {}),
|
|
154
|
-
...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
|
|
155
|
-
...(options.livePath ? { livePath: resolvePath(options.livePath) } : {}),
|
|
156
|
-
...(options.backupPath ? { backupPath: resolvePath(options.backupPath) } : {}),
|
|
157
|
-
...(options.singBoxBin ? { singBoxBinary: resolvePath(options.singBoxBin) } : {}),
|
|
158
|
-
...(options.chromeBin ? { chromeBinary: resolvePath(options.chromeBin) } : {}),
|
|
159
|
-
verify: !options.skipVerify,
|
|
160
|
-
...(options.reload ? { reload: true } : {}),
|
|
161
|
-
});
|
|
162
|
-
lines.push(`Staging: ${updateResult.build.outputPath}`);
|
|
163
|
-
lines.push(updateResult.verification
|
|
164
|
-
? `Verified scenarios: ${updateResult.verification.scenarios.filter((scenario) => scenario.passed).length}/${updateResult.verification.scenarios.length}`
|
|
165
|
-
: "Verified scenarios: skipped");
|
|
166
|
-
lines.push(`Live: ${updateResult.livePath}`);
|
|
167
|
-
if (updateResult.backupPath) {
|
|
168
|
-
lines.push(`Backup: ${updateResult.backupPath}`);
|
|
169
|
-
}
|
|
95
|
+
lines.push("Live update: requested, but skipped in preview mode.");
|
|
170
96
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
97
|
+
lines.push("");
|
|
98
|
+
lines.push("Rules diff:");
|
|
99
|
+
lines.push(preview.rulesDiff.diff);
|
|
100
|
+
lines.push("");
|
|
101
|
+
lines.push("Builder config diff:");
|
|
102
|
+
lines.push(preview.configDiff.diff);
|
|
103
|
+
if (preview.stagingDiff) {
|
|
104
|
+
lines.push("");
|
|
105
|
+
lines.push("Staging config diff:");
|
|
106
|
+
lines.push(preview.stagingDiff.diff);
|
|
178
107
|
}
|
|
179
108
|
process.stdout.write(`${lines.join("\n")}\n`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
await writeGeneratedRules({
|
|
112
|
+
filePath: rulesPath,
|
|
113
|
+
plan,
|
|
114
|
+
});
|
|
115
|
+
await updateBuilderAuthoring({
|
|
116
|
+
configPath,
|
|
117
|
+
rulesPath,
|
|
118
|
+
...(plan.scheduleIntervalMinutes ? { intervalMinutes: plan.scheduleIntervalMinutes } : {}),
|
|
119
|
+
...(plan.groupDefaults ? { groupDefaults: plan.groupDefaults } : {}),
|
|
120
|
+
...(plan.verificationOverrides ? { verificationOverrides: plan.verificationOverrides } : {}),
|
|
180
121
|
});
|
|
122
|
+
const lines = [
|
|
123
|
+
`Config: ${configPath}`,
|
|
124
|
+
`Rules: ${rulesPath}`,
|
|
125
|
+
`Provider requested: ${planResult.providerRequested}`,
|
|
126
|
+
`Provider used: ${planResult.providerUsed}`,
|
|
127
|
+
`Templates: ${plan.templateIds.length > 0 ? plan.templateIds.join(", ") : "(none)"}`,
|
|
128
|
+
`Generated rules: ${plan.beforeBuiltins.length + plan.afterBuiltins.length}`,
|
|
129
|
+
];
|
|
130
|
+
if (plan.notes.length > 0) {
|
|
131
|
+
lines.push(`Notes: ${plan.notes.length}`);
|
|
132
|
+
lines.push(...plan.notes.map((note) => `- ${note}`));
|
|
133
|
+
}
|
|
134
|
+
if (options.installSchedule) {
|
|
135
|
+
const intervalMinutes = plan.scheduleIntervalMinutes ?? effectiveConfig.schedule.intervalMinutes;
|
|
136
|
+
const schedule = await installLaunchdSchedule({
|
|
137
|
+
configPath,
|
|
138
|
+
intervalMinutes,
|
|
139
|
+
cliEntrypoint: resolveCliEntrypoint(import.meta.url),
|
|
140
|
+
label: options.label,
|
|
141
|
+
...(options.launchAgentsDir ? { launchAgentsDir: resolvePath(options.launchAgentsDir) } : {}),
|
|
142
|
+
...(options.logsDir ? { logsDir: resolvePath(options.logsDir) } : {}),
|
|
143
|
+
force: options.forceSchedule === true,
|
|
144
|
+
load: options.load !== false,
|
|
145
|
+
});
|
|
146
|
+
lines.push(`LaunchAgent: ${schedule.plistPath}`);
|
|
147
|
+
}
|
|
148
|
+
if (options.update) {
|
|
149
|
+
const updateResult = await runUpdate({
|
|
150
|
+
config: effectiveConfig,
|
|
151
|
+
...(options.subscriptionFile ? { subscriptionFile: options.subscriptionFile } : {}),
|
|
152
|
+
...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
|
|
153
|
+
...(options.livePath ? { livePath: resolvePath(options.livePath) } : {}),
|
|
154
|
+
...(options.backupPath ? { backupPath: resolvePath(options.backupPath) } : {}),
|
|
155
|
+
...(options.singBoxBin ? { singBoxBinary: resolvePath(options.singBoxBin) } : {}),
|
|
156
|
+
...(options.chromeBin ? { chromeBinary: resolvePath(options.chromeBin) } : {}),
|
|
157
|
+
verify: !options.skipVerify,
|
|
158
|
+
...(options.reload ? { reload: true } : {}),
|
|
159
|
+
});
|
|
160
|
+
lines.push(`Staging: ${updateResult.build.outputPath}`);
|
|
161
|
+
lines.push(updateResult.verification
|
|
162
|
+
? `Verified scenarios: ${updateResult.verification.scenarios.filter((scenario) => scenario.passed).length}/${updateResult.verification.scenarios.length}`
|
|
163
|
+
: "Verified scenarios: skipped");
|
|
164
|
+
lines.push(`Live: ${updateResult.livePath}`);
|
|
165
|
+
if (updateResult.backupPath) {
|
|
166
|
+
lines.push(`Backup: ${updateResult.backupPath}`);
|
|
167
|
+
}
|
|
168
|
+
lines.push(`Reload: ${updateResult.reloaded ? "triggered" : "skipped"}`);
|
|
169
|
+
}
|
|
170
|
+
else if (!options.skipBuild) {
|
|
171
|
+
const build = await buildConfigArtifact({
|
|
172
|
+
config: effectiveConfig,
|
|
173
|
+
...(options.subscriptionFile ? { subscriptionFile: options.subscriptionFile } : {}),
|
|
174
|
+
...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
|
|
175
|
+
});
|
|
176
|
+
lines.push(`Staging: ${build.outputPath}`);
|
|
177
|
+
}
|
|
178
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
181
179
|
}
|
|
182
180
|
function resolvePath(filePath) {
|
|
183
181
|
return filePath.startsWith("/") ? filePath : path.resolve(process.cwd(), filePath);
|