odant-work 1.0.0 → 1.0.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.
@@ -1,6 +1,43 @@
1
1
  # Прогресс: sources/data
2
2
 
3
3
  ## Последние изменения
4
+ - [14:30, 29.10] Обновление комплектации и лицензионного центра **ODANT-WORK** (`odant-work@1.0.2`, `work-license-server@1.0.3`):
5
+ - **10 вечных лицензий + 1 год поддержки Enterprise в комплекте (`license-server/src/catalog.js`, `sources/modules/license/index.js`, `store.js`, `form/license`):**
6
+ 1. В базовую поставку комплекса (`5 000 000 ₽`) включены **10 вечных одновременных лицензий** (`baseSeats: 10`) и **1-й год поддержки максимального уровня Enterprise** (`includedSupportTier: 'enterprise'`, 24/7, реакция до 15 минут, безлимитные обращения).
7
+ 2. Дальнейшее продление технической поддержки и докупка дополнительных годовых мест — **по желанию клиента** (10 вечных лицензий работают бессрочно).
8
+ - **Гибридная политика моделей ИИ (`catalog.js`, `landing.js`, `agent.js`, `form/license`):**
9
+ 1. Явно зафиксировано, что 4 интегрированные локальные модели предназначены для **базовых ежедневных операций** внутри контура предприятия.
10
+ 2. Если требуются более мощные модели ИИ, их можно свободно подключать **через стандартный API из любого источника** (внешние облачные провайдеры, корпоративный GPU-кластер или коммерческий API регионального партнёра).
11
+ - **Интеграция ИИ-агента на левую вкладку админ-панели (`/admin`, `license-server/src/landing.js`, `assets/landing.css`, `assets/landing.js`, `src/agent.js`):**
12
+ 1. В `/admin` создана двухколоночная рабочая область `.admin-workspace` с левой панелью навигации по вкладкам (`ИИ-агент + Все разделы`, `Только ИИ-агент`, `Лицензии`, `Заказы ЮKassa`, `Франшизы и партнёры`, `Тикеты SLA`) и встроенным на левую вкладку **ИИ-агентом администратора** (`#admAgentCard`).
13
+ 2. ИИ-агент наделён административными инструментами: формирование живой сводки по реестру сервера, выпуск и подпись сертификатов `Ed25519`, проведение оплаты ожидающих заказов ЮKassa и проверка квот франшиз с автоматическим обновлением таблиц админки.
14
+ - [14:15, 29.10] Доработка пакетировщика `oda-packets`, навигации по вкладкам в подвале `work-form`, представлений «Обороты» (`form/turnovers`), «Анализ» (`form/analysis`) и стандартной вьюхи редактора объекта (`form/object` с `allowTools: false`):
15
+ - **Расчёт сальдо «На начало» при выборе текущего периода в `oda-packets` (`sheet.js`, `postings.js`, `journal.js`, `oda/components/packets/packets.js`):**
16
+ 1. В `_syncPacketRange(res)` убран принудительный сброс `from`/`to` на «Весь период», когда начало выбранного периода лежит позже последней проводки в базе (`this.from > r.end`, например при выборе `4 кв. 2026 г.`, `Сегодня`, `Текущая неделя`, `Текущий месяц`, `Текущий квартал`): отчёт теперь сохраняет границы периода и выводит реальное входящее сальдо «На начало» и исходящее «На конец».
17
+ 2. В `_restorePeriodState` добавлено вычисление границ `_boundsFromPacketsKey` для ключей `now` / `now:*` / масок периодов, а в `oda-packets` добавлен наблюдатель `_onValueChanged` для внешней синхронизации `value`.
18
+ - **Навигация внутри `work-form` на вкладках справа в футере без создания новых `iframe` (`$server/$folder/handlers/pages/form/$handler/form.js`, `$server/$folder/lib/tools/tools.js`):**
19
+ 1. В `work-form` добавлен стек вкладок `formTabs` и метод `openInForm(targetItem, nav)`, перехватывающий переходы внутри формы (`window.execute`, переходы к счетам, подклассам и объектам).
20
+ 2. При открытии 2 и более экранов (`formTabs.length > 1`) справа на футере (`#formFooter`) отображается полоса вкладок `.form-tabs-bar` с мгновенным переключением и закрытием вкладок `×`.
21
+ 3. Из `#formFooter` убраны сервисные кнопки от `$item` самой формы (`#mainTools`) — сервисные кнопки отображаются строго от `$focusedItem` (`#focusedTools`), поэтому на представлениях счёта (`Обороты`, `Анализ`, `Проводки`) они не дублируются снизу.
22
+ - **Представление «Обороты» (`form/turnovers` в `postings.js`):**
23
+ 1. Выбор группировки (`Нет / Дни / Недели / Месяцы / Кварталы / Годы / Операции / Счета / Все`) перенесён компактным дропдауном (`<select title="Группировать">`) в верхнюю полосу `.filter-strip`, боковая панель `.group-panel` убрана.
24
+ 2. В правой таблице документов (`.docs-panel`) последним полем добавлена узкая колонка с кнопкой-иконкой проводки (`icons:list` без текста) для открытия карточки проводки.
25
+ - **Представление «Анализ» (`form/analysis` в `postings.js`, `sources/data/api.js` → `buildCatalogAnalyticFields`):**
26
+ 1. В `db_schema` (`schemaSubtree`) для каждого аналитического слота счёта собираются поля прилинкованного справочника (`Наименование` + поля схемы `$catalog`, вложенных структур `$struct` и `OVERLAY` у `$virtual`) с реально существующими значениями `options`.
27
+ 2. Слева на вьюхе «Анализ» вместо устаревших карточек слотов оформлена панель аналитических признаков (`Аналитика | Значение`) с выбором значений полей справочника (`setFeatureValue`) и перестановкой порядка `↑↓` (`moveFeature`), а строка быстрого фильтра встроена под шапкой таблицы без лишней верхней панели `.analysis-toolbar`.
28
+ - **Стандартная вьюха редактора объекта (`$server/$folder/$class/handlers/pages/form/object/$handler/{class.js,object.js}`, `objects.js`, `form.js`):**
29
+ 1. Создан штатный хендлер представления объекта `form/object` с атрибутом `allowTools: false`, отключающим верхний тулбар хендлеров в `work-form`.
30
+ 2. Вьюха `item-object` рендерится прямо в `work-form` на вкладке (с сервисными кнопками `Провести / Проведен / Отменить`, `Печать`, `Удалить / Восстановить` слева в подвале и кнопками `OK / 💾 / Закрыть` справа в подвале).
31
+ - [12:00, 29.10] Обновление лицензионного сервера `work.odant.org` (`work-license-server@1.0.1`), витрины ПАК **ODANT-WORK** (`odant-work@1.0.1`), интерактивной карты регионов РФ и панели администратора (`/admin`):
32
+ - **Брендинг и паспорт комплекса ODANT-WORK (`license-server/src/catalog.js`, `sources/modules/license/index.js`, `form/license`):**
33
+ 1. Фирменный логотип ODANT (`favicon.ico` → `/assets/odant-logo.png`), полное исключение упоминаний «1С» и брендов моделей на витрине (указаны типы и назначение 4 предустановленных локальных моделей: языковая LLM, голосовая ASR/TTS, генерация изображений, векторный поиск / RAG).
34
+ 2. Точная спецификация платформы **AMD Ryzen™ AI Max+ PRO 495** (Zen 5, 16 ядер / 32 потока, до 5,2 ГГц, 80 МБ кэша), **AMD Radeon™ 8065S Graphics** (40 ядер, 3000 МГц, до 61 TFLOPS FP16), **до 132 TOPS** (NPU 55 TOPS), **192 ГБ LPDDR5x-8533 Unified RAM**, **4 ТБ NVMe PCIe 4.0 SSD**, **AMD PRO / AMD Memory Guard**.
35
+ 3. Стоимость базового комплекса — `5 000 000 ₽` (включая вечную лицензию на `5` одновременных сессий и 1-й год поддержки), тарифы дополнительных годовых мест по SLA: **Start** — `10 000 ₽/год`, **Business** — `15 000 ₽/год`, **Enterprise** — `20 000 ₽/год` со скидкой от объёма до `−25%`; раздел «Докупка лицензий» доступен только авторизованным пользователям.
36
+ - **Вкладка «ИИ-агенты», интерактивная карта субъектов РФ и админ-панель `/admin` (`license-server/src/landing.js`, `assets/landing.css`, `assets/landing.js`, `assets/russia-regions.json`, `src/agent.js`):**
37
+ 1. Раздел **«ИИ-агенты»**: демонстрация встроенного ИИ-консультанта (кнопка `?` в каждой форме, полнодуплексный голосовой диалог, ролевые инструменты) и интерактивная орбитальная схема мультиагентной системы из `13` ролевых субагентов и `26+` навыков.
38
+ 2. **Интерактивная карта субъектов РФ (`assets/russia-regions.json`, `scripts/build-russia-map.mjs`):** 85 векторных контуров из OpenStreetMap в проекции Альберса с топологическим упрощением, фильтр по федеральным округам, масштабирование/перетаскивание, расчёт квот франшиз по населению, базового паушального взноса `500 000 ₽ × индекс региона`, резервирования со счётом ЮKassa на невозвратный залог `100 000 ₽` и полной оплаты паушального взноса в течение 1 года (`POST /api/partners/reserve`).
39
+ 3. **Админ-панель сервера лицензий (`/admin`, `#admin`):** сводные KPI, форма выпуска и подписи сертификатов `Ed25519` (`WORK-LIC-v1`), таблицы выпущенных лицензий с просмотром JSON-сертификата, заказов ЮKassa с проведением оплаты в один клик, резервов региональных франшиз / партнёров и тикетов техподдержки (`MAX`, `Telegram`, `VK`) с ответом инженера.
40
+ 4. Реквизиты разработчика **«Бизнес Интер Софт»** (`390000, г. Рязань, ул. Ленина, 47`, `+7 (4912) 77-70-21`, `+7 (4912) 77-70-22`, `odant.ru`), мягкий деловой анимированный фон, тёмная/светлая темы и публикация пакетов `odant-work@1.0.1` и `work-license-server@1.0.1` в npm.
4
41
  - [16:40, 28.10] Полнодуплексный диалоговый механизм с взаимным перебиванием (User Barge-In & AI Barge-In, как в ChatGPT Voice) в `.task`, `item-consultant` и `form/chat`:
