@thesashadev/girl-agent 0.4.1 → 0.4.2
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/CHANGELOG.md +17 -0
- package/README.md +159 -118
- package/dist/cli.js +417 -175
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -497,6 +497,161 @@ var init_markdown = __esm({
|
|
|
497
497
|
}
|
|
498
498
|
});
|
|
499
499
|
|
|
500
|
+
// src/telegram/reactions.ts
|
|
501
|
+
function normalizeBotReactionEmoji(emoji) {
|
|
502
|
+
if (!emoji) return void 0;
|
|
503
|
+
const trimmed = emoji.trim();
|
|
504
|
+
if (!trimmed) return void 0;
|
|
505
|
+
if (BOT_REACTION_ALLOWED.has(trimmed)) return trimmed;
|
|
506
|
+
const stripped = trimmed.replace(/\uFE0F/g, "");
|
|
507
|
+
if (BOT_REACTION_ALLOWED.has(stripped)) return stripped;
|
|
508
|
+
const mapped = FALLBACK[trimmed] ?? FALLBACK[stripped];
|
|
509
|
+
if (mapped && BOT_REACTION_ALLOWED.has(mapped)) return mapped;
|
|
510
|
+
return void 0;
|
|
511
|
+
}
|
|
512
|
+
var BOT_REACTION_ALLOWED, FALLBACK;
|
|
513
|
+
var init_reactions = __esm({
|
|
514
|
+
"src/telegram/reactions.ts"() {
|
|
515
|
+
"use strict";
|
|
516
|
+
init_esm_shims();
|
|
517
|
+
BOT_REACTION_ALLOWED = /* @__PURE__ */ new Set([
|
|
518
|
+
"\u{1F44D}",
|
|
519
|
+
"\u{1F44E}",
|
|
520
|
+
"\u2764",
|
|
521
|
+
"\u{1F525}",
|
|
522
|
+
"\u{1F970}",
|
|
523
|
+
"\u{1F44F}",
|
|
524
|
+
"\u{1F601}",
|
|
525
|
+
"\u{1F914}",
|
|
526
|
+
"\u{1F92F}",
|
|
527
|
+
"\u{1F631}",
|
|
528
|
+
"\u{1F92C}",
|
|
529
|
+
"\u{1F622}",
|
|
530
|
+
"\u{1F389}",
|
|
531
|
+
"\u{1F929}",
|
|
532
|
+
"\u{1F92E}",
|
|
533
|
+
"\u{1F4A9}",
|
|
534
|
+
"\u{1F64F}",
|
|
535
|
+
"\u{1F44C}",
|
|
536
|
+
"\u{1F54A}",
|
|
537
|
+
"\u{1F921}",
|
|
538
|
+
"\u{1F971}",
|
|
539
|
+
"\u{1F974}",
|
|
540
|
+
"\u{1F60D}",
|
|
541
|
+
"\u{1F433}",
|
|
542
|
+
"\u2764\u200D\u{1F525}",
|
|
543
|
+
"\u{1F31A}",
|
|
544
|
+
"\u{1F32D}",
|
|
545
|
+
"\u{1F4AF}",
|
|
546
|
+
"\u{1F923}",
|
|
547
|
+
"\u26A1",
|
|
548
|
+
"\u{1F34C}",
|
|
549
|
+
"\u{1F3C6}",
|
|
550
|
+
"\u{1F494}",
|
|
551
|
+
"\u{1F928}",
|
|
552
|
+
"\u{1F610}",
|
|
553
|
+
"\u{1F353}",
|
|
554
|
+
"\u{1F37E}",
|
|
555
|
+
"\u{1F48B}",
|
|
556
|
+
"\u{1F595}",
|
|
557
|
+
"\u{1F608}",
|
|
558
|
+
"\u{1F634}",
|
|
559
|
+
"\u{1F62D}",
|
|
560
|
+
"\u{1F913}",
|
|
561
|
+
"\u{1F47B}",
|
|
562
|
+
"\u{1F468}\u200D\u{1F4BB}",
|
|
563
|
+
"\u{1F440}",
|
|
564
|
+
"\u{1F383}",
|
|
565
|
+
"\u{1F648}",
|
|
566
|
+
"\u{1F607}",
|
|
567
|
+
"\u{1F628}",
|
|
568
|
+
"\u{1F91D}",
|
|
569
|
+
"\u270D",
|
|
570
|
+
"\u{1F917}",
|
|
571
|
+
"\u{1FAE1}",
|
|
572
|
+
"\u{1F385}",
|
|
573
|
+
"\u{1F384}",
|
|
574
|
+
"\u2603",
|
|
575
|
+
"\u{1F485}",
|
|
576
|
+
"\u{1F92A}",
|
|
577
|
+
"\u{1F5FF}",
|
|
578
|
+
"\u{1F192}",
|
|
579
|
+
"\u{1F498}",
|
|
580
|
+
"\u{1F649}",
|
|
581
|
+
"\u{1F984}",
|
|
582
|
+
"\u{1F618}",
|
|
583
|
+
"\u{1F48A}",
|
|
584
|
+
"\u{1F64A}",
|
|
585
|
+
"\u{1F60E}",
|
|
586
|
+
"\u{1F47E}",
|
|
587
|
+
"\u{1F937}\u200D\u2642",
|
|
588
|
+
"\u{1F937}",
|
|
589
|
+
"\u{1F937}\u200D\u2640",
|
|
590
|
+
"\u{1F621}"
|
|
591
|
+
]);
|
|
592
|
+
FALLBACK = {
|
|
593
|
+
"\u2764\uFE0F": "\u2764",
|
|
594
|
+
"\u{1F496}": "\u2764",
|
|
595
|
+
"\u{1F497}": "\u2764",
|
|
596
|
+
"\u{1F495}": "\u2764",
|
|
597
|
+
"\u{1F493}": "\u2764",
|
|
598
|
+
"\u{1F49E}": "\u2764",
|
|
599
|
+
"\u{1FA77}": "\u2764",
|
|
600
|
+
"\u{1F49C}": "\u2764",
|
|
601
|
+
"\u{1F499}": "\u2764",
|
|
602
|
+
"\u{1F49A}": "\u2764",
|
|
603
|
+
"\u{1F9E1}": "\u2764",
|
|
604
|
+
"\u{1F49B}": "\u2764",
|
|
605
|
+
"\u{1F90D}": "\u2764",
|
|
606
|
+
"\u{1F5A4}": "\u2764",
|
|
607
|
+
"\u{1F90E}": "\u2764",
|
|
608
|
+
"\u{1F60F}": "\u{1F60E}",
|
|
609
|
+
"\u{1F644}": "\u{1F928}",
|
|
610
|
+
"\u{1F97A}": "\u{1F979}",
|
|
611
|
+
"\u{1F979}": "\u{1F62D}",
|
|
612
|
+
"\u{1F480}": "\u{1F5FF}",
|
|
613
|
+
"\u{1F602}": "\u{1F923}",
|
|
614
|
+
"\u{1F92D}": "\u{1F917}",
|
|
615
|
+
"\u{1F92B}": "\u{1FAE1}",
|
|
616
|
+
"\u{1F910}": "\u{1FAE1}",
|
|
617
|
+
"\u{1F643}": "\u{1F970}",
|
|
618
|
+
"\u{1F642}": "\u{1F970}",
|
|
619
|
+
"\u{1F60A}": "\u{1F970}",
|
|
620
|
+
"\u{1F605}": "\u{1F601}",
|
|
621
|
+
"\u{1F606}": "\u{1F923}",
|
|
622
|
+
"\u{1F60B}": "\u{1F60D}",
|
|
623
|
+
"\u{1F61C}": "\u{1F92A}",
|
|
624
|
+
"\u{1F61D}": "\u{1F92A}",
|
|
625
|
+
"\u{1F61B}": "\u{1F92A}",
|
|
626
|
+
"\u{1F62C}": "\u{1F628}",
|
|
627
|
+
"\u{1F924}": "\u{1F974}",
|
|
628
|
+
"\u{1F62A}": "\u{1F971}",
|
|
629
|
+
"\u{1F614}": "\u{1F622}",
|
|
630
|
+
"\u{1F61E}": "\u{1F622}",
|
|
631
|
+
"\u{1F61F}": "\u{1F914}",
|
|
632
|
+
"\u{1F615}": "\u{1F914}",
|
|
633
|
+
"\u{1F976}": "\u{1F974}",
|
|
634
|
+
"\u{1F927}": "\u{1F974}",
|
|
635
|
+
"\u{1F912}": "\u{1F48A}",
|
|
636
|
+
"\u{1F637}": "\u{1F48A}",
|
|
637
|
+
"\u{1F915}": "\u{1F48A}",
|
|
638
|
+
"\u{1F922}": "\u{1F92E}",
|
|
639
|
+
"\u{1F44B}": "\u{1F91D}",
|
|
640
|
+
"\u270A": "\u{1F3C6}",
|
|
641
|
+
"\u{1F44A}": "\u{1F3C6}",
|
|
642
|
+
"\u{1F4AA}": "\u{1F3C6}",
|
|
643
|
+
"\u{1F64C}": "\u{1F64F}",
|
|
644
|
+
"\u{1FAF6}": "\u2764",
|
|
645
|
+
"\u{1F973}": "\u{1F389}",
|
|
646
|
+
"\u{1F38A}": "\u{1F389}",
|
|
647
|
+
"\u2728": "\u26A1",
|
|
648
|
+
"\u2B50": "\u{1F3C6}",
|
|
649
|
+
"\u{1F31F}": "\u{1F3C6}",
|
|
650
|
+
"\u{1F972}": "\u{1F62D}"
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
|
|
500
655
|
// src/telegram/bot.ts
|
|
501
656
|
var bot_exports = {};
|
|
502
657
|
__export(bot_exports, {
|
|
@@ -550,19 +705,23 @@ function makeBotAdapter(cfg) {
|
|
|
550
705
|
await onMessage(msg).catch(() => {
|
|
551
706
|
});
|
|
552
707
|
});
|
|
708
|
+
try {
|
|
709
|
+
await bot.init();
|
|
710
|
+
} catch (e) {
|
|
711
|
+
throw new Error(`Telegram bot init failed: ${e?.message ?? e}. \u041F\u0440\u043E\u0432\u0435\u0440\u044C BOT_TOKEN (BotFather), \u0434\u043E\u0441\u0442\u0443\u043F \u043A api.telegram.org \u0438 \u0447\u0442\u043E \u0434\u0440\u0443\u0433\u043E\u0439 \u0438\u043D\u0441\u0442\u0430\u043D\u0441 \u0431\u043E\u0442\u0430 \u043D\u0435 \u0434\u0435\u0440\u0436\u0438\u0442 long-polling.`);
|
|
712
|
+
}
|
|
713
|
+
const me = bot.botInfo;
|
|
714
|
+
selfInfo = {
|
|
715
|
+
username: me.username ?? void 0,
|
|
716
|
+
displayName: [me.first_name, me.last_name].filter(Boolean).join(" ") || void 0
|
|
717
|
+
};
|
|
553
718
|
bot.start({
|
|
554
719
|
drop_pending_updates: true,
|
|
555
720
|
allowed_updates: ["message", "edited_message", "callback_query", "message_reaction"]
|
|
556
|
-
}).catch(() => {
|
|
721
|
+
}).catch((e) => {
|
|
722
|
+
process.stderr.write(`[bot] long-polling stopped: ${e?.message ?? e}
|
|
723
|
+
`);
|
|
557
724
|
});
|
|
558
|
-
try {
|
|
559
|
-
const me = await bot.api.getMe();
|
|
560
|
-
selfInfo = {
|
|
561
|
-
username: me.username ?? void 0,
|
|
562
|
-
displayName: [me.first_name, me.last_name].filter(Boolean).join(" ") || void 0
|
|
563
|
-
};
|
|
564
|
-
} catch {
|
|
565
|
-
}
|
|
566
725
|
},
|
|
567
726
|
async sendText(chatId, text) {
|
|
568
727
|
if (hasSpoilers(text)) {
|
|
@@ -584,11 +743,19 @@ function makeBotAdapter(cfg) {
|
|
|
584
743
|
}
|
|
585
744
|
},
|
|
586
745
|
async setReaction(chatId, messageId, emoji) {
|
|
746
|
+
const normalized = normalizeBotReactionEmoji(emoji);
|
|
747
|
+
if (!normalized) {
|
|
748
|
+
process.stderr.write(`[bot] reaction "${emoji}" \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F Bot API \u0438 \u043D\u0435\u0442 \u0437\u0430\u043C\u0435\u043D\u044B \u2014 \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0430\u0435\u043C
|
|
749
|
+
`);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
587
752
|
try {
|
|
588
753
|
await bot.api.setMessageReaction(chatId, messageId, [
|
|
589
|
-
{ type: "emoji", emoji }
|
|
754
|
+
{ type: "emoji", emoji: normalized }
|
|
590
755
|
]);
|
|
591
|
-
} catch {
|
|
756
|
+
} catch (e) {
|
|
757
|
+
process.stderr.write(`[bot] setMessageReaction("${normalized}", chat=${chatId}, msg=${messageId}) failed: ${e?.message ?? e}
|
|
758
|
+
`);
|
|
592
759
|
}
|
|
593
760
|
},
|
|
594
761
|
async editText(chatId, messageId, newText) {
|
|
@@ -656,6 +823,7 @@ var init_bot = __esm({
|
|
|
656
823
|
"use strict";
|
|
657
824
|
init_esm_shims();
|
|
658
825
|
init_markdown();
|
|
826
|
+
init_reactions();
|
|
659
827
|
}
|
|
660
828
|
});
|
|
661
829
|
|
|
@@ -1856,6 +2024,8 @@ var init_presence = __esm({
|
|
|
1856
2024
|
});
|
|
1857
2025
|
|
|
1858
2026
|
// src/engine/daily-life.ts
|
|
2027
|
+
import { promises as fs3 } from "fs";
|
|
2028
|
+
import path5 from "path";
|
|
1859
2029
|
function localDateStr(tz, now = /* @__PURE__ */ new Date()) {
|
|
1860
2030
|
try {
|
|
1861
2031
|
const fmt = new Intl.DateTimeFormat("en-CA", { timeZone: tz, year: "numeric", month: "2-digit", day: "2-digit" });
|
|
@@ -1878,7 +2048,7 @@ function localWeekday(tz, now = /* @__PURE__ */ new Date()) {
|
|
|
1878
2048
|
return "";
|
|
1879
2049
|
}
|
|
1880
2050
|
}
|
|
1881
|
-
function buildPrompt(cfg, persona, weekday, dateLocal, conflict) {
|
|
2051
|
+
function buildPrompt(cfg, persona, weekday, dateLocal, conflict, recentEvents) {
|
|
1882
2052
|
const conflictNote = conflict && conflict.level > 0 ? `
|
|
1883
2053
|
|
|
1884
2054
|
\u0412\u0410\u0416\u041D\u041E: \u0443 \u043D\u0435\u0451 \u0441\u0435\u0439\u0447\u0430\u0441 \u041A\u041E\u041D\u0424\u041B\u0418\u041A\u0422 \u0441 \u043D\u0438\u043C (level ${conflict.level}, \u043F\u0440\u0438\u0447\u0438\u043D\u0430: "${conflict.reason ?? "\u2014"}"). \u042D\u0442\u043E \u0432\u043B\u0438\u044F\u0435\u0442 \u043D\u0430 \u0435\u0451 \u0434\u0435\u043D\u044C:
|
|
@@ -1892,7 +2062,13 @@ function buildPrompt(cfg, persona, weekday, dateLocal, conflict) {
|
|
|
1892
2062
|
${cfg.busySchedule.map((s) => `- ${s.label}: ${s.from}-${s.to}${s.days ? ` (${s.days.join(", ")})` : ""}`).join("\n")}
|
|
1893
2063
|
|
|
1894
2064
|
\u0423\u0427\u0418\u0422\u042B\u0412\u0410\u0419 \u044D\u0442\u043E \u043F\u0440\u0438 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 blocks: \u0435\u0441\u043B\u0438 busySlot \u043F\u0435\u0440\u0435\u043A\u0440\u044B\u0432\u0430\u0435\u0442 \u0432\u0440\u0435\u043C\u044F, activity \u0434\u043E\u043B\u0436\u043D\u0430 \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043E\u0432\u0430\u0442\u044C. \u0414\u043B\u044F \u0432\u043E\u0437\u0440\u0430\u0441\u0442\u0430 \u0434\u043E 17 \u043B\u0435\u0442 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439 "\u0432 \u0448\u043A\u043E\u043B\u0435", "\u043D\u0430 \u0443\u0440\u043E\u043A\u0435", "\u0443\u0440\u043E\u043A\u0438", "\u043F\u0435\u0440\u0435\u043C\u0435\u043D\u0430"; \u041D\u0415 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439 "\u043F\u0430\u0440\u0430", "\u043B\u0435\u043A\u0446\u0438\u044F", "\u0443\u043D\u0438\u0432\u0435\u0440", "\u043F\u0440\u0435\u043F\u043E\u0434". \u0414\u043B\u044F 17+ \u043C\u043E\u0436\u043D\u043E \u043A\u043E\u043B\u043B\u0435\u0434\u0436/\u0443\u043D\u0438\u0432\u0435\u0440 \u0435\u0441\u043B\u0438 \u043F\u043E\u0434\u0445\u043E\u0434\u0438\u0442 persona. phoneAvailable=false \u0442\u043E\u043B\u044C\u043A\u043E \u043A\u043E\u0433\u0434\u0430 \u0442\u0435\u043B\u0435\u0444\u043E\u043D \u0440\u0435\u0430\u043B\u044C\u043D\u043E \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D.` : "";
|
|
1895
|
-
|
|
2065
|
+
const recentNote = recentEvents.length > 0 ? `
|
|
2066
|
+
|
|
2067
|
+
\u0427\u0422\u041E \u0423\u0416\u0415 \u0411\u042B\u041B\u041E \u0412 \u041F\u0420\u0415\u0414\u042B\u0414\u0423\u0429\u0418\u0415 \u0414\u041D\u0418 (\u041D\u0415 \u041F\u041E\u0412\u0422\u041E\u0420\u042F\u0422\u042C \u2014 \u044D\u0442\u043E \u0440\u043E\u0432\u043D\u043E \u0442\u0435 \u0436\u0435 \u0441\u043E\u0431\u044B\u0442\u0438\u044F, \u043D\u0435\u043B\u044C\u0437\u044F \u043D\u0438 \u0438\u0445, \u043D\u0438 \u0438\u0445 \u043F\u0435\u0440\u0435\u0444\u0440\u0430\u0437):
|
|
2068
|
+
${recentEvents.map((e) => `- ${e}`).join("\n")}
|
|
2069
|
+
|
|
2070
|
+
\u0413\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0439 \u0441\u0435\u0433\u043E\u0434\u043D\u044F \u0421\u0412\u0415\u0416\u0418\u0415 \u0441\u043E\u0431\u044B\u0442\u0438\u044F, \u043E\u0442\u043B\u0438\u0447\u043D\u044B\u0435 \u043E\u0442 \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u0435\u043D\u043D\u044B\u0445 \u043F\u043E \u0441\u0443\u0442\u0438 (\u0430 \u043D\u0435 \u043F\u043E \u0444\u043E\u0440\u043C\u0443\u043B\u0438\u0440\u043E\u0432\u043A\u0435). \u0415\u0441\u043B\u0438 \u0438\u0434\u0435\u044F \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0435\u0442\u0441\u044F \u2014 \u043F\u0440\u0438\u0434\u0443\u043C\u0430\u0439 \u0434\u0440\u0443\u0433\u0443\u044E.` : "";
|
|
2071
|
+
return `\u0418\u043C\u044F: ${cfg.name}, ${cfg.age}. \u0421\u0442\u0430\u0434\u0438\u044F \u043E\u0442\u043D\u043E\u0448\u0435\u043D\u0438\u0439 \u0441 \u043D\u0438\u043C: ${cfg.stage}. \u0427\u0430\u0441\u043E\u0432\u043E\u0439 \u043F\u043E\u044F\u0441: ${cfg.tz}. \u0421\u0435\u0433\u043E\u0434\u043D\u044F: ${weekday}, ${dateLocal}.${conflictNote}${busyNote}${recentNote}
|
|
1896
2072
|
|
|
1897
2073
|
\u041F\u0435\u0440\u0441\u043E\u043D\u0430 (\u0432\u044B\u0436\u0438\u043C\u043A\u0430):
|
|
1898
2074
|
${persona.slice(0, 1200)}
|
|
@@ -1925,8 +2101,8 @@ phoneAvailable=false \u043A\u043E\u0433\u0434\u0430: \u0441\u043F\u0438\u0442, \
|
|
|
1925
2101
|
}
|
|
1926
2102
|
async function loadOrGenerateDailyLife(llm, cfg, now = /* @__PURE__ */ new Date(), conflict = null) {
|
|
1927
2103
|
const dateLocal = localDateStr(cfg.tz, now);
|
|
1928
|
-
const
|
|
1929
|
-
const existing = await readMd(cfg.slug,
|
|
2104
|
+
const path15 = `daily-life/${dateLocal}.md`;
|
|
2105
|
+
const existing = await readMd(cfg.slug, path15);
|
|
1930
2106
|
if (existing) {
|
|
1931
2107
|
try {
|
|
1932
2108
|
const m = existing.match(/<!--daily:(.+?)-->/s);
|
|
@@ -1936,12 +2112,13 @@ async function loadOrGenerateDailyLife(llm, cfg, now = /* @__PURE__ */ new Date(
|
|
|
1936
2112
|
}
|
|
1937
2113
|
const persona = await readMd(cfg.slug, "persona.md");
|
|
1938
2114
|
const weekday = localWeekday(cfg.tz, now);
|
|
2115
|
+
const recentEvents = await loadRecentEvents(cfg.slug, dateLocal, 5);
|
|
1939
2116
|
let dl;
|
|
1940
2117
|
try {
|
|
1941
2118
|
const raw = await llm.chat(
|
|
1942
2119
|
[
|
|
1943
2120
|
{ role: "system", content: SYS },
|
|
1944
|
-
{ role: "user", content: buildPrompt(cfg, persona, weekday, dateLocal, conflict) }
|
|
2121
|
+
{ role: "user", content: buildPrompt(cfg, persona, weekday, dateLocal, conflict, recentEvents) }
|
|
1945
2122
|
],
|
|
1946
2123
|
{ temperature: 0.95, maxTokens: 3500, json: true }
|
|
1947
2124
|
);
|
|
@@ -1958,7 +2135,7 @@ async function loadOrGenerateDailyLife(llm, cfg, now = /* @__PURE__ */ new Date(
|
|
|
1958
2135
|
dl = { dateLocal, vibe: "\u043E\u0431\u044B\u0447\u043D\u044B\u0439 \u0434\u0435\u043D\u044C", blocks: [], events: [], wants: [] };
|
|
1959
2136
|
}
|
|
1960
2137
|
const human = renderDailyLifeHuman(dl);
|
|
1961
|
-
await writeMd(cfg.slug,
|
|
2138
|
+
await writeMd(cfg.slug, path15, `${human}
|
|
1962
2139
|
|
|
1963
2140
|
<!--daily:${JSON.stringify(dl)}-->
|
|
1964
2141
|
`);
|
|
@@ -1992,6 +2169,32 @@ function currentBlock(dl, tz, now = /* @__PURE__ */ new Date()) {
|
|
|
1992
2169
|
const h = localHour(tz, now);
|
|
1993
2170
|
return dl.blocks?.find((b) => h >= b.fromHour && h < b.toHour) ?? dl.blocks?.[dl.blocks.length - 1];
|
|
1994
2171
|
}
|
|
2172
|
+
async function loadRecentEvents(slug, todayLocal, days) {
|
|
2173
|
+
try {
|
|
2174
|
+
const dir = path5.join(profileDir(slug), "daily-life");
|
|
2175
|
+
const files = await fs3.readdir(dir).catch(() => []);
|
|
2176
|
+
const recent = files.filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).map((f) => f.replace(/\.md$/, "")).filter((d) => d < todayLocal).sort().slice(-days);
|
|
2177
|
+
const out = [];
|
|
2178
|
+
for (const day of recent) {
|
|
2179
|
+
const raw = await readMd(slug, `daily-life/${day}.md`);
|
|
2180
|
+
if (!raw) continue;
|
|
2181
|
+
const m = raw.match(/<!--daily:(.+?)-->/s);
|
|
2182
|
+
if (!m || !m[1]) continue;
|
|
2183
|
+
try {
|
|
2184
|
+
const parsed = JSON.parse(m[1]);
|
|
2185
|
+
if (Array.isArray(parsed.events)) {
|
|
2186
|
+
for (const e of parsed.events) {
|
|
2187
|
+
if (typeof e === "string" && e.trim()) out.push(e.trim());
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
} catch {
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
return out.slice(-20);
|
|
2194
|
+
} catch {
|
|
2195
|
+
return [];
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
1995
2198
|
function dailyLifePromptFragment(dl, tz, now = /* @__PURE__ */ new Date()) {
|
|
1996
2199
|
const b = currentBlock(dl, tz, now);
|
|
1997
2200
|
const parts = [
|
|
@@ -2023,11 +2226,11 @@ var init_daily_life = __esm({
|
|
|
2023
2226
|
});
|
|
2024
2227
|
|
|
2025
2228
|
// src/engine/conflict.ts
|
|
2026
|
-
import { promises as
|
|
2027
|
-
import
|
|
2229
|
+
import { promises as fs4 } from "fs";
|
|
2230
|
+
import path6 from "path";
|
|
2028
2231
|
async function readConflict(slug) {
|
|
2029
2232
|
try {
|
|
2030
|
-
const raw = await
|
|
2233
|
+
const raw = await fs4.readFile(path6.join(profileDir(slug), "conflict.json"), "utf8");
|
|
2031
2234
|
const parsed = JSON.parse(raw);
|
|
2032
2235
|
return { ...empty, ...parsed, history: parsed.history ?? [] };
|
|
2033
2236
|
} catch {
|
|
@@ -2036,7 +2239,7 @@ async function readConflict(slug) {
|
|
|
2036
2239
|
}
|
|
2037
2240
|
async function writeConflict(slug, c) {
|
|
2038
2241
|
await ensureProfile(slug);
|
|
2039
|
-
await
|
|
2242
|
+
await fs4.writeFile(path6.join(profileDir(slug), "conflict.json"), JSON.stringify(c, null, 2), "utf8");
|
|
2040
2243
|
}
|
|
2041
2244
|
function activeConflict(c, now = /* @__PURE__ */ new Date()) {
|
|
2042
2245
|
const cold = c.coldUntil ? new Date(c.coldUntil).getTime() > now.getTime() : false;
|
|
@@ -2160,9 +2363,9 @@ var init_conflict = __esm({
|
|
|
2160
2363
|
});
|
|
2161
2364
|
|
|
2162
2365
|
// src/engine/memory-palace.ts
|
|
2163
|
-
import { promises as
|
|
2366
|
+
import { promises as fs5 } from "fs";
|
|
2164
2367
|
import { createHash } from "crypto";
|
|
2165
|
-
import
|
|
2368
|
+
import path7 from "path";
|
|
2166
2369
|
function wordsFrom(text) {
|
|
2167
2370
|
return [...text.toLowerCase().matchAll(/[a-zа-яё0-9]{3,}/gi)].map((match) => match[0]).filter((token) => !STOP_WORDS.has(token));
|
|
2168
2371
|
}
|
|
@@ -2292,9 +2495,9 @@ async function ensureDefaults(cfg) {
|
|
|
2292
2495
|
["time/promises.md", "# promises\n"],
|
|
2293
2496
|
["memory/uncertain.md", "# uncertain\n"]
|
|
2294
2497
|
];
|
|
2295
|
-
await Promise.all(defaults.map(async ([
|
|
2296
|
-
const current = await readMd(cfg.slug,
|
|
2297
|
-
if (!current.trim()) await writeMd(cfg.slug,
|
|
2498
|
+
await Promise.all(defaults.map(async ([path15, content]) => {
|
|
2499
|
+
const current = await readMd(cfg.slug, path15);
|
|
2500
|
+
if (!current.trim()) await writeMd(cfg.slug, path15, content + "\n");
|
|
2298
2501
|
}));
|
|
2299
2502
|
}
|
|
2300
2503
|
function scoreDrawer(drawer, tokens, query) {
|
|
@@ -2331,7 +2534,7 @@ async function listPalaceDrawers(cfg) {
|
|
|
2331
2534
|
}
|
|
2332
2535
|
async function listChildDirs(slug, rel) {
|
|
2333
2536
|
try {
|
|
2334
|
-
const entries = await
|
|
2537
|
+
const entries = await fs5.readdir(path7.join(profileDir(slug), rel), { withFileTypes: true });
|
|
2335
2538
|
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
2336
2539
|
} catch {
|
|
2337
2540
|
return [];
|
|
@@ -2339,7 +2542,7 @@ async function listChildDirs(slug, rel) {
|
|
|
2339
2542
|
}
|
|
2340
2543
|
async function listChildFiles(slug, rel) {
|
|
2341
2544
|
try {
|
|
2342
|
-
const entries = await
|
|
2545
|
+
const entries = await fs5.readdir(path7.join(profileDir(slug), rel), { withFileTypes: true });
|
|
2343
2546
|
return entries.filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
|
|
2344
2547
|
} catch {
|
|
2345
2548
|
return [];
|
|
@@ -4359,13 +4562,13 @@ var init_daily_summarizer = __esm({
|
|
|
4359
4562
|
});
|
|
4360
4563
|
|
|
4361
4564
|
// src/engine/stickers.ts
|
|
4362
|
-
import { promises as
|
|
4363
|
-
import
|
|
4565
|
+
import { promises as fs6 } from "fs";
|
|
4566
|
+
import path8 from "path";
|
|
4364
4567
|
async function libraryPath(cfg) {
|
|
4365
4568
|
const rel = "stickers/library.md";
|
|
4366
4569
|
const current = await readMd(cfg.slug, rel);
|
|
4367
4570
|
if (!current.trim()) await writeMd(cfg.slug, rel, DEFAULT_LIBRARY);
|
|
4368
|
-
return
|
|
4571
|
+
return path8.join(profileDir(cfg.slug), rel);
|
|
4369
4572
|
}
|
|
4370
4573
|
async function listStickers(cfg) {
|
|
4371
4574
|
await libraryPath(cfg);
|
|
@@ -4387,8 +4590,8 @@ async function addStickerToLibrary(cfg, fileId, emoji = "", tags = []) {
|
|
|
4387
4590
|
await libraryPath(cfg);
|
|
4388
4591
|
const existing = await listStickers(cfg);
|
|
4389
4592
|
if (existing.some((s) => s.fileId === fileId)) return;
|
|
4390
|
-
const p =
|
|
4391
|
-
await
|
|
4593
|
+
const p = path8.join(profileDir(cfg.slug), "stickers/library.md");
|
|
4594
|
+
await fs6.appendFile(p, `${fileId} | ${emoji} | ${tags.join(",")}
|
|
4392
4595
|
`, "utf8");
|
|
4393
4596
|
}
|
|
4394
4597
|
var DEFAULT_LIBRARY;
|
|
@@ -6728,21 +6931,21 @@ var init_memory_palace2 = __esm({
|
|
|
6728
6931
|
});
|
|
6729
6932
|
|
|
6730
6933
|
// src/migrations/index.ts
|
|
6731
|
-
import { promises as
|
|
6732
|
-
import
|
|
6934
|
+
import { promises as fs7 } from "fs";
|
|
6935
|
+
import path9 from "path";
|
|
6733
6936
|
import { readFileSync } from "fs";
|
|
6734
6937
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6735
6938
|
async function readMigrationState() {
|
|
6736
6939
|
try {
|
|
6737
|
-
const raw = await
|
|
6940
|
+
const raw = await fs7.readFile(MIGRATIONS_FILE(), "utf8");
|
|
6738
6941
|
return JSON.parse(raw);
|
|
6739
6942
|
} catch {
|
|
6740
6943
|
return { appliedMigrations: [], lastRunVersion: "0.0.0", lastRunAt: "" };
|
|
6741
6944
|
}
|
|
6742
6945
|
}
|
|
6743
6946
|
async function writeMigrationState(state) {
|
|
6744
|
-
await
|
|
6745
|
-
await
|
|
6947
|
+
await fs7.mkdir(DATA_ROOT, { recursive: true });
|
|
6948
|
+
await fs7.writeFile(MIGRATIONS_FILE(), JSON.stringify(state, null, 2), "utf8");
|
|
6746
6949
|
}
|
|
6747
6950
|
async function pendingMigrations() {
|
|
6748
6951
|
const state = await readMigrationState();
|
|
@@ -6835,15 +7038,15 @@ function formatUpdateWarnings(warnings) {
|
|
|
6835
7038
|
function currentVersion() {
|
|
6836
7039
|
try {
|
|
6837
7040
|
const here = fileURLToPath3(import.meta.url);
|
|
6838
|
-
let dir =
|
|
7041
|
+
let dir = path9.dirname(here);
|
|
6839
7042
|
for (let i = 0; i < 5; i++) {
|
|
6840
|
-
const candidate =
|
|
7043
|
+
const candidate = path9.join(dir, "package.json");
|
|
6841
7044
|
try {
|
|
6842
7045
|
const pkg = JSON.parse(readFileSync(candidate, "utf8"));
|
|
6843
7046
|
if (pkg.name === "@thesashadev/girl-agent" && pkg.version) return pkg.version;
|
|
6844
7047
|
} catch {
|
|
6845
7048
|
}
|
|
6846
|
-
dir =
|
|
7049
|
+
dir = path9.dirname(dir);
|
|
6847
7050
|
}
|
|
6848
7051
|
return "unknown";
|
|
6849
7052
|
} catch {
|
|
@@ -6859,7 +7062,7 @@ var init_migrations = __esm({
|
|
|
6859
7062
|
init_add_use_wss_default();
|
|
6860
7063
|
init_ensure_communication_md();
|
|
6861
7064
|
init_memory_palace2();
|
|
6862
|
-
MIGRATIONS_FILE = () =>
|
|
7065
|
+
MIGRATIONS_FILE = () => path9.join(DATA_ROOT, ".migrations.json");
|
|
6863
7066
|
ALL_MIGRATIONS = [
|
|
6864
7067
|
migration0112,
|
|
6865
7068
|
migration0113,
|
|
@@ -7021,23 +7224,23 @@ __export(addons_exports, {
|
|
|
7021
7224
|
updateSettings: () => updateSettings,
|
|
7022
7225
|
validateManifest: () => validateManifest
|
|
7023
7226
|
});
|
|
7024
|
-
import { promises as
|
|
7025
|
-
import
|
|
7227
|
+
import { promises as fs10 } from "fs";
|
|
7228
|
+
import path12 from "path";
|
|
7026
7229
|
import os3 from "os";
|
|
7027
7230
|
import { execFile } from "child_process";
|
|
7028
7231
|
import { promisify } from "util";
|
|
7029
7232
|
function addonsDir() {
|
|
7030
|
-
const root = process.env.GIRL_AGENT_DATA ?
|
|
7031
|
-
return
|
|
7233
|
+
const root = process.env.GIRL_AGENT_DATA ? path12.resolve(process.env.GIRL_AGENT_DATA, "..") : path12.join(os3.homedir(), ".local", "share", "girl-agent");
|
|
7234
|
+
return path12.join(root, "addons");
|
|
7032
7235
|
}
|
|
7033
7236
|
async function ensureDir() {
|
|
7034
7237
|
const dir = addonsDir();
|
|
7035
|
-
await
|
|
7238
|
+
await fs10.mkdir(dir, { recursive: true });
|
|
7036
7239
|
return dir;
|
|
7037
7240
|
}
|
|
7038
7241
|
async function readJsonOrEmpty(p, fallback) {
|
|
7039
7242
|
try {
|
|
7040
|
-
const raw = await
|
|
7243
|
+
const raw = await fs10.readFile(p, "utf8");
|
|
7041
7244
|
return JSON.parse(raw);
|
|
7042
7245
|
} catch {
|
|
7043
7246
|
return fallback;
|
|
@@ -7045,12 +7248,12 @@ async function readJsonOrEmpty(p, fallback) {
|
|
|
7045
7248
|
}
|
|
7046
7249
|
async function listInstalled() {
|
|
7047
7250
|
const dir = await ensureDir();
|
|
7048
|
-
const indexPath =
|
|
7251
|
+
const indexPath = path12.join(dir, "installed.json");
|
|
7049
7252
|
return await readJsonOrEmpty(indexPath, []);
|
|
7050
7253
|
}
|
|
7051
7254
|
async function writeInstalled(list) {
|
|
7052
7255
|
const dir = await ensureDir();
|
|
7053
|
-
await
|
|
7256
|
+
await fs10.writeFile(path12.join(dir, "installed.json"), JSON.stringify(list, null, 2), "utf8");
|
|
7054
7257
|
}
|
|
7055
7258
|
async function fetchRegistry() {
|
|
7056
7259
|
try {
|
|
@@ -7064,17 +7267,17 @@ async function fetchRegistry() {
|
|
|
7064
7267
|
}
|
|
7065
7268
|
}
|
|
7066
7269
|
async function unpackGaa(gaaPath) {
|
|
7067
|
-
const tmpDir =
|
|
7068
|
-
await
|
|
7270
|
+
const tmpDir = path12.join(os3.tmpdir(), `gaa-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
7271
|
+
await fs10.mkdir(tmpDir, { recursive: true });
|
|
7069
7272
|
await execFileAsync("unzip", ["-o", "-q", gaaPath, "-d", tmpDir]);
|
|
7070
|
-
const entries = await
|
|
7273
|
+
const entries = await fs10.readdir(tmpDir);
|
|
7071
7274
|
if (entries.length === 1) {
|
|
7072
|
-
const sub =
|
|
7073
|
-
const st = await
|
|
7275
|
+
const sub = path12.join(tmpDir, entries[0]);
|
|
7276
|
+
const st = await fs10.stat(sub);
|
|
7074
7277
|
if (st.isDirectory()) {
|
|
7075
|
-
const innerManifest =
|
|
7278
|
+
const innerManifest = path12.join(sub, "manifest.json");
|
|
7076
7279
|
try {
|
|
7077
|
-
await
|
|
7280
|
+
await fs10.access(innerManifest);
|
|
7078
7281
|
return sub;
|
|
7079
7282
|
} catch {
|
|
7080
7283
|
}
|
|
@@ -7083,34 +7286,34 @@ async function unpackGaa(gaaPath) {
|
|
|
7083
7286
|
return tmpDir;
|
|
7084
7287
|
}
|
|
7085
7288
|
async function packGaa(addonDir, outputPath) {
|
|
7086
|
-
const manifestPath =
|
|
7087
|
-
const manifestRaw = await
|
|
7289
|
+
const manifestPath = path12.join(addonDir, "manifest.json");
|
|
7290
|
+
const manifestRaw = await fs10.readFile(manifestPath, "utf8");
|
|
7088
7291
|
const manifest = JSON.parse(manifestRaw);
|
|
7089
7292
|
validateManifest(manifest);
|
|
7090
|
-
const out = outputPath ??
|
|
7293
|
+
const out = outputPath ?? path12.join(process.cwd(), `${manifest.id}.gaa`);
|
|
7091
7294
|
try {
|
|
7092
|
-
await
|
|
7295
|
+
await fs10.unlink(out);
|
|
7093
7296
|
} catch {
|
|
7094
7297
|
}
|
|
7095
|
-
const dirName =
|
|
7096
|
-
const parentDir =
|
|
7298
|
+
const dirName = path12.basename(addonDir);
|
|
7299
|
+
const parentDir = path12.dirname(addonDir);
|
|
7097
7300
|
await execFileAsync("zip", ["-r", "-q", out, dirName], { cwd: parentDir });
|
|
7098
7301
|
return out;
|
|
7099
7302
|
}
|
|
7100
7303
|
async function installFromDir(addonDir, profileSlug, source = "local") {
|
|
7101
|
-
const manifestPath =
|
|
7102
|
-
const manifestRaw = await
|
|
7304
|
+
const manifestPath = path12.join(addonDir, "manifest.json");
|
|
7305
|
+
const manifestRaw = await fs10.readFile(manifestPath, "utf8");
|
|
7103
7306
|
const manifest = JSON.parse(manifestRaw);
|
|
7104
7307
|
validateManifest(manifest);
|
|
7105
7308
|
const applied = [];
|
|
7106
7309
|
const installedFiles = [];
|
|
7107
|
-
const filesDir =
|
|
7310
|
+
const filesDir = path12.join(addonDir, "files");
|
|
7108
7311
|
try {
|
|
7109
|
-
const fileStat = await
|
|
7312
|
+
const fileStat = await fs10.stat(filesDir);
|
|
7110
7313
|
if (fileStat.isDirectory() && profileSlug) {
|
|
7111
7314
|
const fileEntries = await walkDir(filesDir);
|
|
7112
7315
|
for (const relPath of fileEntries) {
|
|
7113
|
-
const content = await
|
|
7316
|
+
const content = await fs10.readFile(path12.join(filesDir, relPath), "utf8");
|
|
7114
7317
|
await writeMd(profileSlug, relPath, content);
|
|
7115
7318
|
installedFiles.push(relPath);
|
|
7116
7319
|
}
|
|
@@ -7118,9 +7321,9 @@ async function installFromDir(addonDir, profileSlug, source = "local") {
|
|
|
7118
7321
|
}
|
|
7119
7322
|
} catch {
|
|
7120
7323
|
}
|
|
7121
|
-
const patchPath =
|
|
7324
|
+
const patchPath = path12.join(addonDir, "config.patch.json");
|
|
7122
7325
|
try {
|
|
7123
|
-
const patchRaw = await
|
|
7326
|
+
const patchRaw = await fs10.readFile(patchPath, "utf8");
|
|
7124
7327
|
const patch = JSON.parse(patchRaw);
|
|
7125
7328
|
if (profileSlug) {
|
|
7126
7329
|
const cfg = await readConfig(profileSlug);
|
|
@@ -7132,11 +7335,11 @@ async function installFromDir(addonDir, profileSlug, source = "local") {
|
|
|
7132
7335
|
}
|
|
7133
7336
|
} catch {
|
|
7134
7337
|
}
|
|
7135
|
-
const codePatchPath =
|
|
7338
|
+
const codePatchPath = path12.join(addonDir, "code.patch");
|
|
7136
7339
|
try {
|
|
7137
|
-
const patchContent = await
|
|
7340
|
+
const patchContent = await fs10.readFile(codePatchPath, "utf8");
|
|
7138
7341
|
if (patchContent.trim()) {
|
|
7139
|
-
const projectRoot =
|
|
7342
|
+
const projectRoot = path12.resolve(import.meta.url.replace("file://", ""), "../../../");
|
|
7140
7343
|
try {
|
|
7141
7344
|
await execFileAsync("git", ["apply", "--check", codePatchPath], { cwd: projectRoot });
|
|
7142
7345
|
await execFileAsync("git", ["apply", codePatchPath], { cwd: projectRoot });
|
|
@@ -7147,25 +7350,25 @@ async function installFromDir(addonDir, profileSlug, source = "local") {
|
|
|
7147
7350
|
}
|
|
7148
7351
|
} catch {
|
|
7149
7352
|
}
|
|
7150
|
-
const themePath =
|
|
7353
|
+
const themePath = path12.join(addonDir, "theme.css");
|
|
7151
7354
|
try {
|
|
7152
|
-
const css = await
|
|
7355
|
+
const css = await fs10.readFile(themePath, "utf8");
|
|
7153
7356
|
const dir2 = await ensureDir();
|
|
7154
|
-
await
|
|
7357
|
+
await fs10.writeFile(path12.join(dir2, `theme-${manifest.id}.css`), css, "utf8");
|
|
7155
7358
|
applied.push("\u0442\u0435\u043C\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0430");
|
|
7156
7359
|
} catch {
|
|
7157
7360
|
}
|
|
7158
7361
|
const dir = await ensureDir();
|
|
7159
|
-
const addonStorePath =
|
|
7160
|
-
await
|
|
7161
|
-
await
|
|
7362
|
+
const addonStorePath = path12.join(dir, manifest.id);
|
|
7363
|
+
await fs10.mkdir(addonStorePath, { recursive: true });
|
|
7364
|
+
await fs10.copyFile(manifestPath, path12.join(addonStorePath, "manifest.json"));
|
|
7162
7365
|
const allFiles = await walkDir(addonDir);
|
|
7163
7366
|
for (const f of allFiles) {
|
|
7164
7367
|
if (f === "manifest.json") continue;
|
|
7165
|
-
const src =
|
|
7166
|
-
const dst =
|
|
7167
|
-
await
|
|
7168
|
-
await
|
|
7368
|
+
const src = path12.join(addonDir, f);
|
|
7369
|
+
const dst = path12.join(addonStorePath, f);
|
|
7370
|
+
await fs10.mkdir(path12.dirname(dst), { recursive: true });
|
|
7371
|
+
await fs10.copyFile(src, dst);
|
|
7169
7372
|
}
|
|
7170
7373
|
const list = await listInstalled();
|
|
7171
7374
|
const item = {
|
|
@@ -7186,7 +7389,7 @@ async function installFromGaa(gaaPath, profileSlug) {
|
|
|
7186
7389
|
try {
|
|
7187
7390
|
return await installFromDir(dir, profileSlug, "file");
|
|
7188
7391
|
} finally {
|
|
7189
|
-
await
|
|
7392
|
+
await fs10.rm(dir, { recursive: true, force: true }).catch(() => {
|
|
7190
7393
|
});
|
|
7191
7394
|
}
|
|
7192
7395
|
}
|
|
@@ -7209,12 +7412,12 @@ async function installFromRegistry(id, registryManifest, profileSlug) {
|
|
|
7209
7412
|
const res = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
7210
7413
|
if (!res.ok) throw new Error(`\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0430\u0434\u0434\u043E\u043D: HTTP ${res.status}`);
|
|
7211
7414
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
7212
|
-
const tmpGaa =
|
|
7213
|
-
await
|
|
7415
|
+
const tmpGaa = path12.join(os3.tmpdir(), `${id}-${Date.now()}.gaa`);
|
|
7416
|
+
await fs10.writeFile(tmpGaa, buf);
|
|
7214
7417
|
try {
|
|
7215
7418
|
return await installFromGaa(tmpGaa, profileSlug);
|
|
7216
7419
|
} finally {
|
|
7217
|
-
await
|
|
7420
|
+
await fs10.unlink(tmpGaa).catch(() => {
|
|
7218
7421
|
});
|
|
7219
7422
|
}
|
|
7220
7423
|
}
|
|
@@ -7223,11 +7426,11 @@ async function uninstall(id) {
|
|
|
7223
7426
|
const next = list.filter((a) => a.manifest.id !== id);
|
|
7224
7427
|
if (next.length === list.length) return false;
|
|
7225
7428
|
const dir = addonsDir();
|
|
7226
|
-
const addonStore =
|
|
7227
|
-
await
|
|
7429
|
+
const addonStore = path12.join(dir, id);
|
|
7430
|
+
await fs10.rm(addonStore, { recursive: true, force: true }).catch(() => {
|
|
7228
7431
|
});
|
|
7229
|
-
const themePath =
|
|
7230
|
-
await
|
|
7432
|
+
const themePath = path12.join(dir, `theme-${id}.css`);
|
|
7433
|
+
await fs10.unlink(themePath).catch(() => {
|
|
7231
7434
|
});
|
|
7232
7435
|
await writeInstalled(next);
|
|
7233
7436
|
return true;
|
|
@@ -7258,11 +7461,11 @@ function validateManifest(m) {
|
|
|
7258
7461
|
}
|
|
7259
7462
|
async function walkDir(dir, prefix = "") {
|
|
7260
7463
|
const result = [];
|
|
7261
|
-
const entries = await
|
|
7464
|
+
const entries = await fs10.readdir(dir, { withFileTypes: true });
|
|
7262
7465
|
for (const e of entries) {
|
|
7263
7466
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
7264
7467
|
if (e.isDirectory()) {
|
|
7265
|
-
result.push(...await walkDir(
|
|
7468
|
+
result.push(...await walkDir(path12.join(dir, e.name), rel));
|
|
7266
7469
|
} else {
|
|
7267
7470
|
result.push(rel);
|
|
7268
7471
|
}
|
|
@@ -7282,16 +7485,16 @@ function deepMerge(target, source) {
|
|
|
7282
7485
|
}
|
|
7283
7486
|
async function getAddonReadme(id) {
|
|
7284
7487
|
const dir = addonsDir();
|
|
7285
|
-
const readmePath =
|
|
7488
|
+
const readmePath = path12.join(dir, id, "README.md");
|
|
7286
7489
|
try {
|
|
7287
|
-
return await
|
|
7490
|
+
return await fs10.readFile(readmePath, "utf8");
|
|
7288
7491
|
} catch {
|
|
7289
7492
|
return null;
|
|
7290
7493
|
}
|
|
7291
7494
|
}
|
|
7292
7495
|
async function getAddonFiles(id) {
|
|
7293
7496
|
const dir = addonsDir();
|
|
7294
|
-
const addonDir =
|
|
7497
|
+
const addonDir = path12.join(dir, id);
|
|
7295
7498
|
try {
|
|
7296
7499
|
return await walkDir(addonDir);
|
|
7297
7500
|
} catch {
|
|
@@ -7335,9 +7538,9 @@ var HttpError = class extends Error {
|
|
|
7335
7538
|
};
|
|
7336
7539
|
var Router = class {
|
|
7337
7540
|
routes = [];
|
|
7338
|
-
add(method,
|
|
7541
|
+
add(method, path15, handler) {
|
|
7339
7542
|
const paramNames = [];
|
|
7340
|
-
const parts =
|
|
7543
|
+
const parts = path15.split("/").map((part) => {
|
|
7341
7544
|
if (part.startsWith(":")) {
|
|
7342
7545
|
paramNames.push(part.slice(1));
|
|
7343
7546
|
return "([^/]+)";
|
|
@@ -7352,20 +7555,20 @@ var Router = class {
|
|
|
7352
7555
|
handler
|
|
7353
7556
|
});
|
|
7354
7557
|
}
|
|
7355
|
-
get(
|
|
7356
|
-
this.add("GET",
|
|
7558
|
+
get(path15, h) {
|
|
7559
|
+
this.add("GET", path15, h);
|
|
7357
7560
|
}
|
|
7358
|
-
post(
|
|
7359
|
-
this.add("POST",
|
|
7561
|
+
post(path15, h) {
|
|
7562
|
+
this.add("POST", path15, h);
|
|
7360
7563
|
}
|
|
7361
|
-
put(
|
|
7362
|
-
this.add("PUT",
|
|
7564
|
+
put(path15, h) {
|
|
7565
|
+
this.add("PUT", path15, h);
|
|
7363
7566
|
}
|
|
7364
|
-
delete(
|
|
7365
|
-
this.add("DELETE",
|
|
7567
|
+
delete(path15, h) {
|
|
7568
|
+
this.add("DELETE", path15, h);
|
|
7366
7569
|
}
|
|
7367
|
-
patch(
|
|
7368
|
-
this.add("PATCH",
|
|
7570
|
+
patch(path15, h) {
|
|
7571
|
+
this.add("PATCH", path15, h);
|
|
7369
7572
|
}
|
|
7370
7573
|
match(method, pathname) {
|
|
7371
7574
|
for (const r of this.routes) {
|
|
@@ -7685,6 +7888,60 @@ init_runtime_bus();
|
|
|
7685
7888
|
// src/webui/routes/profiles.ts
|
|
7686
7889
|
init_esm_shims();
|
|
7687
7890
|
init_md();
|
|
7891
|
+
|
|
7892
|
+
// src/telegram/proxy-parse.ts
|
|
7893
|
+
init_esm_shims();
|
|
7894
|
+
function parseTelegramProxyInput(raw) {
|
|
7895
|
+
if (raw == null) return void 0;
|
|
7896
|
+
if (typeof raw === "object") {
|
|
7897
|
+
if (!raw.ip || !raw.port) return void 0;
|
|
7898
|
+
if (raw.MTProxy && raw.secret) {
|
|
7899
|
+
return { ip: raw.ip, port: raw.port, MTProxy: true, secret: raw.secret, timeout: raw.timeout };
|
|
7900
|
+
}
|
|
7901
|
+
const socksType = raw.socksType === 4 ? 4 : 5;
|
|
7902
|
+
return {
|
|
7903
|
+
ip: raw.ip,
|
|
7904
|
+
port: raw.port,
|
|
7905
|
+
socksType,
|
|
7906
|
+
username: raw.username,
|
|
7907
|
+
password: raw.password,
|
|
7908
|
+
timeout: raw.timeout
|
|
7909
|
+
};
|
|
7910
|
+
}
|
|
7911
|
+
const trimmed = raw.trim();
|
|
7912
|
+
if (!trimmed) return void 0;
|
|
7913
|
+
try {
|
|
7914
|
+
const url = new URL(trimmed);
|
|
7915
|
+
const isMtproxy = url.protocol === "tg:" && url.hostname === "proxy" || /^https?:$/.test(url.protocol) && url.hostname === "t.me" && url.pathname.replace(/^\//, "") === "proxy";
|
|
7916
|
+
if (isMtproxy) {
|
|
7917
|
+
const ip = url.searchParams.get("server")?.trim();
|
|
7918
|
+
const port2 = Number(url.searchParams.get("port"));
|
|
7919
|
+
const secret = url.searchParams.get("secret")?.trim();
|
|
7920
|
+
if (!ip || !Number.isInteger(port2) || port2 <= 0 || !secret) return void 0;
|
|
7921
|
+
return { ip, port: port2, MTProxy: true, secret };
|
|
7922
|
+
}
|
|
7923
|
+
if (url.protocol === "socks4:" || url.protocol === "socks5:") {
|
|
7924
|
+
const socksType = url.protocol === "socks4:" ? 4 : 5;
|
|
7925
|
+
const port2 = Number(url.port);
|
|
7926
|
+
if (!url.hostname || !Number.isInteger(port2) || port2 <= 0) return void 0;
|
|
7927
|
+
return {
|
|
7928
|
+
ip: url.hostname,
|
|
7929
|
+
port: port2,
|
|
7930
|
+
socksType,
|
|
7931
|
+
username: url.username ? decodeURIComponent(url.username) : void 0,
|
|
7932
|
+
password: url.password ? decodeURIComponent(url.password) : void 0
|
|
7933
|
+
};
|
|
7934
|
+
}
|
|
7935
|
+
return void 0;
|
|
7936
|
+
} catch {
|
|
7937
|
+
}
|
|
7938
|
+
const [host, portRaw] = trimmed.split(":");
|
|
7939
|
+
const port = Number(portRaw);
|
|
7940
|
+
if (!host || !Number.isInteger(port) || port <= 0) return void 0;
|
|
7941
|
+
return { ip: host, port, socksType: 5 };
|
|
7942
|
+
}
|
|
7943
|
+
|
|
7944
|
+
// src/webui/routes/profiles.ts
|
|
7688
7945
|
init_runtime_bus();
|
|
7689
7946
|
init_stages();
|
|
7690
7947
|
|
|
@@ -7993,8 +8250,8 @@ function fallbackBusySchedule(name, age) {
|
|
|
7993
8250
|
init_llm();
|
|
7994
8251
|
init_llm_update();
|
|
7995
8252
|
init_llm2();
|
|
7996
|
-
import { promises as
|
|
7997
|
-
import
|
|
8253
|
+
import { promises as fs8 } from "fs";
|
|
8254
|
+
import path10 from "path";
|
|
7998
8255
|
var MEMORY_FILES = [
|
|
7999
8256
|
"persona.md",
|
|
8000
8257
|
"speech.md",
|
|
@@ -8011,7 +8268,7 @@ var MEMORY_FILES = [
|
|
|
8011
8268
|
function isAllowedMemoryPath(p) {
|
|
8012
8269
|
if (!p || typeof p !== "string") return false;
|
|
8013
8270
|
if (p.includes("..")) return false;
|
|
8014
|
-
if (
|
|
8271
|
+
if (path10.isAbsolute(p)) return false;
|
|
8015
8272
|
if (p.startsWith("config.json")) return false;
|
|
8016
8273
|
if (p.startsWith("agenda.json")) return false;
|
|
8017
8274
|
if (MEMORY_FILES.includes(p)) return true;
|
|
@@ -8056,6 +8313,13 @@ function registerProfileRoutes(r) {
|
|
|
8056
8313
|
if (!incoming || typeof incoming !== "object") throw new HttpError(400, "invalid body");
|
|
8057
8314
|
const merged = { ...cur, ...incoming, slug: cur.slug };
|
|
8058
8315
|
if (incoming.ownerId !== void 0) merged.ownerId = normalizeOwnerId(incoming.ownerId);
|
|
8316
|
+
if (incoming.telegram) {
|
|
8317
|
+
merged.telegram = {
|
|
8318
|
+
...cur.telegram,
|
|
8319
|
+
...incoming.telegram,
|
|
8320
|
+
proxy: parseTelegramProxyInput(incoming.telegram.proxy)
|
|
8321
|
+
};
|
|
8322
|
+
}
|
|
8059
8323
|
await writeConfig(merged);
|
|
8060
8324
|
return { config: merged };
|
|
8061
8325
|
});
|
|
@@ -8065,6 +8329,7 @@ function registerProfileRoutes(r) {
|
|
|
8065
8329
|
const slug = data.slug || slugify(data.name);
|
|
8066
8330
|
const existing = await readConfig(slug);
|
|
8067
8331
|
if (existing) throw new HttpError(409, `profile already exists: ${slug}`);
|
|
8332
|
+
const incomingTg = data.telegram ?? {};
|
|
8068
8333
|
const cfg = {
|
|
8069
8334
|
slug,
|
|
8070
8335
|
name: data.name,
|
|
@@ -8074,7 +8339,10 @@ function registerProfileRoutes(r) {
|
|
|
8074
8339
|
mode: data.mode ?? "bot",
|
|
8075
8340
|
stage: data.stage ?? "tg-given-cold",
|
|
8076
8341
|
llm: data.llm ?? { presetId: "claudehub", proto: "anthropic", apiKey: "", model: "claude-sonnet-4.6" },
|
|
8077
|
-
telegram:
|
|
8342
|
+
telegram: {
|
|
8343
|
+
...incomingTg,
|
|
8344
|
+
proxy: parseTelegramProxyInput(incomingTg.proxy)
|
|
8345
|
+
},
|
|
8078
8346
|
privacy: data.privacy ?? "owner-only",
|
|
8079
8347
|
ownerId: normalizeOwnerId(data.ownerId),
|
|
8080
8348
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -8186,29 +8454,29 @@ function registerProfileRoutes(r) {
|
|
|
8186
8454
|
const entries = [];
|
|
8187
8455
|
for (const f of MEMORY_FILES) entries.push({ rel: f });
|
|
8188
8456
|
try {
|
|
8189
|
-
const dailyDir =
|
|
8190
|
-
const list = await
|
|
8457
|
+
const dailyDir = path10.join(dir, "memory", "daily");
|
|
8458
|
+
const list = await fs8.readdir(dailyDir);
|
|
8191
8459
|
for (const f of list) if (/^\d{4}-\d{2}-\d{2}\.md$/.test(f)) entries.push({ rel: `memory/daily/${f}` });
|
|
8192
8460
|
} catch {
|
|
8193
8461
|
}
|
|
8194
8462
|
try {
|
|
8195
|
-
const epDir =
|
|
8196
|
-
const list = await
|
|
8463
|
+
const epDir = path10.join(dir, "memory", "episodes");
|
|
8464
|
+
const list = await fs8.readdir(epDir);
|
|
8197
8465
|
for (const f of list) if (/^[\w\-]{1,80}\.md$/.test(f)) entries.push({ rel: `memory/episodes/${f}` });
|
|
8198
8466
|
} catch {
|
|
8199
8467
|
}
|
|
8200
8468
|
try {
|
|
8201
|
-
const palaceDir =
|
|
8202
|
-
const wings = await
|
|
8469
|
+
const palaceDir = path10.join(dir, "memory", "palace");
|
|
8470
|
+
const wings = await fs8.readdir(palaceDir, { withFileTypes: true });
|
|
8203
8471
|
for (const wing of wings) {
|
|
8204
8472
|
if (!wing.isDirectory() || !/^[\w\-]{1,80}$/.test(wing.name)) continue;
|
|
8205
|
-
const halls = await
|
|
8473
|
+
const halls = await fs8.readdir(path10.join(palaceDir, wing.name), { withFileTypes: true });
|
|
8206
8474
|
for (const hall of halls) {
|
|
8207
8475
|
if (!hall.isDirectory() || !/^[\w\-]{1,80}$/.test(hall.name)) continue;
|
|
8208
|
-
const rooms = await
|
|
8476
|
+
const rooms = await fs8.readdir(path10.join(palaceDir, wing.name, hall.name), { withFileTypes: true });
|
|
8209
8477
|
for (const room of rooms) {
|
|
8210
8478
|
if (!room.isDirectory() || !/^[\w\-]{1,80}$/.test(room.name)) continue;
|
|
8211
|
-
const drawers = await
|
|
8479
|
+
const drawers = await fs8.readdir(path10.join(palaceDir, wing.name, hall.name, room.name));
|
|
8212
8480
|
for (const drawer of drawers) {
|
|
8213
8481
|
if (/^[\w\-]{1,120}\.md$/.test(drawer)) entries.push({ rel: `memory/palace/${wing.name}/${hall.name}/${room.name}/${drawer}` });
|
|
8214
8482
|
}
|
|
@@ -8219,7 +8487,7 @@ function registerProfileRoutes(r) {
|
|
|
8219
8487
|
}
|
|
8220
8488
|
for (const e of entries) {
|
|
8221
8489
|
try {
|
|
8222
|
-
const stat = await
|
|
8490
|
+
const stat = await fs8.stat(path10.join(dir, e.rel));
|
|
8223
8491
|
items.push({ path: e.rel, size: stat.size, mtime: stat.mtimeMs });
|
|
8224
8492
|
} catch {
|
|
8225
8493
|
}
|
|
@@ -8583,9 +8851,9 @@ function registerPresetRoutes(r) {
|
|
|
8583
8851
|
// src/webui/routes/system.ts
|
|
8584
8852
|
init_esm_shims();
|
|
8585
8853
|
init_md();
|
|
8586
|
-
import { promises as
|
|
8854
|
+
import { promises as fs9 } from "fs";
|
|
8587
8855
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
8588
|
-
import
|
|
8856
|
+
import path11 from "path";
|
|
8589
8857
|
import os2 from "os";
|
|
8590
8858
|
var cachedVersion = null;
|
|
8591
8859
|
async function readPackageVersion() {
|
|
@@ -8593,15 +8861,15 @@ async function readPackageVersion() {
|
|
|
8593
8861
|
const candidates = [];
|
|
8594
8862
|
try {
|
|
8595
8863
|
const here = fileURLToPath4(import.meta.url);
|
|
8596
|
-
candidates.push(
|
|
8597
|
-
candidates.push(
|
|
8598
|
-
candidates.push(
|
|
8864
|
+
candidates.push(path11.resolve(path11.dirname(here), "..", "package.json"));
|
|
8865
|
+
candidates.push(path11.resolve(path11.dirname(here), "..", "..", "package.json"));
|
|
8866
|
+
candidates.push(path11.resolve(path11.dirname(here), "..", "..", "..", "package.json"));
|
|
8599
8867
|
} catch {
|
|
8600
8868
|
}
|
|
8601
|
-
candidates.push(
|
|
8869
|
+
candidates.push(path11.resolve(process.cwd(), "package.json"));
|
|
8602
8870
|
for (const c of candidates) {
|
|
8603
8871
|
try {
|
|
8604
|
-
const raw = await
|
|
8872
|
+
const raw = await fs9.readFile(c, "utf8");
|
|
8605
8873
|
const parsed = JSON.parse(raw);
|
|
8606
8874
|
if (parsed.name === "@thesashadev/girl-agent" && parsed.version) {
|
|
8607
8875
|
cachedVersion = parsed.version;
|
|
@@ -8652,8 +8920,8 @@ function registerSystemRoutes(r) {
|
|
|
8652
8920
|
// src/webui/routes/addons.ts
|
|
8653
8921
|
init_esm_shims();
|
|
8654
8922
|
init_addons();
|
|
8655
|
-
import { promises as
|
|
8656
|
-
import
|
|
8923
|
+
import { promises as fs11 } from "fs";
|
|
8924
|
+
import path13 from "path";
|
|
8657
8925
|
import os4 from "os";
|
|
8658
8926
|
function registerAddonRoutes(r) {
|
|
8659
8927
|
r.get("/api/addons", async () => {
|
|
@@ -8680,13 +8948,13 @@ function registerAddonRoutes(r) {
|
|
|
8680
8948
|
const data = body;
|
|
8681
8949
|
if (!data?.gaaBase64) throw new HttpError(400, "gaaBase64 required");
|
|
8682
8950
|
const buf = Buffer.from(data.gaaBase64, "base64");
|
|
8683
|
-
const tmpPath =
|
|
8684
|
-
await
|
|
8951
|
+
const tmpPath = path13.join(os4.tmpdir(), `upload-${Date.now()}.gaa`);
|
|
8952
|
+
await fs11.writeFile(tmpPath, buf);
|
|
8685
8953
|
try {
|
|
8686
8954
|
const result = await installFromGaa(tmpPath, data.profileSlug);
|
|
8687
8955
|
return { ok: true, installed: result.addon, applied: result.applied };
|
|
8688
8956
|
} finally {
|
|
8689
|
-
await
|
|
8957
|
+
await fs11.unlink(tmpPath).catch(() => {
|
|
8690
8958
|
});
|
|
8691
8959
|
}
|
|
8692
8960
|
});
|
|
@@ -8698,13 +8966,13 @@ function registerAddonRoutes(r) {
|
|
|
8698
8966
|
const res = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
8699
8967
|
if (!res.ok) throw new HttpError(502, `fetch failed: HTTP ${res.status}`);
|
|
8700
8968
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
8701
|
-
const tmpPath =
|
|
8702
|
-
await
|
|
8969
|
+
const tmpPath = path13.join(os4.tmpdir(), `url-${Date.now()}.gaa`);
|
|
8970
|
+
await fs11.writeFile(tmpPath, buf);
|
|
8703
8971
|
try {
|
|
8704
8972
|
const result = await installFromGaa(tmpPath, data.profileSlug);
|
|
8705
8973
|
return { ok: true, installed: result.addon, applied: result.applied };
|
|
8706
8974
|
} finally {
|
|
8707
|
-
await
|
|
8975
|
+
await fs11.unlink(tmpPath).catch(() => {
|
|
8708
8976
|
});
|
|
8709
8977
|
}
|
|
8710
8978
|
} else {
|
|
@@ -9707,8 +9975,8 @@ function tail(text, limit) {
|
|
|
9707
9975
|
if (text.length <= limit) return text;
|
|
9708
9976
|
return text.slice(-limit);
|
|
9709
9977
|
}
|
|
9710
|
-
function setNested(obj,
|
|
9711
|
-
const parts =
|
|
9978
|
+
function setNested(obj, path15, value) {
|
|
9979
|
+
const parts = path15.split(".");
|
|
9712
9980
|
let cur = obj;
|
|
9713
9981
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
9714
9982
|
const p = parts[i];
|
|
@@ -9727,14 +9995,14 @@ var DEFAULT_PROXY = "https://tgproxy.girl-agent.com";
|
|
|
9727
9995
|
function proxyUrl() {
|
|
9728
9996
|
return process.env.GIRL_AGENT_AUTH_PROXY ?? DEFAULT_PROXY;
|
|
9729
9997
|
}
|
|
9730
|
-
async function post(
|
|
9731
|
-
const res = await fetch(`${proxyUrl()}${
|
|
9998
|
+
async function post(path15, body) {
|
|
9999
|
+
const res = await fetch(`${proxyUrl()}${path15}`, {
|
|
9732
10000
|
method: "POST",
|
|
9733
10001
|
headers: { "Content-Type": "application/json" },
|
|
9734
10002
|
body: JSON.stringify(body)
|
|
9735
10003
|
});
|
|
9736
10004
|
const data = await res.json();
|
|
9737
|
-
if (!res.ok) throw new Error(data.error ?? `proxy ${
|
|
10005
|
+
if (!res.ok) throw new Error(data.error ?? `proxy ${path15} failed (${res.status})`);
|
|
9738
10006
|
return data;
|
|
9739
10007
|
}
|
|
9740
10008
|
function remoteSendCode(phone) {
|
|
@@ -10165,8 +10433,8 @@ init_esm_shims();
|
|
|
10165
10433
|
init_llm2();
|
|
10166
10434
|
init_stages();
|
|
10167
10435
|
init_communication();
|
|
10168
|
-
import
|
|
10169
|
-
import
|
|
10436
|
+
import fs12 from "fs/promises";
|
|
10437
|
+
import path14 from "path";
|
|
10170
10438
|
import os6 from "os";
|
|
10171
10439
|
init_md();
|
|
10172
10440
|
init_runtime();
|
|
@@ -10249,7 +10517,7 @@ async function runServer(rawArgv) {
|
|
|
10249
10517
|
}
|
|
10250
10518
|
if (!args.yes) {
|
|
10251
10519
|
process.stderr.write(`\u043F\u0440\u043E\u0444\u0438\u043B\u044C \u041D\u0415 \u0443\u0434\u0430\u043B\u0451\u043D: \u0434\u043E\u0431\u0430\u0432\u044C --yes \u0434\u043B\u044F \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F.
|
|
10252
|
-
\u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043B\u0435\u043D\u043E: ${
|
|
10520
|
+
\u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043B\u0435\u043D\u043E: ${path14.join(DATA_ROOT, args.profile)}
|
|
10253
10521
|
`);
|
|
10254
10522
|
process.exit(1);
|
|
10255
10523
|
}
|
|
@@ -10311,7 +10579,7 @@ data dir: ${DATA_ROOT}
|
|
|
10311
10579
|
}
|
|
10312
10580
|
async function persistAndMaybeStart(cfg, args) {
|
|
10313
10581
|
await writeConfig(cfg);
|
|
10314
|
-
process.stderr.write(`[server] \u043F\u0440\u043E\u0444\u0438\u043B\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D: ${
|
|
10582
|
+
process.stderr.write(`[server] \u043F\u0440\u043E\u0444\u0438\u043B\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D: ${path14.join(DATA_ROOT, cfg.slug)}
|
|
10315
10583
|
`);
|
|
10316
10584
|
if (cfg.llm.apiKey || findPreset(cfg.llm.presetId)?.apiKeyRequired === false) {
|
|
10317
10585
|
try {
|
|
@@ -10427,10 +10695,10 @@ function configFromEnv() {
|
|
|
10427
10695
|
};
|
|
10428
10696
|
}
|
|
10429
10697
|
async function loadConfigFile(file) {
|
|
10430
|
-
const abs =
|
|
10698
|
+
const abs = path14.isAbsolute(file) ? file : path14.join(process.cwd(), file);
|
|
10431
10699
|
let raw;
|
|
10432
10700
|
try {
|
|
10433
|
-
raw = await
|
|
10701
|
+
raw = await fs12.readFile(abs, "utf-8");
|
|
10434
10702
|
} catch (e) {
|
|
10435
10703
|
process.stderr.write(`[server] \u043D\u0435 \u043C\u043E\u0433\u0443 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C ${abs}: ${e?.message ?? e}
|
|
10436
10704
|
`);
|
|
@@ -10496,33 +10764,7 @@ function validateConfig(raw) {
|
|
|
10496
10764
|
return filled;
|
|
10497
10765
|
}
|
|
10498
10766
|
function parseTelegramProxy(raw) {
|
|
10499
|
-
|
|
10500
|
-
try {
|
|
10501
|
-
const url = new URL(raw);
|
|
10502
|
-
if (url.protocol === "tg:" && url.hostname === "proxy") {
|
|
10503
|
-
const ip = url.searchParams.get("server")?.trim();
|
|
10504
|
-
const port2 = Number(url.searchParams.get("port"));
|
|
10505
|
-
const secret = url.searchParams.get("secret")?.trim();
|
|
10506
|
-
if (!ip || !Number.isInteger(port2) || port2 <= 0 || !secret) return void 0;
|
|
10507
|
-
return { ip, port: port2, MTProxy: true, secret };
|
|
10508
|
-
}
|
|
10509
|
-
if (url.protocol !== "socks4:" && url.protocol !== "socks5:") return void 0;
|
|
10510
|
-
const socksType = url.protocol === "socks4:" ? 4 : 5;
|
|
10511
|
-
const port = Number(url.port);
|
|
10512
|
-
if (!url.hostname || !Number.isInteger(port) || port <= 0) return void 0;
|
|
10513
|
-
return {
|
|
10514
|
-
ip: url.hostname,
|
|
10515
|
-
port,
|
|
10516
|
-
socksType,
|
|
10517
|
-
username: url.username ? decodeURIComponent(url.username) : void 0,
|
|
10518
|
-
password: url.password ? decodeURIComponent(url.password) : void 0
|
|
10519
|
-
};
|
|
10520
|
-
} catch {
|
|
10521
|
-
const [host, portRaw] = raw.split(":");
|
|
10522
|
-
const port = Number(portRaw);
|
|
10523
|
-
if (!host || !Number.isInteger(port) || port <= 0) return void 0;
|
|
10524
|
-
return { ip: host, port, socksType: 5 };
|
|
10525
|
-
}
|
|
10767
|
+
return parseTelegramProxyInput(raw);
|
|
10526
10768
|
}
|
|
10527
10769
|
function buildConfigTemplate() {
|
|
10528
10770
|
const sample = {
|