@hirohsu/user-web-feedback 2.8.15 → 2.8.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/dist/cli.cjs +482 -33
- package/dist/index.cjs +479 -30
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -2871,7 +2871,7 @@ var require_main = __commonJS({
|
|
|
2871
2871
|
init_cjs_shims();
|
|
2872
2872
|
var fs9 = require("fs");
|
|
2873
2873
|
var path10 = require("path");
|
|
2874
|
-
var
|
|
2874
|
+
var os7 = require("os");
|
|
2875
2875
|
var crypto5 = require("crypto");
|
|
2876
2876
|
var packageJson = require_package();
|
|
2877
2877
|
var version2 = packageJson.version;
|
|
@@ -2994,7 +2994,7 @@ var require_main = __commonJS({
|
|
|
2994
2994
|
return null;
|
|
2995
2995
|
}
|
|
2996
2996
|
function _resolveHome(envPath) {
|
|
2997
|
-
return envPath[0] === "~" ? path10.join(
|
|
2997
|
+
return envPath[0] === "~" ? path10.join(os7.homedir(), envPath.slice(1)) : envPath;
|
|
2998
2998
|
}
|
|
2999
2999
|
function _configVault(options) {
|
|
3000
3000
|
const debug = Boolean(options && options.debug);
|
|
@@ -3159,7 +3159,9 @@ var require_main = __commonJS({
|
|
|
3159
3159
|
// src/utils/crypto-helper.ts
|
|
3160
3160
|
function loadPasswordFromConfig() {
|
|
3161
3161
|
try {
|
|
3162
|
-
const
|
|
3162
|
+
const envDir = process.env["MCP_DATA_DIR"];
|
|
3163
|
+
const dataDir = envDir || import_path.default.join(import_os.default.homedir(), ".user-web-feedback", "data");
|
|
3164
|
+
const configPath = import_path.default.join(dataDir, "config.json");
|
|
3163
3165
|
if (import_fs.default.existsSync(configPath)) {
|
|
3164
3166
|
const configData = import_fs.default.readFileSync(configPath, "utf8");
|
|
3165
3167
|
const config2 = JSON.parse(configData);
|
|
@@ -3251,7 +3253,7 @@ function maskApiKey(apiKey) {
|
|
|
3251
3253
|
const masked = "*".repeat(maskedLength);
|
|
3252
3254
|
return `${prefix}${masked}${suffix}`;
|
|
3253
3255
|
}
|
|
3254
|
-
var import_crypto, import_fs, import_path, ALGORITHM, IV_LENGTH, SALT, encryptionKeyLogged, cachedPassword;
|
|
3256
|
+
var import_crypto, import_fs, import_path, import_os, ALGORITHM, IV_LENGTH, SALT, encryptionKeyLogged, cachedPassword;
|
|
3255
3257
|
var init_crypto_helper = __esm({
|
|
3256
3258
|
"src/utils/crypto-helper.ts"() {
|
|
3257
3259
|
"use strict";
|
|
@@ -3259,6 +3261,7 @@ var init_crypto_helper = __esm({
|
|
|
3259
3261
|
import_crypto = __toESM(require("crypto"), 1);
|
|
3260
3262
|
import_fs = __toESM(require("fs"), 1);
|
|
3261
3263
|
import_path = __toESM(require("path"), 1);
|
|
3264
|
+
import_os = __toESM(require("os"), 1);
|
|
3262
3265
|
init_logger();
|
|
3263
3266
|
ALGORITHM = "aes-256-gcm";
|
|
3264
3267
|
IV_LENGTH = 16;
|
|
@@ -3340,6 +3343,11 @@ __export(database_exports, {
|
|
|
3340
3343
|
updatePromptConfigs: () => updatePromptConfigs,
|
|
3341
3344
|
updateUserPreferences: () => updateUserPreferences
|
|
3342
3345
|
});
|
|
3346
|
+
function getGlobalDataDir() {
|
|
3347
|
+
const envDir = process.env["MCP_DATA_DIR"];
|
|
3348
|
+
if (envDir) return envDir;
|
|
3349
|
+
return import_path2.default.join(import_os2.default.homedir(), ".user-web-feedback", "data");
|
|
3350
|
+
}
|
|
3343
3351
|
function hashPrompt(prompt) {
|
|
3344
3352
|
return import_crypto2.default.createHash("sha256").update(prompt.trim()).digest("hex").substring(0, 16);
|
|
3345
3353
|
}
|
|
@@ -5202,7 +5210,7 @@ function cleanupExpiredPendingResponses() {
|
|
|
5202
5210
|
`).run(now, deliveredCutoff);
|
|
5203
5211
|
return result.changes;
|
|
5204
5212
|
}
|
|
5205
|
-
var import_better_sqlite3, import_path2, import_fs2, import_crypto2, DB_DIR, DB_PATH, db, SYSTEM_PROMPT_VERSIONS, CURRENT_PROMPT_VERSION, DEFAULT_PROMPT_CONFIGS;
|
|
5213
|
+
var import_better_sqlite3, import_path2, import_fs2, import_os2, import_crypto2, DB_DIR, DB_PATH, db, SYSTEM_PROMPT_VERSIONS, CURRENT_PROMPT_VERSION, DEFAULT_PROMPT_CONFIGS;
|
|
5206
5214
|
var init_database = __esm({
|
|
5207
5215
|
"src/utils/database.ts"() {
|
|
5208
5216
|
"use strict";
|
|
@@ -5210,10 +5218,11 @@ var init_database = __esm({
|
|
|
5210
5218
|
import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
5211
5219
|
import_path2 = __toESM(require("path"), 1);
|
|
5212
5220
|
import_fs2 = __toESM(require("fs"), 1);
|
|
5221
|
+
import_os2 = __toESM(require("os"), 1);
|
|
5213
5222
|
import_crypto2 = __toESM(require("crypto"), 1);
|
|
5214
5223
|
init_crypto_helper();
|
|
5215
5224
|
init_logger();
|
|
5216
|
-
DB_DIR =
|
|
5225
|
+
DB_DIR = getGlobalDataDir();
|
|
5217
5226
|
DB_PATH = import_path2.default.join(DB_DIR, "feedback.db");
|
|
5218
5227
|
db = null;
|
|
5219
5228
|
SYSTEM_PROMPT_VERSIONS = {
|
|
@@ -47318,7 +47327,7 @@ var require_application = __commonJS({
|
|
|
47318
47327
|
};
|
|
47319
47328
|
app.del = deprecate.function(app.delete, "app.del: Use app.delete instead");
|
|
47320
47329
|
app.render = function render(name, options, callback) {
|
|
47321
|
-
var
|
|
47330
|
+
var cache3 = this.cache;
|
|
47322
47331
|
var done = callback;
|
|
47323
47332
|
var engines = this.engines;
|
|
47324
47333
|
var opts = options;
|
|
@@ -47337,7 +47346,7 @@ var require_application = __commonJS({
|
|
|
47337
47346
|
renderOptions.cache = this.enabled("view cache");
|
|
47338
47347
|
}
|
|
47339
47348
|
if (renderOptions.cache) {
|
|
47340
|
-
view =
|
|
47349
|
+
view = cache3[name];
|
|
47341
47350
|
}
|
|
47342
47351
|
if (!view) {
|
|
47343
47352
|
var View2 = this.get("view");
|
|
@@ -47353,7 +47362,7 @@ var require_application = __commonJS({
|
|
|
47353
47362
|
return done(err);
|
|
47354
47363
|
}
|
|
47355
47364
|
if (renderOptions.cache) {
|
|
47356
|
-
|
|
47365
|
+
cache3[name] = view;
|
|
47357
47366
|
}
|
|
47358
47367
|
}
|
|
47359
47368
|
tryRender(view, renderOptions, done);
|
|
@@ -50845,7 +50854,7 @@ var require_supports_color = __commonJS({
|
|
|
50845
50854
|
"node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports2, module2) {
|
|
50846
50855
|
"use strict";
|
|
50847
50856
|
init_cjs_shims();
|
|
50848
|
-
var
|
|
50857
|
+
var os7 = require("os");
|
|
50849
50858
|
var tty = require("tty");
|
|
50850
50859
|
var hasFlag = require_has_flag();
|
|
50851
50860
|
var { env } = process;
|
|
@@ -50893,7 +50902,7 @@ var require_supports_color = __commonJS({
|
|
|
50893
50902
|
return min;
|
|
50894
50903
|
}
|
|
50895
50904
|
if (process.platform === "win32") {
|
|
50896
|
-
const osRelease =
|
|
50905
|
+
const osRelease = os7.release().split(".");
|
|
50897
50906
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
50898
50907
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
50899
50908
|
}
|
|
@@ -83162,14 +83171,14 @@ var require_is_wsl = __commonJS({
|
|
|
83162
83171
|
"node_modules/.pnpm/is-wsl@2.2.0/node_modules/is-wsl/index.js"(exports2, module2) {
|
|
83163
83172
|
"use strict";
|
|
83164
83173
|
init_cjs_shims();
|
|
83165
|
-
var
|
|
83174
|
+
var os7 = require("os");
|
|
83166
83175
|
var fs9 = require("fs");
|
|
83167
83176
|
var isDocker2 = require_is_docker();
|
|
83168
83177
|
var isWsl2 = () => {
|
|
83169
83178
|
if (process.platform !== "linux") {
|
|
83170
83179
|
return false;
|
|
83171
83180
|
}
|
|
83172
|
-
if (
|
|
83181
|
+
if (os7.release().toLowerCase().includes("microsoft")) {
|
|
83173
83182
|
if (isDocker2()) {
|
|
83174
83183
|
return false;
|
|
83175
83184
|
}
|
|
@@ -84801,8 +84810,8 @@ var require_untildify = __commonJS({
|
|
|
84801
84810
|
"node_modules/.pnpm/untildify@4.0.0/node_modules/untildify/index.js"(exports2, module2) {
|
|
84802
84811
|
"use strict";
|
|
84803
84812
|
init_cjs_shims();
|
|
84804
|
-
var
|
|
84805
|
-
var homeDirectory =
|
|
84813
|
+
var os7 = require("os");
|
|
84814
|
+
var homeDirectory = os7.homedir();
|
|
84806
84815
|
module2.exports = (pathWithTilde) => {
|
|
84807
84816
|
if (typeof pathWithTilde !== "string") {
|
|
84808
84817
|
throw new TypeError(`Expected a string, got ${typeof pathWithTilde}`);
|
|
@@ -84840,16 +84849,16 @@ async function defaultBrowserId() {
|
|
|
84840
84849
|
}
|
|
84841
84850
|
return bundleId;
|
|
84842
84851
|
}
|
|
84843
|
-
var
|
|
84852
|
+
var import_os4, import_fs6, import_bplist_parser, import_untildify, macOsVersion, filePath;
|
|
84844
84853
|
var init_default_browser_id = __esm({
|
|
84845
84854
|
"node_modules/.pnpm/default-browser-id@3.0.0/node_modules/default-browser-id/index.js"() {
|
|
84846
84855
|
"use strict";
|
|
84847
84856
|
init_cjs_shims();
|
|
84848
|
-
|
|
84857
|
+
import_os4 = __toESM(require("os"), 1);
|
|
84849
84858
|
import_fs6 = require("fs");
|
|
84850
84859
|
import_bplist_parser = __toESM(require_bplistParser(), 1);
|
|
84851
84860
|
import_untildify = __toESM(require_untildify(), 1);
|
|
84852
|
-
macOsVersion = Number(
|
|
84861
|
+
macOsVersion = Number(import_os4.default.release().split(".")[0]);
|
|
84853
84862
|
filePath = (0, import_untildify.default)(macOsVersion >= 14 ? "~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist" : "~/Library/Preferences/com.apple.LaunchServices.plist");
|
|
84854
84863
|
}
|
|
84855
84864
|
});
|
|
@@ -85698,7 +85707,7 @@ var require_kill = __commonJS({
|
|
|
85698
85707
|
"node_modules/.pnpm/execa@5.1.1/node_modules/execa/lib/kill.js"(exports2, module2) {
|
|
85699
85708
|
"use strict";
|
|
85700
85709
|
init_cjs_shims();
|
|
85701
|
-
var
|
|
85710
|
+
var os7 = require("os");
|
|
85702
85711
|
var onExit2 = require_signal_exit();
|
|
85703
85712
|
var DEFAULT_FORCE_KILL_TIMEOUT2 = 1e3 * 5;
|
|
85704
85713
|
var spawnedKill2 = (kill, signal = "SIGTERM", options = {}) => {
|
|
@@ -85722,7 +85731,7 @@ var require_kill = __commonJS({
|
|
|
85722
85731
|
return isSigterm2(signal) && forceKillAfterTimeout !== false && killResult;
|
|
85723
85732
|
};
|
|
85724
85733
|
var isSigterm2 = (signal) => {
|
|
85725
|
-
return signal ===
|
|
85734
|
+
return signal === os7.constants.signals.SIGTERM || typeof signal === "string" && signal.toUpperCase() === "SIGTERM";
|
|
85726
85735
|
};
|
|
85727
85736
|
var getForceKillAfterTimeout2 = ({ forceKillAfterTimeout = true }) => {
|
|
85728
85737
|
if (forceKillAfterTimeout === true) {
|
|
@@ -91353,6 +91362,10 @@ var PortManager = class {
|
|
|
91353
91362
|
PORT_RANGE_START = 5e3;
|
|
91354
91363
|
PORT_RANGE_END = 5099;
|
|
91355
91364
|
MAX_RETRIES = 20;
|
|
91365
|
+
BROWSER_UNSAFE_PORTS = /* @__PURE__ */ new Set([
|
|
91366
|
+
5060,
|
|
91367
|
+
5061
|
|
91368
|
+
]);
|
|
91356
91369
|
/**
|
|
91357
91370
|
* 檢查連接埠是否可用(增強版本)
|
|
91358
91371
|
*/
|
|
@@ -91406,6 +91419,10 @@ var PortManager = class {
|
|
|
91406
91419
|
*/
|
|
91407
91420
|
async resolvePortConflict(port) {
|
|
91408
91421
|
logger.info(`\u6AA2\u67E5\u9023\u63A5\u57E0 ${port} \u662F\u5426\u53EF\u7528`);
|
|
91422
|
+
if (this.BROWSER_UNSAFE_PORTS.has(port)) {
|
|
91423
|
+
logger.warn(`\u9023\u63A5\u57E0 ${port} \u662F\u700F\u89BD\u5668\u4E0D\u5B89\u5168\u7AEF\u53E3\uFF0C\u81EA\u52D5\u5C0B\u627E\u66FF\u4EE3`);
|
|
91424
|
+
return await this.findAlternativePort(port);
|
|
91425
|
+
}
|
|
91409
91426
|
if (await this.isPortAvailable(port)) {
|
|
91410
91427
|
logger.info(`\u9023\u63A5\u57E0 ${port} \u53EF\u7528\uFF0C\u76F4\u63A5\u4F7F\u7528`);
|
|
91411
91428
|
return port;
|
|
@@ -91423,6 +91440,10 @@ var PortManager = class {
|
|
|
91423
91440
|
if (port > 65535) {
|
|
91424
91441
|
break;
|
|
91425
91442
|
}
|
|
91443
|
+
if (this.BROWSER_UNSAFE_PORTS.has(port)) {
|
|
91444
|
+
logger.debug(`\u9023\u63A5\u57E0 ${port} \u662F\u700F\u89BD\u5668\u4E0D\u5B89\u5168\u7AEF\u53E3\uFF0C\u8DF3\u904E`);
|
|
91445
|
+
continue;
|
|
91446
|
+
}
|
|
91426
91447
|
logger.debug(`\u5617\u8A66\u9023\u63A5\u57E0 ${port}...`);
|
|
91427
91448
|
if (await this.isPortAvailable(port)) {
|
|
91428
91449
|
logger.info(`\u627E\u5230\u53EF\u7528\u9023\u63A5\u57E0: ${port}`);
|
|
@@ -91437,16 +91458,21 @@ var PortManager = class {
|
|
|
91437
91458
|
*/
|
|
91438
91459
|
async findAvailablePort(preferredPort) {
|
|
91439
91460
|
if (preferredPort) {
|
|
91440
|
-
|
|
91441
|
-
|
|
91442
|
-
if (available) {
|
|
91443
|
-
logger.info(`\u4F7F\u7528\u9996\u9078\u9023\u63A5\u57E0: ${preferredPort}`);
|
|
91444
|
-
return preferredPort;
|
|
91461
|
+
if (this.BROWSER_UNSAFE_PORTS.has(preferredPort)) {
|
|
91462
|
+
logger.warn(`\u9996\u9078\u9023\u63A5\u57E0 ${preferredPort} \u662F\u700F\u89BD\u5668\u4E0D\u5B89\u5168\u7AEF\u53E3\uFF0C\u8DF3\u904E`);
|
|
91445
91463
|
} else {
|
|
91446
|
-
logger.
|
|
91464
|
+
logger.debug(`\u6AA2\u67E5\u9996\u9078\u9023\u63A5\u57E0: ${preferredPort}`);
|
|
91465
|
+
const available = await this.isPortAvailable(preferredPort);
|
|
91466
|
+
if (available) {
|
|
91467
|
+
logger.info(`\u4F7F\u7528\u9996\u9078\u9023\u63A5\u57E0: ${preferredPort}`);
|
|
91468
|
+
return preferredPort;
|
|
91469
|
+
} else {
|
|
91470
|
+
logger.warn(`\u9996\u9078\u9023\u63A5\u57E0 ${preferredPort} \u4E0D\u53EF\u7528\uFF0C\u5C0B\u627E\u5176\u4ED6\u9023\u63A5\u57E0...`);
|
|
91471
|
+
}
|
|
91447
91472
|
}
|
|
91448
91473
|
}
|
|
91449
91474
|
for (let port = this.PORT_RANGE_START; port <= this.PORT_RANGE_END; port++) {
|
|
91475
|
+
if (this.BROWSER_UNSAFE_PORTS.has(port)) continue;
|
|
91450
91476
|
logger.debug(`\u6AA2\u67E5\u9023\u63A5\u57E0: ${port}`);
|
|
91451
91477
|
if (await this.isPortAvailable(port)) {
|
|
91452
91478
|
logger.info(`\u627E\u5230\u53EF\u7528\u9023\u63A5\u57E0: ${port}`);
|
|
@@ -91455,6 +91481,7 @@ var PortManager = class {
|
|
|
91455
91481
|
}
|
|
91456
91482
|
for (let i = 0; i < this.MAX_RETRIES; i++) {
|
|
91457
91483
|
const randomPort = Math.floor(Math.random() * (65535 - 1024) + 1024);
|
|
91484
|
+
if (this.BROWSER_UNSAFE_PORTS.has(randomPort)) continue;
|
|
91458
91485
|
logger.debug(`\u5617\u8A66\u96A8\u6A5F\u9023\u63A5\u57E0: ${randomPort}`);
|
|
91459
91486
|
if (await this.isPortAvailable(randomPort)) {
|
|
91460
91487
|
logger.info(`\u627E\u5230\u96A8\u6A5F\u53EF\u7528\u9023\u63A5\u57E0: ${randomPort}`);
|
|
@@ -92598,6 +92625,7 @@ function getPackageVersion() {
|
|
|
92598
92625
|
init_cjs_shims();
|
|
92599
92626
|
var import_fs5 = require("fs");
|
|
92600
92627
|
var import_path5 = __toESM(require("path"), 1);
|
|
92628
|
+
var import_os3 = __toESM(require("os"), 1);
|
|
92601
92629
|
init_logger();
|
|
92602
92630
|
var DEFAULT_LOCK_FILENAME = ".user-feedback.lock";
|
|
92603
92631
|
var DEFAULT_HEALTH_CHECK_TIMEOUT = 3e3;
|
|
@@ -92607,7 +92635,8 @@ var InstanceLock = class {
|
|
|
92607
92635
|
if (this.lockFilePath) {
|
|
92608
92636
|
return this.lockFilePath;
|
|
92609
92637
|
}
|
|
92610
|
-
const
|
|
92638
|
+
const envDir = process.env["MCP_DATA_DIR"];
|
|
92639
|
+
const dataDir = envDir || import_path5.default.join(import_os3.default.homedir(), ".user-web-feedback", "data");
|
|
92611
92640
|
if (!(0, import_fs5.existsSync)(dataDir)) {
|
|
92612
92641
|
(0, import_fs5.mkdirSync)(dataDir, { recursive: true });
|
|
92613
92642
|
}
|
|
@@ -92877,6 +92906,424 @@ var SelfProbeService = class {
|
|
|
92877
92906
|
// src/server/web-server.ts
|
|
92878
92907
|
init_crypto_helper();
|
|
92879
92908
|
init_ai_service();
|
|
92909
|
+
|
|
92910
|
+
// src/utils/ai-provider-factory.ts
|
|
92911
|
+
init_cjs_shims();
|
|
92912
|
+
init_database();
|
|
92913
|
+
init_logger();
|
|
92914
|
+
|
|
92915
|
+
// src/utils/api-provider.ts
|
|
92916
|
+
init_cjs_shims();
|
|
92917
|
+
init_dist();
|
|
92918
|
+
init_database();
|
|
92919
|
+
init_logger();
|
|
92920
|
+
init_mcp_client_manager();
|
|
92921
|
+
init_prompt_aggregator2();
|
|
92922
|
+
var MAX_RETRIES2 = 3;
|
|
92923
|
+
var RETRY_DELAYS2 = [1e3, 2e3, 4e3];
|
|
92924
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
92925
|
+
var CACHE_TTL3 = 5 * 60 * 1e3;
|
|
92926
|
+
function getProviderFromUrl2(apiUrl) {
|
|
92927
|
+
if (!apiUrl) return "google";
|
|
92928
|
+
const normalizedUrl = apiUrl.toLowerCase();
|
|
92929
|
+
if (normalizedUrl.includes("api.openai.com")) return "openai";
|
|
92930
|
+
if (normalizedUrl.includes("api.anthropic.com")) return "anthropic";
|
|
92931
|
+
if (normalizedUrl.includes("generativelanguage.googleapis.com")) return "google";
|
|
92932
|
+
if (normalizedUrl.includes("nvidia.com")) return "nvidia";
|
|
92933
|
+
if (normalizedUrl.includes("bigmodel.cn") || normalizedUrl.includes("z.ai")) return "zai";
|
|
92934
|
+
return "openai";
|
|
92935
|
+
}
|
|
92936
|
+
var APIProvider = class {
|
|
92937
|
+
getName() {
|
|
92938
|
+
return "API Provider";
|
|
92939
|
+
}
|
|
92940
|
+
getMode() {
|
|
92941
|
+
return "api";
|
|
92942
|
+
}
|
|
92943
|
+
async isAvailable() {
|
|
92944
|
+
const settings = getAISettings();
|
|
92945
|
+
return !!(settings?.apiKey && settings.apiKey !== "YOUR_API_KEY_HERE");
|
|
92946
|
+
}
|
|
92947
|
+
async generateReply(request) {
|
|
92948
|
+
try {
|
|
92949
|
+
const cacheKey = `${request.aiMessage}:${request.userContext || ""}`;
|
|
92950
|
+
if (!request.toolResults) {
|
|
92951
|
+
const cached2 = cache2.get(cacheKey);
|
|
92952
|
+
if (cached2 && Date.now() - cached2.timestamp < CACHE_TTL3) {
|
|
92953
|
+
logger.debug("[APIProvider] \u4F7F\u7528\u5FEB\u53D6\u56DE\u8986");
|
|
92954
|
+
return { success: true, reply: cached2.reply, mode: "api" };
|
|
92955
|
+
}
|
|
92956
|
+
}
|
|
92957
|
+
const settings = getAISettings();
|
|
92958
|
+
if (!settings || !settings.apiKey || settings.apiKey === "YOUR_API_KEY_HERE") {
|
|
92959
|
+
logger.warn("[APIProvider] API Key \u672A\u8A2D\u5B9A\u6216\u7121\u6548");
|
|
92960
|
+
return { success: false, error: "\u8ACB\u5148\u5728\u8A2D\u5B9A\u4E2D\u914D\u7F6E AI API Key", mode: "api" };
|
|
92961
|
+
}
|
|
92962
|
+
const aggregator = getPromptAggregator();
|
|
92963
|
+
const cliSettings = getCLISettings();
|
|
92964
|
+
let mcpTools = [];
|
|
92965
|
+
if (request.includeMCPTools) {
|
|
92966
|
+
try {
|
|
92967
|
+
const allTools = mcpClientManager.getAllTools();
|
|
92968
|
+
mcpTools = allTools.map((tool) => ({
|
|
92969
|
+
name: tool.name,
|
|
92970
|
+
description: tool.description,
|
|
92971
|
+
inputSchema: tool.inputSchema
|
|
92972
|
+
}));
|
|
92973
|
+
} catch (error2) {
|
|
92974
|
+
logger.warn("[APIProvider] \u7121\u6CD5\u53D6\u5F97 MCP \u5DE5\u5177", error2);
|
|
92975
|
+
}
|
|
92976
|
+
}
|
|
92977
|
+
const context = aggregator.buildContextSync(request, settings, cliSettings, mcpTools);
|
|
92978
|
+
context.mode = "api";
|
|
92979
|
+
const aggregated = aggregator.aggregate(context);
|
|
92980
|
+
const promptSent = aggregated.fullPrompt;
|
|
92981
|
+
const provider = getProviderFromUrl2(settings.apiUrl);
|
|
92982
|
+
logger.info(`[APIProvider] \u4F7F\u7528 ${provider} \u63D0\u4F9B\u5546, apiUrl: ${settings.apiUrl || "(\u9810\u8A2D)"}`);
|
|
92983
|
+
let reply;
|
|
92984
|
+
if (provider !== "google") {
|
|
92985
|
+
reply = await this.generateWithOpenAI(
|
|
92986
|
+
settings.apiKey,
|
|
92987
|
+
settings.model,
|
|
92988
|
+
settings.apiUrl,
|
|
92989
|
+
promptSent,
|
|
92990
|
+
settings.temperature,
|
|
92991
|
+
settings.maxTokens
|
|
92992
|
+
);
|
|
92993
|
+
} else {
|
|
92994
|
+
reply = await this.generateWithGoogle(
|
|
92995
|
+
settings.apiKey,
|
|
92996
|
+
settings.model,
|
|
92997
|
+
promptSent,
|
|
92998
|
+
settings.temperature,
|
|
92999
|
+
settings.maxTokens
|
|
93000
|
+
);
|
|
93001
|
+
}
|
|
93002
|
+
if (!request.toolResults) {
|
|
93003
|
+
cache2.set(cacheKey, { reply, timestamp: Date.now() });
|
|
93004
|
+
this.cleanExpiredCache();
|
|
93005
|
+
}
|
|
93006
|
+
return { success: true, reply, promptSent, mode: "api" };
|
|
93007
|
+
} catch (error2) {
|
|
93008
|
+
logger.error("[APIProvider] \u751F\u6210\u56DE\u8986\u5931\u6557", error2);
|
|
93009
|
+
return {
|
|
93010
|
+
success: false,
|
|
93011
|
+
error: error2 instanceof Error ? error2.message : "\u672A\u77E5\u932F\u8AA4",
|
|
93012
|
+
mode: "api"
|
|
93013
|
+
};
|
|
93014
|
+
}
|
|
93015
|
+
}
|
|
93016
|
+
async generateWithGoogle(apiKey, model, prompt, temperature, maxTokens, retryCount = 0) {
|
|
93017
|
+
try {
|
|
93018
|
+
const genAI = new GoogleGenerativeAI(apiKey);
|
|
93019
|
+
const generativeModel = genAI.getGenerativeModel({
|
|
93020
|
+
model,
|
|
93021
|
+
generationConfig: {
|
|
93022
|
+
temperature: temperature ?? 0.7,
|
|
93023
|
+
maxOutputTokens: maxTokens ?? 1e3
|
|
93024
|
+
}
|
|
93025
|
+
});
|
|
93026
|
+
const result = await generativeModel.generateContent(prompt);
|
|
93027
|
+
const response = await result.response;
|
|
93028
|
+
const text = response.text();
|
|
93029
|
+
if (!text) throw new Error("AI \u56DE\u8986\u70BA\u7A7A");
|
|
93030
|
+
return text;
|
|
93031
|
+
} catch (error2) {
|
|
93032
|
+
if (error2 instanceof Error) {
|
|
93033
|
+
if (error2.message.includes("429") || error2.message.includes("quota")) {
|
|
93034
|
+
if (retryCount < MAX_RETRIES2) {
|
|
93035
|
+
await this.sleep(RETRY_DELAYS2[retryCount] || 4e3);
|
|
93036
|
+
return this.generateWithGoogle(apiKey, model, prompt, temperature, maxTokens, retryCount + 1);
|
|
93037
|
+
}
|
|
93038
|
+
throw new Error("API \u914D\u984D\u5DF2\u7528\u76E1\u6216\u901F\u7387\u9650\u5236\uFF0C\u8ACB\u7A0D\u5F8C\u518D\u8A66");
|
|
93039
|
+
}
|
|
93040
|
+
if (error2.message.includes("API key") || error2.message.includes("401")) {
|
|
93041
|
+
throw new Error("API Key \u7121\u6548\uFF0C\u8ACB\u6AA2\u67E5\u8A2D\u5B9A");
|
|
93042
|
+
}
|
|
93043
|
+
if (retryCount < MAX_RETRIES2) {
|
|
93044
|
+
await this.sleep(RETRY_DELAYS2[retryCount] || 4e3);
|
|
93045
|
+
return this.generateWithGoogle(apiKey, model, prompt, temperature, maxTokens, retryCount + 1);
|
|
93046
|
+
}
|
|
93047
|
+
}
|
|
93048
|
+
throw error2;
|
|
93049
|
+
}
|
|
93050
|
+
}
|
|
93051
|
+
async generateWithOpenAI(apiKey, model, apiUrl, prompt, temperature, maxTokens, retryCount = 0) {
|
|
93052
|
+
try {
|
|
93053
|
+
const OpenAI = (await import("openai")).default;
|
|
93054
|
+
const client = new OpenAI({
|
|
93055
|
+
apiKey,
|
|
93056
|
+
baseURL: apiUrl || "https://api.openai.com/v1"
|
|
93057
|
+
});
|
|
93058
|
+
const response = await client.chat.completions.create({
|
|
93059
|
+
model,
|
|
93060
|
+
messages: [{ role: "user", content: prompt }],
|
|
93061
|
+
temperature: temperature ?? 0.7,
|
|
93062
|
+
max_tokens: maxTokens ?? 1e3
|
|
93063
|
+
});
|
|
93064
|
+
const text = response.choices?.[0]?.message?.content;
|
|
93065
|
+
if (!text) throw new Error("AI \u56DE\u8986\u70BA\u7A7A");
|
|
93066
|
+
return text;
|
|
93067
|
+
} catch (error2) {
|
|
93068
|
+
if (error2 instanceof Error) {
|
|
93069
|
+
if (error2.message.includes("429") || error2.message.includes("quota") || error2.message.includes("rate")) {
|
|
93070
|
+
if (retryCount < MAX_RETRIES2) {
|
|
93071
|
+
await this.sleep(RETRY_DELAYS2[retryCount] || 4e3);
|
|
93072
|
+
return this.generateWithOpenAI(apiKey, model, apiUrl, prompt, temperature, maxTokens, retryCount + 1);
|
|
93073
|
+
}
|
|
93074
|
+
throw new Error("API \u914D\u984D\u5DF2\u7528\u76E1\u6216\u901F\u7387\u9650\u5236\uFF0C\u8ACB\u7A0D\u5F8C\u518D\u8A66");
|
|
93075
|
+
}
|
|
93076
|
+
if (error2.message.includes("API key") || error2.message.includes("401") || error2.message.includes("Unauthorized")) {
|
|
93077
|
+
throw new Error("API Key \u7121\u6548\uFF0C\u8ACB\u6AA2\u67E5\u8A2D\u5B9A");
|
|
93078
|
+
}
|
|
93079
|
+
if (retryCount < MAX_RETRIES2) {
|
|
93080
|
+
await this.sleep(RETRY_DELAYS2[retryCount] || 4e3);
|
|
93081
|
+
return this.generateWithOpenAI(apiKey, model, apiUrl, prompt, temperature, maxTokens, retryCount + 1);
|
|
93082
|
+
}
|
|
93083
|
+
}
|
|
93084
|
+
throw error2;
|
|
93085
|
+
}
|
|
93086
|
+
}
|
|
93087
|
+
sleep(ms) {
|
|
93088
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
93089
|
+
}
|
|
93090
|
+
cleanExpiredCache() {
|
|
93091
|
+
const now = Date.now();
|
|
93092
|
+
for (const [key, entry] of cache2.entries()) {
|
|
93093
|
+
if (now - entry.timestamp > CACHE_TTL3) cache2.delete(key);
|
|
93094
|
+
}
|
|
93095
|
+
}
|
|
93096
|
+
};
|
|
93097
|
+
|
|
93098
|
+
// src/utils/cli-provider.ts
|
|
93099
|
+
init_cjs_shims();
|
|
93100
|
+
init_database();
|
|
93101
|
+
init_logger();
|
|
93102
|
+
init_cli_executor();
|
|
93103
|
+
init_cli_detector();
|
|
93104
|
+
init_mcp_client_manager();
|
|
93105
|
+
init_prompt_aggregator2();
|
|
93106
|
+
var CLIProvider = class {
|
|
93107
|
+
cliSettings;
|
|
93108
|
+
constructor(cliSettings) {
|
|
93109
|
+
this.cliSettings = cliSettings;
|
|
93110
|
+
}
|
|
93111
|
+
getName() {
|
|
93112
|
+
return `CLI (${this.cliSettings.cliTool})`;
|
|
93113
|
+
}
|
|
93114
|
+
getMode() {
|
|
93115
|
+
return "cli";
|
|
93116
|
+
}
|
|
93117
|
+
async isAvailable() {
|
|
93118
|
+
return isToolAvailable(this.cliSettings.cliTool);
|
|
93119
|
+
}
|
|
93120
|
+
async generateReply(request) {
|
|
93121
|
+
const tool = this.cliSettings.cliTool;
|
|
93122
|
+
const available = await this.isAvailable();
|
|
93123
|
+
if (!available) {
|
|
93124
|
+
logger.warn(`[CLIProvider] CLI tool not available: ${tool}`);
|
|
93125
|
+
return {
|
|
93126
|
+
success: false,
|
|
93127
|
+
error: `CLI \u5DE5\u5177 ${tool} \u672A\u5B89\u88DD\u6216\u4E0D\u53EF\u7528`,
|
|
93128
|
+
mode: "cli",
|
|
93129
|
+
cliTool: tool
|
|
93130
|
+
};
|
|
93131
|
+
}
|
|
93132
|
+
const terminalId = `${request.projectPath || "default"}-${tool}`.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
93133
|
+
let terminal = getCLITerminalById(terminalId);
|
|
93134
|
+
if (!terminal) {
|
|
93135
|
+
terminal = createCLITerminal({
|
|
93136
|
+
id: terminalId,
|
|
93137
|
+
projectName: request.projectName || "\u672A\u547D\u540D\u5C08\u6848",
|
|
93138
|
+
projectPath: request.projectPath || "",
|
|
93139
|
+
tool,
|
|
93140
|
+
status: "running",
|
|
93141
|
+
pid: void 0
|
|
93142
|
+
});
|
|
93143
|
+
} else {
|
|
93144
|
+
updateCLITerminal(terminalId, { status: "running" });
|
|
93145
|
+
}
|
|
93146
|
+
const aggregator = getPromptAggregator();
|
|
93147
|
+
const settings = getAISettings();
|
|
93148
|
+
const cliSettings = getCLISettings();
|
|
93149
|
+
let mcpTools = [];
|
|
93150
|
+
if (request.includeMCPTools) {
|
|
93151
|
+
try {
|
|
93152
|
+
const allTools = mcpClientManager.getAllTools();
|
|
93153
|
+
mcpTools = allTools.map((t) => ({
|
|
93154
|
+
name: t.name,
|
|
93155
|
+
description: t.description,
|
|
93156
|
+
inputSchema: t.inputSchema
|
|
93157
|
+
}));
|
|
93158
|
+
} catch {
|
|
93159
|
+
logger.warn("[CLIProvider] \u7121\u6CD5\u7372\u53D6 MCP \u5DE5\u5177");
|
|
93160
|
+
}
|
|
93161
|
+
}
|
|
93162
|
+
const context = aggregator.buildContextSync(request, settings ?? null, cliSettings, mcpTools);
|
|
93163
|
+
context.mode = "cli";
|
|
93164
|
+
const aggregated = aggregator.aggregate(context);
|
|
93165
|
+
const prompt = aggregated.fullPrompt;
|
|
93166
|
+
logger.info(`[CLIProvider] Prompt \u5927\u5C0F\u5206\u6790:`, {
|
|
93167
|
+
totalLength: prompt.length,
|
|
93168
|
+
totalKB: (prompt.length / 1024).toFixed(2) + " KB",
|
|
93169
|
+
mcpToolsCount: mcpTools.length,
|
|
93170
|
+
mcpToolsSize: JSON.stringify(mcpTools).length,
|
|
93171
|
+
systemPromptLength: settings?.systemPrompt?.length || 0,
|
|
93172
|
+
aiMessageLength: request.aiMessage?.length || 0,
|
|
93173
|
+
userContextLength: request.userContext?.length || 0,
|
|
93174
|
+
timeout: this.cliSettings.cliTimeout
|
|
93175
|
+
});
|
|
93176
|
+
try {
|
|
93177
|
+
const result = await executeCLI({
|
|
93178
|
+
tool,
|
|
93179
|
+
prompt,
|
|
93180
|
+
timeout: this.cliSettings.cliTimeout,
|
|
93181
|
+
workingDirectory: request.projectPath,
|
|
93182
|
+
outputFormat: "text"
|
|
93183
|
+
});
|
|
93184
|
+
insertCLIExecutionLog({
|
|
93185
|
+
terminalId,
|
|
93186
|
+
prompt: prompt.substring(0, 1e3),
|
|
93187
|
+
response: result.success ? result.output.substring(0, 5e3) : null,
|
|
93188
|
+
executionTime: result.executionTime,
|
|
93189
|
+
success: result.success,
|
|
93190
|
+
error: result.error
|
|
93191
|
+
});
|
|
93192
|
+
if (!result.success) {
|
|
93193
|
+
updateCLITerminal(terminalId, { status: "error" });
|
|
93194
|
+
return {
|
|
93195
|
+
success: false,
|
|
93196
|
+
error: result.error || "CLI \u57F7\u884C\u5931\u6557",
|
|
93197
|
+
mode: "cli",
|
|
93198
|
+
cliTool: tool,
|
|
93199
|
+
promptSent: prompt
|
|
93200
|
+
};
|
|
93201
|
+
}
|
|
93202
|
+
if (request.includeMCPTools) {
|
|
93203
|
+
const mcpHandler = createCLIMCPHandler(settings?.maxToolRounds || 10);
|
|
93204
|
+
updateCLITerminal(terminalId, { status: "mcp-processing" });
|
|
93205
|
+
const handlerResult = await mcpHandler.handleResponse(result.output, (call) => {
|
|
93206
|
+
logger.info(`[CLIProvider] \u57F7\u884C MCP \u5DE5\u5177: ${call.toolName}`);
|
|
93207
|
+
});
|
|
93208
|
+
if (handlerResult.toolCallsDetected) {
|
|
93209
|
+
insertCLIExecutionLog({
|
|
93210
|
+
terminalId,
|
|
93211
|
+
prompt: `[MCP] ${handlerResult.toolResults.length} \u500B\u5DE5\u5177\u547C\u53EB`,
|
|
93212
|
+
response: handlerResult.finalResponse.substring(0, 5e3),
|
|
93213
|
+
executionTime: handlerResult.toolResults.reduce((sum, r) => sum + r.executionTime, 0),
|
|
93214
|
+
success: true,
|
|
93215
|
+
error: void 0
|
|
93216
|
+
});
|
|
93217
|
+
}
|
|
93218
|
+
updateCLITerminal(terminalId, { status: "idle" });
|
|
93219
|
+
return {
|
|
93220
|
+
success: true,
|
|
93221
|
+
reply: handlerResult.finalResponse,
|
|
93222
|
+
mode: "cli",
|
|
93223
|
+
cliTool: tool,
|
|
93224
|
+
promptSent: prompt
|
|
93225
|
+
};
|
|
93226
|
+
}
|
|
93227
|
+
updateCLITerminal(terminalId, { status: "idle" });
|
|
93228
|
+
return {
|
|
93229
|
+
success: true,
|
|
93230
|
+
reply: result.output,
|
|
93231
|
+
mode: "cli",
|
|
93232
|
+
cliTool: tool,
|
|
93233
|
+
promptSent: prompt
|
|
93234
|
+
};
|
|
93235
|
+
} catch (error2) {
|
|
93236
|
+
insertCLIExecutionLog({
|
|
93237
|
+
terminalId,
|
|
93238
|
+
prompt: prompt.substring(0, 1e3),
|
|
93239
|
+
response: null,
|
|
93240
|
+
executionTime: 0,
|
|
93241
|
+
success: false,
|
|
93242
|
+
error: error2 instanceof Error ? error2.message : "\u672A\u77E5\u932F\u8AA4"
|
|
93243
|
+
});
|
|
93244
|
+
updateCLITerminal(terminalId, { status: "error" });
|
|
93245
|
+
return {
|
|
93246
|
+
success: false,
|
|
93247
|
+
error: error2 instanceof Error ? error2.message : "\u672A\u77E5\u932F\u8AA4",
|
|
93248
|
+
mode: "cli",
|
|
93249
|
+
cliTool: tool,
|
|
93250
|
+
promptSent: prompt
|
|
93251
|
+
};
|
|
93252
|
+
}
|
|
93253
|
+
}
|
|
93254
|
+
};
|
|
93255
|
+
|
|
93256
|
+
// src/utils/ai-provider-factory.ts
|
|
93257
|
+
var AIProviderFactory = class _AIProviderFactory {
|
|
93258
|
+
static instance;
|
|
93259
|
+
currentProvider = null;
|
|
93260
|
+
fallbackProvider = null;
|
|
93261
|
+
constructor() {
|
|
93262
|
+
}
|
|
93263
|
+
/**
|
|
93264
|
+
* 取得工廠實例 (Singleton)
|
|
93265
|
+
*/
|
|
93266
|
+
static getInstance() {
|
|
93267
|
+
if (!_AIProviderFactory.instance) {
|
|
93268
|
+
_AIProviderFactory.instance = new _AIProviderFactory();
|
|
93269
|
+
}
|
|
93270
|
+
return _AIProviderFactory.instance;
|
|
93271
|
+
}
|
|
93272
|
+
/**
|
|
93273
|
+
* 根據設定取得適當的 Provider
|
|
93274
|
+
*/
|
|
93275
|
+
async getProvider() {
|
|
93276
|
+
const cliSettings = getCLISettings();
|
|
93277
|
+
const mode = cliSettings?.aiMode === "cli" ? "cli" : "api";
|
|
93278
|
+
logger.debug("[AIProviderFactory] \u53D6\u5F97 Provider", { mode, cliTool: cliSettings?.cliTool });
|
|
93279
|
+
if (mode === "cli") {
|
|
93280
|
+
const cliProvider = new CLIProvider(cliSettings);
|
|
93281
|
+
const available = await cliProvider.isAvailable();
|
|
93282
|
+
if (!available) {
|
|
93283
|
+
logger.warn("[AIProviderFactory] CLI Provider \u4E0D\u53EF\u7528");
|
|
93284
|
+
if (cliSettings?.cliFallbackToApi) {
|
|
93285
|
+
logger.info("[AIProviderFactory] \u56DE\u9000\u5230 API Provider");
|
|
93286
|
+
return new APIProvider();
|
|
93287
|
+
}
|
|
93288
|
+
throw new Error(`CLI \u5DE5\u5177 ${cliSettings?.cliTool} \u4E0D\u53EF\u7528\uFF0C\u4E14\u672A\u555F\u7528 API \u56DE\u9000`);
|
|
93289
|
+
}
|
|
93290
|
+
return cliProvider;
|
|
93291
|
+
}
|
|
93292
|
+
return new APIProvider();
|
|
93293
|
+
}
|
|
93294
|
+
/**
|
|
93295
|
+
* 取得當前模式
|
|
93296
|
+
*/
|
|
93297
|
+
getCurrentMode() {
|
|
93298
|
+
const cliSettings = getCLISettings();
|
|
93299
|
+
return cliSettings?.aiMode === "cli" ? "cli" : "api";
|
|
93300
|
+
}
|
|
93301
|
+
/**
|
|
93302
|
+
* 取得當前 CLI 工具名稱
|
|
93303
|
+
*/
|
|
93304
|
+
getCurrentCLITool() {
|
|
93305
|
+
const cliSettings = getCLISettings();
|
|
93306
|
+
return cliSettings?.cliTool;
|
|
93307
|
+
}
|
|
93308
|
+
/**
|
|
93309
|
+
* 使用工廠生成 AI 回覆
|
|
93310
|
+
*/
|
|
93311
|
+
async generateReply(request) {
|
|
93312
|
+
try {
|
|
93313
|
+
const provider = await this.getProvider();
|
|
93314
|
+
logger.info(`[AIProviderFactory] \u4F7F\u7528 ${provider.getName()} \u751F\u6210\u56DE\u8986`);
|
|
93315
|
+
return provider.generateReply(request);
|
|
93316
|
+
} catch (error2) {
|
|
93317
|
+
logger.error("[AIProviderFactory] \u751F\u6210\u56DE\u8986\u5931\u6557", error2);
|
|
93318
|
+
return {
|
|
93319
|
+
success: false,
|
|
93320
|
+
error: error2 instanceof Error ? error2.message : "\u672A\u77E5\u932F\u8AA4"
|
|
93321
|
+
};
|
|
93322
|
+
}
|
|
93323
|
+
}
|
|
93324
|
+
};
|
|
93325
|
+
|
|
93326
|
+
// src/server/web-server.ts
|
|
92880
93327
|
init_mcp_client_manager();
|
|
92881
93328
|
init_cli_detector();
|
|
92882
93329
|
|
|
@@ -93915,8 +94362,9 @@ var WebServer = class {
|
|
|
93915
94362
|
});
|
|
93916
94363
|
return;
|
|
93917
94364
|
}
|
|
93918
|
-
logger.info("\u958B\u59CB\u751F\u6210 AI \u56DE\u8986");
|
|
93919
|
-
const
|
|
94365
|
+
logger.info("\u958B\u59CB\u751F\u6210 AI \u56DE\u8986 (AIProviderFactory)");
|
|
94366
|
+
const factory = AIProviderFactory.getInstance();
|
|
94367
|
+
const result = await factory.generateReply(data);
|
|
93920
94368
|
if (result.success) {
|
|
93921
94369
|
logger.info("AI \u56DE\u8986\u751F\u6210\u6210\u529F");
|
|
93922
94370
|
} else {
|
|
@@ -95294,7 +95742,8 @@ var WebServer = class {
|
|
|
95294
95742
|
const autoReplyTimer = setTimeout(async () => {
|
|
95295
95743
|
logger.info(`\u89F8\u767C\u81EA\u52D5\u56DE\u8986: \u6703\u8A71 ${sessionId}`);
|
|
95296
95744
|
try {
|
|
95297
|
-
const
|
|
95745
|
+
const factory = AIProviderFactory.getInstance();
|
|
95746
|
+
const result = await factory.generateReply({
|
|
95298
95747
|
aiMessage: workSummary,
|
|
95299
95748
|
userContext: "\u4F7F\u7528\u8005\u672A\u5728\u6642\u9593\u5167\u56DE\u61C9\uFF0C\u7CFB\u7D71\u81EA\u52D5\u751F\u6210\u56DE\u8986"
|
|
95300
95749
|
});
|
|
@@ -96408,7 +96857,7 @@ var import_url3 = require("url");
|
|
|
96408
96857
|
init_cjs_shims();
|
|
96409
96858
|
var import_events4 = require("events");
|
|
96410
96859
|
var import_child_process4 = require("child_process");
|
|
96411
|
-
var
|
|
96860
|
+
var os6 = __toESM(require("os"), 1);
|
|
96412
96861
|
|
|
96413
96862
|
// src/supervisor/ipc-bridge.ts
|
|
96414
96863
|
init_cjs_shims();
|
|
@@ -96904,8 +97353,8 @@ var SupervisorService = class extends import_events4.EventEmitter {
|
|
|
96904
97353
|
system: {
|
|
96905
97354
|
platform: process.platform,
|
|
96906
97355
|
nodeVersion: process.version,
|
|
96907
|
-
totalMemory:
|
|
96908
|
-
freeMemory:
|
|
97356
|
+
totalMemory: os6.totalmem(),
|
|
97357
|
+
freeMemory: os6.freemem()
|
|
96909
97358
|
},
|
|
96910
97359
|
restartHistory: this.restartHistory
|
|
96911
97360
|
};
|