neuroalpha 0.6.13 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +14 -10
  2. package/bin/cli.js +79 -69
  3. package/docs//320/230/320/235/320/241/320/242/320/240/320/243/320/232/320/246/320/230/320/257.md +2 -2
  4. package/package.json +4 -5
  5. package/public/activate.html +41 -19
  6. package/public/activate.js +81 -10
  7. package/public/app.js +471 -166
  8. package/public/index.html +9 -39
  9. package/public/styles.css +42 -3
  10. package/server/api/routes.js +595 -906
  11. package/server/auth/index.js +583 -761
  12. package/server/brokers/index.js +14 -3
  13. package/server/config.js +73 -53
  14. package/server/index.js +186 -212
  15. package/server/llm/local-engine.js +843 -0
  16. package/server/llm/providers.js +45 -34
  17. package/server/model/live.js +2 -1
  18. package/server/notify/index.js +304 -466
  19. package/server/strategist/index.js +4 -1
  20. package/deploy/docs/01-central.md +0 -96
  21. package/deploy/docs/02-cloud-instances.md +0 -130
  22. package/deploy/docs/03-desktop-build.md +0 -92
  23. package/deploy/docs/04-client-guide.md +0 -101
  24. package/deploy/docs/05-operations.md +0 -109
  25. package/deploy/docs/06-env-reference.md +0 -91
  26. package/deploy/docs/07-stress-test.md +0 -253
  27. package/deploy/docs/pdf/01-central.pdf +0 -0
  28. package/deploy/docs/pdf/02-cloud-instances.pdf +0 -0
  29. package/deploy/docs/pdf/03-desktop-build.pdf +0 -0
  30. package/deploy/docs/pdf/04-client-guide.pdf +0 -0
  31. package/deploy/docs/pdf/05-operations.pdf +0 -0
  32. package/deploy/docs/pdf/06-env-reference.pdf +0 -0
  33. package/deploy/docs/pdf/07-stress-test.pdf +0 -0
  34. package/deploy/install.sh +0 -128
  35. package/deploy/k8s/instance.yaml +0 -147
  36. package/public/admin.html +0 -604
  37. package/public/landing.html +0 -1207
  38. package/public/legal.html +0 -134
  39. package/scripts/set-admin-password.mjs +0 -30
  40. package/server/billing/yookassa.js +0 -142
  41. package/server/instance/agent.js +0 -259
  42. package/server/instance/central.js +0 -514
  43. package/server/instance/identity.js +0 -79
  44. package/server/instance/provision.js +0 -166
  45. package/server/instance/signing.js +0 -71
  46. package/server/role.js +0 -44
package/public/index.html CHANGED
@@ -11,14 +11,17 @@
11
11
  <script src="https://unpkg.com/dompurify@3.2.6/dist/purify.min.js" integrity="sha384-JEyTNhjM6R1ElGoJns4U2Ln4ofPcqzSsynQkmEc/KGy6336qAZl70tDLufbkla+3" crossorigin="anonymous"></script>
12
12
  </head>
13
13
  <body>
14
+ <div id="lic-error-bar" class="lic-error-bar" hidden>
15
+ <span id="lic-error-text">ЛИЦЕНЗИЯ НЕ УСТАНОВЛЕНА (Торговля и сигналы отключены)</span>
16
+ <button id="btn-get-license" type="button" class="lic-cta-btn">Получить лицензию</button>
17
+ </div>
14
18
  <header>
15
19
  <div class="brand">
16
20
  <button id="btn-chat-toggle" type="button" class="hdr-btn" title="Показать или скрыть панель чата с ИИ-Стратегом">💬 Стратег</button>
17
21
  <span class="logo">◈</span><b>НейроАльфа</b><span class="muted">· Рынок как язык · Мосбиржа</span>
18
22
  </div>
19
23
  <div class="hright">
20
- <a href="/landing" class="hdr-btn" title="Публичная витрина и тарифы">Витрина</a>
21
- <button id="btn-user" type="button" class="hdr-btn" title="Профиль, подписка и боты Telegram / MAX">Профиль</button>
24
+ <button id="btn-user" type="button" class="hdr-btn" title="Лицензия, доступ и уведомления">Лицензия</button>
22
25
  <span id="st" class="dot" title="Подключение…"></span>
23
26
  <button id="btn-theme" class="hdr-btn icon-only" title="Светлая / тёмная тема">☀</button>
24
27
  <button id="btn-help" class="hdr-btn icon-only" title="Справка">?</button>
@@ -89,7 +92,7 @@
89
92
  <button type="button" data-sec="news" id="nnav-news">Новости рынка</button>
90
93
  <div class="ssep"></div>
91
94
  <button type="button" data-sec="overview" id="nnav-overview" hidden>Эксперименты</button>
