@singbox-iac/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/LICENSE +21 -0
- package/README.md +265 -0
- package/dist/cli/command-helpers.d.ts +6 -0
- package/dist/cli/command-helpers.js +34 -0
- package/dist/cli/command-helpers.js.map +1 -0
- package/dist/cli/commands/apply.d.ts +2 -0
- package/dist/cli/commands/apply.js +32 -0
- package/dist/cli/commands/apply.js.map +1 -0
- package/dist/cli/commands/author.d.ts +2 -0
- package/dist/cli/commands/author.js +194 -0
- package/dist/cli/commands/author.js.map +1 -0
- package/dist/cli/commands/build.d.ts +2 -0
- package/dist/cli/commands/build.js +198 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/check.d.ts +2 -0
- package/dist/cli/commands/check.js +23 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.js +35 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.js +23 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/reload.d.ts +2 -0
- package/dist/cli/commands/reload.js +21 -0
- package/dist/cli/commands/reload.js.map +1 -0
- package/dist/cli/commands/run.d.ts +2 -0
- package/dist/cli/commands/run.js +25 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/schedule.d.ts +2 -0
- package/dist/cli/commands/schedule.js +77 -0
- package/dist/cli/commands/schedule.js.map +1 -0
- package/dist/cli/commands/templates.d.ts +2 -0
- package/dist/cli/commands/templates.js +34 -0
- package/dist/cli/commands/templates.js.map +1 -0
- package/dist/cli/commands/update.d.ts +2 -0
- package/dist/cli/commands/update.js +52 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +2 -0
- package/dist/cli/commands/verify.js +49 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +55 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/load-config.d.ts +2 -0
- package/dist/config/load-config.js +29 -0
- package/dist/config/load-config.js.map +1 -0
- package/dist/config/schema.d.ts +548 -0
- package/dist/config/schema.js +92 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/domain/config.d.ts +8 -0
- package/dist/domain/config.js +2 -0
- package/dist/domain/config.js.map +1 -0
- package/dist/domain/node.d.ts +11 -0
- package/dist/domain/node.js +2 -0
- package/dist/domain/node.js.map +1 -0
- package/dist/domain/outbound.d.ts +15 -0
- package/dist/domain/outbound.js +2 -0
- package/dist/domain/outbound.js.map +1 -0
- package/dist/domain/subscription.d.ts +6 -0
- package/dist/domain/subscription.js +2 -0
- package/dist/domain/subscription.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/authoring/index.d.ts +41 -0
- package/dist/modules/authoring/index.js +596 -0
- package/dist/modules/authoring/index.js.map +1 -0
- package/dist/modules/build/index.d.ts +13 -0
- package/dist/modules/build/index.js +39 -0
- package/dist/modules/build/index.js.map +1 -0
- package/dist/modules/compiler/index.d.ts +10 -0
- package/dist/modules/compiler/index.js +305 -0
- package/dist/modules/compiler/index.js.map +1 -0
- package/dist/modules/doctor/index.d.ts +17 -0
- package/dist/modules/doctor/index.js +89 -0
- package/dist/modules/doctor/index.js.map +1 -0
- package/dist/modules/fetcher/index.d.ts +4 -0
- package/dist/modules/fetcher/index.js +42 -0
- package/dist/modules/fetcher/index.js.map +1 -0
- package/dist/modules/init/index.d.ts +12 -0
- package/dist/modules/init/index.js +41 -0
- package/dist/modules/init/index.js.map +1 -0
- package/dist/modules/manager/index.d.ts +29 -0
- package/dist/modules/manager/index.js +133 -0
- package/dist/modules/manager/index.js.map +1 -0
- package/dist/modules/natural-language/index.d.ts +54 -0
- package/dist/modules/natural-language/index.js +458 -0
- package/dist/modules/natural-language/index.js.map +1 -0
- package/dist/modules/parser/index.d.ts +10 -0
- package/dist/modules/parser/index.js +113 -0
- package/dist/modules/parser/index.js.map +1 -0
- package/dist/modules/preview/index.d.ts +22 -0
- package/dist/modules/preview/index.js +141 -0
- package/dist/modules/preview/index.js.map +1 -0
- package/dist/modules/rule-templates/index.d.ts +15 -0
- package/dist/modules/rule-templates/index.js +200 -0
- package/dist/modules/rule-templates/index.js.map +1 -0
- package/dist/modules/schedule/index.d.ts +32 -0
- package/dist/modules/schedule/index.js +155 -0
- package/dist/modules/schedule/index.js.map +1 -0
- package/dist/modules/update/index.d.ts +22 -0
- package/dist/modules/update/index.js +38 -0
- package/dist/modules/update/index.js.map +1 -0
- package/dist/modules/user-rules/index.d.ts +18 -0
- package/dist/modules/user-rules/index.js +98 -0
- package/dist/modules/user-rules/index.js.map +1 -0
- package/dist/modules/verification/index.d.ts +49 -0
- package/dist/modules/verification/index.js +432 -0
- package/dist/modules/verification/index.js.map +1 -0
- package/dist/shared/errors.d.ts +3 -0
- package/dist/shared/errors.js +7 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/logger.d.ts +2 -0
- package/dist/shared/logger.js +5 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/result.d.ts +11 -0
- package/dist/shared/result.js +7 -0
- package/dist/shared/result.js.map +1 -0
- package/docs/antigravity-endpoints.md +77 -0
- package/docs/competitive-landscape.md +45 -0
- package/docs/development-workflow.md +80 -0
- package/docs/natural-language-authoring.md +376 -0
- package/docs/positioning.md +42 -0
- package/docs/releasing.md +72 -0
- package/docs/rule-templates.md +122 -0
- package/docs/rules-dsl.md +107 -0
- package/docs/runtime-on-macos.md +42 -0
- package/docs/sing-box-config-primer.md +39 -0
- package/docs/subscription-format.md +38 -0
- package/examples/builder.config.yaml +220 -0
- package/examples/custom.rules.yaml +18 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sing-box IaC Builder contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# Sing-box IaC Builder
|
|
2
|
+
|
|
3
|
+
Policy-first subscription compiler for `sing-box` on macOS.
|
|
4
|
+
|
|
5
|
+
`Sing-box IaC Builder` turns fragile proxy subscriptions into deterministic, verifiable `sing-box` infrastructure. It fetches provider subscriptions, parses share links into a normalized intermediate model, compiles them with a controlled routing policy, validates the generated configuration, and applies updates safely in a headless macOS environment.
|
|
6
|
+
|
|
7
|
+
This project is built for users who have outgrown GUI clients and template patch scripts:
|
|
8
|
+
|
|
9
|
+
- Subscriptions should provide nodes, not define your whole routing architecture.
|
|
10
|
+
- Route priority should be explicit and testable.
|
|
11
|
+
- Runtime updates should be validated before they touch the live config.
|
|
12
|
+
- `Proxifier`, multiple listeners, AI application routing, and custom rule sets should be first-class use cases.
|
|
13
|
+
|
|
14
|
+
## Why This Exists
|
|
15
|
+
|
|
16
|
+
Most GUI-centric workflows solve "import subscription", not "manage proxy infrastructure".
|
|
17
|
+
|
|
18
|
+
Typical pain points:
|
|
19
|
+
|
|
20
|
+
- Large provider groups with poor or unstable region segmentation
|
|
21
|
+
- Template- or JavaScript-based patching that breaks whenever the upstream subscription changes
|
|
22
|
+
- Opaque config merge behavior and hard-to-debug rule precedence issues
|
|
23
|
+
- High resource usage from GUI shells that should not be involved in a headless proxy runtime
|
|
24
|
+
- Weak support for process-aware routing, `Proxifier`, and application-specific AI egress policies
|
|
25
|
+
|
|
26
|
+
`Sing-box IaC Builder` treats `sing-box` as infrastructure:
|
|
27
|
+
|
|
28
|
+
- `subscription -> parser -> compiler -> check -> publish -> reload`
|
|
29
|
+
- Deterministic route ordering
|
|
30
|
+
- Human-friendly rule authoring
|
|
31
|
+
- Safe rollout with staging and validation
|
|
32
|
+
- macOS-first headless operation via `launchd`
|
|
33
|
+
|
|
34
|
+
## Positioning
|
|
35
|
+
|
|
36
|
+
This is not:
|
|
37
|
+
|
|
38
|
+
- another GUI client
|
|
39
|
+
- an online converter
|
|
40
|
+
- a one-off template filler
|
|
41
|
+
- a generic multi-client subscription merger
|
|
42
|
+
|
|
43
|
+
This is:
|
|
44
|
+
|
|
45
|
+
- a `sing-box` configuration compiler
|
|
46
|
+
- a runtime-safe CLI for headless macOS setups
|
|
47
|
+
- a policy-first abstraction over fragile provider subscriptions
|
|
48
|
+
- a foundation for future natural-language rule authoring
|
|
49
|
+
|
|
50
|
+
## How It Differs
|
|
51
|
+
|
|
52
|
+
| Dimension | Subscription Converters | GUI Clients / Launchers | Sing-box IaC Builder |
|
|
53
|
+
| --- | --- | --- | --- |
|
|
54
|
+
| Core goal | Convert one config format into another | Provide visual client UX | Compile subscriptions into managed `sing-box` infrastructure |
|
|
55
|
+
| Policy control | Often template-driven | Often merged inside the client | Explicit compiler-controlled route policy |
|
|
56
|
+
| Rule priority | Easy to drift with upstream changes | Often opaque | Fixed ordering and testable behavior |
|
|
57
|
+
| Runtime safety | Usually writes output only | Apply path is often hidden | `build -> check -> publish -> reload` |
|
|
58
|
+
| macOS headless | Usually not a focus | Usually not a focus | First-class |
|
|
59
|
+
| `Proxifier` / multi-listener | Rarely central | Awkward to maintain | Core scenario |
|
|
60
|
+
| AI app routing | Usually manual | Possible but brittle | Policy-level capability |
|
|
61
|
+
| User customization | Template edits / scripts | GUI clicks / raw config edits | Declarative DSL, later NL-to-DSL |
|
|
62
|
+
|
|
63
|
+
## Implemented Today
|
|
64
|
+
|
|
65
|
+
The current repository is already beyond Phase 0. It includes:
|
|
66
|
+
|
|
67
|
+
- Base64 Trojan subscription fetching and parsing
|
|
68
|
+
- `sing-box` config compilation with fixed route ordering
|
|
69
|
+
- runtime-safe commands: `build`, `check`, `apply`, `run`, `verify`, `update`
|
|
70
|
+
- config-driven route verification with real `sing-box` and headless Chrome
|
|
71
|
+
- simple YAML user-rules DSL with protected insertion points
|
|
72
|
+
- built-in rule templates for common developer and video-site patterns
|
|
73
|
+
- natural-language authoring that generates DSL, builds config, can install `launchd`, and can optionally probe local AI CLIs
|
|
74
|
+
- macOS helper commands: `init`, `doctor`, `schedule install`, `schedule remove`
|
|
75
|
+
|
|
76
|
+
## Install
|
|
77
|
+
|
|
78
|
+
For local dogfooding today, the CLI can already be installed from a packed tarball:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm pack
|
|
82
|
+
npm install -g ./singbox-iac-cli-0.1.0.tgz
|
|
83
|
+
singbox-iac --help
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For repository-based installs during development:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm install
|
|
90
|
+
npm run build
|
|
91
|
+
npx singbox-iac --help
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The package name is now aligned to the intended public scope, but the repository still stays `"private": true` until the first real publish. The distribution shape is already prepared for npm publishing:
|
|
95
|
+
|
|
96
|
+
- Node shebang on the compiled CLI entrypoint
|
|
97
|
+
- `dist`-only package contents plus docs/examples
|
|
98
|
+
- `prepare` and `prepack` build hooks
|
|
99
|
+
- `bin` and `exports` metadata
|
|
100
|
+
|
|
101
|
+
For a full repeatable distribution smoke, run:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm run release:check
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
That command executes:
|
|
108
|
+
|
|
109
|
+
- `npm run typecheck`
|
|
110
|
+
- `npm run lint`
|
|
111
|
+
- `npm test`
|
|
112
|
+
- `npm run build`
|
|
113
|
+
- `npm pack`
|
|
114
|
+
- clean-directory install smoke with `singbox-iac --help`
|
|
115
|
+
|
|
116
|
+
On success it cleans up the tarball and temp install directory. On failure it keeps them for debugging.
|
|
117
|
+
|
|
118
|
+
For a publish-level dry run without changing the repository's `"private": true` setting:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
npm run release:dry-run
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
That command stages a temporary publishable package copy and runs `npm publish --dry-run`. You can also test a future public package name without editing `package.json`:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
SINGBOX_IAC_PACKAGE_NAME=@singbox-iac/experimental-cli npm run release:dry-run
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Detailed publish notes are in [Releasing](/Users/lvyuanfang/Code/SingBoxConfig/docs/releasing.md).
|
|
131
|
+
|
|
132
|
+
## Planned CLI
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
singbox-iac init
|
|
136
|
+
singbox-iac author
|
|
137
|
+
singbox-iac build
|
|
138
|
+
singbox-iac apply
|
|
139
|
+
singbox-iac update
|
|
140
|
+
singbox-iac doctor
|
|
141
|
+
singbox-iac schedule install
|
|
142
|
+
singbox-iac schedule remove
|
|
143
|
+
singbox-iac templates list
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Project Status
|
|
147
|
+
|
|
148
|
+
The project is currently at a usable MVP-plus stage:
|
|
149
|
+
|
|
150
|
+
- real subscription ingestion works
|
|
151
|
+
- real route verification works
|
|
152
|
+
- real publish flow works
|
|
153
|
+
- simple rule DSL works
|
|
154
|
+
- macOS launchd integration is available
|
|
155
|
+
|
|
156
|
+
The highest-value remaining areas are:
|
|
157
|
+
|
|
158
|
+
- more protocol support beyond Trojan
|
|
159
|
+
- first real npm publish and release automation
|
|
160
|
+
|
|
161
|
+
## Authoring Shortcuts
|
|
162
|
+
|
|
163
|
+
For day-to-day usage, the practical authoring stack is:
|
|
164
|
+
|
|
165
|
+
- built-in policy for protected routes
|
|
166
|
+
- Proxifier for process-aware IDE and app routing
|
|
167
|
+
- built-in templates for common developer and video-site rules
|
|
168
|
+
- natural-language prompts for fast generation
|
|
169
|
+
- YAML DSL only for small exceptions
|
|
170
|
+
|
|
171
|
+
Docs:
|
|
172
|
+
|
|
173
|
+
- [Rules DSL](/Users/lvyuanfang/Code/SingBoxConfig/docs/rules-dsl.md)
|
|
174
|
+
- [Rule Templates](/Users/lvyuanfang/Code/SingBoxConfig/docs/rule-templates.md)
|
|
175
|
+
- [Natural-Language Authoring](/Users/lvyuanfang/Code/SingBoxConfig/docs/natural-language-authoring.md)
|
|
176
|
+
|
|
177
|
+
## Local AI CLI Support
|
|
178
|
+
|
|
179
|
+
This project does not require API keys for authoring.
|
|
180
|
+
|
|
181
|
+
The recommended flow is:
|
|
182
|
+
|
|
183
|
+
- default to deterministic local authoring
|
|
184
|
+
- optionally probe a local AI CLI with `provider=auto`
|
|
185
|
+
- optionally integrate any other CLI through `provider=exec`
|
|
186
|
+
- use `author --preview` before writing when changing prompts or providers
|
|
187
|
+
- always validate and compile through the same DSL and `sing-box` pipeline
|
|
188
|
+
|
|
189
|
+
Current support model:
|
|
190
|
+
|
|
191
|
+
- built-in provider:
|
|
192
|
+
- `claude`
|
|
193
|
+
- generic `exec` integrations:
|
|
194
|
+
- `gemini`
|
|
195
|
+
- `codebuddy`
|
|
196
|
+
- `codex`
|
|
197
|
+
- `opencode`
|
|
198
|
+
- `qodercli` / `qoder`
|
|
199
|
+
- tooling-only detection:
|
|
200
|
+
- `trae`
|
|
201
|
+
|
|
202
|
+
The project should not hard-code every AI CLI vendor. Instead:
|
|
203
|
+
|
|
204
|
+
- keep one or two verified built-ins
|
|
205
|
+
- support broad developer tooling through `provider=exec`
|
|
206
|
+
- allow wrapper scripts for CLIs with noisy or event-stream output
|
|
207
|
+
|
|
208
|
+
The `exec` adapter already supports:
|
|
209
|
+
|
|
210
|
+
- `{{prompt}}`
|
|
211
|
+
- `{{schema}}`
|
|
212
|
+
- `{{context_json}}`
|
|
213
|
+
- `{{full_prompt}}`
|
|
214
|
+
- `{{schema_file}}`
|
|
215
|
+
- `{{output_file}}`
|
|
216
|
+
|
|
217
|
+
and will accept:
|
|
218
|
+
|
|
219
|
+
- exact JSON stdout
|
|
220
|
+
- fenced JSON blocks
|
|
221
|
+
- a balanced JSON object extracted from longer text
|
|
222
|
+
- output written to `{{output_file}}`
|
|
223
|
+
|
|
224
|
+
This is the compatibility layer that makes “support most AI CLIs” practical without turning the project into a vendor-specific adapter zoo.
|
|
225
|
+
|
|
226
|
+
Natural-language authoring is now intent-first for common developer use cases. The user does not need to know the DSL or internal selector names for routine requests such as:
|
|
227
|
+
|
|
228
|
+
- `GitHub 这类开发类都走香港出口`
|
|
229
|
+
- `Antigravity 进程级都走独立入口并路由到美国节点`
|
|
230
|
+
- `Gemini 都出口到新加坡`
|
|
231
|
+
|
|
232
|
+
The authoring layer can compile those sentences into:
|
|
233
|
+
|
|
234
|
+
- explicit site rules
|
|
235
|
+
- selector default changes
|
|
236
|
+
- verification expectation updates
|
|
237
|
+
|
|
238
|
+
so the normal `author -> build -> verify` pipeline still stays consistent.
|
|
239
|
+
|
|
240
|
+
It also understands more mainstream subscription vocabulary, for example:
|
|
241
|
+
|
|
242
|
+
- `Google 服务和 GitHub 这类开发类都走香港`
|
|
243
|
+
- `Apple 服务走香港`
|
|
244
|
+
- `Amazon Prime 和 Apple TV 走新加坡`
|
|
245
|
+
- `视频网站走美国`
|
|
246
|
+
|
|
247
|
+
And it can now go all the way to publish from one sentence:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
./node_modules/.bin/tsx src/cli/index.ts author \
|
|
251
|
+
--config ./builder.config.local.yaml \
|
|
252
|
+
--provider deterministic \
|
|
253
|
+
--prompt "Google 服务和 GitHub 这类开发类都走香港,Gemini 走新加坡,Antigravity 进程级走美国,每30分钟自动更新" \
|
|
254
|
+
--update
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
See:
|
|
258
|
+
|
|
259
|
+
- [Natural-Language Authoring](/Users/lvyuanfang/Code/SingBoxConfig/docs/natural-language-authoring.md)
|
|
260
|
+
|
|
261
|
+
## References
|
|
262
|
+
|
|
263
|
+
- [OpenSpec](https://openspec.pro/)
|
|
264
|
+
- [sing-box documentation](https://sing-box.sagernet.org/configuration/)
|
|
265
|
+
- [sing-box migration guide](https://sing-box.sagernet.org/migration/)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BuilderConfig } from "../config/schema.js";
|
|
2
|
+
export interface SharedCommandOptions {
|
|
3
|
+
readonly config?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function resolveBuilderConfig(options: SharedCommandOptions): Promise<BuilderConfig | undefined>;
|
|
6
|
+
export declare function findDefaultConfigPath(): Promise<string | undefined>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { loadConfig } from "../config/load-config.js";
|
|
5
|
+
const defaultConfigCandidates = ["builder.config.local.yaml", "builder.config.yaml"];
|
|
6
|
+
export async function resolveBuilderConfig(options) {
|
|
7
|
+
if (options.config) {
|
|
8
|
+
return loadConfig(options.config);
|
|
9
|
+
}
|
|
10
|
+
const configPath = await findDefaultConfigPath();
|
|
11
|
+
if (!configPath) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
return loadConfig(configPath);
|
|
15
|
+
}
|
|
16
|
+
export async function findDefaultConfigPath() {
|
|
17
|
+
for (const candidate of defaultConfigCandidates) {
|
|
18
|
+
const filePath = path.resolve(process.cwd(), candidate);
|
|
19
|
+
if (await fileExists(filePath)) {
|
|
20
|
+
return filePath;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
async function fileExists(filePath) {
|
|
26
|
+
try {
|
|
27
|
+
await access(filePath, constants.F_OK);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=command-helpers.js.map
|
|
@@ -0,0 +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,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,MAAM,uBAAuB,GAAG,CAAC,2BAA2B,EAAE,qBAAqB,CAAC,CAAC;AAMrF,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,SAAS,IAAI,uBAAuB,EAAE,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;QACxD,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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { applyConfig } from "../../modules/manager/index.js";
|
|
2
|
+
import { resolveBuilderConfig } from "../command-helpers.js";
|
|
3
|
+
export function registerApplyCommand(program) {
|
|
4
|
+
program
|
|
5
|
+
.command("apply")
|
|
6
|
+
.description("Validate and publish the latest generated config.")
|
|
7
|
+
.option("-c, --config <path>", "path to builder config YAML")
|
|
8
|
+
.option("-i, --input <path>", "path to staging config JSON")
|
|
9
|
+
.option("--live-path <path>", "override live config path")
|
|
10
|
+
.option("--backup-path <path>", "override backup config path")
|
|
11
|
+
.option("--sing-box-bin <path>", "path to sing-box binary")
|
|
12
|
+
.option("--reload", "reload sing-box after publish")
|
|
13
|
+
.action(async (options) => {
|
|
14
|
+
const builderConfig = await resolveBuilderConfig(options);
|
|
15
|
+
const stagingPath = options.input ?? builderConfig?.output.stagingPath;
|
|
16
|
+
const livePath = options.livePath ?? builderConfig?.output.livePath;
|
|
17
|
+
const backupPath = options.backupPath ?? builderConfig?.output.backupPath;
|
|
18
|
+
if (!stagingPath || !livePath) {
|
|
19
|
+
throw new Error("Unable to resolve staging/live paths. Pass --input/--live-path or provide a builder config.");
|
|
20
|
+
}
|
|
21
|
+
await applyConfig({
|
|
22
|
+
stagingPath,
|
|
23
|
+
livePath,
|
|
24
|
+
...(backupPath ? { backupPath } : {}),
|
|
25
|
+
...(options.singBoxBin ? { singBoxBinary: options.singBoxBin } : {}),
|
|
26
|
+
...(options.reload !== undefined ? { reload: options.reload } : {}),
|
|
27
|
+
...(builderConfig?.runtime.reload ? { runtime: builderConfig.runtime.reload } : {}),
|
|
28
|
+
});
|
|
29
|
+
process.stdout.write(`Applied config.\nSource: ${stagingPath}\nLive: ${livePath}\n${backupPath ? `Backup: ${backupPath}\n` : ""}`);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/cli/commands/apply.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,mDAAmD,CAAC;SAChE,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;SAC5D,MAAM,CAAC,oBAAoB,EAAE,6BAA6B,CAAC;SAC3D,MAAM,CAAC,oBAAoB,EAAE,2BAA2B,CAAC;SACzD,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,CAAC;SAC7D,MAAM,CAAC,uBAAuB,EAAE,yBAAyB,CAAC;SAC1D,MAAM,CAAC,UAAU,EAAE,+BAA+B,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC7C,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,EAAE,MAAM,CAAC,WAAW,CAAC;QACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC;QACpE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC;QAE1E,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,CAAC;YAChB,WAAW;YACX,QAAQ;YACR,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpF,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,4BAA4B,WAAW,WAAW,QAAQ,KACxD,UAAU,CAAC,CAAC,CAAC,WAAW,UAAU,IAAI,CAAC,CAAC,CAAC,EAC3C,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { generateAuthoringPlan } from "../../modules/authoring/index.js";
|
|
4
|
+
import { buildConfigArtifact } from "../../modules/build/index.js";
|
|
5
|
+
import { applyPlanToBuilderConfig, updateBuilderAuthoring, writeGeneratedRules, } from "../../modules/natural-language/index.js";
|
|
6
|
+
import { generateAuthoringPreview } from "../../modules/preview/index.js";
|
|
7
|
+
import { installLaunchdSchedule } from "../../modules/schedule/index.js";
|
|
8
|
+
import { runUpdate } from "../../modules/update/index.js";
|
|
9
|
+
import { findDefaultConfigPath, resolveBuilderConfig } from "../command-helpers.js";
|
|
10
|
+
export function registerAuthorCommand(program) {
|
|
11
|
+
program
|
|
12
|
+
.command("author")
|
|
13
|
+
.description("Generate custom rules from a natural-language prompt, then optionally build and schedule.")
|
|
14
|
+
.requiredOption("-p, --prompt <text>", "natural-language routing prompt")
|
|
15
|
+
.option("-c, --config <path>", "path to builder config YAML")
|
|
16
|
+
.option("--provider <provider>", "authoring provider: deterministic, auto, claude, exec")
|
|
17
|
+
.option("--author-timeout-ms <ms>", "timeout for local AI CLI authoring")
|
|
18
|
+
.option("--exec-command <command>", "command for the exec authoring provider")
|
|
19
|
+
.option("--exec-arg <arg>", "append one argument for the exec authoring provider", collectOption, [])
|
|
20
|
+
.option("--rules-out <path>", "override the target custom-rules file")
|
|
21
|
+
.option("--subscription-url <url>", "override subscription URL when building")
|
|
22
|
+
.option("--subscription-file <path>", "use a local subscription file instead of fetching")
|
|
23
|
+
.option("--preview", "print rules/config/staging diffs without writing any files")
|
|
24
|
+
.option("--skip-build", "write rules only and skip config generation")
|
|
25
|
+
.option("--update", "after writing rules, run build + verify + publish")
|
|
26
|
+
.option("--skip-verify", "when used with --update, skip runtime verification before publish")
|
|
27
|
+
.option("--reload", "when used with --update, reload sing-box after publish")
|
|
28
|
+
.option("--live-path <path>", "override live config path when using --update")
|
|
29
|
+
.option("--backup-path <path>", "override backup config path when using --update")
|
|
30
|
+
.option("--sing-box-bin <path>", "path to sing-box binary")
|
|
31
|
+
.option("--chrome-bin <path>", "path to Chrome binary for runtime verification")
|
|
32
|
+
.option("--install-schedule", "install a launchd job after writing rules and building")
|
|
33
|
+
.option("--label <label>", "LaunchAgent label", "org.singbox-iac.update")
|
|
34
|
+
.option("--launch-agents-dir <path>", "override LaunchAgents directory")
|
|
35
|
+
.option("--logs-dir <path>", "override launchd log directory")
|
|
36
|
+
.option("-f, --force-schedule", "replace an existing LaunchAgent file when installing")
|
|
37
|
+
.option("--no-load", "write the LaunchAgent without calling launchctl bootstrap")
|
|
38
|
+
.action(async (options) => {
|
|
39
|
+
const [builderConfig, configPath] = await Promise.all([
|
|
40
|
+
resolveBuilderConfig(options),
|
|
41
|
+
options.config ? Promise.resolve(resolvePath(options.config)) : findDefaultConfigPath(),
|
|
42
|
+
]);
|
|
43
|
+
if (!builderConfig || !configPath) {
|
|
44
|
+
throw new Error("author requires a builder config. Pass --config or run init first.");
|
|
45
|
+
}
|
|
46
|
+
if (options.update && options.skipBuild) {
|
|
47
|
+
throw new Error("author cannot use --update together with --skip-build.");
|
|
48
|
+
}
|
|
49
|
+
const planResult = await generateAuthoringPlan({
|
|
50
|
+
prompt: options.prompt,
|
|
51
|
+
config: builderConfig,
|
|
52
|
+
...(options.provider ? { provider: options.provider } : {}),
|
|
53
|
+
...(options.authorTimeoutMs
|
|
54
|
+
? { timeoutMs: Number.parseInt(options.authorTimeoutMs, 10) }
|
|
55
|
+
: {}),
|
|
56
|
+
...(options.execCommand ? { execCommand: options.execCommand } : {}),
|
|
57
|
+
...(options.execArg.length > 0 ? { execArgs: options.execArg } : {}),
|
|
58
|
+
});
|
|
59
|
+
const plan = planResult.plan;
|
|
60
|
+
const rulesPath = options.rulesOut
|
|
61
|
+
? resolvePath(options.rulesOut)
|
|
62
|
+
: builderConfig.rules.userRulesFile;
|
|
63
|
+
const effectiveConfig = applyPlanToBuilderConfig(builderConfig, {
|
|
64
|
+
rulesPath,
|
|
65
|
+
plan,
|
|
66
|
+
});
|
|
67
|
+
if (options.preview) {
|
|
68
|
+
const preview = await generateAuthoringPreview({
|
|
69
|
+
configPath,
|
|
70
|
+
config: builderConfig,
|
|
71
|
+
plan,
|
|
72
|
+
rulesPath,
|
|
73
|
+
...(options.subscriptionFile ? { subscriptionFile: options.subscriptionFile } : {}),
|
|
74
|
+
...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
|
|
75
|
+
buildStaging: !options.skipBuild,
|
|
76
|
+
});
|
|
77
|
+
const lines = [
|
|
78
|
+
`Config: ${configPath}`,
|
|
79
|
+
`Rules: ${rulesPath}`,
|
|
80
|
+
`Provider requested: ${planResult.providerRequested}`,
|
|
81
|
+
`Provider used: ${planResult.providerUsed}`,
|
|
82
|
+
`Templates: ${plan.templateIds.length > 0 ? plan.templateIds.join(", ") : "(none)"}`,
|
|
83
|
+
`Generated rules: ${plan.beforeBuiltins.length + plan.afterBuiltins.length}`,
|
|
84
|
+
"Preview mode: no files were written.",
|
|
85
|
+
];
|
|
86
|
+
if (plan.notes.length > 0) {
|
|
87
|
+
lines.push(`Notes: ${plan.notes.length}`);
|
|
88
|
+
lines.push(...plan.notes.map((note) => `- ${note}`));
|
|
89
|
+
}
|
|
90
|
+
if (options.installSchedule) {
|
|
91
|
+
lines.push("Schedule install: requested, but skipped in preview mode.");
|
|
92
|
+
}
|
|
93
|
+
if (options.update) {
|
|
94
|
+
lines.push("Live update: requested, but skipped in preview mode.");
|
|
95
|
+
}
|
|
96
|
+
lines.push("");
|
|
97
|
+
lines.push("Rules diff:");
|
|
98
|
+
lines.push(preview.rulesDiff.diff);
|
|
99
|
+
lines.push("");
|
|
100
|
+
lines.push("Builder config diff:");
|
|
101
|
+
lines.push(preview.configDiff.diff);
|
|
102
|
+
if (preview.stagingDiff) {
|
|
103
|
+
lines.push("");
|
|
104
|
+
lines.push("Staging config diff:");
|
|
105
|
+
lines.push(preview.stagingDiff.diff);
|
|
106
|
+
}
|
|
107
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
await writeGeneratedRules({
|
|
111
|
+
filePath: rulesPath,
|
|
112
|
+
plan,
|
|
113
|
+
});
|
|
114
|
+
await updateBuilderAuthoring({
|
|
115
|
+
configPath,
|
|
116
|
+
rulesPath,
|
|
117
|
+
...(plan.scheduleIntervalMinutes ? { intervalMinutes: plan.scheduleIntervalMinutes } : {}),
|
|
118
|
+
...(plan.groupDefaults ? { groupDefaults: plan.groupDefaults } : {}),
|
|
119
|
+
...(plan.verificationOverrides
|
|
120
|
+
? { verificationOverrides: plan.verificationOverrides }
|
|
121
|
+
: {}),
|
|
122
|
+
});
|
|
123
|
+
const lines = [
|
|
124
|
+
`Config: ${configPath}`,
|
|
125
|
+
`Rules: ${rulesPath}`,
|
|
126
|
+
`Provider requested: ${planResult.providerRequested}`,
|
|
127
|
+
`Provider used: ${planResult.providerUsed}`,
|
|
128
|
+
`Templates: ${plan.templateIds.length > 0 ? plan.templateIds.join(", ") : "(none)"}`,
|
|
129
|
+
`Generated rules: ${plan.beforeBuiltins.length + plan.afterBuiltins.length}`,
|
|
130
|
+
];
|
|
131
|
+
if (plan.notes.length > 0) {
|
|
132
|
+
lines.push(`Notes: ${plan.notes.length}`);
|
|
133
|
+
lines.push(...plan.notes.map((note) => `- ${note}`));
|
|
134
|
+
}
|
|
135
|
+
if (options.installSchedule) {
|
|
136
|
+
const intervalMinutes = plan.scheduleIntervalMinutes ?? effectiveConfig.schedule.intervalMinutes;
|
|
137
|
+
const schedule = await installLaunchdSchedule({
|
|
138
|
+
configPath,
|
|
139
|
+
intervalMinutes,
|
|
140
|
+
cliEntrypoint: resolveCliEntrypoint(import.meta.url),
|
|
141
|
+
label: options.label,
|
|
142
|
+
...(options.launchAgentsDir
|
|
143
|
+
? { launchAgentsDir: resolvePath(options.launchAgentsDir) }
|
|
144
|
+
: {}),
|
|
145
|
+
...(options.logsDir ? { logsDir: resolvePath(options.logsDir) } : {}),
|
|
146
|
+
force: options.forceSchedule === true,
|
|
147
|
+
load: options.load !== false,
|
|
148
|
+
});
|
|
149
|
+
lines.push(`LaunchAgent: ${schedule.plistPath}`);
|
|
150
|
+
}
|
|
151
|
+
if (options.update) {
|
|
152
|
+
const updateResult = await runUpdate({
|
|
153
|
+
config: effectiveConfig,
|
|
154
|
+
...(options.subscriptionFile ? { subscriptionFile: options.subscriptionFile } : {}),
|
|
155
|
+
...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
|
|
156
|
+
...(options.livePath ? { livePath: resolvePath(options.livePath) } : {}),
|
|
157
|
+
...(options.backupPath ? { backupPath: resolvePath(options.backupPath) } : {}),
|
|
158
|
+
...(options.singBoxBin ? { singBoxBinary: resolvePath(options.singBoxBin) } : {}),
|
|
159
|
+
...(options.chromeBin ? { chromeBinary: resolvePath(options.chromeBin) } : {}),
|
|
160
|
+
verify: !options.skipVerify,
|
|
161
|
+
...(options.reload ? { reload: true } : {}),
|
|
162
|
+
});
|
|
163
|
+
lines.push(`Staging: ${updateResult.build.outputPath}`);
|
|
164
|
+
lines.push(updateResult.verification
|
|
165
|
+
? `Verified scenarios: ${updateResult.verification.scenarios.filter((scenario) => scenario.passed).length}/${updateResult.verification.scenarios.length}`
|
|
166
|
+
: "Verified scenarios: skipped");
|
|
167
|
+
lines.push(`Live: ${updateResult.livePath}`);
|
|
168
|
+
if (updateResult.backupPath) {
|
|
169
|
+
lines.push(`Backup: ${updateResult.backupPath}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else if (!options.skipBuild) {
|
|
173
|
+
const build = await buildConfigArtifact({
|
|
174
|
+
config: effectiveConfig,
|
|
175
|
+
...(options.subscriptionFile ? { subscriptionFile: options.subscriptionFile } : {}),
|
|
176
|
+
...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
|
|
177
|
+
});
|
|
178
|
+
lines.push(`Staging: ${build.outputPath}`);
|
|
179
|
+
}
|
|
180
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function resolvePath(filePath) {
|
|
184
|
+
return filePath.startsWith("/") ? filePath : path.resolve(process.cwd(), filePath);
|
|
185
|
+
}
|
|
186
|
+
function resolveCliEntrypoint(moduleUrl) {
|
|
187
|
+
const commandModulePath = fileURLToPath(moduleUrl);
|
|
188
|
+
const extension = path.extname(commandModulePath);
|
|
189
|
+
return path.resolve(path.dirname(commandModulePath), "..", `index${extension}`);
|
|
190
|
+
}
|
|
191
|
+
function collectOption(value, previous) {
|
|
192
|
+
return [...previous, value];
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=author.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author.js","sourceRoot":"","sources":["../../../src/cli/commands/author.ts"],"names":[],"mappings":"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"}
|