From 320b197d3f38fe916c484181852e43624a4e8ff7 Mon Sep 17 00:00:00 2001
From: GtxFury <32810165+GtxFury@users.noreply.github.com>
Date: Wed, 22 Apr 2026 22:56:46 +0800
Subject: [PATCH 1/4] Update README
Added promotional images and links to README.
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index 2a60eb7..0a2e95a 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
+
+
+
+
From 4c6d709a4722b8e56127ac3cb768c5e6037021a7 Mon Sep 17 00:00:00 2001
From: GtxFury <32810165+GtxFury@users.noreply.github.com>
Date: Wed, 22 Apr 2026 22:57:35 +0800
Subject: [PATCH 2/4] Update
Updated image source link for the first screenshot in README.
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0a2e95a..87cf2df 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
+
From 4000058e1d00e94cea571fcd1b7ebc90a3754243 Mon Sep 17 00:00:00 2001
From: GtxFury <32810165+GtxFury@users.noreply.github.com>
Date: Thu, 23 Apr 2026 08:01:15 +0800
Subject: [PATCH 3/4] Update
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 87cf2df..5206019 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
+
From 72c145e6f8ce5a97ccf5a0df300a273bc80f8c2e Mon Sep 17 00:00:00 2001
From: lunping98
Date: Wed, 24 Jun 2026 10:17:52 +0800
Subject: [PATCH 4/4] fix: bound captured mihomo output
---
.../main-process/bounded-output-buffer.js | 22 ++++++++++++++
electron/main-process/mihomo-service.js | 5 ++--
package.json | 1 +
test/bounded-output-buffer.test.js | 30 +++++++++++++++++++
4 files changed, 56 insertions(+), 2 deletions(-)
create mode 100644 electron/main-process/bounded-output-buffer.js
create mode 100644 test/bounded-output-buffer.test.js
diff --git a/electron/main-process/bounded-output-buffer.js b/electron/main-process/bounded-output-buffer.js
new file mode 100644
index 0000000..ab98de2
--- /dev/null
+++ b/electron/main-process/bounded-output-buffer.js
@@ -0,0 +1,22 @@
+const DEFAULT_MAX_OUTPUT_CHARS = 256 * 1024;
+
+function appendBoundedOutput(currentOutput, nextChunk, maxChars = DEFAULT_MAX_OUTPUT_CHARS) {
+ if (!Number.isFinite(maxChars) || maxChars <= 0) {
+ return '';
+ }
+
+ const current = typeof currentOutput === 'string' ? currentOutput : '';
+ const next = Buffer.isBuffer(nextChunk) ? nextChunk.toString() : String(nextChunk ?? '');
+ const combined = current + next;
+
+ if (combined.length <= maxChars) {
+ return combined;
+ }
+
+ return combined.slice(-maxChars);
+}
+
+module.exports = {
+ DEFAULT_MAX_OUTPUT_CHARS,
+ appendBoundedOutput,
+};
diff --git a/electron/main-process/mihomo-service.js b/electron/main-process/mihomo-service.js
index 41bdf75..133b06d 100644
--- a/electron/main-process/mihomo-service.js
+++ b/electron/main-process/mihomo-service.js
@@ -17,6 +17,7 @@ module.exports = function initMihomoService(context) {
const { applyOverrides } = require('../ipc-handlers/overrides');
const { getMihomoControllerParam, cleanupSocketFile } = require('../utils/socket-path');
const { RunningMode, setRunningMode, getRunningMode, isServiceMode, getSocketPath, getServiceSocketPath, getSidecarSocketPath } = require('../utils/running-mode');
+ const { appendBoundedOutput } = require('./bounded-output-buffer');
console.log('[mihomo-service] applyOverrides函数已导入:', typeof applyOverrides);
async function waitForProcessExit(proc, timeoutMs = 5000) {
@@ -1200,7 +1201,7 @@ module.exports = function initMihomoService(context) {
spawnedProcess.stdout.on('data', (data) => {
const logContent = data.toString();
- stdoutOutput += logContent; // 收集 stdout 输出
+ stdoutOutput = appendBoundedOutput(stdoutOutput, logContent); // 收集最近的 stdout 输出
console.log(`mihomo stdout: ${logContent}`);
// 检测 TUN 启动失败
@@ -1258,7 +1259,7 @@ module.exports = function initMihomoService(context) {
spawnedProcess.stderr.on('data', (data) => {
const errorText = data.toString();
- stderrOutput += errorText; // 收集 stderr 输出
+ stderrOutput = appendBoundedOutput(stderrOutput, errorText); // 收集最近的 stderr 输出
console.error(`mihomo stderr: ${errorText}`);
safeSend('mihomo-error', errorText);
process.stderr.write(data);
diff --git a/package.json b/package.json
index 4301bb5..694776d 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"build": "next build",
"start": "next start",
"lint": "next lint",
+ "test": "node --test",
"rebuild:native": "electron-rebuild -f -w better-sqlite3",
"postinstall": "electron-builder install-app-deps",
"prepare": "node scripts/prepare.mjs",
diff --git a/test/bounded-output-buffer.test.js b/test/bounded-output-buffer.test.js
new file mode 100644
index 0000000..7511ab6
--- /dev/null
+++ b/test/bounded-output-buffer.test.js
@@ -0,0 +1,30 @@
+const assert = require('node:assert/strict');
+const test = require('node:test');
+
+const {
+ DEFAULT_MAX_OUTPUT_CHARS,
+ appendBoundedOutput,
+} = require('../electron/main-process/bounded-output-buffer');
+
+test('appendBoundedOutput keeps short output unchanged', () => {
+ const output = appendBoundedOutput('hello', '\nworld', 32);
+
+ assert.equal(output, 'hello\nworld');
+});
+
+test('appendBoundedOutput caps retained output and keeps newest content', () => {
+ let output = '';
+
+ output = appendBoundedOutput(output, '12345', 10);
+ output = appendBoundedOutput(output, '67890', 10);
+ output = appendBoundedOutput(output, 'abcde', 10);
+
+ assert.equal(output, '67890abcde');
+ assert.equal(output.length, 10);
+});
+
+test('appendBoundedOutput truncates a single large chunk to the configured limit', () => {
+ const output = appendBoundedOutput('', 'x'.repeat(DEFAULT_MAX_OUTPUT_CHARS + 5), 16);
+
+ assert.equal(output, 'x'.repeat(16));
+});