92
- <button type="button" data-sec="cloud" id="snav-cloud">Подписка и уведомления</button>
95
+ <button type="button" data-sec="cloud" id="snav-cloud">Лицензия</button>
93
96
  <button type="button" data-sec="llm" id="snav-llm">Модели ИИ</button>
94
97
  </aside>
95
98
  <div class="spane">
@@ -246,7 +249,7 @@
246
249
  </section>
247
250
 
248
251
  <section class="ssec" data-sec="cloud" id="cloud-box" hidden>
249
- <div class="stitle">Подписка, лицензия и уведомления (Telegram / MAX)</div>
252
+ <div class="stitle">Лицензия терминала, доступ и уведомления (Telegram / MAX)</div>
250
253
  <div class="scard spadded" id="cloud-pane"></div>
251
254
  </section>
252
255
 
@@ -254,11 +257,12 @@
254
257
  <div class="stitle bar">
255
258
  <span id="llm-sum">Модели ИИ для Стратега</span>
256
259
  <div class="row-gap" style="align-items:center">
257
- <button type="button" id="btn-llm-open-add" class="primary">+ Подключить ИИ-сервис</button>
260
+ <button type="button" id="btn-llm-open-add" class="primary">+ Подключить внешний ИИ-сервис</button>
258
261
  </div>
259
262
  </div>
260
263
  <div class="scard spadded">
261
264
  <div id="llm-active-banner"></div>
265
+ <div id="local-llm-box" style="margin-bottom:16px"></div>
262
266
  <div id="llm-form-slot">
263
267
  <details id="llm-add-box" class="llm-form-card">
264
268
  <summary id="llm-add-sum">+ Подключить новый сервис или локальную модель ИИ</summary>
@@ -372,40 +376,6 @@
372
376
  </div>
373
377
  </div>
374
378
 
375
- <!-- Модальное окно подписания Договора-оферты и Декларации о рисках -->
376
- <div id="offer-modal" class="modal" hidden>
377
- <div class="modal-box" style="max-width:680px">
378
- <div class="modal-head">
379
- <b>Договор публичной оферты и Декларация о рисках</b>
380
- <button id="offer-close" class="icon">✕</button>
381
- </div>
382
- <div class="md" style="max-height:300px;overflow-y:auto;padding:12px 16px;border-bottom:1px solid var(--line);font-size:13px;line-height:1.55">
383
- <p style="margin-top:0"><b>1. Предмет договора:</b> Настоящая Публичная оферта регулирует предоставление доступа к облачной аналитической платформе «НейроАльфа» (PaaS/SaaS) согласно выбранному тарифному плану («Инвестор», «Профи», «VIP»).</p>
384
- <p><b>2. Правовой статус (отсутствие ИИР и ДУ):</b> Сервис является исключительно программно-техническим средством (калькулятором статистических закономерностей). Исполнитель <b>не осуществляет инвестиционное консультирование</b>, не даёт индивидуальных инвестиционных рекомендаций (ФЗ № 39-ФЗ) и не осуществляет доверительное управление. Все сделки совершаются Пользователем самостоятельно на его личном брокерском счёте.</p>
385
- <p><b>3. Параметры тарифов и предельные уровни доходности:</b>
386
- <br>• <b>«Инвестор» (3 900 ₽/мес)</b> — 1 брокерский счёт, стартовый лимит до 1 000 000 ₽ (+ реинвестирование всей заработанной прибыли), торговля только от покупки («Только в рост (без шорта)»);
387
- <br>• <b>«Профи» (9 900 ₽/мес)</b> — до 5 брокерских счетов, стартовый лимит до 1 000 000 ₽ на каждом счёте (+ реинвестирование всей заработанной прибыли), торговля в рост и в падение (с шортами);
388
- <br>• <b>«VIP» (по индивидуальному согласованию)</b> — количество счетов и начальная сумма торговли по согласованию, торговля в рост и в падение (с шортами).
389
- </p>
390
- <p><b>4. Запрет автоследования и ретрансляции сигналов:</b> Пользователю строго запрещается подключать к платформе счета, участвующие в сервисах автоследования или копирования сделок (как в роли ведущего/автора стратегии, так и в роли подписчика), а также передавать или перепродавать сигналы третьим лицам. При обнаружении признаков автоследования счёт автоматически блокируется.</p>
391
- <p style="margin-bottom:0"><b>5. Декларация о рисках:</b> Торговля ценными бумагами сопряжена с риском потери части или всего инвестированного капитала. Результаты на исторических данных не гарантируют доходности в будущем. Полный текст документа: <a href="/legal" target="_blank" style="color:var(--accent)">открыть /legal →</a></p>
392
- </div>
393
- <div style="padding:14px 18px;display:grid;gap:10px;font-size:13px">
394
- <label style="display:flex;gap:10px;align-items:flex-start;cursor:pointer">
395
- <input type="checkbox" id="term-offer-chk1" style="width:16px;height:16px;margin-top:2px;flex:none">
396
- <span>Я прочитал(а) и безоговорочно принимаю условия <a href="/legal#offer" target="_blank" style="color:var(--accent)">Договора публичной оферты</a> и <a href="/legal#privacy" target="_blank" style="color:var(--accent)">Политики обработки персональных данных</a>.</span>
397
- </label>
398
- <label style="display:flex;gap:10px;align-items:flex-start;cursor:pointer">
399
- <input type="checkbox" id="term-offer-chk2" style="width:16px;height:16px;margin-top:2px;flex:none">
400
- <span>Я ознакомлен(а) с <a href="/legal#risks" target="_blank" style="color:var(--accent)">Декларацией о рисках</a>, понимаю, что сервис не является индивидуальной инвестиционной рекомендацией, и обязуюсь <b>не использовать автоследование</b> на подключаемых счетах.</span>
401
- </label>
402
- <div class="row-gap" style="justify-content:flex-end;margin-top:4px">
403
- <button type="button" id="term-offer-decline">Отказ (Отмена)</button>
404
- <button type="button" class="primary" id="term-offer-accept" disabled>Подписать оферту и продолжить →</button>
405
- </div>
406
- </div>
407
- </div>
408
- </div>
409
379
  <div id="toast"></div>
