de-AI: remove AI comments and boolean theater across TypeScript + ucode

This commit is contained in:
Dushnilin
2026-08-19 18:15:35 +03:00
parent 0964b79171
commit 4094a41b5d
24 changed files with 22 additions and 99 deletions
+6 -6
View File
@@ -1,9 +1,9 @@
export function parseValueList(value: string): string[] {
return value
.split(/\n/) // Split to array by newline separator
.map((line) => line.split('//')[0].split('#')[0]) // Remove comments
.join(' ') // Build clean string
.split(/[,\s]+/) // Split to array by comma and space
.map((s) => s.trim()) // Remove extra spaces
.filter(Boolean); // Leave nonempty items
.split(/\n/)
.map((line) => line.split('//')[0].split('#')[0])
.join(' ')
.split(/[,\s]+/)
.map((s) => s.trim())
.filter(Boolean);
}
@@ -158,7 +158,7 @@ async function isComponentActionStillRunning(
state.job_id === jobId &&
state.component === component &&
state.action === action &&
state.running === true,
state.running,
)
);
}
@@ -32,7 +32,6 @@ class TabService {
attributeFilter: ['class'],
});
// initial check
this.notify();
}
@@ -303,7 +303,7 @@ async function completeSubscriptionUpdateJob(
const shouldNotify = jobId
? shouldNotifyOwnedUiAction('subscription', jobId)
: false;
const failed = !response.success || response.data.success === false;
const failed = !response.success || !response.data.success;
const message = response.success
? response.data.message || _('Failed to update subscriptions')
: response.error || _('Failed to update subscriptions');
@@ -751,7 +751,6 @@ async function handleTestLatency(
try {
if (latencyType === 'proxy') {
// Test proxy latency immediately
const parsedTag = tag.startsWith('[') ? JSON.parse(tag)[0] : tag;
const response = await TachyonShellMethods.getClashApiProxyLatency(
parsedTag,
@@ -1936,7 +1935,6 @@ async function onStoreUpdate(
}
async function onPageMount() {
// Cleanup before mount
onPageUnmount();
dashboardMounted = true;
@@ -1956,7 +1954,6 @@ async function onPageMount() {
}
}
// Add new listener
store.subscribe(onStoreUpdate);
startActionStateWatcher();
void renderSectionsWidget();
@@ -1980,9 +1977,7 @@ function onPageUnmount() {
stopActionStateWatcher();
sectionsRefreshQueued = false;
sectionsRefreshPromise = null;
// Remove old listener
store.unsubscribe(onStoreUpdate);
// Clear store
store.reset(['bandwidthWidget', 'trafficTotalWidget', 'systemInfoWidget']);
}
@@ -577,8 +577,6 @@ function renderAiWatchdogSection(state: AdvancedSettingsState) {
{ class: 'tachyon_adv__hint' },
_('Advanced self-healing features. Requires Watchdog to be enabled.'),
),
// Health Checks group
E('div', { class: 'tachyon_adv__group' }, [
E('h4', { class: 'tachyon_adv__group-title' }, _('Health Checks')),
toggle('proxyHealthEnabled', 'Enable Proxy Health Monitor'),
@@ -606,8 +604,6 @@ function renderAiWatchdogSection(state: AdvancedSettingsState) {
])
: E('span', {}),
]),
// Protection group
E('div', { class: 'tachyon_adv__group' }, [
E('h4', { class: 'tachyon_adv__group-title' }, _('Protection')),
toggle(
@@ -623,8 +619,6 @@ function renderAiWatchdogSection(state: AdvancedSettingsState) {
'Graceful Degradation (skip failed checks, continue)',
),
]),
// Monitoring group
E('div', { class: 'tachyon_adv__group' }, [
E(
'h4',
@@ -657,8 +651,6 @@ function renderAiWatchdogSection(state: AdvancedSettingsState) {
])
: E('span', {}),
]),
// Optimization group
E('div', { class: 'tachyon_adv__group' }, [
E('h4', { class: 'tachyon_adv__group-title' }, _('Optimization')),
toggle(
@@ -674,8 +666,6 @@ function renderAiWatchdogSection(state: AdvancedSettingsState) {
'Persistent Smart Detect (survive reboots)',
),
]),
// AI Agent API group
E('div', { class: 'tachyon_adv__group' }, [
E(
'h4',
@@ -730,8 +720,6 @@ function renderAiWatchdogSection(state: AdvancedSettingsState) {
),
),
]),
// AI Doctor (ChatGPT / DeepSeek API) group
E('div', { class: 'tachyon_adv__group' }, [
E(
'h4',
@@ -19,7 +19,6 @@ export function render() {
),
),
E('div', { class: 'tachyon_dashboard-page__content' }, [
// Widgets section
E('div', { class: 'tachyon_dashboard-page__widgets-section' }, [
E(
'div',
@@ -62,9 +61,7 @@ export function render() {
}),
),
]),
// Clients section
E('div', { id: 'dashboard-connections-grid' }, []),
// All outbounds
E(
'div',
{ id: 'dashboard-sections-grid' },
@@ -600,7 +600,7 @@ async function handleServiceRuntimeAction({
throw new Error(result.error);
}
if (result.data.success === false) {
if (!result.data.success) {
throw new Error(result.data.message || _('Service action failed'));
}
@@ -867,7 +867,6 @@ async function handleRunAiDoctor() {
.map((s) => s.trim())
.filter(Boolean);
// Save to History
const nowStr = new Date().toLocaleTimeString();
saveAiDoctorHistory({ timestamp: nowStr, report, quickFixes });
let historyEntries = getAiDoctorHistory();
@@ -2151,7 +2150,6 @@ function restorePersistedDiagnosticRun() {
async function onPageMount() {
const preserveHiddenResult = diagnosticCompletedWhileHidden;
// Cleanup before mount
onPageUnmount({
preserveCompletedResult: preserveHiddenResult,
preservePersistedRun: true,
@@ -2187,23 +2185,13 @@ async function onPageMount() {
resetDiagnosticsChecks();
}
// Add new listener
store.subscribe(onStoreUpdate);
startServiceActionStateWatcher();
// Initial checks render
renderDiagnosticsChecks();
// Initial run checks action render
renderDiagnosticRunActionWidget();
// Initial available actions render
renderDiagnosticAvailableActionsWidget();
// Initial system info render
renderDiagnosticSystemInfoWidget();
// Initial Wiki disclaimer render
renderWikiDisclaimerWidget();
if (hasRuntimeSnapshot) {
@@ -2226,7 +2214,6 @@ function onPageUnmount({
stopServiceActionStateWatcher();
servicesInfoRefreshPromise = null;
// Remove old listener
store.unsubscribe(onStoreUpdate);
if (!preserveCompletedResult && !store.get().diagnosticsRunAction.loading) {
@@ -85,7 +85,6 @@ export function renderAiChatModal() {
chatInput.value = '';
renderMessages();
// Typing indicator
const typingMsg: ChatMessage = {
sender: 'assistant',
text: '🤖 ' + _('Thinking...'),
@@ -104,7 +103,7 @@ export function renderAiChatModal() {
'/usr/bin/tachyon',
{ timeout: 120000 },
)) as { success?: boolean; data?: unknown };
chatHistory.pop(); // Remove typing indicator
chatHistory.pop();
let answerText = _('Failed to receive response from AI service.');
if (res && res.success) {
@@ -153,7 +152,6 @@ export function renderAiChatModal() {
if (e.key === 'Enter') handleSend();
};
// Quick prompt buttons
const quickPrompts = [
{ label: '🩺 ' + _('Check YouTube'), query: 'Check YouTube availability' },
{ label: '🔍 ' + _('Why Discord fails?'), query: 'Why Discord fails?' },
@@ -241,7 +241,6 @@ export function renderServiceCheckModal() {
return;
}
// Mode Switcher Toolbar
const activeSectionsBtn = renderButton({
text: 'Активные маршруты',
classNames: [
@@ -281,12 +280,10 @@ export function renderServiceCheckModal() {
],
);
// Extract unique sections for filter dropdown
const sectionNames = Array.from(new Set(targets.map((t) => t.section)));
let activeFilter = 'ALL';
let searchQuery = '';
// Summary Stats Elements
const totalStatEl = E(
'b',
{
@@ -352,7 +349,6 @@ export function renderServiceCheckModal() {
],
);
// Progress Bar Container
const progressBarInner = E('div', {
style:
'width: 0%; height: 100%; background: var(--color-success, #28a745); transition: width 0.2s ease;',
@@ -366,7 +362,6 @@ export function renderServiceCheckModal() {
[progressBarInner],
);
// Section Filter Dropdown (compact select replacing noisy button grid)
const sectionSelect = E(
'select',
{
@@ -30,7 +30,7 @@ export function shouldRefreshComponentStateBeforeRender(
uiState?: Pick<Tachyon.UiState, 'actions'>,
) {
return Boolean(
uiState?.actions.component.some((state) => state.running === true),
uiState?.actions.component.some((state) => state.running),
);
}
@@ -617,7 +617,7 @@ async function completeComponentActionJob(
const shouldNotify = shouldNotifyOwnedUiAction('component', jobId);
const modalController = getActiveProgressModalController();
if (!response.success || response.data.success === false) {
if (!response.success || !response.data.success) {
const message = response.success
? response.data.message || _('Failed to execute')
: response.error || _('Failed to execute');
@@ -1071,7 +1071,6 @@ function getComponentCards(): ComponentCard[] {
singBoxInstalled,
);
// Add Sing-box variant actions (only show names, no 'Install' prefix)
if (!singBoxStable) {
singBoxActions.push({
key: 'singBoxInstallStable',
@@ -1226,7 +1225,6 @@ function renderComponentCard(card: ComponentCard) {
const checkResult = getVisibleCheckResult(card.component);
// 1. Header (displays Title, Current Version, no badges)
const headerChildren: Node[] = [
E('b', { class: 'tachyon_updates-page__component__title' }, card.title),
E(
@@ -1256,7 +1254,6 @@ function renderComponentCard(card: ComponentCard) {
headerChildren,
);
// 2. Details (renders status messages for check results)
const detailsChildren: Node[] = [];
if (checkResult && checkResult.status) {
@@ -1365,7 +1362,6 @@ function renderComponentCard(card: ComponentCard) {
)
: null;
// 3. Actions classification
const primaryActions: ComponentActionButton[] = [];
const dangerActions: ComponentActionButton[] = [];
const variantActions: ComponentActionButton[] = [];
@@ -1382,7 +1378,6 @@ function renderComponentCard(card: ComponentCard) {
const actionElements: Node[] = [];
// Render primary and danger buttons in a main row
const primaryButtons = primaryActions.map((action) => {
const loading = updatesActions[action.key].loading;
const isUpdateOrInstall =
@@ -1420,7 +1415,6 @@ function renderComponentCard(card: ComponentCard) {
);
}
// Render variant buttons if any
if (variantActions.length > 0) {
const variantButtons = variantActions.map((action) => {
const loading = updatesActions[action.key].loading;
@@ -2832,7 +2832,6 @@ function render() {
)
),
E("div", { class: "tachyon_dashboard-page__content" }, [
// Widgets section
E("div", { class: "tachyon_dashboard-page__widgets-section" }, [
E(
"div",
@@ -2875,9 +2874,7 @@ function render() {
})
)
]),
// Clients section
E("div", { id: "dashboard-connections-grid" }, []),
// All outbounds
E(
"div",
{ id: "dashboard-sections-grid" },
@@ -3221,7 +3218,7 @@ async function isComponentActionStillRunning(jobId, component, action) {
{ timeout: GET_UI_STATE_RPC_TIMEOUT_MS }
);
return response.success && response.data.actions.component.some(
(state) => state.job_id === jobId && state.component === component && state.action === action && state.running === true
(state) => state.job_id === jobId && state.component === component && state.action === action && state.running
);
}
function componentActionFailure(response, parsedResponse) {
@@ -6691,7 +6688,7 @@ async function completeSubscriptionUpdateJob(jobId, sectionName, response) {
return;
}
const shouldNotify = jobId ? shouldNotifyOwnedUiAction("subscription", jobId) : false;
const failed2 = !response.success || response.data.success === false;
const failed2 = !response.success || !response.data.success;
const message = response.success ? response.data.message || _("Failed to update subscriptions") : response.error || _("Failed to update subscriptions");
if (failed2 && isTransientRpcError(message)) {
void refreshRuntimeUiState({ force: true });
@@ -12331,7 +12328,7 @@ async function handleServiceRuntimeAction({
if (!result.success) {
throw new Error(result.error);
}
if (result.data.success === false) {
if (!result.data.success) {
throw new Error(result.data.message || _("Service action failed"));
}
await waitForTachyonRunningState(expectedRunning);
@@ -15916,7 +15913,7 @@ function shouldResetCheckResultsOnMount({
}
function shouldRefreshComponentStateBeforeRender(uiState) {
return Boolean(
uiState?.actions.component.some((state) => state.running === true)
uiState?.actions.component.some((state) => state.running)
);
}
function shouldExposeCheckResults({
@@ -16718,7 +16715,7 @@ async function completeComponentActionJob(key, jobId, response) {
}
const shouldNotify = shouldNotifyOwnedUiAction("component", jobId);
const modalController = getActiveProgressModalController();
if (!response.success || response.data.success === false) {
if (!response.success || !response.data.success) {
const message = response.success ? response.data.message || _("Failed to execute") : response.error || _("Failed to execute");
if (isTransientRpcError(message)) {
setActionLoading(key, false);
-2
View File
@@ -23,8 +23,6 @@ function now_ms() {
let common = require("core.common");
let as_string = common.as_string;
// Creates an isolated bus. Each instance owns its subscriber table, dedup
// state and counters, so tests can build a fresh bus per assertion.
function bus() {
let handlers = {}; // type -> array of subscriber records
let last_emit = {}; // dedup key -> monotonic ms of last accepted emit
@@ -3083,7 +3083,6 @@ function diagnose_json() {
let res = run_doctor_checks();
let problems = [];
// Parse the text report lines into structured objects
for (let line in split(res.report, "\n")) {
line = trim(as_string(line));
if (line == "") continue;
@@ -3110,7 +3109,6 @@ function diagnose_json() {
// "→" is U+2192, encoded as 3 UTF-8 bytes (E2 86 92); skip all 3
let suggested_fix = arrow_idx >= 0 ? trim(substr(clean, arrow_idx + 3)) : "";
// Detect if already fixed inline (FIXED: prefix in suggested_fix)
if (index(suggested_fix, "FIXED:") >= 0) {
fixed_inline = true;
severity = "info"; // was critical but already fixed
+1 -3
View File
@@ -665,17 +665,15 @@ function nft_source_match_args(section, family, sets) {
: [ "ip", "saddr", "@" + as_string(sets.sources) ];
}
// Build a negative nftables source-IP match for excluded_ips.
// nft accepts: ip saddr != { addr1, addr2, ... } as a single argument.
function nft_excluded_source_match_args(section, family) {
let excluded = list_option(section, "excluded_ips");
if (length(excluded) == 0)
return [];
let ip_key = family == 6 ? "ip6" : "ip";
let want_family = family;
let addrs = [];
for (let ip in excluded)
if (core_ip.ip_family(as_string(ip)) == want_family)
if (core_ip.ip_family(as_string(ip)) == family)
push(addrs, as_string(ip));
if (length(addrs) == 0)
return [];
-1
View File
@@ -606,7 +606,6 @@ function stop_service(owner_pid) {
}
let status = command_status_from_args([ BIN_PATH, "stop" ]);
// Clean up orphaned logread -f processes left by watchdog instances.
// These survive tachyon stop because background subprocesses (reload_firewall,
// restart) inherit the logread pipe read-end, preventing SIGPIPE delivery.
// Use pkill to target only logread in follow mode, not one-shot logread calls.
@@ -790,7 +790,6 @@ function start_main() {
}
function start_impl() {
// Clean up orphaned /tmp/tachyon-* temp files from processes killed mid-operation
// (e.g. config generator killed during restart). 30-min threshold is safe since
// all tachyon temp files are created and deleted within seconds under normal operation.
command_status("find /tmp -maxdepth 1 -name 'tachyon-*' -mmin +30 -delete 2>/dev/null; true");
-1
View File
@@ -588,7 +588,6 @@ function reload_sing_box_runtime(previous_pid, config_hash_before, config_hash_a
command_success_from_args([ "logger", "-t", "tachyon", "[info] Hot-reloading sing-box runtime (SIGHUP) PID: " + active_pid ]);
if (active_pid > 0 && pid_is_sing_box(active_pid)) {
if (command_success_from_args([ "kill", "-HUP", as_string(active_pid) ])) {
// Verify process survived SIGHUP reload
command_success_from_args([ "sleep", "1" ]);
let check_pid = sing_box_service_pid_runtime();
if (check_pid > 0 && pid_is_sing_box(check_pid)) {
+2 -3
View File
@@ -1952,7 +1952,7 @@ function view_devices(token, chat_id, msg_id) {
let ip = fields[2];
let hostname = fields[3] == "*" ? "Неизвестно" : fields[3];
let is_blocked = blocked_macs[mac] ? true : false;
let is_blocked = blocked_macs[mac];
let status_icon = is_blocked ? "🚫" : "🟢";
text += status_icon + " <b>" + escape_html(hostname) + "</b>\n";
@@ -2069,7 +2069,7 @@ function valid_updatable_component(name) {
zapret2: 1,
byedpi: 1
};
return allowed[name] ? true : false;
return allowed[name];
}
// ─── Dispatcher ──────────────────────────────────────────────────────────────
@@ -2893,7 +2893,6 @@ function send_api(message) {
let cfg = settings();
if (cfg.enabled != "1" || !cfg.bot_token || !cfg.admin_ids) return 1;
// Check if this is a non-critical watchdog message and we are in quiet hours
let is_critical = (index(message, "Упал") >= 0 || index(message, "Ошибка") >= 0);
if (!is_critical && in_quiet_hours(cfg)) return 0;
@@ -108,7 +108,6 @@ function switch_server(srv_name) {
exec_output("sleep 1.5");
}
// 1. Generate WireGuard keys
let keypair_data = exec_output("/usr/bin/sing-box generate wg-keypair 2>/dev/null");
let private_key = null;
let public_key = null;
@@ -135,7 +134,6 @@ if (!private_key || !public_key) {
exit(1);
}
// 2. Perform registration
let install_id = "";
let fcm_token = "";
let tos = exec_output("date -u +'%Y-%m-%dT%H:%M:%SZ' 2>/dev/null") || "2026-07-17T20:52:00Z";
@@ -196,13 +194,11 @@ for (let prefix in api_prefixes) {
let code = parsed.errors ? parsed.errors[0].code : null;
if (code == 1015 || index(as_string(msg), "1015") >= 0) {
// Rotate proxy server if available
if (length(available_servers) > 0 && server_try_index < 4) {
let next_srv = available_servers[(server_try_index + 1) % length(available_servers)];
server_try_index++;
switch_server(next_srv);
// Retry request with rotated proxy server
parsed = call_api("POST", url, "", tmp_req_file);
if (parsed && parsed.success && parsed.result) {
response_data = parsed.result;
@@ -228,7 +224,6 @@ if (!response_data) {
exit(1);
}
// 3. Make sure warp_enabled is true
if (!response_data.warp_enabled) {
let patch_body = { warp_enabled: true };
let tmp_patch = exec_output("mktemp 2>/dev/null") || "/tmp/warp_patch.json";
@@ -239,7 +234,6 @@ if (!response_data.warp_enabled) {
fs.unlink(tmp_patch);
}
// 4. Optionally apply WARP+ license key if provided as first arg
let license_key = ARGV[0] || "";
if (license_key != "") {
let patch_body = { license_key: license_key };
@@ -254,7 +248,6 @@ if (license_key != "") {
// Restore original proxy server selection
restore_original_server();
// 5. Select fastest endpoint IP using TCP latency probes (via curl)
let probe_ips = [
"162.159.192.1", "162.159.192.6",
"162.159.193.1", "162.159.193.6",
@@ -297,7 +290,6 @@ let warp_ports = [
];
let random_port = warp_ports[time() % length(warp_ports)];
// 6. Formulate CPS packets
let warp_cps_payloads = [
"<b 0xce000000010897a297ecc34cd6dd000044d0ec2e2e1ea2991f467ace4222129b5a098823784694b4897b9986ae0b7280135fa85e196d9ad980b150122129ce2a9379531b0fd3e871ca5fdb883c369832f730e272d7b8b74f393f9f0fa43f11e510ecb2219a52984410c204cf875585340c62238e14ad04dff382f2c200e0ee22fe743b9c6b8b043121c5710ec289f471c91ee414fca8b8be8419ae8ce7ffc53837f6ade262891895f3f4cecd31bc93ac5599e18e4f01b472362b8056c3172b513051f8322d1062997ef4a383b01706598d08d48c221d30e74c7ce000cdad36b706b1bf9b0607c32ec4b3203a4ee21ab64df336212b9758280803fcab14933b0e7ee1e04a7becce3e2633f4852585c567894a5f9efe9706a151b615856647e8b7dba69ab357b3982f554549bef9256111b2d67afde0b496f16962d4957ff654232aa9e845b61463908309cfd9de0a6abf5f425f577d7e5f6440652aa8da5f73588e82e9470f3b21b27b28c649506ae1a7f5f15b876f56abc4615f49911549b9bb39dd804fde182bd2dcec0c33bad9b138ca07d4a4a1650a2c2686acea05727e2a78962a840ae428f55627516e73c83dd8893b02358e81b524b4d99fda6df52b3a8d7a5291326e7ac9d773c5b43b8444554ef5aea104a738ed650aa979674bbed38da58ac29d87c29d387d80b526065baeb073ce65f075ccb56e47533aef357dceaa8293a523c5f6f790be90e4731123d3c6152a70576e90b4ab5bc5ead01576c68ab633ff7d36dcde2a0b2c68897e1acfc4d6483aaaeb635dd63c96b2b6a7a2bfe042f6aed82e5363aa850aace12ee3b1a93f30d8ab9537df483152a5527faca21efc9981b304f11fc95336f5b9637b174c5a0659e2b22e159a9fed4b8e93047371175b1d6d9cc8ab745f3b2281537d1c75fb9451871864efa5d184c38c185fd203de206751b92620f7c369e031d2041e152040920ac2c5ab5340bfc9d0561176abf10a147287ea90758575ac6a9f5ac9f390d0d5b23ee12af583383d994e22c0cf42383834bcd3ada1b3825a0664d8f3fb678261d57601ddf94a8a68a7c273a18c08aa99c7ad8c6c42eab67718843597ec9930457359dfdfbce024afc2dcf9348579a57d8d3490b2fa99f278f1c37d87dad9b221acd575192ffae1784f8e60ec7cee4068b6b988f0433d96d6a1b1865f4e155e9fe020279f434f3bf1bd117b717b92f6cd1cc9bea7d45978bcc3f24bda631a36910110a6ec06da35f8966c9279d130347594f13e9e07514fa370754d1424c0a1545c5070ef9fb2acd14233e8a50bfc5978b5bdf8bc1714731f798d21e2004117c61f2989dd44f0cf027b27d4019e81ed4b5c31db347c4a3a4d85048d7093cf16753d7b0d15e078f5c7a5205dc2f87e330a1f716738dce1c6180e9d02869b5546f1c4d2748f8c90d9693cba4e0079297d22fd61402dea32ff0eb69ebd65a5d0b687d87e3a8b2c42b648aa723c7c7daf37abcc4bb85caea2ee8f55bec20e913b3324ab8f5c3304f820d42ad1b9f2ffc1a3af9927136b4419e1e579ab4c2ae3c776d293d397d575df181e6cae0a4ada5d67ecea171cca3288d57c7bbdaee3befe745fb7d634f70386d873b90c4d6c6596bb65af68f9e5121e67ebf0d89d3c909ceedfb32ce9575a7758ff080724e1ab5d5f43074ecb53a479af21ed03d7b6899c36631c0166f9d47e5e1d4528a5d3d3f744029c4b1c190cbfbad06f5f83f7ad0429fa9a2719c56ffe3783460e166de2d8>",
"<b 0xc7000000010809a1ed4edbbe7615000044d017a61a0d774f04290f119e701ef0035df2b0ed571b0b575e6a07246b856eb6ec036fef07f1e07b861251ad737abeb67e64be714c1dcd865312b1b6c35c089c997aeb5c18f808696fe97289513945d84ca846467603e94e44224877f2c1d3261e4ac18740be4bd064369c94fc08978d99b54bf615250998639010c1284248e1d73004b81fcb20b559d8a17eced7eab3964b5b88ca7a3b8579fc8c1c934189e77143b4ac434138114b1048651b56545b87acbef0952763538f3ddeb37cfc6d58b4881c3b719d7ff78f6ee1324a2914a32381c05a64c700466d280be007253bb030d179c4f1b3dc221e1974e2ee6d6e2b9e8d709159b5ef22e1783dbba845c20ca1c83b066c73835920ad70b806df0aee0351e3fc9ab1e42e8b2a30fe235ff0612eee19744949cecee0463b76514ad90c1f7ceaa557c18586ab561d49482e73c85d0143785da14a441bf82f78783b61cccd44aecb1947516e79b5ca5a6b3a8aed6040fae0eeabdc55a88dc19ade832d99fca90c7a629cacc07192d7e47e3c6a271b95b0ea3392562a06a1cab79f40ea92916ebee197b7b5f14b251824e1ed20ff2ca80b1f03a43e45157589bc61b978e97851025b3b7ccc17d291e1cb60fe48a5c26829dce11dd23c2e73265a9ebf8617c985e4fee4681e863f990061f4dea465a7d2524bd0edcf4b48d4b8f25fc359b15babd2637284a4774077dca60091f1a781cfee1bef9713dd5943a579d7470bc5970542fbb27fdf77880a8d8751b1f642c7a3f019a05ab94bf63d3525ef34e9290b5c8d477f2714e6d6e3e4d35c1983f5e16fda57fcdf071b513f8f088dbe8d5a97577d17a5383a496c3f313adfdd47c962bbaebd6aa13b46439eb742622c29ca067db0ec1853064c3cbbffe0a215a19fce47d49703ed58ebbd89721172d256d1cf30188106fb2f863186511401fad54d087aa2fb3d1b85768db386bd7102e8060ac157bac011acdcdae2799b9aee1467c3424013455bd028fcaacdc3c77d28ea199967d617ea7d0d0815f3cc407934a76d1293dccba210d1709a13e5dd67c9ba47cd113f5bdd740358eff13164159fd09bc2f7ec6cfa64d9df7e2e2f88706b0ff3a92ccf6f078456cfe0bdd89292cfe2680badc1eac9f7d36efe8eb6912c7b164508d13e6c0911c15f73c233cbe4fc70ff2ade1e1be4bbb738e0939159e2078a9438f05b756a003371f4861481c38f1cdd2d7b06deb62869e9fe79a8abaa920646fa2e8fa28f0d80c136376c7b56046bae4c05c0cdf64efb8c47bbfc5a1a4c0b045061ef0d71618e0d206a1d7f245fd5c03191b152673ba8dff8e1b8de7c50234a93cba91e3888adb228cc02beded4b1c0946797d3ef02dec2edb6ad0ac21f89f4be364c317da7c22440e9f358d512203f4b7ab20388af68b8915d0152db2c8a0687bfaea870f7529bb92a22b35bd79bc6d490591406346ecd78342ee3563c4883a8251679691c2d4e963397e24653520795511b018915374c954bddb940a9d7a16d1c8bd798fc7dbfb0599a7074e13f87e14efa8d511bb2579ec029b1bda18fe971b30fbe19e986ff2686a69bf3f1bb929de93ae70345ebca998b11e0a2b41890cba628d8f6e7c4e94790735e5299b4ff07cd3080f7d53c9cbe1911d2cd5925b3213e033c272506a87886cf761a283a779564d3241e3c28f632e166b5d756e1786ce077614c4444e3f2aed5decb3613b925ea3e558c21d4faf8ba54edd0f3a5d4>",
@@ -324,7 +316,6 @@ let i3 = to_hex(generate_extra_cps());
let i4 = to_hex(generate_extra_cps());
let i5 = to_hex(generate_extra_cps());
// 7. Output result
write_json({
success: true,
local_address: response_data.config.interface.addresses.v4 + "/32 " + response_data.config.interface.addresses.v6 + "/128",
+1 -6
View File
@@ -821,7 +821,6 @@ function ai_heal_subnet_cache() {
// /tmp file missing or empty, restore from persistent storage
let content = fs.readfile(etc_path);
if (content == null || content == "") continue;
// Ensure /tmp dir exists
command_success_from_args(["mkdir", "-p", tmp_dir]);
if (fs.writefile(tmp_path, content) != null) {
push(restored, entry);
@@ -1072,15 +1071,13 @@ function ai_heal_dns_loop() {
let detour_section = common.option(cfg, "dns_detour_section", "");
if (detour_section == "") return;
// Check if DNS is working
if (controller.is_dns_working()) {
// DNS works — if we were in recovery, try to restore
let recovery = read_dns_recovery_state();
if (recovery.phase == "detour_disabled") {
let reenable_cooldown = recovery.ts ? (now - int(recovery.ts)) : 0;
if (reenable_cooldown < 300) return;
let test_dns = controller.is_dns_working();
if (test_dns) {
if (controller.is_dns_working()) {
log_message("DNS loop recovery: DNS works, re-enabling DNS detour section", "info");
system("/sbin/uci set tachyon.settings.dns_detour_enabled='1' >/dev/null 2>&1");
system("/sbin/uci commit tachyon >/dev/null 2>&1");
@@ -1108,7 +1105,6 @@ function ai_heal_dns_loop() {
return;
}
// Check if detour section is empty
let cache_path = "/var/run/tachyon/section-cache/" + detour_section + ".json";
let cache = common.object_or_empty(common.read_json_file(cache_path));
let servers = common.array_or_empty(cache.servers);
@@ -1683,7 +1679,6 @@ function worker() {
ai_heal_subnet_cache();
run_zero_rtt_prefetching();
// Ensure /etc/tachyon exists for persistent smart detect
// Throws when it already exists, which is the expected case on every boot
// after the first.
try { fs.mkdir("/etc/tachyon"); } catch(e) {}
@@ -126,7 +126,6 @@ function parse_text_domains(text) {
// Strip inline comments
line = replace(line, /[ \t]+\/\/.*$/, "");
line = replace(line, /[ \t]+#.*$/, "");
// Split by comma or whitespace for multi-domain lines
for (let token in split(line, /[,\s]+/)) {
token = trim(token);
// Strip leading dots (domain_suffix style) and wildcards
@@ -50,7 +50,6 @@ let url_query_params = runtime_url.query_params;
const CONFIG_NAME = "tachyon";
// Convert a UCI value that may be a binary buffer (<b 0x...>) to a plain hex string.
// UCI stores values written as '<b 0x...>' strings as binary, which when
// serialized back to JSON appear as '<b 0x...>' — invalid for sing-box.
function uci_bin_to_hex(val) {
@@ -445,7 +444,6 @@ function base_config(settings, service_address, runtime_context) {
}
}
// Read remote hosts lists cache file
let hosts_cache_st = fs.stat(HOSTS_CACHE_FILE);
if (hosts_cache_st != null && int(hosts_cache_st.size) > 0) {
let fh = null;
@@ -977,7 +977,7 @@ function add_subscription_source_with_state(config, section, source_index, sourc
let added = 0;
for (let i = 0; i < length(prepared); i++) {
let outbound = prepared[i];
let is_group = group_flags[i] === true;
let is_group = group_flags[i];
if (is_group && length(array_or_empty(outbound.outbounds)) == 0) {
warn("skipped empty subscription group for rule '", section_name, "': ", as_string(display_names[i] || outbound.tag || "unknown"), "\n");
continue;