droid-patch 0.5.0 → 0.6.1
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 +91 -16
- package/README.zh-CN.md +91 -16
- package/dist/{alias-DVggcM0G.mjs → alias-DKVU8DM_.mjs} +9 -1
- package/dist/alias-DKVU8DM_.mjs.map +1 -0
- package/dist/cli.mjs +119 -18
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/dist/alias-DVggcM0G.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as removeAlias, d as listAllMetadata, f as loadAliasMetadata, i as listAliases, l as createMetadata, m as patchDroid, n as createAlias, o as removeAliasesByFilter, p as saveAliasMetadata, r as createAliasForWrapper, t as clearAllAliases, u as formatPatches } from "./alias-
|
|
2
|
+
import { a as removeAlias, d as listAllMetadata, f as loadAliasMetadata, i as listAliases, l as createMetadata, m as patchDroid, n as createAlias, o as removeAliasesByFilter, p as saveAliasMetadata, r as createAliasForWrapper, t as clearAllAliases, u as formatPatches } from "./alias-DKVU8DM_.mjs";
|
|
3
3
|
import bin from "tiny-bin";
|
|
4
4
|
import { styleText } from "node:util";
|
|
5
5
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -415,7 +415,48 @@ const server = http.createServer(async (req, res) => {
|
|
|
415
415
|
return;
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
-
//
|
|
418
|
+
// === Standalone mode (controlled by STANDALONE_MODE env) ===
|
|
419
|
+
// Whitelist approach: only allow core LLM APIs, mock everything else
|
|
420
|
+
if (process.env.STANDALONE_MODE === '1') {
|
|
421
|
+
const pathname = url.pathname;
|
|
422
|
+
|
|
423
|
+
// Whitelist: Core APIs that should be forwarded to upstream
|
|
424
|
+
const isCoreLLMApi = pathname.startsWith('/api/llm/a/') || pathname.startsWith('/api/llm/o/');
|
|
425
|
+
// /api/tools/exa/search is already handled above
|
|
426
|
+
|
|
427
|
+
if (!isCoreLLMApi) {
|
|
428
|
+
// Special handling for specific routes
|
|
429
|
+
if (pathname === '/api/sessions/create') {
|
|
430
|
+
log('Mock (dynamic):', pathname);
|
|
431
|
+
const sessionId = \`local-\${Date.now()}-\${Math.random().toString(36).slice(2, 10)}\`;
|
|
432
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
433
|
+
res.end(JSON.stringify({ id: sessionId }));
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (pathname === '/api/cli/whoami') {
|
|
438
|
+
log('Mock (401):', pathname);
|
|
439
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
440
|
+
res.end(JSON.stringify({ error: 'Unauthorized', message: 'Local mode - use token fallback' }));
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (pathname === '/api/tools/get-url-contents') {
|
|
445
|
+
log('Mock (404):', pathname);
|
|
446
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
447
|
+
res.end(JSON.stringify({ error: 'Not available', message: 'Use local URL fetch fallback' }));
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// All other non-core APIs: return empty success
|
|
452
|
+
log('Mock (default):', pathname);
|
|
453
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
454
|
+
res.end(JSON.stringify({}));
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Proxy core LLM requests to upstream API
|
|
419
460
|
log('Proxy:', req.method, url.pathname);
|
|
420
461
|
|
|
421
462
|
const proxyUrl = new URL(FACTORY_API + url.pathname + url.search);
|
|
@@ -477,7 +518,8 @@ process.on('SIGINT', () => { server.close(); process.exit(0); });
|
|
|
477
518
|
* - Proxy is killed when droid exits
|
|
478
519
|
* - Supports multiple droid instances running simultaneously
|
|
479
520
|
*/
|
|
480
|
-
function generateUnifiedWrapper(droidPath, proxyScriptPath) {
|
|
521
|
+
function generateUnifiedWrapper(droidPath, proxyScriptPath, standalone = false) {
|
|
522
|
+
const standaloneEnv = standalone ? "STANDALONE_MODE=1 " : "";
|
|
481
523
|
return `#!/bin/bash
|
|
482
524
|
# Droid with WebSearch
|
|
483
525
|
# Auto-generated by droid-patch --websearch
|
|
@@ -487,6 +529,7 @@ PROXY_SCRIPT="${proxyScriptPath}"
|
|
|
487
529
|
DROID_BIN="${droidPath}"
|
|
488
530
|
PROXY_PID=""
|
|
489
531
|
PORT_FILE="/tmp/droid-websearch-\$\$.port"
|
|
532
|
+
STANDALONE="${standalone ? "1" : "0"}"
|
|
490
533
|
|
|
491
534
|
# Cleanup function - kill proxy when droid exits
|
|
492
535
|
cleanup() {
|
|
@@ -502,13 +545,14 @@ cleanup() {
|
|
|
502
545
|
trap cleanup EXIT INT TERM
|
|
503
546
|
|
|
504
547
|
[ -n "\$DROID_SEARCH_DEBUG" ] && echo "[websearch] Starting proxy..." >&2
|
|
548
|
+
[ "\$STANDALONE" = "1" ] && [ -n "\$DROID_SEARCH_DEBUG" ] && echo "[websearch] Standalone mode enabled" >&2
|
|
505
549
|
|
|
506
550
|
# Start proxy with port 0 (system will assign available port)
|
|
507
551
|
# Proxy writes actual port to PORT_FILE
|
|
508
552
|
if [ -n "\$DROID_SEARCH_DEBUG" ]; then
|
|
509
|
-
SEARCH_PROXY_PORT=0 SEARCH_PROXY_PORT_FILE="\$PORT_FILE" node "\$PROXY_SCRIPT" 2>&1 &
|
|
553
|
+
${standaloneEnv}SEARCH_PROXY_PORT=0 SEARCH_PROXY_PORT_FILE="\$PORT_FILE" node "\$PROXY_SCRIPT" 2>&1 &
|
|
510
554
|
else
|
|
511
|
-
SEARCH_PROXY_PORT=0 SEARCH_PROXY_PORT_FILE="\$PORT_FILE" node "\$PROXY_SCRIPT" >/dev/null 2>&1 &
|
|
555
|
+
${standaloneEnv}SEARCH_PROXY_PORT=0 SEARCH_PROXY_PORT_FILE="\$PORT_FILE" node "\$PROXY_SCRIPT" >/dev/null 2>&1 &
|
|
512
556
|
fi
|
|
513
557
|
PROXY_PID=\$!
|
|
514
558
|
|
|
@@ -561,16 +605,18 @@ exit \$DROID_EXIT_CODE
|
|
|
561
605
|
* @param droidPath - Path to droid binary
|
|
562
606
|
* @param aliasName - Alias name for the wrapper
|
|
563
607
|
* @param apiBase - Custom API base URL for proxy to forward requests to
|
|
608
|
+
* @param standalone - Standalone mode: mock non-LLM Factory APIs
|
|
564
609
|
*/
|
|
565
|
-
async function createWebSearchUnifiedFiles(outputDir, droidPath, aliasName, apiBase) {
|
|
610
|
+
async function createWebSearchUnifiedFiles(outputDir, droidPath, aliasName, apiBase, standalone = false) {
|
|
566
611
|
if (!existsSync(outputDir)) await mkdir(outputDir, { recursive: true });
|
|
567
612
|
const proxyScriptPath = join(outputDir, `${aliasName}-proxy.js`);
|
|
568
613
|
const wrapperScriptPath = join(outputDir, aliasName);
|
|
569
614
|
await writeFile(proxyScriptPath, generateSearchProxyServer(apiBase || "https://api.factory.ai"));
|
|
570
615
|
console.log(`[*] Created proxy script: ${proxyScriptPath}`);
|
|
571
|
-
await writeFile(wrapperScriptPath, generateUnifiedWrapper(droidPath, proxyScriptPath));
|
|
616
|
+
await writeFile(wrapperScriptPath, generateUnifiedWrapper(droidPath, proxyScriptPath, standalone));
|
|
572
617
|
await chmod(wrapperScriptPath, 493);
|
|
573
618
|
console.log(`[*] Created wrapper: ${wrapperScriptPath}`);
|
|
619
|
+
if (standalone) console.log(`[*] Standalone mode enabled`);
|
|
574
620
|
return {
|
|
575
621
|
wrapperScript: wrapperScriptPath,
|
|
576
622
|
preloadScript: proxyScriptPath
|
|
@@ -629,21 +675,23 @@ function findDefaultDroidPath() {
|
|
|
629
675
|
for (const p of paths) if (existsSync(p)) return p;
|
|
630
676
|
return join(home, ".droid", "bin", "droid");
|
|
631
677
|
}
|
|
632
|
-
bin("droid-patch", "CLI tool to patch droid binary with various modifications").package("droid-patch", version).option("--is-custom", "Patch isCustom:!0 to isCustom:!1 (enable context compression for custom models)").option("--skip-login", "Inject a fake FACTORY_API_KEY to bypass login requirement (no real key needed)").option("--api-base <url>", "Replace
|
|
678
|
+
bin("droid-patch", "CLI tool to patch droid binary with various modifications").package("droid-patch", version).option("--is-custom", "Patch isCustom:!0 to isCustom:!1 (enable context compression for custom models)").option("--skip-login", "Inject a fake FACTORY_API_KEY to bypass login requirement (no real key needed)").option("--api-base <url>", "Replace API URL (standalone: binary patch, max 22 chars; with --websearch: proxy forward target, no limit)").option("--websearch", "Enable local WebSearch proxy (each instance runs own proxy, auto-cleanup on exit)").option("--standalone", "Standalone mode: mock non-LLM Factory APIs (use with --websearch)").option("--reasoning-effort", "Enable reasoning effort for custom models (set to high, enable UI selector)").option("--disable-telemetry", "Disable telemetry and Sentry error reporting (block data uploads)").option("--dry-run", "Verify patches without actually modifying the binary").option("-p, --path <path>", "Path to the droid binary").option("-o, --output <dir>", "Output directory for patched binary").option("--no-backup", "Do not create backup of original binary").option("-v, --verbose", "Enable verbose output").argument("[alias]", "Alias name for the patched binary").action(async (options, args) => {
|
|
633
679
|
const alias = args?.[0];
|
|
634
680
|
const isCustom = options["is-custom"];
|
|
635
681
|
const skipLogin = options["skip-login"];
|
|
636
682
|
const apiBase = options["api-base"];
|
|
637
683
|
const websearch = options["websearch"];
|
|
684
|
+
const standalone = options["standalone"];
|
|
638
685
|
const websearchTarget = websearch ? apiBase || "https://api.factory.ai" : void 0;
|
|
639
686
|
const reasoningEffort = options["reasoning-effort"];
|
|
687
|
+
const noTelemetry = options["disable-telemetry"];
|
|
640
688
|
const dryRun = options["dry-run"];
|
|
641
689
|
const path = options.path || findDefaultDroidPath();
|
|
642
690
|
const outputDir = options.output;
|
|
643
691
|
const backup = options.backup !== false;
|
|
644
692
|
const verbose = options.verbose;
|
|
645
693
|
const outputPath = outputDir && alias ? join(outputDir, alias) : void 0;
|
|
646
|
-
if (websearch && !isCustom && !skipLogin && !reasoningEffort) {
|
|
694
|
+
if (websearch && !isCustom && !skipLogin && !reasoningEffort && !noTelemetry) {
|
|
647
695
|
if (!alias) {
|
|
648
696
|
console.log(styleText("red", "Error: Alias name required for --websearch"));
|
|
649
697
|
console.log(styleText("gray", "Usage: npx droid-patch --websearch <alias>"));
|
|
@@ -654,8 +702,9 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
654
702
|
console.log(styleText("cyan", "═".repeat(60)));
|
|
655
703
|
console.log();
|
|
656
704
|
console.log(styleText("white", `Forward target: ${websearchTarget}`));
|
|
705
|
+
if (standalone) console.log(styleText("white", `Standalone mode: enabled`));
|
|
657
706
|
console.log();
|
|
658
|
-
const { wrapperScript } = await createWebSearchUnifiedFiles(join(homedir(), ".droid-patch", "proxy"), path, alias, websearchTarget);
|
|
707
|
+
const { wrapperScript } = await createWebSearchUnifiedFiles(join(homedir(), ".droid-patch", "proxy"), path, alias, websearchTarget, standalone);
|
|
659
708
|
await createAliasForWrapper(wrapperScript, alias, verbose);
|
|
660
709
|
const droidVersion = getDroidVersion(path);
|
|
661
710
|
await saveAliasMetadata(createMetadata(alias, path, {
|
|
@@ -663,7 +712,9 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
663
712
|
skipLogin: false,
|
|
664
713
|
apiBase: apiBase || null,
|
|
665
714
|
websearch: true,
|
|
666
|
-
reasoningEffort: false
|
|
715
|
+
reasoningEffort: false,
|
|
716
|
+
noTelemetry: false,
|
|
717
|
+
standalone
|
|
667
718
|
}, {
|
|
668
719
|
droidPatchVersion: version,
|
|
669
720
|
droidVersion
|
|
@@ -693,19 +744,23 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
693
744
|
console.log(styleText("gray", " export DROID_SEARCH_DEBUG=1"));
|
|
694
745
|
return;
|
|
695
746
|
}
|
|
696
|
-
if (!isCustom && !skipLogin && !apiBase && !websearch && !reasoningEffort) {
|
|
747
|
+
if (!isCustom && !skipLogin && !apiBase && !websearch && !reasoningEffort && !noTelemetry) {
|
|
697
748
|
console.log(styleText("yellow", "No patch flags specified. Available patches:"));
|
|
698
749
|
console.log(styleText("gray", " --is-custom Patch isCustom for custom models"));
|
|
699
750
|
console.log(styleText("gray", " --skip-login Bypass login by injecting a fake API key"));
|
|
700
|
-
console.log(styleText("gray", " --api-base Replace
|
|
751
|
+
console.log(styleText("gray", " --api-base Replace API URL (standalone: max 22 chars; with --websearch: no limit)"));
|
|
701
752
|
console.log(styleText("gray", " --websearch Enable local WebSearch proxy"));
|
|
702
753
|
console.log(styleText("gray", " --reasoning-effort Set reasoning effort level for custom models"));
|
|
754
|
+
console.log(styleText("gray", " --disable-telemetry Disable telemetry and Sentry error reporting"));
|
|
755
|
+
console.log(styleText("gray", " --standalone Standalone mode: mock non-LLM Factory APIs"));
|
|
703
756
|
console.log();
|
|
704
757
|
console.log("Usage examples:");
|
|
705
758
|
console.log(styleText("cyan", " npx droid-patch --is-custom droid-custom"));
|
|
706
759
|
console.log(styleText("cyan", " npx droid-patch --skip-login droid-nologin"));
|
|
707
760
|
console.log(styleText("cyan", " npx droid-patch --is-custom --skip-login droid-patched"));
|
|
708
761
|
console.log(styleText("cyan", " npx droid-patch --websearch droid-search"));
|
|
762
|
+
console.log(styleText("cyan", " npx droid-patch --websearch --standalone droid-local"));
|
|
763
|
+
console.log(styleText("cyan", " npx droid-patch --disable-telemetry droid-private"));
|
|
709
764
|
console.log(styleText("cyan", " npx droid-patch --websearch --api-base=http://127.0.0.1:20002 my-droid"));
|
|
710
765
|
process.exit(1);
|
|
711
766
|
}
|
|
@@ -786,6 +841,26 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
786
841
|
replacement: Buffer.from("if(0&&!B.supportedReasoningEfforts.includes(R))")
|
|
787
842
|
});
|
|
788
843
|
}
|
|
844
|
+
if (noTelemetry) {
|
|
845
|
+
patches.push({
|
|
846
|
+
name: "noTelemetrySentryEnv1",
|
|
847
|
+
description: "Break ENABLE_SENTRY env var check (E->X)",
|
|
848
|
+
pattern: Buffer.from("ENABLE_SENTRY"),
|
|
849
|
+
replacement: Buffer.from("XNABLE_SENTRY")
|
|
850
|
+
});
|
|
851
|
+
patches.push({
|
|
852
|
+
name: "noTelemetrySentryEnv2",
|
|
853
|
+
description: "Break VITE_VERCEL_ENV env var check (V->X)",
|
|
854
|
+
pattern: Buffer.from("VITE_VERCEL_ENV"),
|
|
855
|
+
replacement: Buffer.from("XITE_VERCEL_ENV")
|
|
856
|
+
});
|
|
857
|
+
patches.push({
|
|
858
|
+
name: "noTelemetryFlushBlock",
|
|
859
|
+
description: "Make flushToWeb always return (!0|| = always true)",
|
|
860
|
+
pattern: Buffer.from("this.webEvents.length===0"),
|
|
861
|
+
replacement: Buffer.from("!0||this.webEvents.length")
|
|
862
|
+
});
|
|
863
|
+
}
|
|
789
864
|
try {
|
|
790
865
|
const result = await patchDroid({
|
|
791
866
|
inputPath: path,
|
|
@@ -817,11 +892,12 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
817
892
|
if (result.success && result.outputPath && alias) {
|
|
818
893
|
console.log();
|
|
819
894
|
if (websearch) {
|
|
820
|
-
const { wrapperScript } = await createWebSearchUnifiedFiles(join(homedir(), ".droid-patch", "proxy"), result.outputPath, alias, websearchTarget);
|
|
895
|
+
const { wrapperScript } = await createWebSearchUnifiedFiles(join(homedir(), ".droid-patch", "proxy"), result.outputPath, alias, websearchTarget, standalone);
|
|
821
896
|
await createAliasForWrapper(wrapperScript, alias, verbose);
|
|
822
897
|
console.log();
|
|
823
898
|
console.log(styleText("cyan", "WebSearch enabled"));
|
|
824
899
|
console.log(styleText("white", ` Forward target: ${websearchTarget}`));
|
|
900
|
+
if (standalone) console.log(styleText("white", ` Standalone mode: enabled`));
|
|
825
901
|
} else await createAlias(result.outputPath, alias, verbose);
|
|
826
902
|
const droidVersion = getDroidVersion(path);
|
|
827
903
|
await saveAliasMetadata(createMetadata(alias, path, {
|
|
@@ -829,7 +905,9 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
829
905
|
skipLogin: !!skipLogin,
|
|
830
906
|
apiBase: apiBase || null,
|
|
831
907
|
websearch: !!websearch,
|
|
832
|
-
reasoningEffort: !!reasoningEffort
|
|
908
|
+
reasoningEffort: !!reasoningEffort,
|
|
909
|
+
noTelemetry: !!noTelemetry,
|
|
910
|
+
standalone: !!standalone
|
|
833
911
|
}, {
|
|
834
912
|
droidPatchVersion: version,
|
|
835
913
|
droidVersion
|
|
@@ -849,7 +927,7 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
849
927
|
}
|
|
850
928
|
}).command("list", "List all droid-patch aliases").action(async () => {
|
|
851
929
|
await listAliases();
|
|
852
|
-
}).command("remove", "Remove alias(es) by name or filter").argument("[alias-or-path]", "Alias name or file path to remove").option("--patch-version <version>", "Remove aliases created by this droid-patch version").option("--droid-version <version>", "Remove aliases for this droid version").option("--flag <flag>", "Remove aliases with this flag (is-custom, skip-login, websearch, api-base, reasoning-effort)").action(async (options, args) => {
|
|
930
|
+
}).command("remove", "Remove alias(es) by name or filter").argument("[alias-or-path]", "Alias name or file path to remove").option("--patch-version <version>", "Remove aliases created by this droid-patch version").option("--droid-version <version>", "Remove aliases for this droid version").option("--flag <flag>", "Remove aliases with this flag (is-custom, skip-login, websearch, api-base, reasoning-effort, disable-telemetry, standalone)").action(async (options, args) => {
|
|
853
931
|
const target = args?.[0];
|
|
854
932
|
const patchVersion = options["patch-version"];
|
|
855
933
|
const droidVersion = options["droid-version"];
|
|
@@ -984,6 +1062,26 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
984
1062
|
replacement: Buffer.from("if(0&&!B.supportedReasoningEfforts.includes(R))")
|
|
985
1063
|
});
|
|
986
1064
|
}
|
|
1065
|
+
if (meta.patches.noTelemetry) {
|
|
1066
|
+
patches.push({
|
|
1067
|
+
name: "noTelemetrySentryEnv1",
|
|
1068
|
+
description: "Break ENABLE_SENTRY env var check (E->X)",
|
|
1069
|
+
pattern: Buffer.from("ENABLE_SENTRY"),
|
|
1070
|
+
replacement: Buffer.from("XNABLE_SENTRY")
|
|
1071
|
+
});
|
|
1072
|
+
patches.push({
|
|
1073
|
+
name: "noTelemetrySentryEnv2",
|
|
1074
|
+
description: "Break VITE_VERCEL_ENV env var check (V->X)",
|
|
1075
|
+
pattern: Buffer.from("VITE_VERCEL_ENV"),
|
|
1076
|
+
replacement: Buffer.from("XITE_VERCEL_ENV")
|
|
1077
|
+
});
|
|
1078
|
+
patches.push({
|
|
1079
|
+
name: "noTelemetryFlushBlock",
|
|
1080
|
+
description: "Make flushToWeb always return (!0|| = always true)",
|
|
1081
|
+
pattern: Buffer.from("this.webEvents.length===0"),
|
|
1082
|
+
replacement: Buffer.from("!0||this.webEvents.length")
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
987
1085
|
const outputPath = join(join(homedir(), ".droid-patch", "bins"), `${meta.name}-patched`);
|
|
988
1086
|
if (patches.length > 0) {
|
|
989
1087
|
if (!(await patchDroid({
|
|
@@ -1008,8 +1106,11 @@ bin("droid-patch", "CLI tool to patch droid binary with various modifications").
|
|
|
1008
1106
|
}
|
|
1009
1107
|
if (meta.patches.websearch || !!meta.patches.proxy) {
|
|
1010
1108
|
const forwardTarget = meta.patches.apiBase || meta.patches.proxy || "https://api.factory.ai";
|
|
1011
|
-
await createWebSearchUnifiedFiles(join(homedir(), ".droid-patch", "proxy"), patches.length > 0 ? outputPath : newBinaryPath, meta.name, forwardTarget);
|
|
1012
|
-
if (verbose)
|
|
1109
|
+
await createWebSearchUnifiedFiles(join(homedir(), ".droid-patch", "proxy"), patches.length > 0 ? outputPath : newBinaryPath, meta.name, forwardTarget, meta.patches.standalone || false);
|
|
1110
|
+
if (verbose) {
|
|
1111
|
+
console.log(styleText("gray", ` Regenerated websearch wrapper`));
|
|
1112
|
+
if (meta.patches.standalone) console.log(styleText("gray", ` Standalone mode: enabled`));
|
|
1113
|
+
}
|
|
1013
1114
|
if (meta.patches.proxy && !meta.patches.websearch) {
|
|
1014
1115
|
meta.patches.websearch = true;
|
|
1015
1116
|
meta.patches.apiBase = meta.patches.proxy;
|