410
380
  <script src="app.js" type="module"></script>
411
381
  </body>
package/public/styles.css CHANGED
@@ -47,8 +47,9 @@ body.light {
47
47
  --hover-bg: #f0f3f6;
48
48
  }
49
49
  * { box-sizing: border-box; }
50
+ [hidden] { display: none !important; }
50
51
  html, body { height: 100%; }
51
- body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; overflow: hidden; }
52
+ body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; overflow: hidden; display: flex; flex-direction: column; }
52
53
  a, a:visited { color: var(--accent); text-decoration: none; }
53
54
  a:hover { color: var(--accent); text-decoration: underline; }
54
55
  .muted { color: var(--muted); }
@@ -58,7 +59,45 @@ a:hover { color: var(--accent); text-decoration: underline; }
58
59
  .neg { color: var(--red); }
59
60
  h4 { margin: 18px 0 6px; font-size: 13px; color: var(--muted); font-weight: 500; }
60
61
 
61
- header { height: 48px; display: flex; justify-content: space-between; align-items: center; padding: 0 16px; border-bottom: 1px solid var(--line); background: var(--panel); }
62
+ header { height: 48px; flex: none; display: flex; justify-content: space-between; align-items: center; padding: 0 16px; border-bottom: 1px solid var(--line); background: var(--panel); }
63
+ .lic-error-bar {
64
+ background: #d32f2f;
65
+ color: #ffffff;
66
+ flex: none;
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ flex-wrap: wrap;
71
+ gap: 12px;
72
+ padding: 5px 16px;
73
+ font-size: 13px;
74
+ font-weight: 600;
75
+ }
76
+ .lic-error-bar button.lic-cta-btn {
77
+ background: #ffffff;
78
+ color: #1e293b;
79
+ border: 0;
80
+ border-radius: 5px;
81
+ padding: 4px 12px;
82
+ font-size: 12.5px;
83
+ font-weight: 700;
84
+ box-shadow: 0 1px 3px rgba(0,0,0,0.28);
85
+ }
86
+ .lic-error-bar button.lic-cta-btn:hover {
87
+ background: #f1f5f9;
88
+ color: #0f172a;
89
+ }
90
+ .hdr-btn.lic-err {
91
+ background: rgba(211, 47, 47, 0.16);
92
+ border-color: #ef4444;
93
+ color: #f87171;
94
+ font-weight: 600;
95
+ }
96
+ body.light .hdr-btn.lic-err {
97
+ background: #fee2e2;
98
+ border-color: #dc2626;
99
+ color: #b91c1c;
100
+ }
62
101
  .brand { display: flex; gap: 8px; align-items: center; }
63
102
  .logo { color: var(--accent); font-size: 18px; }
64
103
  .hright { display: flex; gap: 8px; align-items: center; }
@@ -99,7 +138,7 @@ button.icon-lg { width: 40px; height: 40px; padding: 0; font-size: 15px; flex: n
99
138
  .hdr-btn { padding: 4px 10px; font-size: 12.5px; }
100
139
  .hdr-btn.icon-only { width: 30px; height: 30px; padding: 0; }
101
140
 
102
- main { display: grid; grid-template-columns: var(--chat-w) 5px 1fr; height: calc(100vh - 48px); }
141
+ main { display: grid; grid-template-columns: var(--chat-w) 5px 1fr; flex: 1; min-height: 0; }
103
142
  body.chat-closed main { grid-template-columns: 1fr; }
104
143
  body.chat-closed .chat, body.chat-closed #splitter { display: none; }
105
144
  #btn-chat-toggle.active { border-color: var(--accent); color: var(--accent); background: var(--accent-bg); font-weight: 600; }