5
42
  - **Мгновенное перебивание ИИ человеком (`sources/modules/agent/session.js`, `loop.js`, `index.js`, `ui/voice.js`, `ui/panel.js`, `ui/feed.js`):**
6
43
  1. В `session.prompt` добавлена поддержка `interrupt: true` и `spokenText`, а также отдельный метод `interrupt`: при перебивании (голосом в момент начала фразы или текстом в режиме диалога) активный стрим модели немедленно обрывается (`s.controller.abort('barge_in')`), ответ ассистента обрезается до реально прозвучавшей части (`spokenText`) с пометкой `interrupted: true` (`· прервано собеседником` в ленте и `[прервано собеседником]` в контексте `toMessages`), и цикл без паузы переключается на новую реплику человека.
@@ -2,10 +2,10 @@
2
2
  * Клиентский модуль лицензирования ПАК WORK (sources/modules/license/index.js).
3
3
  *
4
4
  * Отвечает за:
5
- * - паспорт программно-аппаратного комплекса (AMD Ryzen 495 8085, 192 ГБ RAM, SSD 4 ТБ)
5
+ * - паспорт программно-аппаратного комплекса (AMD Ryzen™ AI Max+ PRO 495, 192 ГБ RAM, SSD 4 ТБ)
6
6
  * и реестр предустановленных моделей ИИ (Qwen 3 30B + Голосовая + Генерация изображений + Embedding);
