@singbox-iac/cli 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -24
- package/dist/cli/commands/author.d.ts +2 -0
- package/dist/cli/commands/author.js +49 -19
- package/dist/cli/commands/author.js.map +1 -1
- package/dist/cli/commands/build.js +25 -13
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/diagnose.d.ts +2 -0
- package/dist/cli/commands/diagnose.js +120 -0
- package/dist/cli/commands/diagnose.js.map +1 -0
- package/dist/cli/commands/doctor.js +21 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/restart.js +42 -2
- package/dist/cli/commands/restart.js.map +1 -1
- package/dist/cli/commands/rulesets.d.ts +2 -0
- package/dist/cli/commands/rulesets.js +125 -0
- package/dist/cli/commands/rulesets.js.map +1 -0
- package/dist/cli/commands/runtime-watchdog.d.ts +2 -0
- package/dist/cli/commands/runtime-watchdog.js +45 -0
- package/dist/cli/commands/runtime-watchdog.js.map +1 -0
- package/dist/cli/commands/setup.js +190 -20
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/start.js +29 -1
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.js +135 -28
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/stop.js +19 -1
- package/dist/cli/commands/stop.js.map +1 -1
- package/dist/cli/commands/use.js +3 -1
- package/dist/cli/commands/use.js.map +1 -1
- package/dist/cli/index.js +12 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/config/schema.d.ts +49 -6
- package/dist/config/schema.js +17 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/modules/authoring/index.js +25 -8
- package/dist/modules/authoring/index.js.map +1 -1
- package/dist/modules/build/index.d.ts +4 -1
- package/dist/modules/build/index.js +17 -4
- package/dist/modules/build/index.js.map +1 -1
- package/dist/modules/bundle-registry/index.d.ts +46 -0
- package/dist/modules/bundle-registry/index.js +650 -0
- package/dist/modules/bundle-registry/index.js.map +1 -0
- package/dist/modules/desktop-runtime/index.d.ts +11 -0
- package/dist/modules/desktop-runtime/index.js +41 -0
- package/dist/modules/desktop-runtime/index.js.map +1 -1
- package/dist/modules/diagnostics/index.d.ts +28 -0
- package/dist/modules/diagnostics/index.js +288 -0
- package/dist/modules/diagnostics/index.js.map +1 -0
- package/dist/modules/layered-authoring/index.d.ts +45 -0
- package/dist/modules/layered-authoring/index.js +549 -0
- package/dist/modules/layered-authoring/index.js.map +1 -0
- package/dist/modules/natural-language/index.d.ts +6 -3
- package/dist/modules/natural-language/index.js +74 -69
- package/dist/modules/natural-language/index.js.map +1 -1
- package/dist/modules/proxifier/index.d.ts +1 -14
- package/dist/modules/proxifier/index.js +10 -139
- package/dist/modules/proxifier/index.js.map +1 -1
- package/dist/modules/rule-set-catalog/index.d.ts +25 -0
- package/dist/modules/rule-set-catalog/index.js +135 -0
- package/dist/modules/rule-set-catalog/index.js.map +1 -0
- package/dist/modules/runtime-watchdog/index.d.ts +73 -0
- package/dist/modules/runtime-watchdog/index.js +532 -0
- package/dist/modules/runtime-watchdog/index.js.map +1 -0
- package/dist/modules/status/index.d.ts +48 -0
- package/dist/modules/status/index.js +254 -23
- package/dist/modules/status/index.js.map +1 -1
- package/dist/modules/system-proxy/index.d.ts +31 -0
- package/dist/modules/system-proxy/index.js +164 -0
- package/dist/modules/system-proxy/index.js.map +1 -0
- package/docs/agent-context.md +131 -0
- package/docs/natural-language-authoring.md +106 -1
- package/docs/proxifier-onboarding.md +15 -4
- package/docs/rule-templates.md +2 -0
- package/docs/runtime-modes.md +84 -0
- package/docs/runtime-on-macos.md +53 -4
- package/examples/builder.config.yaml +60 -0
- package/package.json +3 -2
- package/dist/cli/commands/quickstart.d.ts +0 -2
- package/dist/cli/commands/quickstart.js +0 -54
- package/dist/cli/commands/quickstart.js.map +0 -1
|
@@ -35,7 +35,7 @@ export function registerDoctorCommand(program) {
|
|
|
35
35
|
: {}),
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
process.stdout.write(
|
|
38
|
+
process.stdout.write(renderDoctorOutput(report, configPath));
|
|
39
39
|
if (report.checks.some((check) => check.status === "FAIL")) {
|
|
40
40
|
throw new Error("Doctor found blocking failures.");
|
|
41
41
|
}
|
|
@@ -44,4 +44,24 @@ export function registerDoctorCommand(program) {
|
|
|
44
44
|
function pathResolve(filePath) {
|
|
45
45
|
return filePath.startsWith("/") ? filePath : path.resolve(process.cwd(), filePath);
|
|
46
46
|
}
|
|
47
|
+
function renderDoctorOutput(report, configPath) {
|
|
48
|
+
const lines = [
|
|
49
|
+
"Readiness check: environment and config prerequisites for singbox-iac.",
|
|
50
|
+
"",
|
|
51
|
+
...renderSection("Context", [`config: ${configPath ?? "(missing)"}`]),
|
|
52
|
+
"",
|
|
53
|
+
...renderSection("Checks", report.checks.map((check) => `[${check.status}] ${check.name}: ${check.details}`)),
|
|
54
|
+
"",
|
|
55
|
+
...renderSection("Result", [formatDoctorResult(report.checks)]),
|
|
56
|
+
];
|
|
57
|
+
return `${lines.join("\n")}\n`;
|
|
58
|
+
}
|
|
59
|
+
function formatDoctorResult(checks) {
|
|
60
|
+
return checks.some((check) => check.status === "FAIL")
|
|
61
|
+
? "blocking-failures: yes"
|
|
62
|
+
: "blocking-failures: no";
|
|
63
|
+
}
|
|
64
|
+
function renderSection(title, items) {
|
|
65
|
+
return [`${title}:`, ...items.map((item) => `- ${item}`)];
|
|
66
|
+
}
|
|
47
67
|
//# sourceMappingURL=doctor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { installDesktopRuntimeAgent, removeDesktopRuntimeAgent, restartDesktopRuntimeAgent, } from "../../modules/desktop-runtime/index.js";
|
|
3
3
|
import { checkConfig, resolveSingBoxBinary } from "../../modules/manager/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import { installRuntimeWatchdogAgent, removeRuntimeWatchdogAgent, } from "../../modules/runtime-watchdog/index.js";
|
|
5
|
+
import { findDefaultConfigPath, resolveBuilderConfig, resolveCliEntrypoint, } from "../command-helpers.js";
|
|
5
6
|
export function registerRestartCommand(program) {
|
|
6
7
|
program
|
|
7
8
|
.command("restart")
|
|
@@ -14,13 +15,20 @@ export function registerRestartCommand(program) {
|
|
|
14
15
|
.option("--no-load", "write the runtime LaunchAgent without calling launchctl bootstrap")
|
|
15
16
|
.action(async (options) => {
|
|
16
17
|
const builderConfig = await resolveBuilderConfig(options);
|
|
18
|
+
const configPath = options.config
|
|
19
|
+
? resolvePath(options.config)
|
|
20
|
+
: await findDefaultConfigPath();
|
|
17
21
|
if (!builderConfig) {
|
|
18
22
|
throw new Error("Restart requires a builder config. Run `singbox-iac go` first.");
|
|
19
23
|
}
|
|
24
|
+
if (!configPath) {
|
|
25
|
+
throw new Error("Restart requires a builder config path.");
|
|
26
|
+
}
|
|
20
27
|
if (builderConfig.runtime.desktop.profile === "none") {
|
|
21
28
|
throw new Error("Desktop runtime profile is disabled in this config. Re-run onboarding or set runtime.desktop.profile first.");
|
|
22
29
|
}
|
|
23
30
|
const label = options.label ?? builderConfig.runtime.desktop.launchAgentLabel;
|
|
31
|
+
const watchdogLabel = builderConfig.runtime.desktop.watchdog.launchAgentLabel;
|
|
24
32
|
const singBoxBinary = await resolveSingBoxBinary(options.singBoxBin ? resolvePath(options.singBoxBin) : undefined, builderConfig.runtime.dependencies.singBoxBinary);
|
|
25
33
|
await checkConfig({
|
|
26
34
|
configPath: builderConfig.output.livePath,
|
|
@@ -29,7 +37,9 @@ export function registerRestartCommand(program) {
|
|
|
29
37
|
const hasOverrides = options.singBoxBin !== undefined ||
|
|
30
38
|
options.launchAgentsDir !== undefined ||
|
|
31
39
|
options.logsDir !== undefined;
|
|
32
|
-
|
|
40
|
+
const needsWatchdogLifecycle = builderConfig.runtime.desktop.profile === "system-proxy" &&
|
|
41
|
+
builderConfig.runtime.desktop.watchdog.enabled;
|
|
42
|
+
if (options.load !== false && !hasOverrides && !needsWatchdogLifecycle) {
|
|
33
43
|
try {
|
|
34
44
|
await restartDesktopRuntimeAgent({ label });
|
|
35
45
|
process.stdout.write(`${[
|
|
@@ -50,6 +60,15 @@ export function registerRestartCommand(program) {
|
|
|
50
60
|
? { launchAgentsDir: resolvePath(options.launchAgentsDir) }
|
|
51
61
|
: {}),
|
|
52
62
|
});
|
|
63
|
+
if (builderConfig.runtime.desktop.profile === "system-proxy" &&
|
|
64
|
+
builderConfig.runtime.desktop.watchdog.enabled) {
|
|
65
|
+
await removeRuntimeWatchdogAgent({
|
|
66
|
+
label: watchdogLabel,
|
|
67
|
+
...(options.launchAgentsDir
|
|
68
|
+
? { launchAgentsDir: resolvePath(options.launchAgentsDir) }
|
|
69
|
+
: {}),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
53
72
|
const result = await installDesktopRuntimeAgent({
|
|
54
73
|
liveConfigPath: builderConfig.output.livePath,
|
|
55
74
|
singBoxBinary,
|
|
@@ -61,11 +80,32 @@ export function registerRestartCommand(program) {
|
|
|
61
80
|
force: true,
|
|
62
81
|
load: options.load !== false,
|
|
63
82
|
});
|
|
83
|
+
const watchdogResult = builderConfig.runtime.desktop.profile === "system-proxy" &&
|
|
84
|
+
builderConfig.runtime.desktop.watchdog.enabled
|
|
85
|
+
? await installRuntimeWatchdogAgent({
|
|
86
|
+
configPath,
|
|
87
|
+
cliEntrypoint: resolveCliEntrypoint(import.meta.url),
|
|
88
|
+
intervalSeconds: builderConfig.runtime.desktop.watchdog.intervalSeconds,
|
|
89
|
+
label: watchdogLabel,
|
|
90
|
+
...(options.launchAgentsDir
|
|
91
|
+
? { launchAgentsDir: resolvePath(options.launchAgentsDir) }
|
|
92
|
+
: {}),
|
|
93
|
+
...(options.logsDir ? { logsDir: resolvePath(options.logsDir) } : {}),
|
|
94
|
+
force: true,
|
|
95
|
+
load: options.load !== false,
|
|
96
|
+
})
|
|
97
|
+
: undefined;
|
|
64
98
|
process.stdout.write(`${[
|
|
65
99
|
`Restarted desktop runtime profile: ${builderConfig.runtime.desktop.profile}`,
|
|
66
100
|
`Label: ${result.label}`,
|
|
67
101
|
`Live config: ${builderConfig.output.livePath}`,
|
|
68
102
|
`LaunchAgent: ${result.plistPath}`,
|
|
103
|
+
...(watchdogResult
|
|
104
|
+
? [
|
|
105
|
+
`Watchdog: ${watchdogResult.label}`,
|
|
106
|
+
`Watchdog LaunchAgent: ${watchdogResult.plistPath}`,
|
|
107
|
+
]
|
|
108
|
+
: []),
|
|
69
109
|
].join("\n")}\n`);
|
|
70
110
|
});
|
|
71
111
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../src/cli/commands/restart.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,
|
|
1
|
+
{"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../src/cli/commands/restart.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { listBuiltInPreferredSiteRuleSetTags, listSiteBundles, } from "../../modules/bundle-registry/index.js";
|
|
2
|
+
import { defaultOfficialRuleSetCatalogCachePath, loadOfficialRuleSetCatalog, } from "../../modules/rule-set-catalog/index.js";
|
|
3
|
+
import { findDefaultConfigPath, resolveBuilderConfig } from "../command-helpers.js";
|
|
4
|
+
export function registerRuleSetsCommand(program) {
|
|
5
|
+
const root = program
|
|
6
|
+
.command("rulesets")
|
|
7
|
+
.description("Inspect configured and official sing-box rule-set tags.");
|
|
8
|
+
root
|
|
9
|
+
.command("list")
|
|
10
|
+
.description("Show configured rule sets and refreshable official upstream tags.")
|
|
11
|
+
.option("-c, --config <path>", "path to builder config YAML")
|
|
12
|
+
.option("--refresh", "refresh the official upstream catalog before printing")
|
|
13
|
+
.option("--filter <text>", "only show official tags containing this text")
|
|
14
|
+
.option("--kind <kind>", "filter official tags by kind: geosite, geoip, or all", "all")
|
|
15
|
+
.option("--all", "print all matching official tags in human-readable output")
|
|
16
|
+
.option("--json", "print the full machine-readable report")
|
|
17
|
+
.action(async (options) => {
|
|
18
|
+
const configPath = options.config ?? (await findDefaultConfigPath());
|
|
19
|
+
const config = configPath ? await resolveBuilderConfig({ config: configPath }) : undefined;
|
|
20
|
+
const catalog = await loadOfficialRuleSetCatalog({
|
|
21
|
+
refresh: options.refresh === true,
|
|
22
|
+
cachePath: defaultOfficialRuleSetCatalogCachePath(),
|
|
23
|
+
});
|
|
24
|
+
const configuredTags = [...(config?.ruleSets.map((ruleSet) => ruleSet.tag) ?? [])].sort();
|
|
25
|
+
const configuredTagSet = new Set(configuredTags);
|
|
26
|
+
const filter = options.filter?.toLowerCase().trim();
|
|
27
|
+
const selectedKinds = normalizeKinds(options.kind);
|
|
28
|
+
const geositeTags = filterOfficialTags(catalog.geositeTags, selectedKinds.has("geosite"), filter);
|
|
29
|
+
const geoipTags = filterOfficialTags(catalog.geoipTags, selectedKinds.has("geoip"), filter);
|
|
30
|
+
const builtInBundleCoverage = listSiteBundles()
|
|
31
|
+
.map((bundle) => {
|
|
32
|
+
const preferredRuleSetTags = [...(bundle.preferredRuleSetTags ?? [])];
|
|
33
|
+
return {
|
|
34
|
+
id: bundle.id,
|
|
35
|
+
name: bundle.name,
|
|
36
|
+
preferredRuleSetTags,
|
|
37
|
+
activeRuleSetTags: preferredRuleSetTags.filter((tag) => configuredTagSet.has(tag)),
|
|
38
|
+
usingFallback: preferredRuleSetTags.every((tag) => !configuredTagSet.has(tag)),
|
|
39
|
+
};
|
|
40
|
+
})
|
|
41
|
+
.filter((bundle) => bundle.preferredRuleSetTags.length > 0 ||
|
|
42
|
+
(filter
|
|
43
|
+
? bundle.id.includes(filter) || bundle.name.toLowerCase().includes(filter)
|
|
44
|
+
: true));
|
|
45
|
+
if (options.json === true) {
|
|
46
|
+
process.stdout.write(`${JSON.stringify({
|
|
47
|
+
configPath: configPath ?? null,
|
|
48
|
+
configuredTags,
|
|
49
|
+
officialCatalog: {
|
|
50
|
+
cachePath: catalog.cachePath,
|
|
51
|
+
source: catalog.source,
|
|
52
|
+
refreshedAt: catalog.refreshedAt,
|
|
53
|
+
geositeRef: catalog.geositeRef,
|
|
54
|
+
geoipRef: catalog.geoipRef,
|
|
55
|
+
geositeTags,
|
|
56
|
+
geoipTags,
|
|
57
|
+
},
|
|
58
|
+
builtInSiteBundleCoverage: builtInBundleCoverage,
|
|
59
|
+
builtInPreferredRuleSetTags: listBuiltInPreferredSiteRuleSetTags(),
|
|
60
|
+
}, null, 2)}\n`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const lines = [
|
|
64
|
+
"Rule-set inventory: configured tags plus official upstream geosite/geoip catalog.",
|
|
65
|
+
"",
|
|
66
|
+
"Context",
|
|
67
|
+
`- builder-config: ${configPath ?? "(none)"}`,
|
|
68
|
+
`- cache: ${catalog.cachePath}`,
|
|
69
|
+
`- catalog-source: ${catalog.source}`,
|
|
70
|
+
`- refreshed-at: ${catalog.refreshedAt}`,
|
|
71
|
+
`- upstream-geosite-ref: ${catalog.geositeRef}`,
|
|
72
|
+
`- upstream-geoip-ref: ${catalog.geoipRef}`,
|
|
73
|
+
"",
|
|
74
|
+
"Configured",
|
|
75
|
+
`- count: ${configuredTags.length}`,
|
|
76
|
+
`- tags: ${configuredTags.length > 0 ? configuredTags.join(", ") : "(none)"}`,
|
|
77
|
+
"",
|
|
78
|
+
"Built-In Site Bundle Coverage",
|
|
79
|
+
];
|
|
80
|
+
if (builtInBundleCoverage.length === 0) {
|
|
81
|
+
lines.push("- bundles: (none)");
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
for (const bundle of builtInBundleCoverage) {
|
|
85
|
+
lines.push(`- ${bundle.name}: preferred=${bundle.preferredRuleSetTags.join(", ")}; active=${bundle.activeRuleSetTags.length > 0 ? bundle.activeRuleSetTags.join(", ") : "(none)"}; mode=${bundle.usingFallback ? "fallback" : "rule-set"}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
lines.push("", "Official Catalog", `- geosite-count: ${geositeTags.length}`, `- geoip-count: ${geoipTags.length}`);
|
|
89
|
+
if (filter) {
|
|
90
|
+
lines.push(`- filter: ${filter}`);
|
|
91
|
+
}
|
|
92
|
+
if (options.all === true || filter) {
|
|
93
|
+
if (geositeTags.length > 0) {
|
|
94
|
+
lines.push(`- geosite-tags: ${geositeTags.join(", ")}`);
|
|
95
|
+
}
|
|
96
|
+
if (geoipTags.length > 0) {
|
|
97
|
+
lines.push(`- geoip-tags: ${geoipTags.join(", ")}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
lines.push("- official-tags: use --all or --filter <text> to inspect individual upstream tags");
|
|
102
|
+
}
|
|
103
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function normalizeKinds(kind) {
|
|
107
|
+
const normalized = kind.toLowerCase();
|
|
108
|
+
if (normalized === "geosite") {
|
|
109
|
+
return new Set(["geosite"]);
|
|
110
|
+
}
|
|
111
|
+
if (normalized === "geoip") {
|
|
112
|
+
return new Set(["geoip"]);
|
|
113
|
+
}
|
|
114
|
+
return new Set(["geosite", "geoip"]);
|
|
115
|
+
}
|
|
116
|
+
function filterOfficialTags(tags, enabled, filter) {
|
|
117
|
+
if (!enabled) {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
if (!filter) {
|
|
121
|
+
return tags;
|
|
122
|
+
}
|
|
123
|
+
return tags.filter((tag) => tag.toLowerCase().includes(filter));
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=rulesets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rulesets.js","sourceRoot":"","sources":["../../../src/cli/commands/rulesets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { loadConfig } from "../../config/load-config.js";
|
|
3
|
+
import { runRuntimeWatchdogTick } from "../../modules/runtime-watchdog/index.js";
|
|
4
|
+
import { findDefaultConfigPath } from "../command-helpers.js";
|
|
5
|
+
export function registerRuntimeWatchdogCommand(program) {
|
|
6
|
+
program
|
|
7
|
+
.command("runtime-watchdog")
|
|
8
|
+
.description("Internal command used by the desktop runtime watchdog LaunchAgent.")
|
|
9
|
+
.option("-c, --config <path>", "path to builder config YAML")
|
|
10
|
+
.option("--json", "print machine-readable JSON")
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
const configPath = options.config
|
|
13
|
+
? resolvePath(options.config)
|
|
14
|
+
: await findDefaultConfigPath();
|
|
15
|
+
if (!configPath) {
|
|
16
|
+
throw new Error("runtime-watchdog requires a builder config path.");
|
|
17
|
+
}
|
|
18
|
+
const config = await loadConfig(configPath);
|
|
19
|
+
const result = await runRuntimeWatchdogTick({
|
|
20
|
+
config,
|
|
21
|
+
configPath,
|
|
22
|
+
});
|
|
23
|
+
if (options.json) {
|
|
24
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
process.stdout.write(`${[
|
|
28
|
+
`Watchdog label: ${config.runtime.desktop.watchdog.launchAgentLabel}`,
|
|
29
|
+
`Result: ${result.state.lastResult}`,
|
|
30
|
+
...(result.state.lastRecoveryAction
|
|
31
|
+
? [`Recovery action: ${result.state.lastRecoveryAction}`]
|
|
32
|
+
: []),
|
|
33
|
+
...(result.state.lastTrigger ? [`Trigger: ${result.state.lastTrigger}`] : []),
|
|
34
|
+
`Recorded: ${result.state.lastCheckedAt}`,
|
|
35
|
+
`Message: ${result.state.lastMessage}`,
|
|
36
|
+
...(result.state.lastReassertAt ? [`Last reassert: ${result.state.lastReassertAt}`] : []),
|
|
37
|
+
...(result.state.lastRestartAt ? [`Last restart: ${result.state.lastRestartAt}`] : []),
|
|
38
|
+
...(result.state.lastError ? [`Error: ${result.state.lastError}`] : []),
|
|
39
|
+
].join("\n")}\n`);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function resolvePath(filePath) {
|
|
43
|
+
return filePath.startsWith("/") ? filePath : path.resolve(process.cwd(), filePath);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=runtime-watchdog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-watchdog.js","sourceRoot":"","sources":["../../../src/cli/commands/runtime-watchdog.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,UAAU,8BAA8B,CAAC,OAAgB;IAC7D,OAAO;SACJ,OAAO,CAAC,kBAAkB,CAAC;SAC3B,WAAW,CAAC,oEAAoE,CAAC;SACjF,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;SAC5D,MAAM,CAAC,QAAQ,EAAE,6BAA6B,CAAC;SAC/C,MAAM,CAAC,KAAK,EAAE,OAAsC,EAAE,EAAE;QACvD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM;YAC/B,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;YAC7B,CAAC,CAAC,MAAM,qBAAqB,EAAE,CAAC;QAClC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC;YAC1C,MAAM;YACN,UAAU;SACX,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG;YACD,mBAAmB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,EAAE;YACrE,WAAW,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE;YACpC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB;gBACjC,CAAC,CAAC,CAAC,oBAAoB,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC;gBACzD,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,YAAY,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7E,aAAa,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE;YACzC,YAAY,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE;YACtC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzF,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,iBAAiB,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SACxE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CACjB,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAOD,SAAS,WAAW,CAAC,QAAgB;IACnC,OAAO,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;AACrF,CAAC"}
|
|
@@ -9,6 +9,7 @@ import { buildConfigArtifact, resolveEffectiveIntent } from "../../modules/build
|
|
|
9
9
|
import { updateBuilderDesktopRuntime } from "../../modules/desktop-runtime/index.js";
|
|
10
10
|
import { runDoctor } from "../../modules/doctor/index.js";
|
|
11
11
|
import { initWorkspace } from "../../modules/init/index.js";
|
|
12
|
+
import { applyLayeredAuthoringUpdate, materializeLayeredAuthoringState, resolveLayeredAuthoringPath, resolveLayeredAuthoringState, writeLayeredAuthoringState, } from "../../modules/layered-authoring/index.js";
|
|
12
13
|
import { applyConfig, checkConfig, resolveSingBoxBinary } from "../../modules/manager/index.js";
|
|
13
14
|
import { applyPlanToBuilderConfig, selectVerificationScenariosForPrompt, updateBuilderAuthoring, writeGeneratedRules, } from "../../modules/natural-language/index.js";
|
|
14
15
|
import { selectProxifierBundlesFromPrompt, writeProxifierScaffold, } from "../../modules/proxifier/index.js";
|
|
@@ -92,23 +93,44 @@ export async function runSetupFlow(options) {
|
|
|
92
93
|
...(options.execCommand ? { execCommand: options.execCommand } : {}),
|
|
93
94
|
...(options.execArg.length > 0 ? { execArgs: options.execArg } : {}),
|
|
94
95
|
});
|
|
96
|
+
const currentLayeredState = await resolveLayeredAuthoringState({
|
|
97
|
+
config: builderConfig,
|
|
98
|
+
});
|
|
99
|
+
const nextLayeredState = applyLayeredAuthoringUpdate({
|
|
100
|
+
current: currentLayeredState.state,
|
|
101
|
+
prompt: options.prompt,
|
|
102
|
+
plan: planResult.plan,
|
|
103
|
+
mode: "replace",
|
|
104
|
+
appliedAt: new Date().toISOString(),
|
|
105
|
+
});
|
|
106
|
+
const nextResolvedLayeredState = materializeLayeredAuthoringState({
|
|
107
|
+
filePath: resolveLayeredAuthoringPath(builderConfig.rules.userRulesFile),
|
|
108
|
+
exists: true,
|
|
109
|
+
state: nextLayeredState,
|
|
110
|
+
});
|
|
95
111
|
effectiveConfig = applyPlanToBuilderConfig(builderConfig, {
|
|
96
112
|
rulesPath: builderConfig.rules.userRulesFile,
|
|
97
|
-
plan:
|
|
113
|
+
plan: nextResolvedLayeredState.mergedPlan,
|
|
98
114
|
});
|
|
99
115
|
await writeGeneratedRules({
|
|
100
116
|
filePath: effectiveConfig.rules.userRulesFile,
|
|
101
|
-
plan:
|
|
117
|
+
plan: nextResolvedLayeredState.mergedPlan,
|
|
118
|
+
});
|
|
119
|
+
await writeLayeredAuthoringState({
|
|
120
|
+
rulesPath: effectiveConfig.rules.userRulesFile,
|
|
121
|
+
state: nextLayeredState,
|
|
102
122
|
});
|
|
103
123
|
await updateBuilderAuthoring({
|
|
104
124
|
configPath,
|
|
105
125
|
rulesPath: effectiveConfig.rules.userRulesFile,
|
|
106
|
-
...(
|
|
107
|
-
? { intervalMinutes:
|
|
126
|
+
...(nextResolvedLayeredState.mergedPlan.scheduleIntervalMinutes
|
|
127
|
+
? { intervalMinutes: nextResolvedLayeredState.mergedPlan.scheduleIntervalMinutes }
|
|
108
128
|
: {}),
|
|
109
|
-
...(
|
|
110
|
-
|
|
111
|
-
|
|
129
|
+
...(nextResolvedLayeredState.mergedPlan.groupDefaults
|
|
130
|
+
? { groupDefaults: nextResolvedLayeredState.mergedPlan.groupDefaults }
|
|
131
|
+
: {}),
|
|
132
|
+
...(nextResolvedLayeredState.mergedPlan.verificationOverrides
|
|
133
|
+
? { verificationOverrides: nextResolvedLayeredState.mergedPlan.verificationOverrides }
|
|
112
134
|
: {}),
|
|
113
135
|
});
|
|
114
136
|
builderConfig = await loadConfig(configPath);
|
|
@@ -116,9 +138,13 @@ export async function runSetupFlow(options) {
|
|
|
116
138
|
planSummary = {
|
|
117
139
|
providerRequested: planResult.providerRequested,
|
|
118
140
|
providerUsed: planResult.providerUsed,
|
|
119
|
-
templates:
|
|
120
|
-
generatedRules:
|
|
121
|
-
|
|
141
|
+
templates: nextResolvedLayeredState.mergedPlan.templateIds,
|
|
142
|
+
generatedRules: nextResolvedLayeredState.mergedPlan.beforeBuiltins.length +
|
|
143
|
+
nextResolvedLayeredState.mergedPlan.afterBuiltins.length,
|
|
144
|
+
notes: nextResolvedLayeredState.mergedPlan.notes,
|
|
145
|
+
intent: nextResolvedLayeredState.mergedIntent,
|
|
146
|
+
ambiguities: planResult.ambiguities,
|
|
147
|
+
groupDefaults: nextResolvedLayeredState.mergedPlan.groupDefaults ?? {},
|
|
122
148
|
};
|
|
123
149
|
}
|
|
124
150
|
const lines = [`Config: ${configPath}`, `Rules: ${effectiveConfig.rules.userRulesFile}`];
|
|
@@ -190,13 +216,7 @@ export async function runSetupFlow(options) {
|
|
|
190
216
|
lines.push(...formatDoctorSummary(doctorReport));
|
|
191
217
|
}
|
|
192
218
|
if (planSummary) {
|
|
193
|
-
lines.push(
|
|
194
|
-
lines.push(`Provider used: ${planSummary.providerUsed}`);
|
|
195
|
-
lines.push(`Templates: ${planSummary.templates.length > 0 ? planSummary.templates.join(", ") : "(none)"}`);
|
|
196
|
-
lines.push(`Generated rules: ${planSummary.generatedRules}`);
|
|
197
|
-
if (planSummary.notes.length > 0) {
|
|
198
|
-
lines.push(...planSummary.notes.map((note) => `- ${note}`));
|
|
199
|
-
}
|
|
219
|
+
lines.push(...formatIntentSummary(planSummary));
|
|
200
220
|
}
|
|
201
221
|
const selectedProxifierBundles = options.prompt
|
|
202
222
|
? selectProxifierBundlesFromPrompt(options.prompt)
|
|
@@ -290,7 +310,7 @@ export async function runSetupFlow(options) {
|
|
|
290
310
|
configuredScenarios: effectiveConfig.verification.scenarios,
|
|
291
311
|
});
|
|
292
312
|
assertVerificationReportPassed(verification);
|
|
293
|
-
lines.push(
|
|
313
|
+
lines.push(...formatVerificationSummary(verification));
|
|
294
314
|
}
|
|
295
315
|
if (shouldApply) {
|
|
296
316
|
await applyConfig({
|
|
@@ -345,6 +365,9 @@ export async function runSetupFlow(options) {
|
|
|
345
365
|
lines.push(`LaunchAgent: ${schedule.plistPath}`);
|
|
346
366
|
}
|
|
347
367
|
lines.push(`Proxy ports: mixed ${effectiveConfig.listeners.mixed.listen}:${effectiveConfig.listeners.mixed.port}, proxifier ${effectiveConfig.listeners.proxifier.listen}:${effectiveConfig.listeners.proxifier.port}`);
|
|
368
|
+
if (!shouldRun) {
|
|
369
|
+
lines.push("Runtime: not started (--no-run).");
|
|
370
|
+
}
|
|
348
371
|
if (shouldApply) {
|
|
349
372
|
lines.push(desktopRuntimeProfile === "none"
|
|
350
373
|
? "Next: sing-box run -c ~/.config/sing-box/config.json"
|
|
@@ -360,7 +383,7 @@ export async function runSetupFlow(options) {
|
|
|
360
383
|
lines.push("Next: singbox-iac run");
|
|
361
384
|
lines.push("Next: singbox-iac update --reload");
|
|
362
385
|
}
|
|
363
|
-
process.stdout.write(`${lines
|
|
386
|
+
process.stdout.write(`${renderCliSummary(lines)}\n`);
|
|
364
387
|
if (!shouldRun || !buildSummary) {
|
|
365
388
|
return;
|
|
366
389
|
}
|
|
@@ -387,7 +410,9 @@ export async function runSetupFlow(options) {
|
|
|
387
410
|
if (shouldOpenBrowser) {
|
|
388
411
|
const runtimeScenarios = selectVerificationScenariosForRuntimeMode(runtimeMode, effectiveConfig.verification.scenarios);
|
|
389
412
|
const selectedScenarios = options.prompt
|
|
390
|
-
? selectVerificationScenariosForPrompt(options.prompt, runtimeScenarios
|
|
413
|
+
? selectVerificationScenariosForPrompt(options.prompt, runtimeScenarios, {
|
|
414
|
+
activeRuleSetTags: effectiveConfig.ruleSets.map((ruleSet) => ruleSet.tag),
|
|
415
|
+
})
|
|
391
416
|
: runtimeScenarios.slice(0, Math.min(runtimeModeDefaults.visibleBrowserScenarioLimit, runtimeScenarios.length));
|
|
392
417
|
const visibleScenarios = selectedScenarios.map((scenario) => ({
|
|
393
418
|
id: scenario.id,
|
|
@@ -441,6 +466,151 @@ function formatDoctorSummary(report) {
|
|
|
441
466
|
}
|
|
442
467
|
return lines;
|
|
443
468
|
}
|
|
469
|
+
function formatIntentSummary(planSummary) {
|
|
470
|
+
const lines = [
|
|
471
|
+
`Intent: provider ${planSummary.providerUsed}${planSummary.providerUsed !== planSummary.providerRequested ? ` (requested ${planSummary.providerRequested})` : ""}`,
|
|
472
|
+
];
|
|
473
|
+
if (planSummary.templates.length > 0) {
|
|
474
|
+
lines.push(`Intent templates: ${planSummary.templates.join(", ")}`);
|
|
475
|
+
}
|
|
476
|
+
const strategyLines = [
|
|
477
|
+
...formatProcessPolicies(planSummary.intent),
|
|
478
|
+
...formatSitePolicies(planSummary.intent.sitePolicies),
|
|
479
|
+
...formatGroupDefaults(planSummary.groupDefaults),
|
|
480
|
+
];
|
|
481
|
+
if (strategyLines.length > 0) {
|
|
482
|
+
lines.push(`Intent strategies (${strategyLines.length}):`);
|
|
483
|
+
lines.push(...strategyLines.map((line) => `- ${line}`));
|
|
484
|
+
}
|
|
485
|
+
lines.push(`Generated rules: ${planSummary.generatedRules}`);
|
|
486
|
+
if (planSummary.notes.length > 0) {
|
|
487
|
+
lines.push(...planSummary.notes.map((note) => `- ${note}`));
|
|
488
|
+
}
|
|
489
|
+
return lines;
|
|
490
|
+
}
|
|
491
|
+
function formatProcessPolicies(intent) {
|
|
492
|
+
return intent.processPolicies.map((policy) => {
|
|
493
|
+
const target = formatProcessMatchers(policy.match);
|
|
494
|
+
return `${target} -> ${policy.outboundGroup} via ${policy.inbound}`;
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
function formatProcessMatchers(match) {
|
|
498
|
+
const values = [...(match.processName ?? []), ...(match.bundleId ?? [])];
|
|
499
|
+
if (values.length === 0) {
|
|
500
|
+
return "process flow";
|
|
501
|
+
}
|
|
502
|
+
return values.join(", ");
|
|
503
|
+
}
|
|
504
|
+
function formatSitePolicies(sitePolicies) {
|
|
505
|
+
return sitePolicies.slice(0, 8).map((policy) => {
|
|
506
|
+
const matcher = describeSiteMatch(policy);
|
|
507
|
+
if (policy.action.type === "reject") {
|
|
508
|
+
return `${matcher} -> reject`;
|
|
509
|
+
}
|
|
510
|
+
return `${matcher} -> ${policy.action.outboundGroup}`;
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
function describeSiteMatch(policy) {
|
|
514
|
+
if (policy.match.domainSuffix?.length) {
|
|
515
|
+
return policy.match.domainSuffix.join(", ");
|
|
516
|
+
}
|
|
517
|
+
if (policy.match.domain?.length) {
|
|
518
|
+
return policy.match.domain.join(", ");
|
|
519
|
+
}
|
|
520
|
+
if (policy.match.ruleSet?.length) {
|
|
521
|
+
return `rule-set ${policy.match.ruleSet.join(", ")}`;
|
|
522
|
+
}
|
|
523
|
+
if (policy.match.inbound?.length) {
|
|
524
|
+
return `inbound ${policy.match.inbound.join(", ")}`;
|
|
525
|
+
}
|
|
526
|
+
if (policy.match.protocol) {
|
|
527
|
+
return `protocol ${policy.match.protocol}`;
|
|
528
|
+
}
|
|
529
|
+
return policy.name ?? "generated policy";
|
|
530
|
+
}
|
|
531
|
+
function formatGroupDefaults(groupDefaults) {
|
|
532
|
+
const knownGroups = [
|
|
533
|
+
["processProxy", "default Process-Proxy"],
|
|
534
|
+
["aiOut", "default AI-Out"],
|
|
535
|
+
["devCommonOut", "default Dev-Common-Out"],
|
|
536
|
+
["stitchOut", "default Stitch-Out"],
|
|
537
|
+
];
|
|
538
|
+
const lines = [];
|
|
539
|
+
for (const [key, label] of knownGroups) {
|
|
540
|
+
const override = groupDefaults[key];
|
|
541
|
+
if (!override || typeof override !== "object" || Array.isArray(override)) {
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
const record = override;
|
|
545
|
+
if (!record.defaultTarget && !record.defaultNodePattern) {
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
lines.push(`${label} -> ${record.defaultTarget ?? "(unchanged)"}${record.defaultNodePattern ? ` (pattern ${record.defaultNodePattern})` : ""}`);
|
|
549
|
+
}
|
|
550
|
+
return lines;
|
|
551
|
+
}
|
|
552
|
+
function formatVerificationSummary(report) {
|
|
553
|
+
const passed = report.scenarios.filter((scenario) => scenario.passed).length;
|
|
554
|
+
const lines = [`Verified scenarios: ${passed}/${report.scenarios.length}`];
|
|
555
|
+
lines.push(...report.scenarios.map((scenario) => formatVerificationScenario(scenario)));
|
|
556
|
+
return lines;
|
|
557
|
+
}
|
|
558
|
+
function formatVerificationScenario(scenario) {
|
|
559
|
+
const status = scenario.passed ? "PASS" : "FAIL";
|
|
560
|
+
return `- [${status}] ${scenario.name} -> ${scenario.expectedOutboundTag} via ${scenario.inboundTag}`;
|
|
561
|
+
}
|
|
562
|
+
function renderCliSummary(lines) {
|
|
563
|
+
const ansi = createAnsiStyler();
|
|
564
|
+
return lines
|
|
565
|
+
.map((line) => {
|
|
566
|
+
if (line.startsWith("Config:") || line.startsWith("Rules:")) {
|
|
567
|
+
return ansi.header(line);
|
|
568
|
+
}
|
|
569
|
+
if (line.startsWith("Doctor:")) {
|
|
570
|
+
return ansi.section(line);
|
|
571
|
+
}
|
|
572
|
+
if (line.startsWith("Intent:") || line.startsWith("Intent templates:")) {
|
|
573
|
+
return ansi.section(line);
|
|
574
|
+
}
|
|
575
|
+
if (line.startsWith("Intent strategies") || line.startsWith("Verified scenarios:")) {
|
|
576
|
+
return ansi.section(line);
|
|
577
|
+
}
|
|
578
|
+
if (line.startsWith("- [PASS]")) {
|
|
579
|
+
return ansi.success(line);
|
|
580
|
+
}
|
|
581
|
+
if (line.startsWith("- [WARN]") || line.startsWith("Warnings:")) {
|
|
582
|
+
return ansi.warn(line);
|
|
583
|
+
}
|
|
584
|
+
if (line.startsWith("- [FAIL]")) {
|
|
585
|
+
return ansi.fail(line);
|
|
586
|
+
}
|
|
587
|
+
if (line.startsWith("Live:") ||
|
|
588
|
+
line.startsWith("Backup:") ||
|
|
589
|
+
line.startsWith("LaunchAgent:")) {
|
|
590
|
+
return ansi.success(line);
|
|
591
|
+
}
|
|
592
|
+
if (line.startsWith("Runtime: not started")) {
|
|
593
|
+
return ansi.warn(line);
|
|
594
|
+
}
|
|
595
|
+
if (line.startsWith("Next:")) {
|
|
596
|
+
return ansi.info(line);
|
|
597
|
+
}
|
|
598
|
+
return line;
|
|
599
|
+
})
|
|
600
|
+
.join("\n");
|
|
601
|
+
}
|
|
602
|
+
function createAnsiStyler() {
|
|
603
|
+
const enabled = process.stdout.isTTY === true && process.env.NO_COLOR === undefined;
|
|
604
|
+
const wrap = (code, value) => enabled ? `\u001B[${code}m${value}\u001B[0m` : value;
|
|
605
|
+
return {
|
|
606
|
+
header: (value) => wrap("1;36", value),
|
|
607
|
+
section: (value) => wrap("1;34", value),
|
|
608
|
+
success: (value) => wrap("32", value),
|
|
609
|
+
warn: (value) => wrap("33", value),
|
|
610
|
+
fail: (value) => wrap("31", value),
|
|
611
|
+
info: (value) => wrap("36", value),
|
|
612
|
+
};
|
|
613
|
+
}
|
|
444
614
|
async function pathExists(filePath) {
|
|
445
615
|
try {
|
|
446
616
|
await access(filePath, constants.F_OK);
|