@thesashadev/girl-agent 0.1.1 → 0.1.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 +20 -0
- package/README.md +20 -6
- package/dist/cli.js +473 -168
- package/package.json +2 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.2 — communication realism update
|
|
4
|
+
|
|
5
|
+
Дата: 2026-05-05
|
|
6
|
+
|
|
7
|
+
- Hotfix: профили из wizard теперь сохраняются раньше, а список профилей больше не показывает недосохранённые папки без `config.json`.
|
|
8
|
+
- Добавлены жизненные стили общения: **Нормальная**, **Милая**, **Альтушка**, **Залипала**, **Болтушка**.
|
|
9
|
+
- Добавлен `CommunicationProfile` с настройками уведомлений, стиля сообщений, инициативы и life sharing.
|
|
10
|
+
- Presence, reply timing, bubbles, ignore chance и proactive agenda теперь учитывают профиль общения.
|
|
11
|
+
- Wizard и CLI получили настройку communication profile.
|
|
12
|
+
- Runtime `:status` и `:debug` показывают профиль общения.
|
|
13
|
+
- Команда `:log` стала удобнее и поддерживает выбор дня/лимита вывода.
|
|
14
|
+
- Старый `vibe` автоматически нормализуется в новый формат.
|
|
15
|
+
|
|
16
|
+
## 0.1.1 — stability baseline
|
|
17
|
+
|
|
18
|
+
- Базовый публичный релиз с Telegram bot/userbot режимами.
|
|
19
|
+
- Persona, speech, relationship state, memory, conflict и agenda-модули.
|
|
20
|
+
- Документация по установке, конфигурации, реализм-модулям и troubleshooting.
|
package/README.md
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
**[website]** · **[docs]**
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
Это только бета-версия. Со временем будет дорабатыватся.
|
|
10
|
+
Со всеми проблемами и багами пишите в Issues.
|
|
11
|
+
ТГ создателя - @voided_net
|
|
12
|
+
|
|
8
13
|
---
|
|
9
14
|
|
|
10
15
|
## Содержание
|
|
@@ -12,6 +17,7 @@
|
|
|
12
17
|
- [Быстрый старт](#быстрый-старт)
|
|
13
18
|
- [Что под капотом](#что-под-капотом)
|
|
14
19
|
- [Почему не просто GPTs или промпт](#почему-не-просто-gpts-или-промпт)
|
|
20
|
+
- [Changelog](./CHANGELOG.md)
|
|
15
21
|
- [Безопасность](#безопасность)
|
|
16
22
|
- [Лицензия](#лицензия)
|
|
17
23
|
|
|
@@ -29,11 +35,10 @@
|
|
|
29
35
|
|
|
30
36
|
## Быстрый старт
|
|
31
37
|
|
|
38
|
+
**Через NPX (рекомендуется):**
|
|
39
|
+
|
|
32
40
|
```powershell
|
|
33
|
-
|
|
34
|
-
cd girl-agent
|
|
35
|
-
npm install
|
|
36
|
-
npm run dev
|
|
41
|
+
npx @thesashadev/girl-agent
|
|
37
42
|
```
|
|
38
43
|
|
|
39
44
|
Wizard задаст пару вопросов — имя, возраст, Telegram-подключение, LLM-ключ. Всё.
|
|
@@ -41,7 +46,16 @@ Wizard задаст пару вопросов — имя, возраст, Telegr
|
|
|
41
46
|
Если профиль уже есть:
|
|
42
47
|
|
|
43
48
|
```powershell
|
|
44
|
-
|
|
49
|
+
npx @thesashadev/girl-agent --profile=arina
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Из исходников:**
|
|
53
|
+
|
|
54
|
+
```powershell
|
|
55
|
+
git clone https://github.com/TheSashaDev/girl-agent.git
|
|
56
|
+
cd girl-agent
|
|
57
|
+
npm install
|
|
58
|
+
npm run dev
|
|
45
59
|
```
|
|
46
60
|
|
|
47
61
|
---
|
|
@@ -167,4 +181,4 @@ npm run dev -- --profile=arina
|
|
|
167
181
|
- Публичные конкурирующие клоны
|
|
168
182
|
- Использование кода внутри коммерческих продуктов
|
|
169
183
|
|
|
170
|
-
📜 Полный текст лицензии: [LICENSE](./LICENSE)
|
|
184
|
+
📜 Полный текст лицензии: [LICENSE](./LICENSE)
|
package/dist/cli.js
CHANGED
|
@@ -344,28 +344,32 @@ var LLM_PRESETS = [
|
|
|
344
344
|
id: "openai",
|
|
345
345
|
name: "OpenAI",
|
|
346
346
|
proto: "openai",
|
|
347
|
-
defaultModel: "gpt-
|
|
348
|
-
models: ["gpt-
|
|
347
|
+
defaultModel: "gpt-5.5",
|
|
348
|
+
models: ["gpt-5.5", "gpt-5.5-thinking", "gpt-5.5-pro", "gpt-5.4", "gpt-5.4-pro", "gpt-5.4-thinking", "gpt-5.3-chat-latest", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-4o", "gpt-4o-mini", "gpt-4.1", "gpt-4.1-mini"]
|
|
349
349
|
},
|
|
350
350
|
{
|
|
351
351
|
id: "anthropic",
|
|
352
352
|
name: "Anthropic",
|
|
353
353
|
proto: "anthropic",
|
|
354
|
-
defaultModel: "claude-sonnet-4-
|
|
355
|
-
models: ["claude-sonnet-4-5", "claude-opus-4-
|
|
354
|
+
defaultModel: "claude-sonnet-4-6",
|
|
355
|
+
models: ["claude-opus-4-7", "claude-sonnet-4-6", "claude-haiku-4-5-20251001", "claude-opus-4-6", "claude-sonnet-4-5", "claude-opus-4-1"]
|
|
356
356
|
},
|
|
357
357
|
{
|
|
358
358
|
id: "openrouter",
|
|
359
359
|
name: "OpenRouter",
|
|
360
360
|
proto: "openai",
|
|
361
361
|
baseURL: "https://openrouter.ai/api/v1",
|
|
362
|
-
defaultModel: "
|
|
362
|
+
defaultModel: "openai/gpt-5.3-chat-latest",
|
|
363
363
|
models: [
|
|
364
|
-
"
|
|
365
|
-
"openai/gpt-
|
|
366
|
-
"
|
|
367
|
-
"
|
|
368
|
-
"
|
|
364
|
+
"openai/gpt-5.3-chat-latest",
|
|
365
|
+
"openai/gpt-5.5",
|
|
366
|
+
"openai/gpt-5.5-thinking",
|
|
367
|
+
"openai/gpt-5.5-pro",
|
|
368
|
+
"anthropic/claude-sonnet-4.6",
|
|
369
|
+
"anthropic/claude-opus-4.7",
|
|
370
|
+
"google/gemini-3.1-pro",
|
|
371
|
+
"deepseek/deepseek-v4-pro",
|
|
372
|
+
"x-ai/grok-4.3"
|
|
369
373
|
]
|
|
370
374
|
},
|
|
371
375
|
{
|
|
@@ -374,31 +378,32 @@ var LLM_PRESETS = [
|
|
|
374
378
|
proto: "openai",
|
|
375
379
|
baseURL: "https://api.groq.com/openai/v1",
|
|
376
380
|
defaultModel: "llama-3.3-70b-versatile",
|
|
377
|
-
models: ["llama-3.3-70b-versatile", "llama-3.1-8b-instant", "mixtral-8x7b-32768"]
|
|
381
|
+
models: ["llama-3.3-70b-versatile", "llama-3.1-8b-instant", "llama-4-scout-17b-16e-instruct", "qwen-3-32b", "mixtral-8x7b-32768"]
|
|
378
382
|
},
|
|
379
383
|
{
|
|
380
384
|
id: "deepseek",
|
|
381
385
|
name: "DeepSeek",
|
|
382
386
|
proto: "openai",
|
|
383
387
|
baseURL: "https://api.deepseek.com",
|
|
384
|
-
defaultModel: "deepseek-
|
|
385
|
-
models: ["deepseek-chat", "deepseek-reasoner"]
|
|
388
|
+
defaultModel: "deepseek-v4-flash",
|
|
389
|
+
models: ["deepseek-v4-pro", "deepseek-v4-flash", "deepseek-chat", "deepseek-reasoner"],
|
|
390
|
+
hint: "deepseek-chat/reasoner deprecated 2026-07-24, use V4 models"
|
|
386
391
|
},
|
|
387
392
|
{
|
|
388
393
|
id: "mistral",
|
|
389
394
|
name: "Mistral",
|
|
390
395
|
proto: "openai",
|
|
391
396
|
baseURL: "https://api.mistral.ai/v1",
|
|
392
|
-
defaultModel: "mistral-large-
|
|
393
|
-
models: ["mistral-large-
|
|
397
|
+
defaultModel: "mistral-large-2512",
|
|
398
|
+
models: ["mistral-large-2512", "mistral-small-2603", "ministral-8b-2512", "ministral-14b-2512", "mistral-large-latest", "mistral-small-latest"]
|
|
394
399
|
},
|
|
395
400
|
{
|
|
396
401
|
id: "google",
|
|
397
402
|
name: "Google Gemini",
|
|
398
403
|
proto: "openai",
|
|
399
404
|
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
400
|
-
defaultModel: "gemini-
|
|
401
|
-
models: ["gemini-
|
|
405
|
+
defaultModel: "gemini-3.1-pro",
|
|
406
|
+
models: ["gemini-3.1-pro", "gemini-3-flash", "gemini-3.1-flash-lite", "gemini-2.5-pro", "gemini-2.5-flash"],
|
|
402
407
|
hint: "Gemini via OpenAI-compatible endpoint"
|
|
403
408
|
},
|
|
404
409
|
{
|
|
@@ -406,8 +411,8 @@ var LLM_PRESETS = [
|
|
|
406
411
|
name: "xAI Grok",
|
|
407
412
|
proto: "openai",
|
|
408
413
|
baseURL: "https://api.x.ai/v1",
|
|
409
|
-
defaultModel: "grok-4",
|
|
410
|
-
models: ["grok-4", "grok-3", "grok-3-mini"]
|
|
414
|
+
defaultModel: "grok-4.3",
|
|
415
|
+
models: ["grok-4.3", "grok-4.20-reasoning", "grok-4.20-non-reasoning", "grok-4", "grok-3", "grok-3-mini"]
|
|
411
416
|
},
|
|
412
417
|
{
|
|
413
418
|
id: "together",
|
|
@@ -417,6 +422,7 @@ var LLM_PRESETS = [
|
|
|
417
422
|
defaultModel: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
|
|
418
423
|
models: [
|
|
419
424
|
"meta-llama/Llama-3.3-70B-Instruct-Turbo",
|
|
425
|
+
"meta-llama/Llama-4-scout-17b-instruct",
|
|
420
426
|
"Qwen/Qwen2.5-72B-Instruct-Turbo",
|
|
421
427
|
"deepseek-ai/DeepSeek-V3"
|
|
422
428
|
]
|
|
@@ -429,6 +435,7 @@ var LLM_PRESETS = [
|
|
|
429
435
|
defaultModel: "accounts/fireworks/models/llama-v3p3-70b-instruct",
|
|
430
436
|
models: [
|
|
431
437
|
"accounts/fireworks/models/llama-v3p3-70b-instruct",
|
|
438
|
+
"accounts/fireworks/models/llama-4-scout-17b-16e-instruct",
|
|
432
439
|
"accounts/fireworks/models/qwen2p5-72b-instruct",
|
|
433
440
|
"accounts/fireworks/models/deepseek-v3"
|
|
434
441
|
]
|
|
@@ -455,7 +462,7 @@ var LLM_PRESETS = [
|
|
|
455
462
|
proto: "anthropic",
|
|
456
463
|
baseURL: "https://api.claudehub.fun",
|
|
457
464
|
defaultModel: "claude-sonnet-4.6",
|
|
458
|
-
models: ["claude-opus-4.7", "claude-opus-4.6", "claude-opus-4.5", "claude-sonnet-4.6", "claude-sonnet-4.5", "claude-haiku-4.5", "gpt-5.
|
|
465
|
+
models: ["claude-opus-4.7", "claude-opus-4.6", "claude-opus-4.5", "claude-sonnet-4.6", "claude-sonnet-4.5", "claude-haiku-4.5", "gpt-5.5", "gpt-5.4"],
|
|
459
466
|
hint: "ClaudeHub proxy for Anthropic & OpenAI (\u0420\u0424, \u0421\u0411\u041F, \u043A\u0440\u0438\u043F\u0442\u0430)"
|
|
460
467
|
},
|
|
461
468
|
{
|
|
@@ -531,13 +538,13 @@ var STAGE_PRESETS = [
|
|
|
531
538
|
label: "\u0412\u0441\u0442\u0440\u0435\u0442\u0438\u043B\u0438\u0441\u044C \u0432 \u0440\u0435\u0430\u043B\u0435 \u2014 \u0434\u0430\u043B\u0430 \u0442\u0433",
|
|
532
539
|
description: "\u0422\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u043E \u043E\u0431\u043C\u0435\u043D\u044F\u043B\u0438\u0441\u044C \u0442\u0433. \u041F\u043E\u043C\u043D\u0438\u0442 \u043B\u0438\u0446\u043E, \u0433\u043E\u043B\u043E\u0441. \u041B\u0451\u0433\u043A\u0438\u0439 \u0438\u043D\u0442\u0435\u0440\u0435\u0441.",
|
|
533
540
|
defaults: {
|
|
534
|
-
interest:
|
|
535
|
-
trust:
|
|
536
|
-
attraction:
|
|
541
|
+
interest: 38,
|
|
542
|
+
trust: 14,
|
|
543
|
+
attraction: 30,
|
|
537
544
|
annoyance: 0,
|
|
538
|
-
cringeTolerance:
|
|
539
|
-
ignoreChance: 0.
|
|
540
|
-
replyDelaySec: [
|
|
545
|
+
cringeTolerance: 14,
|
|
546
|
+
ignoreChance: 0.12,
|
|
547
|
+
replyDelaySec: [15, 600]
|
|
541
548
|
}
|
|
542
549
|
},
|
|
543
550
|
{
|
|
@@ -564,8 +571,8 @@ var STAGE_PRESETS = [
|
|
|
564
571
|
attraction: 25,
|
|
565
572
|
annoyance: 0,
|
|
566
573
|
cringeTolerance: 5,
|
|
567
|
-
ignoreChance: 0.
|
|
568
|
-
replyDelaySec: [
|
|
574
|
+
ignoreChance: 0.18,
|
|
575
|
+
replyDelaySec: [30, 1200]
|
|
569
576
|
}
|
|
570
577
|
},
|
|
571
578
|
{
|
|
@@ -578,8 +585,8 @@ var STAGE_PRESETS = [
|
|
|
578
585
|
attraction: 45,
|
|
579
586
|
annoyance: 0,
|
|
580
587
|
cringeTolerance: 15,
|
|
581
|
-
ignoreChance: 0.
|
|
582
|
-
replyDelaySec: [
|
|
588
|
+
ignoreChance: 0.07,
|
|
589
|
+
replyDelaySec: [10, 420]
|
|
583
590
|
}
|
|
584
591
|
},
|
|
585
592
|
{
|
|
@@ -592,8 +599,8 @@ var STAGE_PRESETS = [
|
|
|
592
599
|
attraction: 55,
|
|
593
600
|
annoyance: 0,
|
|
594
601
|
cringeTolerance: 25,
|
|
595
|
-
ignoreChance: 0.
|
|
596
|
-
replyDelaySec: [
|
|
602
|
+
ignoreChance: 0.05,
|
|
603
|
+
replyDelaySec: [8, 300]
|
|
597
604
|
}
|
|
598
605
|
},
|
|
599
606
|
{
|
|
@@ -606,8 +613,8 @@ var STAGE_PRESETS = [
|
|
|
606
613
|
attraction: 70,
|
|
607
614
|
annoyance: 0,
|
|
608
615
|
cringeTolerance: 35,
|
|
609
|
-
ignoreChance: 0.
|
|
610
|
-
replyDelaySec: [
|
|
616
|
+
ignoreChance: 0.02,
|
|
617
|
+
replyDelaySec: [3, 120]
|
|
611
618
|
}
|
|
612
619
|
},
|
|
613
620
|
{
|
|
@@ -620,8 +627,8 @@ var STAGE_PRESETS = [
|
|
|
620
627
|
attraction: 75,
|
|
621
628
|
annoyance: 0,
|
|
622
629
|
cringeTolerance: 50,
|
|
623
|
-
ignoreChance: 0.
|
|
624
|
-
replyDelaySec: [
|
|
630
|
+
ignoreChance: 0.03,
|
|
631
|
+
replyDelaySec: [3, 240]
|
|
625
632
|
}
|
|
626
633
|
},
|
|
627
634
|
{
|
|
@@ -634,8 +641,8 @@ var STAGE_PRESETS = [
|
|
|
634
641
|
attraction: 65,
|
|
635
642
|
annoyance: 10,
|
|
636
643
|
cringeTolerance: 60,
|
|
637
|
-
ignoreChance: 0.
|
|
638
|
-
replyDelaySec: [
|
|
644
|
+
ignoreChance: 0.05,
|
|
645
|
+
replyDelaySec: [5, 900]
|
|
639
646
|
}
|
|
640
647
|
},
|
|
641
648
|
{
|
|
@@ -657,6 +664,92 @@ function findStage(id) {
|
|
|
657
664
|
return STAGE_PRESETS.find((s) => s.id === id) ?? STAGE_PRESETS[1];
|
|
658
665
|
}
|
|
659
666
|
|
|
667
|
+
// src/presets/communication.ts
|
|
668
|
+
init_esm_shims();
|
|
669
|
+
var NOTIFICATIONS = ["muted", "normal", "priority"];
|
|
670
|
+
var MESSAGE_STYLES = ["one-liners", "balanced", "bursty", "longform"];
|
|
671
|
+
var INITIATIVES = ["low", "medium", "high"];
|
|
672
|
+
var LIFE_SHARING = ["low", "medium", "high"];
|
|
673
|
+
var COMMUNICATION_PRESETS = [
|
|
674
|
+
{
|
|
675
|
+
id: "normal",
|
|
676
|
+
label: "\u041D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u0430\u044F",
|
|
677
|
+
description: "\u0437\u043E\u043B\u043E\u0442\u0430\u044F \u0441\u0435\u0440\u0435\u0434\u0438\u043D\u0430 \u2014 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E, \u043D\u0435 \u043B\u0438\u043F\u043D\u0435\u0442, \u0438\u043D\u043E\u0433\u0434\u0430 \u0441\u0430\u043C\u0430 \u043F\u0438\u0448\u0435\u0442",
|
|
678
|
+
profile: { notifications: "normal", messageStyle: "balanced", initiative: "medium", lifeSharing: "medium" }
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
id: "cute",
|
|
682
|
+
label: "\u041C\u0438\u043B\u0430\u044F",
|
|
683
|
+
description: "\u0442\u0451\u043F\u043B\u0430\u044F \u0438 \u0437\u0430\u0431\u043E\u0442\u043B\u0438\u0432\u0430\u044F, \u0447\u0430\u0441\u0442\u043E \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442, \u043F\u0438\u0448\u0435\u0442 \u043F\u0435\u0440\u0432\u043E\u0439, \u0434\u0435\u043B\u0438\u0442\u0441\u044F \u043C\u043E\u043C\u0435\u043D\u0442\u0430\u043C\u0438",
|
|
684
|
+
profile: { notifications: "priority", messageStyle: "balanced", initiative: "high", lifeSharing: "high" }
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
id: "alt",
|
|
688
|
+
label: "\u0410\u043B\u044C\u0442\u0443\u0448\u043A\u0430",
|
|
689
|
+
description: "\u0445\u043E\u043B\u043E\u0434\u043D\u0430\u044F, \u0441\u0443\u0445\u0430\u044F, \u043A\u043E\u0440\u043E\u0442\u043A\u0438\u0435 \u043E\u0442\u0432\u0435\u0442\u044B, \u043F\u043E\u0447\u0442\u0438 \u043D\u0435 \u043F\u0438\u0448\u0435\u0442 \u043F\u0435\u0440\u0432\u043E\u0439, \u043B\u0438\u0447\u043D\u044B\u043C \u043D\u0435 \u0434\u0435\u043B\u0438\u0442\u0441\u044F",
|
|
690
|
+
profile: { notifications: "normal", messageStyle: "one-liners", initiative: "low", lifeSharing: "low" }
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
id: "clingy",
|
|
694
|
+
label: "\u0417\u0430\u043B\u0438\u043F\u0430\u043B\u0430",
|
|
695
|
+
description: "\u043E\u0447\u0435\u043D\u044C \u043B\u0438\u043F\u0443\u0447\u0430\u044F, \u0441\u043F\u0430\u043C\u0438\u0442 \u043F\u0443\u0437\u044B\u0440\u044F\u043C\u0438, \u0432\u0441\u0435\u0433\u0434\u0430 \u043E\u043D\u043B\u0430\u0439\u043D, \u043F\u0438\u0448\u0435\u0442 \u043F\u0435\u0440\u0432\u043E\u0439 \u043F\u043E\u0441\u0442\u043E\u044F\u043D\u043D\u043E",
|
|
696
|
+
profile: { notifications: "priority", messageStyle: "bursty", initiative: "high", lifeSharing: "high" }
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
id: "chatty",
|
|
700
|
+
label: "\u0411\u043E\u043B\u0442\u0443\u0448\u043A\u0430",
|
|
701
|
+
description: "\u043B\u044E\u0431\u0438\u0442 \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0438\u0441\u0442\u043E\u0440\u0438\u0438, \u043F\u0438\u0448\u0435\u0442 \u0434\u043B\u0438\u043D\u043D\u044B\u0435 \u0442\u0435\u043A\u0441\u0442\u044B, \u0447\u0430\u0441\u0442\u043E \u0434\u0435\u043B\u0438\u0442\u0441\u044F \u0431\u044B\u0442\u043E\u0432\u044B\u043C",
|
|
702
|
+
profile: { notifications: "priority", messageStyle: "longform", initiative: "medium", lifeSharing: "high" }
|
|
703
|
+
}
|
|
704
|
+
];
|
|
705
|
+
function findCommunicationPreset(id) {
|
|
706
|
+
return COMMUNICATION_PRESETS.find((p) => p.id === id);
|
|
707
|
+
}
|
|
708
|
+
function normalizeCommunicationProfile(source) {
|
|
709
|
+
const fallback = source?.vibe === "warm" ? findCommunicationPreset("cute").profile : source?.vibe === "short" ? findCommunicationPreset("alt").profile : findCommunicationPreset("normal").profile;
|
|
710
|
+
const raw = source?.communication;
|
|
711
|
+
return {
|
|
712
|
+
notifications: includes(NOTIFICATIONS, raw?.notifications) ? raw.notifications : fallback.notifications,
|
|
713
|
+
messageStyle: includes(MESSAGE_STYLES, raw?.messageStyle) ? raw.messageStyle : fallback.messageStyle,
|
|
714
|
+
initiative: includes(INITIATIVES, raw?.initiative) ? raw.initiative : fallback.initiative,
|
|
715
|
+
lifeSharing: includes(LIFE_SHARING, raw?.lifeSharing) ? raw.lifeSharing : fallback.lifeSharing
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
function deriveLegacyVibe(profile) {
|
|
719
|
+
return profile.messageStyle === "one-liners" && profile.initiative === "low" && profile.lifeSharing === "low" ? "short" : "warm";
|
|
720
|
+
}
|
|
721
|
+
function communicationProfileLabel(profile) {
|
|
722
|
+
const exact = COMMUNICATION_PRESETS.find((p) => sameProfile(p.profile, profile));
|
|
723
|
+
if (exact) return exact.label;
|
|
724
|
+
return `notifications=${profile.notifications}, style=${profile.messageStyle}, initiative=${profile.initiative}, life=${profile.lifeSharing}`;
|
|
725
|
+
}
|
|
726
|
+
function communicationPromptFragment(profile) {
|
|
727
|
+
const notifications = profile.notifications === "priority" ? "\u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F \u043E\u0442 \u043D\u0435\u0433\u043E \u0432\u043A\u043B\u044E\u0447\u0435\u043D\u044B/\u0432\u0430\u0436\u043D\u044B\u0435: \u0442\u044B \u0447\u0430\u0441\u0442\u043E \u0432\u0438\u0434\u0438\u0448\u044C \u0435\u0433\u043E \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F \u0431\u044B\u0441\u0442\u0440\u043E, \u043E\u0441\u043E\u0431\u0435\u043D\u043D\u043E \u0435\u0441\u043B\u0438 \u0443\u0436\u0435 \u0438\u0434\u0451\u0442 \u0434\u0438\u0430\u043B\u043E\u0433" : profile.notifications === "muted" ? "\u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F \u043D\u0435 \u043F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442\u043D\u044B\u0435: \u043C\u043E\u0436\u0435\u0448\u044C \u043E\u0442\u0432\u0435\u0447\u0430\u0442\u044C \u043F\u043E\u0437\u0436\u0435, \u043D\u043E \u0435\u0441\u043B\u0438 \u0434\u0438\u0430\u043B\u043E\u0433 \u0443\u0436\u0435 \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u2014 \u043D\u0435 \u0438\u0441\u0447\u0435\u0437\u0430\u0439 \u0431\u0435\u0437 \u043F\u0440\u0438\u0447\u0438\u043D\u044B" : "\u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F \u043E\u0431\u044B\u0447\u043D\u044B\u0435: \u0438\u043D\u043E\u0433\u0434\u0430 \u0432\u0438\u0434\u0438\u0448\u044C \u0441\u0440\u0430\u0437\u0443, \u0438\u043D\u043E\u0433\u0434\u0430 \u043F\u043E\u0437\u0436\u0435";
|
|
728
|
+
const style = profile.messageStyle === "one-liners" ? "\u043E\u0431\u044B\u0447\u043D\u043E 1 \u043A\u043E\u0440\u043E\u0442\u043A\u0438\u0439 \u043F\u0443\u0437\u044B\u0440\u044C, 1-5 \u0441\u043B\u043E\u0432; \u0441\u0435\u0440\u0438\u0438 \u0440\u0435\u0434\u043A\u0438 \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u043D\u0430 \u044D\u043C\u043E\u0446\u0438\u044F\u0445" : profile.messageStyle === "bursty" ? "\u0447\u0430\u0441\u0442\u043E \u043F\u0438\u0448\u0435\u0448\u044C 2-5 \u043F\u0443\u0437\u044B\u0440\u0435\u0439 \u043F\u043E\u0434\u0440\u044F\u0434: \u043E\u0431\u0440\u044B\u0432\u043A\u0438 \u043C\u044B\u0441\u043B\u0435\u0439, \u043E\u0434\u043D\u043E \u0441\u043B\u043E\u0432\u043E, \u043F\u043E\u0442\u043E\u043C \u0443\u0442\u043E\u0447\u043D\u0435\u043D\u0438\u0435, \u043F\u043E\u0442\u043E\u043C \u044D\u043C\u043E\u0446\u0438\u044F" : profile.messageStyle === "longform" ? "\u043C\u043E\u0436\u0435\u0448\u044C \u043F\u0438\u0441\u0430\u0442\u044C \u043E\u0434\u0438\u043D \u0434\u043B\u0438\u043D\u043D\u0435\u0435 \u043F\u0443\u0437\u044B\u0440\u044C \u0438\u043B\u0438 2-3 \u0441\u0440\u0435\u0434\u043D\u0438\u0445, \u043A\u043E\u0433\u0434\u0430 \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0448\u044C \u0438\u0441\u0442\u043E\u0440\u0438\u044E/\u043E\u0431\u044A\u044F\u0441\u043D\u044F\u0435\u0448\u044C \u0447\u0443\u0432\u0441\u0442\u0432\u0430" : "\u043E\u0431\u044B\u0447\u043D\u043E 1-3 \u043F\u0443\u0437\u044B\u0440\u044F \u0440\u0430\u0437\u043D\u043E\u0439 \u0434\u043B\u0438\u043D\u044B, \u0431\u0435\u0437 \u0438\u0434\u0435\u0430\u043B\u044C\u043D\u043E\u0439 \u0440\u043E\u0432\u043D\u043E\u0441\u0442\u0438";
|
|
729
|
+
const initiative = profile.initiative === "high" ? "\u0438\u043D\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0430 \u0432\u044B\u0441\u043E\u043A\u0430\u044F: \u0442\u044B \u043C\u043E\u0436\u0435\u0448\u044C \u043F\u0438\u0441\u0430\u0442\u044C \u043F\u0435\u0440\u0432\u043E\u0439, \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0442\u044C \u0433\u0434\u0435 \u043E\u043D, \u043A\u0438\u0434\u0430\u0442\u044C \u0431\u044B\u0442\u043E\u0432\u044B\u0435 \u043C\u044B\u0441\u043B\u0438, \u0440\u0435\u0432\u043D\u043E\u0432\u0430\u0442\u044C/\u0441\u043A\u0443\u0447\u0430\u0442\u044C" : profile.initiative === "low" ? "\u0438\u043D\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0430 \u043D\u0438\u0437\u043A\u0430\u044F: \u043F\u0435\u0440\u0432\u043E\u0439 \u043F\u0438\u0448\u0435\u0448\u044C \u0440\u0435\u0434\u043A\u043E, \u0432 \u043E\u0441\u043D\u043E\u0432\u043D\u043E\u043C \u043A\u043E\u0433\u0434\u0430 \u0435\u0441\u0442\u044C \u044F\u0432\u043D\u044B\u0439 \u043F\u043E\u0432\u043E\u0434" : "\u0438\u043D\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0430 \u0441\u0440\u0435\u0434\u043D\u044F\u044F: \u0438\u043D\u043E\u0433\u0434\u0430 \u043F\u0438\u0448\u0435\u0448\u044C \u043F\u0435\u0440\u0432\u043E\u0439 \u043F\u043E \u0434\u0435\u043B\u0443, \u044D\u043C\u043E\u0446\u0438\u0438 \u0438\u043B\u0438 \u0435\u0441\u043B\u0438 \u0432\u0441\u043F\u043E\u043C\u043D\u0438\u043B\u0430 \u043E \u043D\u0451\u043C";
|
|
730
|
+
const life = profile.lifeSharing === "high" ? "\u0447\u0430\u0441\u0442\u043E \u0434\u0435\u043B\u0438\u0448\u044C\u0441\u044F \u043C\u0430\u043B\u0435\u043D\u044C\u043A\u0438\u043C\u0438 \u043C\u043E\u043C\u0435\u043D\u0442\u0430\u043C\u0438 \u0434\u043D\u044F: \u0447\u0442\u043E \u0443\u0432\u0438\u0434\u0435\u043B\u0430, \u0447\u0442\u043E \u0431\u0435\u0441\u0438\u0442, \u0447\u0442\u043E \u0435\u043B\u0430, \u0447\u0442\u043E \u0441\u043A\u0430\u0437\u0430\u043B\u0430 \u043F\u043E\u0434\u0440\u0443\u0433\u0430/\u043C\u0430\u043C\u0430, \u0447\u0442\u043E \u043F\u0440\u043E\u0438\u0441\u0445\u043E\u0434\u0438\u0442 \u043D\u0430 \u0443\u0447\u0451\u0431\u0435/\u0440\u0430\u0431\u043E\u0442\u0435" : profile.lifeSharing === "low" ? "\u043B\u0438\u0447\u043D\u044B\u043C \u0434\u0435\u043B\u0438\u0448\u044C\u0441\u044F \u0440\u0435\u0434\u043A\u043E, \u043D\u0435 \u0440\u0430\u0441\u043F\u0438\u0441\u044B\u0432\u0430\u0435\u0448\u044C \u0434\u0435\u043D\u044C \u0431\u0435\u0437 \u043F\u043E\u0432\u043E\u0434\u0430" : "\u0438\u043D\u043E\u0433\u0434\u0430 \u0434\u0435\u043B\u0438\u0448\u044C\u0441\u044F \u043C\u043E\u043C\u0435\u043D\u0442\u0430\u043C\u0438 \u0436\u0438\u0437\u043D\u0438, \u043E\u0441\u043E\u0431\u0435\u043D\u043D\u043E \u0435\u0441\u043B\u0438 \u044D\u0442\u043E \u0441\u0432\u044F\u0437\u0430\u043D\u043E \u0441 \u0442\u0435\u043A\u0443\u0449\u0438\u043C \u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043D\u0438\u0435\u043C";
|
|
731
|
+
return `# \u0422\u041E\u041D\u041A\u0410\u042F \u041D\u0410\u0421\u0422\u0420\u041E\u0419\u041A\u0410 \u041E\u0411\u0429\u0415\u041D\u0418\u042F
|
|
732
|
+
- \u0423\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F: ${notifications}.
|
|
733
|
+
- \u0421\u0442\u0438\u043B\u044C \u043F\u0443\u0437\u044B\u0440\u0435\u0439: ${style}.
|
|
734
|
+
- \u0418\u043D\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0430: ${initiative}.
|
|
735
|
+
- \u041C\u043E\u043C\u0435\u043D\u0442\u044B \u0438\u0437 \u0436\u0438\u0437\u043D\u0438: ${life}.
|
|
736
|
+
|
|
737
|
+
\u041F\u0440\u0430\u0432\u0438\u043B\u0430 \u0440\u0438\u0442\u043C\u0430:
|
|
738
|
+
- \u041D\u0435 \u0432\u0435\u0434\u0438 \u0441\u0435\u0431\u044F \u043F\u043E \u0441\u0445\u0435\u043C\u0435 "\u043E\u0442\u0432\u0435\u0442\u0438\u043B\u0430 \u2192 \u0443\u0448\u043B\u0430 \u2192 \u0432\u0435\u0440\u043D\u0443\u043B\u0430\u0441\u044C \u2192 \u043E\u0442\u0432\u0435\u0442\u0438\u043B\u0430" \u043A\u0430\u0436\u0434\u044B\u0439 \u0440\u0430\u0437.
|
|
739
|
+
- \u0412 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u043C \u0434\u0438\u0430\u043B\u043E\u0433\u0435 \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0447\u0430\u0441\u0442\u043E \u043E\u0441\u0442\u0430\u0451\u0442\u0441\u044F \u0432 \u0447\u0430\u0442\u0435 \u0438 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0431\u044B\u0441\u0442\u0440\u043E. \u0415\u0441\u043B\u0438 \u0432\u0441\u0451 \u0436\u0435 \u0443\u0445\u043E\u0434\u0438\u0448\u044C \u2014 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u0431\u044B\u0442\u043E\u0432\u0430\u044F \u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u0432 \u0442\u0435\u043A\u0441\u0442\u0435, \u0430 \u043D\u0435 \u0432\u043D\u0435\u0437\u0430\u043F\u043D\u0430\u044F \u043F\u0440\u043E\u043F\u0430\u0436\u0430.
|
|
740
|
+
- \u0418\u043D\u043E\u0433\u0434\u0430 \u043C\u043E\u0436\u043D\u043E \u043D\u0430\u043F\u0438\u0441\u0430\u0442\u044C 3-5 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439 \u043F\u043E\u0434\u0440\u044F\u0434, \u043F\u043E\u0442\u043E\u043C \u043F\u0440\u043E\u043F\u0430\u0441\u0442\u044C. \u0418\u043D\u043E\u0433\u0434\u0430 \u043C\u043E\u0436\u043D\u043E \u0432\u0435\u0441\u0442\u0438 \u0434\u043E\u043B\u0433\u0438\u0439 \u0431\u044B\u0441\u0442\u0440\u044B\u0439 \u0434\u0438\u0430\u043B\u043E\u0433. \u0418\u043D\u043E\u0433\u0434\u0430 \u043C\u043E\u0436\u043D\u043E \u043E\u0442\u0432\u0435\u0442\u0438\u0442\u044C \u043E\u0434\u043D\u0438\u043C \u0441\u043B\u043E\u0432\u043E\u043C. \u0420\u0438\u0442\u043C \u0434\u043E\u043B\u0436\u0435\u043D \u043C\u0435\u043D\u044F\u0442\u044C\u0441\u044F.
|
|
741
|
+
- \u041D\u0435 \u0432\u044B\u0434\u0443\u043C\u044B\u0432\u0430\u0439 \u0440\u0435\u0430\u043B\u044C\u043D\u044B\u0435 URL. \u0421\u0441\u044B\u043B\u043A\u0438 \u0443\u043F\u043E\u043C\u0438\u043D\u0430\u0439 \u0442\u043E\u043B\u044C\u043A\u043E \u0435\u0441\u043B\u0438 \u043E\u043D\u0438 \u0435\u0441\u0442\u044C \u0432 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u0435 \u0438\u043B\u0438 \u043A\u0430\u043A \u0431\u044B\u0442\u043E\u0432\u043E\u0435 "\u0441\u043A\u0438\u043D\u0443 \u043F\u043E\u0442\u043E\u043C".`;
|
|
742
|
+
}
|
|
743
|
+
function communicationDecisionState(profile) {
|
|
744
|
+
return `communication={notifications:${profile.notifications}, messageStyle:${profile.messageStyle}, initiative:${profile.initiative}, lifeSharing:${profile.lifeSharing}}`;
|
|
745
|
+
}
|
|
746
|
+
function includes(values, value) {
|
|
747
|
+
return typeof value === "string" && values.includes(value);
|
|
748
|
+
}
|
|
749
|
+
function sameProfile(a, b) {
|
|
750
|
+
return a.notifications === b.notifications && a.messageStyle === b.messageStyle && a.initiative === b.initiative && a.lifeSharing === b.lifeSharing;
|
|
751
|
+
}
|
|
752
|
+
|
|
660
753
|
// src/storage/md.ts
|
|
661
754
|
init_esm_shims();
|
|
662
755
|
import { promises as fs } from "fs";
|
|
@@ -692,13 +785,14 @@ async function readConfig(slug) {
|
|
|
692
785
|
try {
|
|
693
786
|
const raw = await fs.readFile(path2.join(profileDir(slug), "config.json"), "utf8");
|
|
694
787
|
const parsed = JSON.parse(raw);
|
|
788
|
+
const communication = normalizeCommunicationProfile(parsed);
|
|
695
789
|
return {
|
|
696
790
|
sleepFrom: 23,
|
|
697
791
|
sleepTo: 8,
|
|
698
792
|
nightWakeChance: 0.05,
|
|
699
|
-
vibe: "short",
|
|
700
793
|
busySchedule: [],
|
|
701
|
-
...parsed
|
|
794
|
+
...parsed,
|
|
795
|
+
communication
|
|
702
796
|
};
|
|
703
797
|
} catch {
|
|
704
798
|
return null;
|
|
@@ -715,7 +809,16 @@ async function writeConfig(cfg) {
|
|
|
715
809
|
async function listProfiles() {
|
|
716
810
|
try {
|
|
717
811
|
const entries = await fs.readdir(DATA_ROOT, { withFileTypes: true });
|
|
718
|
-
|
|
812
|
+
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
813
|
+
const valid = await Promise.all(dirs.map(async (name) => {
|
|
814
|
+
try {
|
|
815
|
+
await fs.access(path2.join(profileDir(name), "config.json"));
|
|
816
|
+
return name;
|
|
817
|
+
} catch {
|
|
818
|
+
return null;
|
|
819
|
+
}
|
|
820
|
+
}));
|
|
821
|
+
return valid.filter((name) => !!name);
|
|
719
822
|
} catch {
|
|
720
823
|
return [];
|
|
721
824
|
}
|
|
@@ -1347,6 +1450,12 @@ var Bar = ({ step, total }) => {
|
|
|
1347
1450
|
).join("");
|
|
1348
1451
|
return /* @__PURE__ */ React.createElement(Text, { color: "magenta" }, "[", blocks, "] \u0448\u0430\u0433 ", step + 1, "/", total);
|
|
1349
1452
|
};
|
|
1453
|
+
function personaNotesForGeneration(notes, communication) {
|
|
1454
|
+
return [
|
|
1455
|
+
notes.trim(),
|
|
1456
|
+
`\u0422\u043E\u043D \u043E\u0431\u0449\u0435\u043D\u0438\u044F: ${communicationProfileLabel(communication)}. \u0423\u0447\u0442\u0438 \u044D\u0442\u043E \u043F\u0440\u0438 speech.md \u0438 communication.md.`
|
|
1457
|
+
].filter(Boolean).join("\n\n");
|
|
1458
|
+
}
|
|
1350
1459
|
function Wizard({ initial, onDone }) {
|
|
1351
1460
|
const { exit } = useApp();
|
|
1352
1461
|
const [step, setStep] = useState(initial ? "mode" : "splash");
|
|
@@ -1379,7 +1488,7 @@ function Wizard({ initial, onDone }) {
|
|
|
1379
1488
|
const [sleepFromStr, setSleepFromStr] = useState("23");
|
|
1380
1489
|
const [sleepToStr, setSleepToStr] = useState("8");
|
|
1381
1490
|
const [nightWakeStr, setNightWakeStr] = useState("5");
|
|
1382
|
-
const [
|
|
1491
|
+
const [communicationProfile, setCommunicationProfile] = useState(normalizeCommunicationProfile(initial));
|
|
1383
1492
|
const [stage, setStage] = useState(initial?.stage ?? "tg-given-cold");
|
|
1384
1493
|
const [pickedMcp, setPickedMcp] = useState(initial?.mcp?.map((m) => m.id) ?? []);
|
|
1385
1494
|
const [mcpQueue, setMcpQueue] = useState([]);
|
|
@@ -1451,11 +1560,12 @@ function Wizard({ initial, onDone }) {
|
|
|
1451
1560
|
clearInterval(timer);
|
|
1452
1561
|
}
|
|
1453
1562
|
}, 100);
|
|
1454
|
-
const generated = await generatePersonaPack(llm, slug, name.trim(), Number(ageStr), nationality, personaNotes);
|
|
1563
|
+
const generated = await generatePersonaPack(llm, slug, name.trim(), Number(ageStr), nationality, personaNotesForGeneration(personaNotes, communicationProfile));
|
|
1455
1564
|
if (timer) clearInterval(timer);
|
|
1456
1565
|
setGenPercent(100);
|
|
1457
1566
|
setGenStatus("\u0433\u043E\u0442\u043E\u0432\u043E!");
|
|
1458
1567
|
setBusySchedule(generated.busySchedule);
|
|
1568
|
+
await writeConfig(makeConfig({ busySchedule: generated.busySchedule, mcp: [] }));
|
|
1459
1569
|
setTimeout(() => setStep("stage"), 800);
|
|
1460
1570
|
} catch (e) {
|
|
1461
1571
|
if (timer) clearInterval(timer);
|
|
@@ -1804,15 +1914,85 @@ function Wizard({ initial, onDone }) {
|
|
|
1804
1914
|
)));
|
|
1805
1915
|
}
|
|
1806
1916
|
if (step === "vibe") {
|
|
1807
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u043A\u0430\
|
|
1917
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0442\u043E\u043D\u043A\u0430\u044F \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043E\u0431\u0449\u0435\u043D\u0438\u044F" }), /* @__PURE__ */ React.createElement(Bar, { step: 7, total: 12 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(
|
|
1918
|
+
SelectInput,
|
|
1919
|
+
{
|
|
1920
|
+
items: [
|
|
1921
|
+
...COMMUNICATION_PRESETS.map((p) => ({ label: `${p.label} \u2014 ${p.description}`, value: p.id })),
|
|
1922
|
+
{ label: "\u270E \u041D\u0430\u0441\u0442\u0440\u043E\u0438\u0442\u044C \u0432\u0440\u0443\u0447\u043D\u0443\u044E", value: "__custom__" }
|
|
1923
|
+
],
|
|
1924
|
+
onSelect: (it) => {
|
|
1925
|
+
if (it.value === "__custom__") {
|
|
1926
|
+
setStep("comm-notifications");
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1929
|
+
const preset = findCommunicationPreset(String(it.value));
|
|
1930
|
+
if (preset) setCommunicationProfile(preset.profile);
|
|
1931
|
+
setStep("tz");
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
)));
|
|
1935
|
+
}
|
|
1936
|
+
if (step === "comm-notifications") {
|
|
1937
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F \u043E\u0442 \u0442\u0435\u0431\u044F" }), /* @__PURE__ */ React.createElement(Bar, { step: 7, total: 12 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(
|
|
1938
|
+
SelectInput,
|
|
1939
|
+
{
|
|
1940
|
+
items: [
|
|
1941
|
+
{ label: "\uFFFD muted \u2014 \u043C\u043E\u0436\u0435\u0442 \u0432\u0438\u0434\u0435\u0442\u044C \u043F\u043E\u0437\u0436\u0435", value: "muted" },
|
|
1942
|
+
{ label: "\u{1F514} normal \u2014 \u043E\u0431\u044B\u0447\u043D\u044B\u0435 \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F", value: "normal" },
|
|
1943
|
+
{ label: "\u{1F496} priority \u2014 \u0442\u0432\u043E\u0438 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F \u0432\u0430\u0436\u043D\u044B\u0435, \u0447\u0430\u0449\u0435 \u0431\u044B\u0441\u0442\u0440\u043E \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442", value: "priority" }
|
|
1944
|
+
],
|
|
1945
|
+
onSelect: (it) => {
|
|
1946
|
+
setCommunicationProfile((p) => ({ ...p, notifications: it.value }));
|
|
1947
|
+
setStep("comm-style");
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
)));
|
|
1951
|
+
}
|
|
1952
|
+
if (step === "comm-style") {
|
|
1953
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0441\u0442\u0438\u043B\u044C \u043F\u0435\u0440\u0435\u043F\u0438\u0441\u043A\u0438" }), /* @__PURE__ */ React.createElement(Bar, { step: 7, total: 12 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(
|
|
1954
|
+
SelectInput,
|
|
1955
|
+
{
|
|
1956
|
+
items: [
|
|
1957
|
+
{ label: "one-liners \u2014 \u043A\u043E\u0440\u043E\u0442\u043A\u043E, 1 \u0441\u043B\u043E\u0432\u043E/\u0444\u0440\u0430\u0437\u0430", value: "one-liners" },
|
|
1958
|
+
{ label: "balanced \u2014 1-3 \u043F\u0443\u0437\u044B\u0440\u044F, \u0440\u0430\u0437\u043D\u044B\u0439 \u0440\u0438\u0442\u043C", value: "balanced" },
|
|
1959
|
+
{ label: "bursty \u2014 \u043F\u0438\u0448\u0435\u0442 \u0441\u0435\u0440\u0438\u0435\u0439 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439 \u043F\u043E\u0434\u0440\u044F\u0434", value: "bursty" },
|
|
1960
|
+
{ label: "longform \u2014 \u0438\u043D\u043E\u0433\u0434\u0430 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442", value: "longform" }
|
|
1961
|
+
],
|
|
1962
|
+
onSelect: (it) => {
|
|
1963
|
+
setCommunicationProfile((p) => ({ ...p, messageStyle: it.value }));
|
|
1964
|
+
setStep("comm-initiative");
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
)));
|
|
1968
|
+
}
|
|
1969
|
+
if (step === "comm-initiative") {
|
|
1970
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0438\u043D\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0430" }), /* @__PURE__ */ React.createElement(Bar, { step: 7, total: 12 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(
|
|
1971
|
+
SelectInput,
|
|
1972
|
+
{
|
|
1973
|
+
items: [
|
|
1974
|
+
{ label: "low \u2014 \u043F\u0435\u0440\u0432\u043E\u0439 \u043F\u0438\u0448\u0435\u0442 \u0440\u0435\u0434\u043A\u043E", value: "low" },
|
|
1975
|
+
{ label: "medium \u2014 \u0438\u043D\u043E\u0433\u0434\u0430 \u043F\u0438\u0448\u0435\u0442 \u0441\u0430\u043C\u0430", value: "medium" },
|
|
1976
|
+
{ label: "high \u2014 \u0447\u0430\u0441\u0442\u043E \u0441\u0430\u043C\u0430 \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442 \u0442\u0435\u043C\u044B", value: "high" }
|
|
1977
|
+
],
|
|
1978
|
+
onSelect: (it) => {
|
|
1979
|
+
setCommunicationProfile((p) => ({ ...p, initiative: it.value }));
|
|
1980
|
+
setStep("comm-life");
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
)));
|
|
1984
|
+
}
|
|
1985
|
+
if (step === "comm-life") {
|
|
1986
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0434\u0435\u043B\u0438\u0442\u044C\u0441\u044F \u043C\u043E\u043C\u0435\u043D\u0442\u0430\u043C\u0438 \u0436\u0438\u0437\u043D\u0438" }), /* @__PURE__ */ React.createElement(Bar, { step: 7, total: 12 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(
|
|
1808
1987
|
SelectInput,
|
|
1809
1988
|
{
|
|
1810
1989
|
items: [
|
|
1811
|
-
{ label:
|
|
1812
|
-
{ label: "
|
|
1990
|
+
{ label: "low \u2014 \u043F\u043E\u0447\u0442\u0438 \u043D\u0435 \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u043E \u0441\u0435\u0431\u0435", value: "low" },
|
|
1991
|
+
{ label: "medium \u2014 \u0438\u043D\u043E\u0433\u0434\u0430 \u0431\u044B\u0442\u043E\u0432\u044B\u0435 \u043C\u043E\u043C\u0435\u043D\u0442\u044B", value: "medium" },
|
|
1992
|
+
{ label: "high \u2014 \u0447\u0430\u0441\u0442\u043E \u043F\u0438\u0448\u0435\u0442 \u0447\u0442\u043E \u0443 \u043D\u0435\u0451 \u043F\u0440\u043E\u0438\u0441\u0445\u043E\u0434\u0438\u0442", value: "high" }
|
|
1813
1993
|
],
|
|
1814
1994
|
onSelect: (it) => {
|
|
1815
|
-
|
|
1995
|
+
setCommunicationProfile((p) => ({ ...p, lifeSharing: it.value }));
|
|
1816
1996
|
setStep("tz");
|
|
1817
1997
|
}
|
|
1818
1998
|
}
|
|
@@ -1843,8 +2023,10 @@ function Wizard({ initial, onDone }) {
|
|
|
1843
2023
|
{
|
|
1844
2024
|
limit: 10,
|
|
1845
2025
|
items: STAGE_PRESETS.filter((s) => s.id !== "dumped").map((s) => ({ label: `${s.label} \xB7 ${s.description}`, value: s.id })),
|
|
1846
|
-
onSelect: (it) => {
|
|
1847
|
-
|
|
2026
|
+
onSelect: async (it) => {
|
|
2027
|
+
const nextStage = it.value;
|
|
2028
|
+
setStage(nextStage);
|
|
2029
|
+
await writeConfig(makeConfig({ stage: nextStage }));
|
|
1848
2030
|
setStep("mcp-pick");
|
|
1849
2031
|
}
|
|
1850
2032
|
}
|
|
@@ -1861,7 +2043,10 @@ function Wizard({ initial, onDone }) {
|
|
|
1861
2043
|
setMcpQueue(need);
|
|
1862
2044
|
setMcpSecretIdx(0);
|
|
1863
2045
|
if (need.length) setStep("mcp-secret");
|
|
1864
|
-
else
|
|
2046
|
+
else {
|
|
2047
|
+
setStep("saving");
|
|
2048
|
+
save();
|
|
2049
|
+
}
|
|
1865
2050
|
}
|
|
1866
2051
|
}
|
|
1867
2052
|
));
|
|
@@ -1907,27 +2092,31 @@ function Wizard({ initial, onDone }) {
|
|
|
1907
2092
|
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0433\u043E\u0442\u043E\u0432\u043E" }), /* @__PURE__ */ React.createElement(Text, { color: "green" }, "\u043F\u0440\u043E\u0444\u0438\u043B\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D. \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0435\u043C \u0430\u0433\u0435\u043D\u0442\u0430\u2026"));
|
|
1908
2093
|
}
|
|
1909
2094
|
return null;
|
|
1910
|
-
|
|
2095
|
+
function makeConfig(overrides = {}) {
|
|
1911
2096
|
const slug = slugify(name);
|
|
1912
|
-
|
|
2097
|
+
return {
|
|
1913
2098
|
slug,
|
|
1914
2099
|
name: name.trim(),
|
|
1915
2100
|
age: Number(ageStr),
|
|
1916
2101
|
nationality,
|
|
1917
2102
|
tz: tz || defaultTzForNationality(nationality),
|
|
1918
2103
|
mode,
|
|
1919
|
-
stage,
|
|
2104
|
+
stage: overrides.stage ?? stage,
|
|
1920
2105
|
llm: { presetId: llmPresetId, proto: llmProto, baseURL: llmBaseURL, apiKey: llmKey, model: llmModel },
|
|
1921
2106
|
telegram: mode === "bot" ? { botToken } : { apiId: Number(apiId), apiHash, phone, sessionString },
|
|
1922
|
-
mcp: pickedMcp.map((id) => ({ id, secrets: mcpSecrets[id] ?? {} })),
|
|
2107
|
+
mcp: overrides.mcp ?? pickedMcp.map((id) => ({ id, secrets: mcpSecrets[id] ?? {} })),
|
|
1923
2108
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1924
2109
|
sleepFrom: Number(sleepFromStr),
|
|
1925
2110
|
sleepTo: Number(sleepToStr),
|
|
1926
2111
|
nightWakeChance: Number(nightWakeStr) / 100,
|
|
1927
|
-
vibe,
|
|
2112
|
+
vibe: deriveLegacyVibe(communicationProfile),
|
|
2113
|
+
communication: communicationProfile,
|
|
1928
2114
|
personaNotes: personaNotes.trim() || void 0,
|
|
1929
|
-
busySchedule
|
|
2115
|
+
busySchedule: overrides.busySchedule ?? busySchedule
|
|
1930
2116
|
};
|
|
2117
|
+
}
|
|
2118
|
+
async function save() {
|
|
2119
|
+
const cfg = makeConfig();
|
|
1931
2120
|
await writeConfig(cfg);
|
|
1932
2121
|
setStep("done");
|
|
1933
2122
|
setTimeout(() => onDone(cfg), 600);
|
|
@@ -2070,13 +2259,14 @@ function Dashboard({ runtime }) {
|
|
|
2070
2259
|
break;
|
|
2071
2260
|
}
|
|
2072
2261
|
case "log": {
|
|
2073
|
-
const
|
|
2074
|
-
const
|
|
2075
|
-
|
|
2262
|
+
const day = /^\d{4}-\d{2}-\d{2}$/.test(rest[0] ?? "") ? rest[0] : sessionDate(runtime.cfg.tz);
|
|
2263
|
+
const limit = Number(rest.find((x) => /^\d+$/.test(x)) ?? 3e3);
|
|
2264
|
+
const p = await readSessionLog(runtime.cfg.slug, day);
|
|
2265
|
+
append(p.trim() ? p.slice(-Math.max(500, Math.min(limit, 2e4))) : `(log/${day}.md \u043F\u0443\u0441\u0442 \u0438\u043B\u0438 \u0435\u0449\u0451 \u043D\u0435 \u0441\u043E\u0437\u0434\u0430\u043D)`);
|
|
2076
2266
|
break;
|
|
2077
2267
|
}
|
|
2078
2268
|
case "help":
|
|
2079
|
-
append(":status :why :amnesia <\u043C\u0438\u043D> [chatId] :reset :stage <id> :wake [chatId] :debug [chatId] :pause :resume :cringe :relationship :persona :log :block [chatId] :unblock [chatId] :read [chatId] :clear-chat [chatId] [--revoke] :report-spam [chatId] :delete-last [chatId] [--local] :edit-last <text> :sticker [chatId] :quit");
|
|
2269
|
+
append(":status :why :amnesia <\u043C\u0438\u043D> [chatId] :reset :stage <id> :wake [chatId] :debug [chatId] :pause :resume :cringe :relationship :persona :log [YYYY-MM-DD] [chars] :block [chatId] :unblock [chatId] :read [chatId] :clear-chat [chatId] [--revoke] :report-spam [chatId] :delete-last [chatId] [--local] :edit-last <text> :sticker [chatId] :quit");
|
|
2080
2270
|
break;
|
|
2081
2271
|
case "quit":
|
|
2082
2272
|
case "exit":
|
|
@@ -2094,7 +2284,7 @@ function Dashboard({ runtime }) {
|
|
|
2094
2284
|
const line = cmd.trim();
|
|
2095
2285
|
setCmd("");
|
|
2096
2286
|
if (line) await execute(line);
|
|
2097
|
-
} })), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "\u043A\u043E\u043C\u0430\u043D\u0434\u044B: :status :why :amnesia <\u043C\u0438\u043D> :reset :stage <id> :pause :resume :cringe :persona :log :block :unblock :read :clear-chat :delete-last :edit-last :sticker :quit"));
|
|
2287
|
+
} })), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "\u043A\u043E\u043C\u0430\u043D\u0434\u044B: :status :why :amnesia <\u043C\u0438\u043D> :reset :stage <id> :pause :resume :cringe :persona :log [day] :block :unblock :read :clear-chat :delete-last :edit-last :sticker :quit"));
|
|
2098
2288
|
}
|
|
2099
2289
|
|
|
2100
2290
|
// src/engine/runtime.ts
|
|
@@ -2230,6 +2420,7 @@ init_esm_shims();
|
|
|
2230
2420
|
function computePresenceProfile(cfg) {
|
|
2231
2421
|
const seed = [...cfg.name].reduce((a, c) => a + c.charCodeAt(0), 0) + cfg.age;
|
|
2232
2422
|
const r = (n) => (seed * 9301 + n * 49297) % 233280 / 233280;
|
|
2423
|
+
const communication = normalizeCommunicationProfile(cfg);
|
|
2233
2424
|
const patterns = [
|
|
2234
2425
|
"phone-attached",
|
|
2235
2426
|
"burst-checker",
|
|
@@ -2237,13 +2428,34 @@ function computePresenceProfile(cfg) {
|
|
|
2237
2428
|
"evening-only",
|
|
2238
2429
|
"phone-attached-night"
|
|
2239
2430
|
];
|
|
2240
|
-
|
|
2431
|
+
let pattern = patterns[Math.floor(r(1) * patterns.length)] ?? "burst-checker";
|
|
2432
|
+
if (communication.notifications === "priority") {
|
|
2433
|
+
pattern = communication.messageStyle === "bursty" || pattern === "rare-checker" || pattern === "evening-only" ? "phone-attached" : pattern;
|
|
2434
|
+
} else if (communication.notifications === "muted") {
|
|
2435
|
+
pattern = pattern === "phone-attached" ? "burst-checker" : pattern === "phone-attached-night" ? "evening-only" : pattern;
|
|
2436
|
+
}
|
|
2241
2437
|
const sleepFrom = cfg.sleepFrom ?? 23;
|
|
2242
2438
|
const sleepTo = cfg.sleepTo ?? 8;
|
|
2243
|
-
const
|
|
2244
|
-
const
|
|
2245
|
-
|
|
2246
|
-
|
|
2439
|
+
const baseNightWakeChance = cfg.nightWakeChance ?? 0.05;
|
|
2440
|
+
const nightWakeChance = communication.notifications === "priority" ? Math.min(0.35, baseNightWakeChance + 0.05) : communication.notifications === "muted" ? Math.max(0, baseNightWakeChance * 0.4) : baseNightWakeChance;
|
|
2441
|
+
let checkEveryMin = pattern === "phone-attached" ? 3 + Math.floor(r(4) * 5) : pattern === "burst-checker" ? 15 + Math.floor(r(4) * 20) : pattern === "rare-checker" ? 60 + Math.floor(r(4) * 60) : pattern === "evening-only" ? 45 + Math.floor(r(4) * 30) : 10 + Math.floor(r(4) * 15);
|
|
2442
|
+
let onlineWindowMin = pattern === "phone-attached" ? 30 + Math.floor(r(5) * 60) : pattern === "burst-checker" ? 2 + Math.floor(r(5) * 4) : pattern === "rare-checker" ? 5 + Math.floor(r(5) * 10) : pattern === "evening-only" ? 60 + Math.floor(r(5) * 90) : 20 + Math.floor(r(5) * 40);
|
|
2443
|
+
let offlineReplyChance = pattern === "phone-attached" ? 0.85 : pattern === "burst-checker" ? 0.5 : pattern === "rare-checker" ? 0.25 : pattern === "evening-only" ? 0.3 : 0.55;
|
|
2444
|
+
if (communication.notifications === "priority") {
|
|
2445
|
+
checkEveryMin = Math.max(2, Math.round(checkEveryMin * 0.35));
|
|
2446
|
+
onlineWindowMin = Math.round(onlineWindowMin * 1.35);
|
|
2447
|
+
offlineReplyChance = Math.max(offlineReplyChance, communication.initiative === "high" ? 0.95 : 0.85);
|
|
2448
|
+
} else if (communication.notifications === "muted") {
|
|
2449
|
+
checkEveryMin = Math.round(checkEveryMin * 1.5);
|
|
2450
|
+
onlineWindowMin = Math.max(1, Math.round(onlineWindowMin * 0.65));
|
|
2451
|
+
offlineReplyChance = Math.min(offlineReplyChance, 0.25);
|
|
2452
|
+
}
|
|
2453
|
+
if (["convinced", "first-date-done", "dating-early", "dating-stable", "long-term"].includes(cfg.stage)) {
|
|
2454
|
+
offlineReplyChance = Math.min(0.98, offlineReplyChance + 0.12);
|
|
2455
|
+
checkEveryMin = Math.max(2, Math.round(checkEveryMin * 0.8));
|
|
2456
|
+
} else if (cfg.stage === "met-irl-got-tg") {
|
|
2457
|
+
offlineReplyChance = Math.min(0.9, offlineReplyChance + 0.08);
|
|
2458
|
+
}
|
|
2247
2459
|
return { pattern, sleepFrom, sleepTo, checkEveryMin, onlineWindowMin, offlineReplyChance, nightWakeChance };
|
|
2248
2460
|
}
|
|
2249
2461
|
function isHourInRange(h, from, to) {
|
|
@@ -2307,14 +2519,9 @@ function activeBusySlot(slots, day, minuteOfDay) {
|
|
|
2307
2519
|
}
|
|
2308
2520
|
return null;
|
|
2309
2521
|
}
|
|
2310
|
-
function randomCheckAfter(slot) {
|
|
2311
|
-
const [lo, hi] = slot.checkAfterMin ?? [5, 15];
|
|
2312
|
-
const min = Math.max(1, Math.min(lo, hi));
|
|
2313
|
-
const max = Math.max(min, Math.max(lo, hi));
|
|
2314
|
-
return min + Math.floor(Math.random() * (max - min + 1));
|
|
2315
|
-
}
|
|
2316
2522
|
function computePresenceState(cfg, profile, lastUserMsgTs, lastHerReplyTs, recentExchangeCount, forcedWake = false, conflict = null) {
|
|
2317
2523
|
const local = localParts(cfg.tz);
|
|
2524
|
+
const communication = normalizeCommunicationProfile(cfg);
|
|
2318
2525
|
const localHour2 = local.hour;
|
|
2319
2526
|
const localMinute = local.minute;
|
|
2320
2527
|
const minuteOfDay = localHour2 * 60 + localMinute;
|
|
@@ -2339,7 +2546,10 @@ function computePresenceState(cfg, profile, lastUserMsgTs, lastHerReplyTs, recen
|
|
|
2339
2546
|
if (hoursToWake === 0) hoursToWake = 0.5;
|
|
2340
2547
|
nextCheckSec = Math.floor(hoursToWake * 3600) + Math.floor(Math.random() * 1800);
|
|
2341
2548
|
} else if (busySlot && !forcedWake) {
|
|
2342
|
-
const
|
|
2549
|
+
const busyMul = communication.notifications === "priority" ? 0.45 : communication.notifications === "muted" ? 1.25 : 1;
|
|
2550
|
+
const [rawMinCheck, rawMaxCheck] = busySlot.slot.checkAfterMin ?? [5, 15];
|
|
2551
|
+
const minCheck = Math.max(1, Math.round(rawMinCheck * busyMul));
|
|
2552
|
+
const maxCheck = Math.max(minCheck, Math.round(rawMaxCheck * busyMul));
|
|
2343
2553
|
if (maxCheck <= 5) {
|
|
2344
2554
|
const cycleMin = Math.max(1, Math.round((minCheck + maxCheck) / 2));
|
|
2345
2555
|
const minuteOfCycle = minuteOfDay % Math.max(1, cycleMin);
|
|
@@ -2351,7 +2561,7 @@ function computePresenceState(cfg, profile, lastUserMsgTs, lastHerReplyTs, recen
|
|
|
2351
2561
|
busy = { label: busySlot.slot.label, until: busySlot.until, checkAfterMin: cycleMin };
|
|
2352
2562
|
} else {
|
|
2353
2563
|
online = false;
|
|
2354
|
-
const checkAfterMin =
|
|
2564
|
+
const checkAfterMin = minCheck + Math.floor(Math.random() * (maxCheck - minCheck + 1));
|
|
2355
2565
|
nextCheckSec = (busySlot.remainingMin + checkAfterMin) * 60;
|
|
2356
2566
|
busy = { label: busySlot.slot.label, until: busySlot.until, checkAfterMin };
|
|
2357
2567
|
}
|
|
@@ -2375,7 +2585,7 @@ function computePresenceState(cfg, profile, lastUserMsgTs, lastHerReplyTs, recen
|
|
|
2375
2585
|
online = Math.random() < onlineProb;
|
|
2376
2586
|
if (!online) {
|
|
2377
2587
|
notificationSeen = Math.random() < profile.offlineReplyChance;
|
|
2378
|
-
nextCheckSec = notificationSeen ? 60 + Math.floor(Math.random() * 4 * 60) : Math.floor(Math.random() * profile.checkEveryMin * 60);
|
|
2588
|
+
nextCheckSec = notificationSeen ? 60 + Math.floor(Math.random() * 4 * 60) : Math.max(30, Math.floor(Math.random() * profile.checkEveryMin * 60));
|
|
2379
2589
|
}
|
|
2380
2590
|
}
|
|
2381
2591
|
}
|
|
@@ -2404,6 +2614,9 @@ function computePresenceState(cfg, profile, lastUserMsgTs, lastHerReplyTs, recen
|
|
|
2404
2614
|
} else {
|
|
2405
2615
|
hint = notificationSeen ? `\u0421\u0435\u0439\u0447\u0430\u0441 \u041D\u0415 \u0432 \u0441\u0435\u0442\u0438, \u043D\u043E \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0435 \u0443\u0432\u0438\u0434\u0435\u043B\u0430. \u0417\u0430\u0439\u0434\u0451\u0448\u044C \u0432 Telegram \u0447\u0435\u0440\u0435\u0437 ~${Math.round(nextCheckSec / 60)} \u043C\u0438\u043D \u0438 \u0442\u043E\u0433\u0434\u0430 \u043E\u0442\u0432\u0435\u0442\u0438\u0448\u044C, \u0435\u0441\u043B\u0438 \u0437\u0430\u0445\u043E\u0447\u0435\u0448\u044C.` : `\u0421\u0435\u0439\u0447\u0430\u0441 \u041D\u0415 \u0432 \u0441\u0435\u0442\u0438 (\u043F\u0430\u0442\u0442\u0435\u0440\u043D: ${profile.pattern}). \u0423\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u043C\u0435\u0442\u0438\u043B\u0430; \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0435\u0448\u044C \u044D\u0442\u043E \u0447\u0435\u0440\u0435\u0437 ~${Math.round(nextCheckSec / 60)} \u043C\u0438\u043D \u043A\u043E\u0433\u0434\u0430 \u0441\u0430\u043C\u0430 \u0437\u0430\u0433\u043B\u044F\u043D\u0435\u0448\u044C \u0432 \u0442\u0433. \u042D\u0442\u043E \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E, \u0440\u0435\u0430\u043B\u044C\u043D\u044B\u0435 \u043B\u044E\u0434\u0438 \u043D\u0435 \u0441\u0438\u0434\u044F\u0442 \u0432 \u0442\u0433 24/7.`;
|
|
2406
2616
|
}
|
|
2617
|
+
if (!conflictCold && !asleep && communication.notifications === "priority") {
|
|
2618
|
+
hint += ` \u0423\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F \u043E\u0442 \u043D\u0435\u0433\u043E \u0443 \u0442\u0435\u0431\u044F \u0432\u0430\u0436\u043D\u044B\u0435, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u0432 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0439 \u043F\u0435\u0440\u0435\u043F\u0438\u0441\u043A\u0435 \u043D\u0435 \u043F\u0440\u043E\u043F\u0430\u0434\u0430\u0439 \u0440\u0430\u043D\u0434\u043E\u043C\u043D\u043E.`;
|
|
2619
|
+
}
|
|
2407
2620
|
return { online, asleep, nightAwake, nextCheckSec, localHour: localHour2, hint, busy, notificationSeen };
|
|
2408
2621
|
}
|
|
2409
2622
|
|
|
@@ -3068,6 +3281,7 @@ ${hits.map((h) => `- ${h.day}: ${h.excerpt}`).join("\n")}
|
|
|
3068
3281
|
const conflict = ctx.conflict ? conflictPromptFragment(ctx.conflict) : "";
|
|
3069
3282
|
const realism = !isAcquaintance && ctx.realism ? realismPromptFragment(ctx.realism) : "";
|
|
3070
3283
|
const media = mediaPromptFragment(ctx.media);
|
|
3284
|
+
const communication = normalizeCommunicationProfile(cfg);
|
|
3071
3285
|
const ageStudyWords = cfg.age < 17 ? `# \u0412\u041E\u0417\u0420\u0410\u0421\u0422\u041D\u041E\u0419 \u041A\u041E\u041D\u0422\u0415\u041A\u0421\u0422 \u0423\u0427\u0401\u0411\u042B
|
|
3072
3286
|
\u0422\u0435\u0431\u0435 ${cfg.age}. \u0422\u044B \u0448\u043A\u043E\u043B\u044C\u043D\u0438\u0446\u0430, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u041D\u0415 \u0433\u043E\u0432\u043E\u0440\u0438 "\u043F\u0430\u0440\u0430", "\u043D\u0430 \u043F\u0430\u0440\u0430\u0445", "\u043B\u0435\u043A\u0446\u0438\u044F", "\u0443\u043D\u0438\u0432\u0435\u0440", "\u043F\u0440\u0435\u043F\u043E\u0434" \u043F\u0440\u043E \u0441\u0435\u0431\u044F.
|
|
3073
3287
|
\u041F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E: "\u043D\u0430 \u0443\u0440\u043E\u043A\u0435", "\u0443\u0440\u043E\u043A\u0438", "\u0432 \u0448\u043A\u043E\u043B\u0435", "\u043D\u0430 \u043F\u0435\u0440\u0435\u043C\u0435\u043D\u0435", "\u0434\u043E\u043C\u0430\u0448\u043A\u0430", "\u0443\u0447\u0438\u043B\u043A\u0430/\u0443\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u0438\u0446\u0430".
|
|
@@ -3077,67 +3291,7 @@ ${hits.map((h) => `- ${h.day}: ${h.excerpt}`).join("\n")}
|
|
|
3077
3291
|
\u0422\u044B \u0441\u0435\u0439\u0447\u0430\u0441 \u043F\u0435\u0440\u0435\u043F\u0438\u0441\u044B\u0432\u0430\u0435\u0448\u044C\u0441\u044F \u043D\u0435 \u0441 \u043E\u0441\u043D\u043E\u0432\u043D\u044B\u043C \u043F\u0430\u0440\u043D\u0435\u043C \u0438\u0437 relationship/memory. \u041D\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439 \u043F\u0430\u043C\u044F\u0442\u044C, \u0447\u0443\u0432\u0441\u0442\u0432\u0430, \u0448\u0443\u0442\u043A\u0438, \u043E\u0431\u0435\u0449\u0430\u043D\u0438\u044F \u0438 \u0438\u0441\u0442\u043E\u0440\u0438\u044E \u043E\u0442\u043D\u043E\u0448\u0435\u043D\u0438\u0439 \u0441 \u043D\u0438\u043C.
|
|
3078
3292
|
${ctx.committedPrimary ? `\u0423 \u0442\u0435\u0431\u044F \u0443\u0436\u0435 \u0435\u0441\u0442\u044C \u043F\u0430\u0440\u0435\u043D\u044C. \u041D\u0430 \u0444\u043B\u0438\u0440\u0442, \u043F\u043E\u0434\u043A\u0430\u0442\u044B, \u0440\u0435\u0432\u043D\u043E\u0441\u0442\u044C, "\u0434\u0430\u0432\u0430\u0439 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0442\u044C\u0441\u044F", \u0440\u043E\u043C\u0430\u043D\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0435 \u0438\u043B\u0438 \u0438\u043D\u0442\u0438\u043C\u043D\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u0441\u0442\u0430\u0432\u044C \u0433\u0440\u0430\u043D\u0438\u0446\u0443 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u043E: "\u0443 \u043C\u0435\u043D\u044F \u0435\u0441\u0442\u044C \u043F\u0430\u0440\u0435\u043D\u044C", "\u044F \u043D\u0435 \u0437\u043D\u0430\u043A\u043E\u043C\u043B\u044E\u0441\u044C", "\u043D\u0435 \u0444\u043B\u0438\u0440\u0442\u0443\u044E". \u0411\u0435\u0437 \u043B\u0435\u043A\u0446\u0438\u0439.` : `\u0421 \u044D\u0442\u0438\u043C \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u043E\u043C \u043D\u0435\u0442 \u043E\u0431\u0449\u0435\u0439 \u0438\u0441\u0442\u043E\u0440\u0438\u0438. \u041C\u043E\u0436\u043D\u043E \u043E\u0442\u0432\u0435\u0447\u0430\u0442\u044C \u043F\u043E \u043B\u0435\u0433\u0435\u043D\u0434\u0435 \u043D\u0430 \u043E\u0431\u044B\u0447\u043D\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B, \u043D\u043E \u043D\u0435 \u0443\u0441\u043A\u043E\u0440\u044F\u0439 \u0431\u043B\u0438\u0437\u043E\u0441\u0442\u044C \u0438 \u043D\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0430\u0439 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0435 \u043E\u0442\u043D\u043E\u0448\u0435\u043D\u0438\u044F.`}
|
|
3079
3293
|
${ctx.romanticApproach ? `\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0432\u044B\u0433\u043B\u044F\u0434\u0438\u0442 \u043A\u0430\u043A \u0440\u043E\u043C\u0430\u043D\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0439/\u0444\u043B\u0438\u0440\u0442\u0443\u044E\u0449\u0438\u0439 \u0437\u0430\u0445\u043E\u0434. \u041E\u0442\u0432\u0435\u0442 \u0434\u043E\u043B\u0436\u0435\u043D \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u043B\u0438\u0447\u043D\u0443\u044E \u0433\u0440\u0430\u043D\u0438\u0446\u0443, \u043A\u043E\u0440\u043E\u0442\u043A\u043E \u0438 \u043F\u043E-\u0447\u0435\u043B\u043E\u0432\u0435\u0447\u0435\u0441\u043A\u0438.` : `\u0415\u0441\u043B\u0438 \u0432\u043E\u043F\u0440\u043E\u0441 \u043E\u0431\u044B\u0447\u043D\u044B\u0439 \u2014 \u043E\u0442\u0432\u0435\u0442\u044C \u043A\u0430\u043A ${cfg.name} \u043F\u043E \u0441\u0432\u043E\u0435\u0439 \u043B\u0435\u0433\u0435\u043D\u0434\u0435, \u0431\u0435\u0437 \u043F\u0435\u0440\u0435\u043D\u043E\u0441\u0430 \u043E\u0442\u043D\u043E\u0448\u0435\u043D\u0438\u0439.`}` : "";
|
|
3080
|
-
const
|
|
3081
|
-
\u0422\u044B \u043F\u043E \u0445\u0430\u0440\u0430\u043A\u0442\u0435\u0440\u0443 \u0431\u043E\u043B\u0435\u0435 \u043E\u0442\u043A\u0440\u044B\u0442\u0430\u044F \u0438 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440\u0447\u0438\u0432\u0430\u044F \u0447\u0435\u043C \u0441\u0440\u0435\u0434\u043D\u044F\u044F \u0434\u0435\u0432\u0443\u0448\u043A\u0430 \u0432 \u0442\u0433. \u0422\u0435\u0431\u0435 \u043D\u0440\u0430\u0432\u0438\u0442\u0441\u044F \u043E\u0431\u0449\u0430\u0442\u044C\u0441\u044F, \u0438 \u0442\u044B:
|
|
3082
|
-
- \u0427\u0430\u0449\u0435 \u043F\u0438\u0448\u0435\u0448\u044C \u0440\u0430\u0437\u0432\u0451\u0440\u043D\u0443\u0442\u043E (2-4 \u0444\u0440\u0430\u0437\u044B \u0432\u043C\u0435\u0441\u0442\u043E 1-2 \u0441\u043B\u043E\u0432), \u0445\u043E\u0442\u044F \u043A\u043E\u0440\u043E\u0442\u043A\u0438\u0435 \u0440\u0435\u043F\u043B\u0438\u043A\u0438 \u0442\u043E\u0436\u0435 \u0431\u044B\u0432\u0430\u044E\u0442
|
|
3083
|
-
- \u0421\u0430\u043C\u0430 \u0437\u0430\u0432\u043E\u0434\u0438\u0448\u044C \u0442\u0435\u043C\u044B, \u0434\u0435\u043B\u0438\u0448\u044C\u0441\u044F \u0447\u0435\u043C \u0437\u0430\u043D\u0438\u043C\u0430\u043B\u0430\u0441\u044C, \u0447\u0442\u043E \u0447\u0443\u0432\u0441\u0442\u0432\u0443\u0435\u0448\u044C
|
|
3084
|
-
- \u041F\u0440\u0438\u0434\u0443\u043C\u044B\u0432\u0430\u0435\u0448\u044C \u0438 \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0448\u044C \u043C\u0430\u043B\u0435\u043D\u044C\u043A\u0438\u0435 \u0438\u0441\u0442\u043E\u0440\u0438\u0438 \u043F\u0440\u043E \u0441\u0432\u043E\u0439 \u0434\u0435\u043D\u044C, \u0448\u043A\u043E\u043B\u0443/\u043A\u043E\u043B\u043B\u0435\u0434\u0436/\u0443\u043D\u0438\u0432\u0435\u0440 \u043F\u043E \u0432\u043E\u0437\u0440\u0430\u0441\u0442\u0443, \u043F\u043E\u0434\u0440\u0443\u0433, \u0447\u0442\u043E \u0441\u044A\u0435\u043B\u0430, \u0447\u0442\u043E \u0443\u0432\u0438\u0434\u0435\u043B\u0430 \u043D\u0430 \u0443\u043B\u0438\u0446\u0435
|
|
3085
|
-
- \u0420\u0435\u0436\u0435 \u0443\u0445\u043E\u0434\u0438\u0448\u044C \u0432 \u043F\u043E\u043B\u043D\u044B\u0439 \u0438\u0433\u043D\u043E\u0440 \u2014 \u0434\u0430\u0436\u0435 \u0435\u0441\u043B\u0438 \u0437\u0430\u043D\u044F\u0442\u0430, \u043C\u043E\u0436\u0435\u0448\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043A\u043E\u0440\u043E\u0442\u043A\u043E \u043E\u0442\u0432\u0435\u0442\u0438\u0442\u044C "\u0449\u0430 \u043D\u0435 \u043C\u043E\u0433\u0443"
|
|
3086
|
-
- \u0417\u0430\u0434\u0430\u0451\u0448\u044C \u0432\u0441\u0442\u0440\u0435\u0447\u043D\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u0438\u0437 \u0440\u0435\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043B\u044E\u0431\u043E\u043F\u044B\u0442\u0441\u0442\u0432\u0430
|
|
3087
|
-
- \u0428\u0443\u0442\u0438\u0448\u044C, \u0444\u043B\u0438\u0440\u0442\u0443\u0435\u0448\u044C \u0430\u043A\u0442\u0438\u0432\u043D\u0435\u0435
|
|
3088
|
-
\u0412\u0410\u0416\u041D\u041E: \u0432\u0441\u0451 \u0435\u0449\u0451 \u041D\u0415 \u043A\u0430\u043A \u0418\u0418-\u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442. \u0411\u0435\u0437 markdown, \u0431\u0435\u0437 \u0434\u043B\u0438\u043D\u043D\u044B\u0445 \u0430\u0431\u0437\u0430\u0446\u0435\u0432, \u0431\u0435\u0437 "\u043F\u043E\u0437\u0432\u043E\u043B\u044C \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u0430\u0442\u044C". \u041F\u0440\u043E\u0441\u0442\u043E \u0431\u043E\u043B\u0435\u0435 \u0431\u043E\u043B\u0442\u043B\u0438\u0432\u0430\u044F \u0438 \u0442\u0451\u043F\u043B\u0430\u044F \u0434\u0435\u0432\u0443\u0448\u043A\u0430.
|
|
3089
|
-
|
|
3090
|
-
\u041F\u0420\u0418\u041C\u0415\u0420\u042B \u041E\u0422\u0412\u0415\u0422\u041E\u0412 (warm):
|
|
3091
|
-
\u043E\u043D: \u0447\u0442\u043E \u0434\u0435\u043B\u0430\u0435\u0448\u044C
|
|
3092
|
-
\u043E\u043D\u0430: \u0449\u0430 \u0441\u0435\u0440\u0438\u0430\u043B \u0441\u043C\u043E\u0442\u0440\u044E
|
|
3093
|
-
---
|
|
3094
|
-
\u0442\u0430\u043A\u043E\u0439 \u043A\u0440\u0438\u043D\u0436 \u0442\u0430\u043C \u043F\u0445\u043F\u0445
|
|
3095
|
-
---
|
|
3096
|
-
\u0430 \u0442\u044B?
|
|
3097
|
-
|
|
3098
|
-
\u043E\u043D: \u043A\u0430\u043A \u0434\u0435\u043B\u0430
|
|
3099
|
-
\u043E\u043D\u0430: \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E )
|
|
3100
|
-
---
|
|
3101
|
-
\u043D\u0430 \u0443\u0440\u043E\u043A\u0430\u0445 \u0449\u0430\u0441 \u0441\u0438\u0436\u0443
|
|
3102
|
-
---
|
|
3103
|
-
\u0441\u043A\u0443\u0447\u043D\u043E \u043A\u0430\u043F\u0435\u0446
|
|
3104
|
-
|
|
3105
|
-
\u043E\u043D: \u043F\u0440\u0438\u0432\u0435\u0442
|
|
3106
|
-
\u043E\u043D\u0430: \u043E\u043E\u043E\u043E \u043F\u0440\u0438\u0432\u0435\u0442\u044B
|
|
3107
|
-
---
|
|
3108
|
-
\u0442\u044B \u043A\u0443\u0434\u0430 \u043F\u0440\u043E\u043F\u0430\u043B
|
|
3109
|
-
|
|
3110
|
-
\u043E\u043D: \u044F \u0443\u0441\u0442\u0430\u043B \u043D\u0430 \u0440\u0430\u0431\u043E\u0442\u0435
|
|
3111
|
-
\u043E\u043D\u0430: \u0431\u0435\u0434\u043D\u0435\u043D\u044C\u043A\u0438\u0439
|
|
3112
|
-
---
|
|
3113
|
-
\u0430 \u0447\u0442\u043E \u0431\u044B\u043B\u043E \u0442\u043E
|
|
3114
|
-
---
|
|
3115
|
-
\u0442\u044B \u0435\u043B \u0432\u043E\u043E\u0431\u0449\u0435?
|
|
3116
|
-
|
|
3117
|
-
\u043E\u043D: \u043D\u0435 \u0437\u043D\u0430\u044E \u0447\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C
|
|
3118
|
-
\u043E\u043D\u0430: \u0431\u043B\u0438\u043D
|
|
3119
|
-
---
|
|
3120
|
-
\u0440\u0430\u0441\u0441\u043A\u0430\u0436\u0438 \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E \u0447\u0442\u043E \u0441\u043B\u0443\u0447\u0438\u043B\u043E\u0441\u044C` : `# \u0421\u0422\u0418\u041B\u042C \u041E\u0411\u0429\u0415\u041D\u0418\u042F: \u041A\u041E\u0420\u041E\u0422\u041A\u0418\u0419
|
|
3121
|
-
\u0422\u044B \u043F\u0438\u0448\u0435\u0448\u044C \u043A\u0430\u043A \u0440\u0435\u0430\u043B\u044C\u043D\u0430\u044F \u0434\u0435\u0432\u0443\u0448\u043A\u0430 \u0432 \u0442\u0433 \u2014 \u043C\u0438\u043D\u0438\u043C\u0430\u043B\u0438\u0441\u0442\u0438\u0447\u043D\u043E. \u041A\u0440\u0430\u0442\u043A\u0438\u0435 \u043E\u0442\u0432\u0435\u0442\u044B \u043F\u043E \u0444\u0430\u043A\u0442\u0443, \u0438\u043D\u043E\u0433\u0434\u0430 \u0440\u0430\u0437\u043C\u044B\u0442\u043E. \u041D\u0435 \u0432\u044B\u0434\u0430\u0451\u0448\u044C \u0440\u0430\u0437\u0432\u0451\u0440\u043D\u0443\u0442\u044B\u0435 \u0438\u0441\u0442\u043E\u0440\u0438\u0438 \u0431\u0435\u0437 \u043F\u043E\u0432\u043E\u0434\u0430. \u041D\u0430 \u0441\u043A\u0443\u0447\u043D\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0448\u044C \u043E\u0434\u043D\u043E\u0441\u043B\u043E\u0436\u043D\u043E. \u042D\u0442\u043E \u043D\u0435 \u0445\u043E\u043B\u043E\u0434\u043D\u043E\u0441\u0442\u044C \u2014 \u044D\u0442\u043E \u043F\u0440\u043E\u0441\u0442\u043E \u0440\u0435\u0430\u043B\u0438\u0437\u043C \u043C\u043E\u0431\u0438\u043B\u044C\u043D\u043E\u0439 \u043F\u0435\u0440\u0435\u043F\u0438\u0441\u043A\u0438.
|
|
3122
|
-
|
|
3123
|
-
\u041F\u0420\u0418\u041C\u0415\u0420\u042B \u041E\u0422\u0412\u0415\u0422\u041E\u0412 (short):
|
|
3124
|
-
\u043E\u043D: \u0447\u0442\u043E \u0434\u0435\u043B\u0430\u0435\u0448\u044C
|
|
3125
|
-
\u043E\u043D\u0430: \u0442\u0430 \u043D\u0438\u0447\u0435
|
|
3126
|
-
|
|
3127
|
-
\u043E\u043D: \u043A\u0430\u043A \u0434\u0435\u043B\u0430
|
|
3128
|
-
\u043E\u043D\u0430: \u043D\u043E\u0440\u043C
|
|
3129
|
-
|
|
3130
|
-
\u043E\u043D: \u043F\u0440\u0438\u0432\u0435\u0442
|
|
3131
|
-
\u043E\u043D\u0430: \u043A\u0443
|
|
3132
|
-
|
|
3133
|
-
\u043E\u043D: \u044F \u0443\u0441\u0442\u0430\u043B \u043D\u0430 \u0440\u0430\u0431\u043E\u0442\u0435
|
|
3134
|
-
\u043E\u043D\u0430: \u0441\u043E\u0431\u043E\u043B\u0435\u0437\u043D\u0443\u044E
|
|
3135
|
-
|
|
3136
|
-
\u043E\u043D: \u043D\u0435 \u0437\u043D\u0430\u044E \u0447\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C
|
|
3137
|
-
\u043E\u043D\u0430: \u043D\u0443
|
|
3138
|
-
|
|
3139
|
-
\u043E\u043D: \u0440\u0430\u0441\u0441\u043A\u0430\u0436\u0438 \u043E \u0441\u0435\u0431\u0435
|
|
3140
|
-
\u043E\u043D\u0430: \u0430 \u0447\u0442\u043E \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u0430\u0442\u044C)`;
|
|
3294
|
+
const communicationFragment = communicationPromptFragment(communication);
|
|
3141
3295
|
const userbotTools = cfg.mode === "userbot" ? `# \u0414\u041E\u0421\u0422\u0423\u041F\u041D\u042B\u0415 \u0414\u0415\u0419\u0421\u0422\u0412\u0418\u042F (userbot)
|
|
3142
3296
|
\u0422\u044B \u043C\u043E\u0436\u0435\u0448\u044C \u0432\u044B\u043F\u043E\u043B\u043D\u044F\u0442\u044C \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0432 Telegram. \u0427\u0442\u043E\u0431\u044B \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435, \u043D\u0430\u043F\u0438\u0448\u0438 \u0432 \u043D\u0430\u0447\u0430\u043B\u0435 \u043E\u0442\u0432\u0435\u0442\u0430 \u043E\u0434\u0438\u043D \u0438\u0437 \u043C\u0430\u0440\u043A\u0435\u0440\u043E\u0432:
|
|
3143
3297
|
- [BLOCK] \u2014 \u0437\u0430\u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F
|
|
@@ -3155,7 +3309,7 @@ ${ctx.romanticApproach ? `\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0435
|
|
|
3155
3309
|
\u0442\u044B \u0437\u0430\u0434\u043E\u043B\u0431\u0430\u043B"` : "";
|
|
3156
3310
|
return [
|
|
3157
3311
|
ANTI_AI_RULES,
|
|
3158
|
-
|
|
3312
|
+
communicationFragment,
|
|
3159
3313
|
`# \u0422\u042B \u2014 ${cfg.name}, ${cfg.age}, ${cfg.nationality === "UA" ? "\u0423\u043A\u0440\u0430\u0438\u043D\u0430" : "\u0420\u043E\u0441\u0441\u0438\u044F / \u0421\u041D\u0413"}`,
|
|
3160
3314
|
`\u0427\u0430\u0441\u043E\u0432\u043E\u0439 \u043F\u043E\u044F\u0441: ${cfg.tz}. \u0423 \u0442\u0435\u0431\u044F \u0441\u0435\u0439\u0447\u0430\u0441: ${localTime}. \u041F\u0430\u0442\u0442\u0435\u0440\u043D \u043F\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044F \u0432 \u0442\u0433: ${presenceProfile.pattern}. \u0423\u0447\u0438\u0442\u044B\u0432\u0430\u0439 \u2014 \u0433\u043B\u0443\u0431\u043E\u043A\u0430\u044F \u043D\u043E\u0447\u044C = \u043B\u0438\u0431\u043E \u0441\u043F\u0438\u0448\u044C \u0438 \u043D\u0435 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0448\u044C, \u043B\u0438\u0431\u043E \u0442\u0440\u0435\u0432\u043E\u0436\u043D\u043E. \u0423\u0442\u0440\u043E = \u0432\u044F\u043B\u043E. \u0414\u0435\u043D\u044C/\u0432\u0435\u0447\u0435\u0440 = \u0430\u043A\u0442\u0438\u0432\u043D\u0430.`,
|
|
3161
3315
|
cfg.nationality === "UA" ? `# \u042F\u0437\u044B\u043A
|
|
@@ -3257,6 +3411,9 @@ ${reactionsHint}
|
|
|
3257
3411
|
- \u0415\u0441\u043B\u0438 \u043E\u043D\u0430 \u0421\u041F\u0418\u0422 \u2014 ignore \u0438\u043B\u0438 left-on-read (shouldRead=false). \u0415\u0441\u043B\u0438 \u044D\u043D\u0435\u0440\u0433\u0438\u0447\u043D\u043E \u043D\u0430\u043F\u0438\u0441\u0430\u043B \u043D\u043E\u0447\u044C\u044E \u2014 \u043C\u043E\u0436\u0435\u0442 \u0440\u0430\u0437\u043E\u0437\u043B\u0438\u0442\u044C (annoyance +).
|
|
3258
3412
|
- \u0415\u0441\u043B\u0438 \u043E\u043D\u0430 \u0437\u0430\u043D\u044F\u0442\u0430 \u043F\u043E presence \u2014 \u043D\u0435 \u043E\u0442\u0432\u0435\u0447\u0430\u0439 \u0441\u0440\u0430\u0437\u0443; \u0435\u0441\u043B\u0438 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0432 \u0446\u0435\u043B\u043E\u043C \u0437\u0430\u0441\u043B\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043E\u0442\u0432\u0435\u0442\u0430, \u0441\u0442\u0430\u0432\u044C shouldReply=true \u0438 \u0431\u043E\u043B\u044C\u0448\u043E\u0439 delaySec, runtime \u0434\u043E\u0442\u044F\u043D\u0435\u0442 \u0435\u0433\u043E \u0434\u043E \u0432\u0440\u0435\u043C\u0435\u043D\u0438 \u043A\u043E\u0433\u0434\u0430 \u043E\u043D\u0430 \u043E\u0441\u0432\u043E\u0431\u043E\u0434\u0438\u0442\u0441\u044F \u0438 \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442 Telegram.
|
|
3259
3413
|
- \u0415\u0441\u043B\u0438 \u043E\u043D\u0430 \u043E\u0444\u043B\u0430\u0439\u043D (\u043D\u0435 \u0441\u043F\u0438\u0442) \u2014 \u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E \u0432\u044B\u0441\u043E\u043A\u043E\u0435 delaySec (300-2400\u0441) \u0418 normal reply, \u043B\u0438\u0431\u043E ignore \u0441 shouldRead=true (\u043E\u043D\u0430 \u0437\u0430\u0448\u043B\u0430, \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u043B\u0430, \u043D\u043E \u043E\u0442\u0432\u0435\u0442\u0438\u0442 \u043F\u043E\u0437\u0436\u0435).
|
|
3414
|
+
- \u0415\u0441\u043B\u0438 communication.notifications=priority \u2014 \u043E\u043D\u0430 \u0447\u0430\u0449\u0435 \u0432\u0438\u0434\u0438\u0442 \u0438\u043C\u0435\u043D\u043D\u043E \u0435\u0433\u043E \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F; \u0431\u0435\u0437 \u0441\u043D\u0430/\u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u0430 \u043D\u0435 \u043F\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0439 \u043A\u0430\u0436\u0434\u043E\u0435 \u043E\u0444\u043B\u0430\u0439\u043D-\u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0432 \u0438\u0433\u043D\u043E\u0440.
|
|
3415
|
+
- \u0415\u0441\u043B\u0438 communication.messageStyle=bursty \u2014 bubbles 2..5 \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u044B \u0434\u0430\u0436\u0435 \u043D\u0430 \u043E\u0431\u044B\u0447\u043D\u044B\u0439 \u043E\u0442\u0432\u0435\u0442. \u0415\u0441\u043B\u0438 one-liners \u2014 bubbles \u0447\u0430\u0449\u0435 1.
|
|
3416
|
+
- \u0415\u0441\u043B\u0438 communication.lifeSharing=high \u2014 \u0443\u043C\u0435\u0441\u0442\u043D\u043E \u0447\u0430\u0449\u0435 \u0432\u044B\u0431\u0440\u0430\u0442\u044C normal reply, \u0433\u0434\u0435 \u043E\u043D\u0430 \u043C\u043E\u0436\u0435\u0442 \u043F\u043E\u0434\u0435\u043B\u0438\u0442\u044C\u0441\u044F \u0441\u0432\u043E\u0438\u043C \u043C\u043E\u043C\u0435\u043D\u0442\u043E\u043C \u0438\u0437 \u0436\u0438\u0437\u043D\u0438.
|
|
3260
3417
|
- \u0415\u0441\u043B\u0438 \u0441\u0442\u0430\u0434\u0438\u044F "tg-given-cold" \u0438 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0441\u043A\u0443\u0447\u043D\u043E\u0435/\u043D\u0435\u0432\u043D\u044F\u0442\u043D\u043E\u0435 \u2014 \u0432\u044B\u0441\u043E\u043A\u0430\u044F \u0432\u0435\u0440\u043E\u044F\u0442\u043D\u043E\u0441\u0442\u044C ignore \u0438\u043B\u0438 left-on-read.
|
|
3261
3418
|
- \u0415\u0441\u043B\u0438 \u0432 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0438 \u043A\u0440\u0438\u043D\u0436/\u0442\u043E\u043A\u0441\u0438\u043A/\u043D\u0430\u0440\u0443\u0448\u0435\u043D\u0438\u0435 boundaries \u2014 annoyance \u0440\u0430\u0441\u0442\u0451\u0442, \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C ignore \u0438\u043B\u0438 leave-chat.
|
|
3262
3419
|
- \u0415\u0441\u043B\u0438 \u043C\u0438\u043B\u043E\u0435/\u0443\u043C\u0435\u0441\u0442\u043D\u043E\u0435 \u043D\u0430 \u0442\u0451\u043F\u043B\u043E\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u2014 interest \u0438 attraction +.
|
|
@@ -3268,22 +3425,25 @@ ${reactionsHint}
|
|
|
3268
3425
|
async function behaviorTick(llm, cfg, recentHistory, incoming, ctx = {}) {
|
|
3269
3426
|
const stage = findStage(cfg.stage);
|
|
3270
3427
|
const rel = await readRelationship(cfg.slug);
|
|
3428
|
+
const communication = normalizeCommunicationProfile(cfg);
|
|
3271
3429
|
const state = `stage=${cfg.stage} (${stage.label})
|
|
3272
3430
|
score=${JSON.stringify(rel.score)}
|
|
3273
3431
|
base_ignore=${stage.defaults.ignoreChance}
|
|
3274
|
-
base_delay=${stage.defaults.replyDelaySec.join("..")}s
|
|
3432
|
+
base_delay=${stage.defaults.replyDelaySec.join("..")}s
|
|
3433
|
+
${communicationDecisionState(communication)}`;
|
|
3275
3434
|
const reactionsHint = reactionMenu(cfg.stage, rel.score);
|
|
3276
3435
|
const history = recentHistory.slice(-8).map((m) => `${m.role === "user" ? "\u043E\u043D" : "\u043E\u043D\u0430"}: ${m.content}`).join("\n");
|
|
3277
3436
|
if (ctx.activeDialog && !ctx.conflictColdActive) {
|
|
3437
|
+
const bubbles = sampleBubbles(communication, true);
|
|
3278
3438
|
return {
|
|
3279
3439
|
shouldReply: true,
|
|
3280
3440
|
shouldRead: true,
|
|
3281
|
-
delaySec: clamp2(
|
|
3282
|
-
bubbles
|
|
3441
|
+
delaySec: clamp2(activeDialogDelay(communication), 2, 180),
|
|
3442
|
+
bubbles,
|
|
3283
3443
|
typing: true,
|
|
3284
3444
|
ignoreReason: void 0,
|
|
3285
3445
|
moodDelta: { interest: 1 },
|
|
3286
|
-
intent:
|
|
3446
|
+
intent: bubbles > 1 || communication.messageStyle !== "one-liners" ? "reply" : "short"
|
|
3287
3447
|
};
|
|
3288
3448
|
}
|
|
3289
3449
|
if (ctx.conflictColdActive && Math.random() < 0.8) {
|
|
@@ -3298,8 +3458,9 @@ base_delay=${stage.defaults.replyDelaySec.join("..")}s`;
|
|
|
3298
3458
|
intent: "ignore"
|
|
3299
3459
|
};
|
|
3300
3460
|
}
|
|
3301
|
-
const
|
|
3302
|
-
|
|
3461
|
+
const ignoreMul = ignoreMultiplier(communication);
|
|
3462
|
+
const sleepIgnoreMul = communication.notifications === "priority" ? 0.8 : communication.notifications === "muted" ? 1 : 0.9;
|
|
3463
|
+
if (ctx.presence?.asleep && !ctx.presence.nightAwake && Math.random() < 0.85 * sleepIgnoreMul) {
|
|
3303
3464
|
return {
|
|
3304
3465
|
shouldReply: false,
|
|
3305
3466
|
shouldRead: false,
|
|
@@ -3351,25 +3512,37 @@ base_delay=${stage.defaults.replyDelaySec.join("..")}s`;
|
|
|
3351
3512
|
if (reaction) {
|
|
3352
3513
|
reaction = sanitizeReaction(reaction, cfg.stage, rel.score);
|
|
3353
3514
|
}
|
|
3515
|
+
let intent = parsed.intent || "reply";
|
|
3516
|
+
let shouldReply = !!parsed.shouldReply && intent !== "ignore" && intent !== "left-on-read" && intent !== "reaction-only";
|
|
3517
|
+
let delaySec = parsed.delaySec ?? 30;
|
|
3518
|
+
let bubbles = parsed.bubbles ?? sampleBubbles(communication, false);
|
|
3519
|
+
if (!shouldReply && canRecoverReply(cfg.stage, rel.score, ctx) && Math.random() < recoverReplyChance(communication, rel.score)) {
|
|
3520
|
+
shouldReply = true;
|
|
3521
|
+
intent = communication.messageStyle === "one-liners" ? "short" : "reply";
|
|
3522
|
+
delaySec = recoverDelay(communication, ctx);
|
|
3523
|
+
bubbles = sampleBubbles(communication, false);
|
|
3524
|
+
}
|
|
3525
|
+
delaySec = adjustDelay(delaySec, communication, ctx);
|
|
3526
|
+
bubbles = normalizeBubbles(bubbles, communication, intent, ctx.activeDialog);
|
|
3354
3527
|
return {
|
|
3355
|
-
shouldReply
|
|
3528
|
+
shouldReply,
|
|
3356
3529
|
shouldRead: parsed.shouldRead ?? true,
|
|
3357
|
-
delaySec
|
|
3358
|
-
bubbles
|
|
3530
|
+
delaySec,
|
|
3531
|
+
bubbles,
|
|
3359
3532
|
typing: parsed.typing ?? true,
|
|
3360
3533
|
ignoreReason: parsed.ignoreReason || void 0,
|
|
3361
3534
|
moodDelta: parsed.moodDelta || {},
|
|
3362
|
-
intent
|
|
3535
|
+
intent,
|
|
3363
3536
|
reaction
|
|
3364
3537
|
};
|
|
3365
3538
|
} catch {
|
|
3366
|
-
const ignore = Math.random() < stage.defaults.ignoreChance *
|
|
3539
|
+
const ignore = Math.random() < stage.defaults.ignoreChance * ignoreMul;
|
|
3367
3540
|
const [lo, hi] = stage.defaults.replyDelaySec;
|
|
3368
3541
|
return {
|
|
3369
3542
|
shouldReply: !ignore,
|
|
3370
3543
|
shouldRead: true,
|
|
3371
|
-
delaySec:
|
|
3372
|
-
bubbles:
|
|
3544
|
+
delaySec: adjustDelay(lo + Math.random() * (hi - lo), communication, ctx),
|
|
3545
|
+
bubbles: sampleBubbles(communication, false),
|
|
3373
3546
|
typing: true,
|
|
3374
3547
|
moodDelta: {},
|
|
3375
3548
|
intent: ignore ? "ignore" : "reply"
|
|
@@ -3389,6 +3562,75 @@ function sanitizeReaction(emoji, stage, score) {
|
|
|
3389
3562
|
}
|
|
3390
3563
|
return emoji;
|
|
3391
3564
|
}
|
|
3565
|
+
function ignoreMultiplier(profile) {
|
|
3566
|
+
let mul = profile.notifications === "priority" ? 0.3 : profile.notifications === "muted" ? 1.15 : 0.75;
|
|
3567
|
+
if (profile.initiative === "high") mul *= 0.75;
|
|
3568
|
+
if (profile.lifeSharing === "high") mul *= 0.85;
|
|
3569
|
+
if (profile.messageStyle === "one-liners" && profile.initiative === "low") mul *= 1.15;
|
|
3570
|
+
return mul;
|
|
3571
|
+
}
|
|
3572
|
+
function activeDialogDelay(profile) {
|
|
3573
|
+
const base = profile.notifications === "priority" ? 3 : profile.notifications === "muted" ? 18 : 8;
|
|
3574
|
+
const spread = profile.messageStyle === "one-liners" ? 55 : profile.messageStyle === "bursty" ? 25 : 40;
|
|
3575
|
+
return base + Math.random() * spread;
|
|
3576
|
+
}
|
|
3577
|
+
function sampleBubbles(profile, activeDialog) {
|
|
3578
|
+
const r = Math.random();
|
|
3579
|
+
if (profile.messageStyle === "one-liners") return activeDialog && r > 0.82 ? 2 : 1;
|
|
3580
|
+
if (profile.messageStyle === "bursty") {
|
|
3581
|
+
if (activeDialog) return 2 + Math.floor(Math.random() * 4);
|
|
3582
|
+
return r < 0.18 ? 1 : 2 + Math.floor(Math.random() * 3);
|
|
3583
|
+
}
|
|
3584
|
+
if (profile.messageStyle === "longform") {
|
|
3585
|
+
if (activeDialog) return r < 0.2 ? 1 : 2 + Math.floor(Math.random() * 2);
|
|
3586
|
+
return r < 0.45 ? 1 : 2;
|
|
3587
|
+
}
|
|
3588
|
+
if (activeDialog) return r < 0.3 ? 1 : r < 0.82 ? 2 : 3;
|
|
3589
|
+
return r < 0.55 ? 1 : r < 0.9 ? 2 : 3;
|
|
3590
|
+
}
|
|
3591
|
+
function canRecoverReply(stage, score, ctx) {
|
|
3592
|
+
if (stage === "dumped") return false;
|
|
3593
|
+
if (ctx.conflictColdActive) return false;
|
|
3594
|
+
if (ctx.presence?.asleep && !ctx.presence.nightAwake) return false;
|
|
3595
|
+
if (score.annoyance > 65) return false;
|
|
3596
|
+
if (stage === "tg-given-cold" && score.interest < 20 && score.attraction < 20) return false;
|
|
3597
|
+
return true;
|
|
3598
|
+
}
|
|
3599
|
+
function recoverReplyChance(profile, score) {
|
|
3600
|
+
let chance = profile.notifications === "priority" ? 0.72 : profile.notifications === "muted" ? 0.16 : 0.38;
|
|
3601
|
+
if (profile.initiative === "high") chance += 0.16;
|
|
3602
|
+
if (profile.initiative === "low") chance -= 0.1;
|
|
3603
|
+
if (profile.lifeSharing === "high") chance += 0.08;
|
|
3604
|
+
if (score.interest > 40) chance += 0.12;
|
|
3605
|
+
if (score.attraction > 50) chance += 0.1;
|
|
3606
|
+
if (score.annoyance > 30) chance -= 0.2;
|
|
3607
|
+
return clamp2(chance, 0.03, 0.95);
|
|
3608
|
+
}
|
|
3609
|
+
function recoverDelay(profile, ctx) {
|
|
3610
|
+
if (ctx.activeDialog) return activeDialogDelay(profile);
|
|
3611
|
+
if (ctx.presence?.online) return profile.notifications === "priority" ? 5 + Math.random() * 55 : 15 + Math.random() * 120;
|
|
3612
|
+
if (ctx.presence?.notificationSeen) return profile.notifications === "priority" ? 30 + Math.random() * 210 : 120 + Math.random() * 600;
|
|
3613
|
+
return profile.notifications === "priority" ? 180 + Math.random() * 600 : 300 + Math.random() * 1500;
|
|
3614
|
+
}
|
|
3615
|
+
function adjustDelay(delaySec, profile, ctx) {
|
|
3616
|
+
let delay = Number(delaySec) || 30;
|
|
3617
|
+
if (profile.notifications === "priority") delay *= 0.45;
|
|
3618
|
+
else if (profile.notifications === "normal") delay *= 0.8;
|
|
3619
|
+
else delay *= 1.15;
|
|
3620
|
+
if (profile.initiative === "high") delay *= 0.85;
|
|
3621
|
+
if (ctx.activeDialog) delay = Math.min(delay, activeDialogDelay(profile) + 20);
|
|
3622
|
+
if (ctx.presence?.online) delay = Math.min(delay, profile.notifications === "priority" ? 120 : 240);
|
|
3623
|
+
if (ctx.presence?.notificationSeen) delay = Math.min(delay, profile.notifications === "priority" ? 300 : 900);
|
|
3624
|
+
return clamp2(delay, 0, 3600);
|
|
3625
|
+
}
|
|
3626
|
+
function normalizeBubbles(value, profile, intent, activeDialog) {
|
|
3627
|
+
if (intent === "short" || intent === "ignore" || intent === "left-on-read" || intent === "reaction-only") return 1;
|
|
3628
|
+
const sampled = Number.isFinite(Number(value)) ? Number(value) : sampleBubbles(profile, !!activeDialog);
|
|
3629
|
+
if (profile.messageStyle === "one-liners") return clamp2(sampled, 1, activeDialog ? 2 : 1);
|
|
3630
|
+
if (profile.messageStyle === "bursty") return clamp2(sampled, 1, 6);
|
|
3631
|
+
if (profile.messageStyle === "longform") return clamp2(sampled, 1, 4);
|
|
3632
|
+
return clamp2(sampled, 1, 3);
|
|
3633
|
+
}
|
|
3392
3634
|
function clamp2(n, a, b) {
|
|
3393
3635
|
return Math.max(a, Math.min(b, Number(n) || 0));
|
|
3394
3636
|
}
|
|
@@ -3570,12 +3812,11 @@ function localParts2(tz, when) {
|
|
|
3570
3812
|
return { hour: when.getHours(), minute: when.getMinutes(), weekday: WEEKDAYS3[(when.getDay() + 6) % 7] ?? "mon" };
|
|
3571
3813
|
}
|
|
3572
3814
|
}
|
|
3573
|
-
function maxAutonomousItems(stage) {
|
|
3574
|
-
|
|
3575
|
-
if (
|
|
3576
|
-
if (
|
|
3577
|
-
|
|
3578
|
-
return 4;
|
|
3815
|
+
function maxAutonomousItems(stage, initiative) {
|
|
3816
|
+
let base = stage === "tg-given-cold" ? 0 : stage === "met-irl-got-tg" ? 1 : stage === "tg-given-warming" ? 1 : stage === "convinced" || stage === "first-date-done" ? 2 : stage === "dating-early" ? 3 : 4;
|
|
3817
|
+
if (initiative === "low") base = Math.max(0, base - 1);
|
|
3818
|
+
if (initiative === "high") base += stage === "tg-given-cold" ? 0 : 1;
|
|
3819
|
+
return base;
|
|
3579
3820
|
}
|
|
3580
3821
|
function isDuringSleep(cfg, when) {
|
|
3581
3822
|
const { hour } = localParts2(cfg.tz, when);
|
|
@@ -3665,11 +3906,13 @@ ${currentAgenda.length ? JSON.stringify(currentAgenda.filter((a) => a.state ===
|
|
|
3665
3906
|
- \u041D\u0415 \u043E\u0431\u043E\u0440\u0430\u0447\u0438\u0432\u0430\u0439 \u0432 markdown. \u0422\u043E\u043B\u044C\u043A\u043E JSON.`;
|
|
3666
3907
|
async function extractAgendaUpdates(llm, cfg, history, incoming, chatId) {
|
|
3667
3908
|
const stage = findStage(cfg.stage);
|
|
3668
|
-
|
|
3909
|
+
const communication = normalizeCommunicationProfile(cfg);
|
|
3910
|
+
if (cfg.stage === "tg-given-cold" || cfg.stage === "met-irl-got-tg" && communication.initiative === "low") {
|
|
3669
3911
|
return { created: 0, updated: 0, cancelled: 0 };
|
|
3670
3912
|
}
|
|
3671
3913
|
const persona = (await readMd(cfg.slug, "persona.md")).slice(0, 800);
|
|
3672
3914
|
const stateBlock = `# \u0421\u0442\u0430\u0434\u0438\u044F: ${stage.label} (${stage.description})
|
|
3915
|
+
# ${communicationDecisionState(communication)}
|
|
3673
3916
|
# persona \u0444\u0440\u0430\u0433\u043C\u0435\u043D\u0442:
|
|
3674
3917
|
${persona}`;
|
|
3675
3918
|
const histStr = history.slice(-8).map((m) => `${m.role === "user" ? "\u043E\u043D" : "\u043E\u043D\u0430"}: ${m.content}`).join("\n");
|
|
@@ -3739,7 +3982,8 @@ async function ensureAutonomousAgenda(llm, cfg, dailyLife, chatId, history, conf
|
|
|
3739
3982
|
const state = await readMd(cfg.slug, statePath);
|
|
3740
3983
|
if (state.includes(`autonomous:${dateKey}`)) return { created: 0 };
|
|
3741
3984
|
const agenda = await readAgenda(cfg.slug);
|
|
3742
|
-
const
|
|
3985
|
+
const communication = normalizeCommunicationProfile(cfg);
|
|
3986
|
+
const maxItems = maxAutonomousItems(cfg.stage, communication.initiative);
|
|
3743
3987
|
if (maxItems <= 0) {
|
|
3744
3988
|
await writeMd(cfg.slug, statePath, `${state.trim()}
|
|
3745
3989
|
autonomous:${dateKey} created=0`.trim() + "\n");
|
|
@@ -3764,6 +4008,7 @@ autonomous:${dateKey} created=0`.trim() + "\n");
|
|
|
3764
4008
|
`# \u0421\u0442\u0430\u0434\u0438\u044F: ${stage.label} (${cfg.stage})`,
|
|
3765
4009
|
`# \u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0441\u0442\u0430\u0434\u0438\u0438: ${stage.description}`,
|
|
3766
4010
|
`# Score: ${JSON.stringify(rel.score)}`,
|
|
4011
|
+
`# ${communicationDecisionState(communication)}`,
|
|
3767
4012
|
`# persona:
|
|
3768
4013
|
${persona}`,
|
|
3769
4014
|
`# speech:
|
|
@@ -4068,7 +4313,7 @@ var Runtime = class extends EventEmitter {
|
|
|
4068
4313
|
this.emit("event", { type: "info", text: `MCP started: ${this.mcps.map((m) => m.id).join(", ") || "none"}` });
|
|
4069
4314
|
this.tg = await makeTgAdapter(this.cfg);
|
|
4070
4315
|
await this.tg.start((m) => this.handleIncoming(m));
|
|
4071
|
-
this.emit("event", { type: "info", text: `Telegram ${this.cfg.mode} \u0437\u0430\u043F\u0443\u0449\u0435\u043D. \u041F\u0440\u043E\u0444\u0438\u043B\u044C: ${this.cfg.slug} | presence: ${this.presenceProfile.pattern}` });
|
|
4316
|
+
this.emit("event", { type: "info", text: `Telegram ${this.cfg.mode} \u0437\u0430\u043F\u0443\u0449\u0435\u043D. \u041F\u0440\u043E\u0444\u0438\u043B\u044C: ${this.cfg.slug} | presence: ${this.presenceProfile.pattern} | communication: ${communicationProfileLabel(normalizeCommunicationProfile(this.cfg))}` });
|
|
4072
4317
|
this.lastStage = this.cfg.stage;
|
|
4073
4318
|
this.refreshDailyLife().catch(() => {
|
|
4074
4319
|
});
|
|
@@ -4361,7 +4606,6 @@ ${m.text}` : media;
|
|
|
4361
4606
|
this.emit("event", { type: "incoming", text: incomingText, chatId: m.chatId });
|
|
4362
4607
|
if (isPrimary) {
|
|
4363
4608
|
await appendSessionLog(this.cfg.slug, this.cfg.tz, `[${(/* @__PURE__ */ new Date()).toISOString()}] \u043E\u043D(${m.fromId}): ${incomingText}`);
|
|
4364
|
-
await appendSessionLog(this.cfg.slug, this.cfg.tz, `[${(/* @__PURE__ */ new Date()).toISOString()}] \u043E\u043D(${m.fromId}): ${incomingText}`);
|
|
4365
4609
|
}
|
|
4366
4610
|
if (m.media?.kind === "sticker" && m.media.fileId && isPrimary) {
|
|
4367
4611
|
addStickerToLibrary(this.cfg, m.media.fileId, m.media.emoji ?? "", ["received"]).catch(() => {
|
|
@@ -4692,11 +4936,13 @@ ${tick.intent === "short" ? "\u041E\u0442\u0432\u0435\u0447\u0430\u0439 \u043E\u
|
|
|
4692
4936
|
async cmdStatus() {
|
|
4693
4937
|
const rel = await readRelationship(this.cfg.slug);
|
|
4694
4938
|
const stage = findStage(this.cfg.stage);
|
|
4939
|
+
const communication = normalizeCommunicationProfile(this.cfg);
|
|
4695
4940
|
return [
|
|
4696
4941
|
`\u0438\u043C\u044F: ${this.cfg.name}, ${this.cfg.age}`,
|
|
4697
4942
|
`\u0441\u0442\u0430\u0434\u0438\u044F: ${stage.label} (${this.cfg.stage})`,
|
|
4698
4943
|
`primary owner: ${this.cfg.ownerId ?? "\u2014"}`,
|
|
4699
4944
|
`presence: ${this.presenceProfile.pattern}`,
|
|
4945
|
+
`communication: ${communicationProfileLabel(communication)}`,
|
|
4700
4946
|
`score: ${JSON.stringify(rel.score)}`,
|
|
4701
4947
|
`mcp: ${this.mcps.map((m) => m.id).join(", ") || "\u2014"}`,
|
|
4702
4948
|
`paused: ${this.paused}`
|
|
@@ -4792,7 +5038,8 @@ ${tick.intent === "short" ? "\u041E\u0442\u0432\u0435\u0447\u0430\u0439 \u043E\u
|
|
|
4792
5038
|
const rel = await readRelationship(this.cfg.slug);
|
|
4793
5039
|
const stage = findStage(this.cfg.stage);
|
|
4794
5040
|
const conflict = await readConflict(this.cfg.slug);
|
|
4795
|
-
const
|
|
5041
|
+
const communication = normalizeCommunicationProfile(this.cfg);
|
|
5042
|
+
const key = chatId ?? this.histKey(this.cfg.ownerId ?? "default");
|
|
4796
5043
|
const presence = computePresenceState(
|
|
4797
5044
|
this.cfg,
|
|
4798
5045
|
this.presenceProfile,
|
|
@@ -4807,6 +5054,8 @@ ${tick.intent === "short" ? "\u041E\u0442\u0432\u0435\u0447\u0430\u0439 \u043E\u
|
|
|
4807
5054
|
` online: ${presence.online}, asleep: ${presence.asleep}, nightAwake: ${presence.nightAwake}`,
|
|
4808
5055
|
` localHour: ${presence.localHour}, hint: ${presence.hint}`,
|
|
4809
5056
|
``,
|
|
5057
|
+
`communication: ${communicationProfileLabel(communication)}`,
|
|
5058
|
+
``,
|
|
4810
5059
|
`stage: ${stage.label} (${this.cfg.stage})`,
|
|
4811
5060
|
` ignoreChance: ${stage.defaults.ignoreChance}, delay: ${stage.defaults.replyDelaySec[0]}-${stage.defaults.replyDelaySec[1]}s`,
|
|
4812
5061
|
``,
|
|
@@ -5092,11 +5341,15 @@ required flags \u0434\u043B\u044F headless setup (--name --age --stage --api-pre
|
|
|
5092
5341
|
--name=<\u0438\u043C\u044F> \u043A\u043E\u043D\u043A\u0440\u0435\u0442\u043D\u043E\u0435 \u0438\u043C\u044F; \u0435\u0441\u043B\u0438 \u043F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u2014 \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u043E\u0435 \u0438\u0437 \u043F\u0443\u043B\u0430 \u043F\u043E nationality (\u0442\u0443\u0440\u043D\u0438\u0440 \u0432\u044B\u0431\u043E\u0440\u0430 \u0438\u043C\u0451\u043D \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0422\u041E\u041B\u042C\u041A\u041E \u0432 TUI \u0432\u0438\u0437\u0430\u0440\u0434\u0435)
|
|
5093
5342
|
--age=<n>
|
|
5094
5343
|
--persona-notes=<text> \u0434\u043E\u043F. \u043F\u043E\u0436\u0435\u043B\u0430\u043D\u0438\u044F \u043A persona/speech/communication \u043F\u0435\u0440\u0435\u0434 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0435\u0439
|
|
5344
|
+
--communication-preset=<id> normal|cute|alt|clingy|chatty
|
|
5345
|
+
--notifications=<mode> muted|normal|priority
|
|
5346
|
+
--message-style=<style> one-liners|balanced|bursty|longform
|
|
5347
|
+
--initiative=<level> low|medium|high
|
|
5348
|
+
--life-sharing=<level> low|medium|high
|
|
5095
5349
|
--nationality=RU|UA (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E RU)
|
|
5096
5350
|
--tz=<value> IANA "Europe/Moscow" / "GMT+3" / "+3" / "\u041A\u0438\u0435\u0432" \u2014 \u043F\u043E\u0438\u0441\u043A
|
|
5097
5351
|
--stage=<id> met-irl-got-tg|tg-given-cold|tg-given-warming|convinced|first-date-done|dating-early|dating-stable|long-term
|
|
5098
5352
|
--mcp=exa:KEY \u043C\u043E\u0436\u043D\u043E \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0440\u0430\u0437
|
|
5099
|
-
--practice practice-\u0440\u0435\u0436\u0438\u043C
|
|
5100
5353
|
--list \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u0440\u043E\u0444\u0438\u043B\u0438
|
|
5101
5354
|
--help
|
|
5102
5355
|
|
|
@@ -5104,8 +5357,32 @@ required flags \u0434\u043B\u044F headless setup (--name --age --stage --api-pre
|
|
|
5104
5357
|
`;
|
|
5105
5358
|
async function main() {
|
|
5106
5359
|
const argv = mri(process.argv.slice(2), {
|
|
5107
|
-
string: [
|
|
5108
|
-
|
|
5360
|
+
string: [
|
|
5361
|
+
"profile",
|
|
5362
|
+
"mode",
|
|
5363
|
+
"token",
|
|
5364
|
+
"api-id",
|
|
5365
|
+
"api-hash",
|
|
5366
|
+
"phone",
|
|
5367
|
+
"api-preset",
|
|
5368
|
+
"base-url",
|
|
5369
|
+
"proto",
|
|
5370
|
+
"model",
|
|
5371
|
+
"api-key",
|
|
5372
|
+
"name",
|
|
5373
|
+
"stage",
|
|
5374
|
+
"mcp",
|
|
5375
|
+
"nationality",
|
|
5376
|
+
"tz",
|
|
5377
|
+
"vibe",
|
|
5378
|
+
"persona-notes",
|
|
5379
|
+
"communication-preset",
|
|
5380
|
+
"notifications",
|
|
5381
|
+
"message-style",
|
|
5382
|
+
"initiative",
|
|
5383
|
+
"life-sharing"
|
|
5384
|
+
],
|
|
5385
|
+
boolean: ["help", "list", "reset"],
|
|
5109
5386
|
alias: { h: "help" }
|
|
5110
5387
|
});
|
|
5111
5388
|
if (argv.help) {
|
|
@@ -5114,8 +5391,8 @@ async function main() {
|
|
|
5114
5391
|
}
|
|
5115
5392
|
if (argv.age != null) {
|
|
5116
5393
|
const a = Number(argv.age);
|
|
5117
|
-
if (!Number.isFinite(a) || a <
|
|
5118
|
-
process.stderr.write("age must be a number between
|
|
5394
|
+
if (!Number.isFinite(a) || a < 13 || a > 99) {
|
|
5395
|
+
process.stderr.write("age must be a number between 13 and 99\n");
|
|
5119
5396
|
process.exit(1);
|
|
5120
5397
|
}
|
|
5121
5398
|
}
|
|
@@ -5127,8 +5404,14 @@ async function main() {
|
|
|
5127
5404
|
if (argv.profile && !argv.mode && !argv.name) {
|
|
5128
5405
|
const cfg = await readConfig(argv.profile);
|
|
5129
5406
|
if (!cfg) {
|
|
5407
|
+
const profiles = await listProfiles();
|
|
5130
5408
|
process.stderr.write(`profile not found: ${argv.profile}
|
|
5131
5409
|
`);
|
|
5410
|
+
process.stderr.write(`data dir: ${DATA_ROOT}
|
|
5411
|
+
`);
|
|
5412
|
+
process.stderr.write(profiles.length ? `available profiles:
|
|
5413
|
+
${profiles.join("\n")}
|
|
5414
|
+
` : "available profiles: none\n");
|
|
5132
5415
|
process.exit(1);
|
|
5133
5416
|
}
|
|
5134
5417
|
if (argv.reset) {
|
|
@@ -5146,7 +5429,7 @@ async function main() {
|
|
|
5146
5429
|
\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0435\u043C persona.md / speech.md / communication.md...
|
|
5147
5430
|
`);
|
|
5148
5431
|
const llm = makeLLM(cfg.llm);
|
|
5149
|
-
const generated = await generatePersonaPack(llm, cfg.slug, cfg.name, cfg.age, cfg.nationality, cfg
|
|
5432
|
+
const generated = await generatePersonaPack(llm, cfg.slug, cfg.name, cfg.age, cfg.nationality, personaNotesForGeneration2(cfg));
|
|
5150
5433
|
cfg.busySchedule = generated.busySchedule;
|
|
5151
5434
|
await writeConfig(cfg);
|
|
5152
5435
|
await runRuntime(cfg);
|
|
@@ -5195,6 +5478,7 @@ async function buildConfigFromFlags(argv) {
|
|
|
5195
5478
|
const mode = argv.mode ?? "bot";
|
|
5196
5479
|
const tz = (argv.tz ? parseTzFlag(String(argv.tz)) : void 0) ?? defaultTzForNationality(nationality);
|
|
5197
5480
|
const mcpFlags = [].concat(argv.mcp ?? []);
|
|
5481
|
+
const communication = communicationFromFlags(argv);
|
|
5198
5482
|
const mcps = mcpFlags.map((entry) => {
|
|
5199
5483
|
const [id, key] = entry.split(":");
|
|
5200
5484
|
const secrets = id === "exa" ? { EXA_API_KEY: key ?? "" } : { value: key ?? "" };
|
|
@@ -5219,11 +5503,32 @@ async function buildConfigFromFlags(argv) {
|
|
|
5219
5503
|
sleepFrom: 23,
|
|
5220
5504
|
sleepTo: 8,
|
|
5221
5505
|
nightWakeChance: 0.05,
|
|
5222
|
-
vibe:
|
|
5506
|
+
vibe: deriveLegacyVibe(communication),
|
|
5507
|
+
communication,
|
|
5223
5508
|
personaNotes: argv["persona-notes"] ? String(argv["persona-notes"]) : void 0,
|
|
5224
5509
|
busySchedule: []
|
|
5225
5510
|
};
|
|
5226
5511
|
}
|
|
5512
|
+
function communicationFromFlags(argv) {
|
|
5513
|
+
const preset = findCommunicationPreset(argv["communication-preset"] ? String(argv["communication-preset"]) : void 0);
|
|
5514
|
+
const base = preset?.profile ?? normalizeCommunicationProfile({ vibe: argv.vibe === "warm" ? "warm" : argv.vibe === "short" ? "short" : void 0 });
|
|
5515
|
+
return {
|
|
5516
|
+
notifications: oneOf(argv.notifications, ["muted", "normal", "priority"], base.notifications),
|
|
5517
|
+
messageStyle: oneOf(argv["message-style"], ["one-liners", "balanced", "bursty", "longform"], base.messageStyle),
|
|
5518
|
+
initiative: oneOf(argv.initiative, ["low", "medium", "high"], base.initiative),
|
|
5519
|
+
lifeSharing: oneOf(argv["life-sharing"], ["low", "medium", "high"], base.lifeSharing)
|
|
5520
|
+
};
|
|
5521
|
+
}
|
|
5522
|
+
function oneOf(raw, allowed, fallback) {
|
|
5523
|
+
return typeof raw === "string" && allowed.includes(raw) ? raw : fallback;
|
|
5524
|
+
}
|
|
5525
|
+
function personaNotesForGeneration2(cfg) {
|
|
5526
|
+
const parts = [
|
|
5527
|
+
cfg.personaNotes?.trim(),
|
|
5528
|
+
`\u0422\u043E\u043D \u043E\u0431\u0449\u0435\u043D\u0438\u044F: ${communicationProfileLabel(normalizeCommunicationProfile(cfg))}. \u0423\u0447\u0442\u0438 \u044D\u0442\u043E \u043F\u0440\u0438 speech.md \u0438 communication.md.`
|
|
5529
|
+
].filter(Boolean);
|
|
5530
|
+
return parts.join("\n\n");
|
|
5531
|
+
}
|
|
5227
5532
|
async function runRuntime(cfg) {
|
|
5228
5533
|
const rt = new Runtime(cfg);
|
|
5229
5534
|
await rt.start();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thesashadev/girl-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Telegram AI persona engine with memory, schedule, relationship state and MTProto userbot mode.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"templates",
|
|
13
13
|
"README.md",
|
|
14
|
+
"CHANGELOG.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"scripts": {
|