7
7
  * - хранение и криптографическую проверку сертификата лицензии Ed25519 (#system/license.json);
8
- * - учёт рабочих мест: 5 вечных (базовый комплект ПАК) + срочные годовые лицензии (Start / Business / Enterprise);
8
+ * - учёт рабочих мест: 10 вечных (базовый комплект ПАК + 1 год поддержки Enterprise) + срочные годовые лицензии по желанию (Start / Business / Enterprise);
9
9
  * - контроль лимита одновременных пользовательских сессий при входе в WORK;
10
10
  * - взаимодействие с лицензионным сервером https://work.odant.org (синхронизация, покупка через ЮKassa,
11
11
  * привязка ботов поддержки MAX, Telegram, VK).
@@ -21,54 +21,57 @@ export const LICENSE_PROTOCOL = 'WORK-LIC-v1';
21
21
  export const DEFAULT_LICENSE_HUB_URL = process.env.WORK_LICENSE_HUB_URL || 'https://work.odant.org';
22
22
  const LICENSE_FILE = './#system/license.json';
23
23
 
24
- /** Эталонная спецификация базового ПАК WORK. */
24
+ /** Эталонная спецификация базового комплекса ODANT-WORK. */
25
25
  export const PAK_HARDWARE_SPEC = Object.freeze({
26
26
  sku: 'WORK-PAK-495-192-4T',
27
- title: 'ПАК WORK AI-Server (Базовый комплект)',
28
- cpu: 'AMD Ryzen 495 8085',
27
+ title: 'ODANT-WORK (Программно-аппаратный комплекс)',
28
+ cpu: 'AMD Ryzen™ AI Max+ PRO 495 (16 ядер / 32 потока Zen 5, до 5.2 ГГц)',
29
+ gpu: 'AMD Radeon™ 8065S Graphics (40 ядер, 3000 МГц, до 61 TFLOPS FP16)',
30
+ npu: 'AMD Ryzen™ AI (до 132 TOPS общий ИИ / 55 TOPS NPU)',
31
+ ram: '192 ГБ 256-bit LPDDR5x-8533 Unified Memory',
29
32
  ramGb: 192,
33
+ ssd: 'SSD 4 ТБ NVMe PCIe 4.0 (RAID0/RAID1)',
30
34
  ssdTb: 4,
35
+ security: 'AMD PRO Technologies, AMD Memory Guard, AMD Secure Processor',
31
36
  basePriceRub: 5_000_000,
32
- baseSeats: 5,
37
+ baseSeats: 10,
33
38
  perpetualBase: true,
34
39
  includedSupportYears: 1,
35
- includedSupportTier: 'business',
36
- configuration: 'Типовая комплексная учётная конфигурация (аналог 1С: Предприятие — справочники, план счетов, двойная запись, ведомости, первичные документы, импорт 1С)',
40
+ includedSupportTier: 'enterprise',
41
+ postYearPolicy: 'Дальнейшее продление поддержки и докупка мест — по желанию (10 вечных лицензий работают бессрочно)',
42
+ modelsPolicy: 'Интегрированные локальные модели предназначены для базовых операций; более мощные ИИ можно подключать через API из любого источника',
43
+ configuration: 'Встроенная система учёта, документооборота, управления процессами и приватный мультимодальный ИИ (справочники, план счетов, двойная запись, ведомости, первичные документы, сквозные процессы и корпоративные коммуникации)',
37
44
  preinstalledModels: Object.freeze([
38
45
  {
39
46
  id: 'Qwen3-30B-A3B',
40
47
  category: 'llm',
41
- title: 'Qwen 3 30B',
42
- role: 'Основная языковая модель (диалог, ИИ-агент, учётные операции, аналитика, код)',
48
+ title: 'Большая языковая модель (LLM)',
49
+ role: 'Диалог, ведение учёта, документооборот, управление процессами, аналитика и генерация кода',
43
50
  path: '/MODELS/Local/Qwen3-30B-A3B',
44
- hfRepo: 'Qwen/Qwen3-30B-A3B',
45
51
  ramEstimateGb: 18.5,
46
52
  },
47
53
  {
48
54
  id: 'Qwen3-Voice',
49
55
  category: 'voice',
50
56
  title: 'Голосовая модель (ASR + TTS)',
51
- role: 'Полнодуплексный голосовой диалог с перебиванием, распознавание и синтез речи (Qwen3-ASR + Qwen3-TTS)',
57
+ role: 'Полнодуплексный голосовой диалог с перебиванием, распознавание и синтез естественной речи',
52
58
  path: '/MODELS/Local/Qwen3-Voice',
53
- hfRepo: 'Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign',
54
59
  ramEstimateGb: 4.2,
55
60
  },
56
61
  {
57
62
  id: 'Flux-Image',
58
63
  category: 'image',
59
- title: 'Генерация изображений',
64
+ title: 'Модель генерации изображений',
60
65
  role: 'Локальный синтез иллюстраций, карточек товаров, схем и визуальных материалов',
61
66
  path: '/MODELS/Local/Flux-Image',
62
- hfRepo: 'black-forest-labs/FLUX.1-schnell',
63
67
  ramEstimateGb: 12.0,
64
68
  },
65
69
  {
66
70
  id: 'Qwen3-Embedding',
67
71
  category: 'embedding',
68
- title: 'Embedding-модель (RAG)',
69
- role: 'Семантический векторный поиск по документам, договорам, проводкам и базе знаний',
72
+ title: 'Модель векторного поиска (Embedding / RAG)',
73
+ role: 'Семантический поиск и индексация договоров, первичных документов, проводок и базы знаний',
70
74
  path: '/MODELS/Local/Qwen3-Embedding',
71
- hfRepo: 'Qwen/Qwen3-Embedding-4B',
72
75
  ramEstimateGb: 2.5,
73
76
  },
74
77
  ]),
@@ -79,7 +82,7 @@ export const SUPPORT_TIERS = Object.freeze({
79
82
  start: Object.freeze({
80
83
  id: 'start',
81
84
  name: 'Start',
82
- pricePerUserYearRub: 15_000,
85
+ pricePerUserYearRub: 10_000,
83
86
  ticketsPerSeatYear: 12,
84
87
  reactionMinutes: 480,
85
88
  reactionText: 'до 8 рабочих часов',
@@ -90,24 +93,24 @@ export const SUPPORT_TIERS = Object.freeze({
90
93
  business: Object.freeze({
91
94
  id: 'business',
92
95
  name: 'Business',
93
- pricePerUserYearRub: 40_000,
96
+ pricePerUserYearRub: 15_000,
94
97
  ticketsPerSeatYear: 48,
95
98
  reactionMinutes: 120,
96
99
  reactionText: 'до 2 часов',
97
100
  scheduleText: '7 дней в неделю (08:00–22:00 МСК)',
98
101
  channels: ['MAX', 'Telegram', 'VK'],
99
- description: 'Бизнес-поддержка: до 48 обращений в год на место, время реакции до 2 часов, помощь по настройке учёта и локальных моделей.',
102
+ description: 'Бизнес-поддержка: до 48 обращений в год на место, время реакции до 2 часов, помощь по настройке учёта, процессов и моделей ИИ.',
100
103
  }),
101
104
  enterprise: Object.freeze({
102
105
  id: 'enterprise',
103
106
  name: 'Enterprise',
104
- pricePerUserYearRub: 100_000,
107
+ pricePerUserYearRub: 20_000,
105
108
  ticketsPerSeatYear: 9999,
106
109
  reactionMinutes: 15,
107
110
  reactionText: 'до 15 минут (24/7)',
108
111
  scheduleText: '24/7/365 (круглосуточно)',
109
112
  channels: ['MAX', 'Telegram', 'VK', 'Выделенный инженер'],
110
- description: 'Приоритетная поддержка 24/7: безлимитные обращения, реакция до 15 минут, персональный инженер и помощь в дообучении моделей (LoRA).',
113
+ description: 'Приоритетная поддержка 24/7: безлимитные обращения, реакция до 15 минут, персональный инженер и помощь в дообучении моделей.',
111
114
  }),
112
115
  });
113
116
 
@@ -300,8 +303,8 @@ export function evaluateLicenseState(lic = loadLocalLicense(), now = Date.now())
300
303
  const baseSupportActive = baseSupportUntil > now;
301
304
 
302
305
  if (baseSupportActive) {
303
- const baseTierKey = String(lic.support?.tier || PAK_HARDWARE_SPEC.includedSupportTier || 'business').toLowerCase();
304
- const baseTierSpec = SUPPORT_TIERS[baseTierKey] || SUPPORT_TIERS.business;
306
+ const baseTierKey = String(lic.support?.tier || PAK_HARDWARE_SPEC.includedSupportTier || 'enterprise').toLowerCase();
307
+ const baseTierSpec = SUPPORT_TIERS[baseTierKey] || SUPPORT_TIERS.enterprise;
305
308
  highestTier = baseTierKey;
306
309
  totalTicketsQuota += baseSeats * baseTierSpec.ticketsPerSeatYear;
307
310
  nearestExpiry = baseSupportUntil;