chore: normalize MCP widgets and remove legacy artifacts

This commit is contained in:
2026-09-09 07:32:12 +03:00
parent 8579bef3fd
commit 11b97c7e86
36 changed files with 108 additions and 697 deletions
@@ -1,9 +1,9 @@
--- ---
name: shd-project-db-audit name: shd-airbase-audit
description: Use when the user asks to inspect ProjectBase tables, validate project data, find duplicate or broken links, or audit ProjectBase quality without changing records. description: Use when the user asks to inspect AirBase tables, validate project data, find duplicate or broken links, or audit AirBase quality without changing records.
--- ---
# ProjectBase audit # AirBase audit
See `references/audit-contract.md` for the bounded read and evidence format. See `references/audit-contract.md` for the bounded read and evidence format.
@@ -12,11 +12,11 @@ See `references/audit-contract.md` for the bounded read and evidence format.
1. Resolve the canonical Base identity. A supplied `project_code` is accepted 1. Resolve the canonical Base identity. A supplied `project_code` is accepted
as the legacy alias only when the server accepts it; prefer the returned as the legacy alias only when the server accepts it; prefer the returned
Base identity for subsequent calls. Base identity for subsequent calls.
2. If no table is named, call `shd_project_db_tables` first and select only the 2. If no table is named, call `shd_airbase_tables` first and select only the
relevant tables. Do not load every table by default. relevant tables. Do not load every table by default.
3. Call `shd_project_db_schema` for each selected table before reading its 3. Call `shd_airbase_schema` for each selected table before reading its
records. Pass the table explicitly when a single-table audit is requested. records. Pass the table explicitly when a single-table audit is requested.
4. Call `shd_project_db_records` with bounded reads and the selected table. 4. Call `shd_airbase_records` with bounded reads and the selected table.
5. Compare records with the returned schema and report only evidence visible in 5. Compare records with the returned schema and report only evidence visible in
the response. the response.
@@ -1,5 +1,5 @@
interface: interface:
display_name: ProjectBase audit display_name: AirBase audit
short_description: Read-only schema and data audit short_description: Read-only schema and data audit
policy: policy:
allow_implicit_invocation: false allow_implicit_invocation: false
@@ -1,6 +1,6 @@
# ProjectBase audit contract # AirBase audit contract
Use this contract for every read-only ProjectBase audit. Use this contract for every read-only AirBase audit.
1. Resolve the canonical Base identity before selecting tables. Treat a 1. Resolve the canonical Base identity before selecting tables. Treat a
user-provided project code as an alias until the server returns the user-provided project code as an alias until the server returns the
@@ -10,8 +10,8 @@ description: Use when the user asks to inspect, compare, validate, create or upd
1. Resolve the project, proposal, terms document or contract before acting. 1. Resolve the project, proposal, terms document or contract before acting.
2. Use `shd_list_proposals` and `shd_get_proposal` for proposal registers and 2. Use `shd_list_proposals` and `shd_get_proposal` for proposal registers and
details. details.
3. Use `shd_list_terms_documents`, `shd_get_terms_document`, 3. Use `shd_list_contracts`, `shd_get_contract`,
`shd_get_terms_document_completeness` and `shd_validate_terms_document` for `shd_get_pdf_scheme_editor_completeness` and `shd_validate_pdf_scheme_editor_document` for
terms and completeness checks. terms and completeness checks.
4. Inspect template capabilities before proposing a template-driven change. 4. Inspect template capabilities before proposing a template-driven change.
5. Report line items, versions, completeness, approvals and publication state 5. Report line items, versions, completeness, approvals and publication state
@@ -13,8 +13,8 @@ readback. Do not invent fields, statuses, identifiers, routes or capabilities.
- Project list, project status, deadlines or project context: use the Projects - Project list, project status, deadlines or project context: use the Projects
Core tools and the `shd-active-projects` or `shd-project-status` workflow. Core tools and the `shd-active-projects` or `shd-project-status` workflow.
- ProjectBase schema, records, links or data quality: use Project DB tools and - AirBase schema, records, links or data quality: use AirBase tools and
the `shd-project-db-audit` workflow. the `shd-airbase-audit` workflow.
- Tasks, task projects, task status or task dates: use Tasks tools and the - Tasks, task projects, task status or task dates: use Tasks tools and the
`shd-task-workflow` workflow. `shd-task-workflow` workflow.
- Project files and paths: use Files tools and the `shd-project-files` workflow. - Project files and paths: use Files tools and the `shd-project-files` workflow.
@@ -11,10 +11,10 @@ description: Use before any SHD bulk create, update, import, archive, delete, or
intended side effect. intended side effect.
2. Read current schemas and records. Estimate affected, skipped, invalid and 2. Read current schemas and records. Estimate affected, skipped, invalid and
ambiguous rows. ambiguous rows.
3. Prefer a server validation or dry-run operation. For ProjectBase use 3. Prefer a server validation or dry-run operation. For AirBase use
`shd_project_db_validate_records`, then `shd_airbase_validate_records`, then
`shd_project_db_bulk_create_records` or `shd_airbase_bulk_create_records` or
`shd_project_db_bulk_upsert_records` with `dry_run: true` when applicable. `shd_airbase_bulk_upsert_records` with `dry_run: true` when applicable.
4. Present the plan and stop unless the user explicitly authorized execution. 4. Present the plan and stop unless the user explicitly authorized execution.
## Execute safely ## Execute safely
@@ -0,0 +1 @@
950024eb11a0b54dad7af732d24c44aba4796392ade66bbf6d5f96f9eeab3c35 index.html
@@ -0,0 +1,5 @@
# AirBase preview widget
This artifact is served by the SHD MCP backend as ui://shd/airbase-preview/v1.html.
The HTML is standalone, uses the MCP Apps bridge first, and keeps window.openai as a compatibility extension. It has no external script or network dependency. The widget provides a read-only AirBase table record preview.
@@ -38,7 +38,7 @@
</style> </style>
</head> </head>
<body> <body>
<main class="shell" data-widget-module="project-db-preview"><section class="card"> <main class="shell" data-widget-module="airbase-preview"><section class="card">
<div class="eyebrow">SHD MCP</div><h1 id="title">SHD</h1><p class="lede" id="desc"></p><div class="summary" id="summary"></div> <div class="eyebrow">SHD MCP</div><h1 id="title">SHD</h1><p class="lede" id="desc"></p><div class="summary" id="summary"></div>
<div class="toolbar"><input class="search" id="search" type="search" autocomplete="off"><button class="refresh" id="refresh" type="button"></button></div> <div class="toolbar"><input class="search" id="search" type="search" autocomplete="off"><button class="refresh" id="refresh" type="button"></button></div>
<div class="status" id="status" role="status" aria-live="polite"></div> <div class="status" id="status" role="status" aria-live="polite"></div>
@@ -48,7 +48,7 @@
<script> <script>
(function(){ (function(){
'use strict'; 'use strict';
var DEFAULT_MODULE='project-db-preview'; var DEFAULT_MODULE='airbase-preview';
var C={ru:{refresh:'Обновить',search:'Поиск по названию, статусу или ID',loading:'Загрузка…',empty:'Нет данных для отображения.',records:'записей',status:'Статус',date:'Дата',value:'Детали',id:'ID',details:'Детали',close:'Закрыть',load:'Не удалось загрузить данные.',detail:'Не удалось загрузить детали.',context:'Для обновления нужен контекст источника',total:'Всего',amount:'Сумма',planned:'План',capacity:'Ёмкость',utilization:'Загрузка',overload:'Перегрузка',warnings:'Предупреждения',complete:'Готово',pending:'Ожидают',approved:'Согласовано',rejected:'Отклонено',progress:'Прогресс',score:'Оценка',member:'Участник',role:'Роль',permissions:'Разрешения',preview:'Предпросмотр',noWarnings:'Предупреждений нет.',health:'Состояние',yes:'Да',no:'Нет'},en:{refresh:'Refresh',search:'Search by name, status or ID',loading:'Loading…',empty:'No data to display.',records:'records',status:'Status',date:'Date',value:'Details',id:'ID',details:'Details',close:'Close',load:'Could not load data.',detail:'Could not load details.',context:'A source context is required to refresh.',total:'Total',amount:'Amount',planned:'Planned',capacity:'Capacity',utilization:'Utilization',overload:'Overload',warnings:'Warnings',complete:'Complete',pending:'Pending',approved:'Approved',rejected:'Rejected',progress:'Progress',score:'Score',member:'Member',role:'Role',permissions:'Permissions',preview:'Preview',noWarnings:'No warnings.',health:'Health',yes:'Yes',no:'No'}}; var C={ru:{refresh:'Обновить',search:'Поиск по названию, статусу или ID',loading:'Загрузка…',empty:'Нет данных для отображения.',records:'записей',status:'Статус',date:'Дата',value:'Детали',id:'ID',details:'Детали',close:'Закрыть',load:'Не удалось загрузить данные.',detail:'Не удалось загрузить детали.',context:'Для обновления нужен контекст источника',total:'Всего',amount:'Сумма',planned:'План',capacity:'Ёмкость',utilization:'Загрузка',overload:'Перегрузка',warnings:'Предупреждения',complete:'Готово',pending:'Ожидают',approved:'Согласовано',rejected:'Отклонено',progress:'Прогресс',score:'Оценка',member:'Участник',role:'Роль',permissions:'Разрешения',preview:'Предпросмотр',noWarnings:'Предупреждений нет.',health:'Состояние',yes:'Да',no:'Нет'},en:{refresh:'Refresh',search:'Search by name, status or ID',loading:'Loading…',empty:'No data to display.',records:'records',status:'Status',date:'Date',value:'Details',id:'ID',details:'Details',close:'Close',load:'Could not load data.',detail:'Could not load details.',context:'A source context is required to refresh.',total:'Total',amount:'Amount',planned:'Planned',capacity:'Capacity',utilization:'Utilization',overload:'Overload',warnings:'Warnings',complete:'Complete',pending:'Pending',approved:'Approved',rejected:'Rejected',progress:'Progress',score:'Score',member:'Member',role:'Role',permissions:'Permissions',preview:'Preview',noWarnings:'No warnings.',health:'Health',yes:'Yes',no:'No'}};
var FIELD_LABELS={ru:{id:'ID',key:'Ключ',project_id:'ID проекта',task_project_id:'ID проекта задачи',linked_project_ids:'Связанные проекты',project_code:'Код проекта',base_reference:'Ссылка на базу',base_public_id:'Публичный ID базы',table_public_id:'Публичный ID таблицы',record_public_id:'Публичный ID записи',title:'Название',name:'Название',description:'Описание',status:'Статус',status_id:'ID статуса',is_done:'Завершено',is_complete:'Завершено',section:'Раздел',sort_order:'Порядок сортировки',created_at:'Создано',updated_at:'Обновлено',due_date:'Срок',deadline:'Дедлайн',starts_at:'Начало',ends_at:'Окончание',url:'Ссылка',diagnostic:'Диагностика',message:'Сообщение',type:'Тип',state:'Состояние',phase:'Этап',health:'Состояние',email:'Электронная почта',username:'Имя пользователя',role:'Роль',permissions:'Разрешения',source:'Источник',module:'Модуль',table:'Таблица',fields:'Поля',value:'Значение',stage:'Стадия',approval_status:'Статус согласования',approval_state:'Состояние согласования',priority:'Приоритет',assignee:'Исполнитель',owner:'Владелец',type:'Тип',category:'Категория',permissions:'Разрешения',permission:'Разрешение',read:'Чтение',write:'Запись',manage:'Управление',admin:'Администратор',view:'Просмотр',create:'Создание',update:'Изменение',delete:'Удаление',error:'Ошибка',warning:'Предупреждение',message:'Сообщение',path:'Путь',link:'Ссылка',amount:'Сумма',total:'Итого',quantity:'Количество',available_quantity:'Доступное количество',stock:'Остаток',planned:'План',planned_hours:'Плановые часы',capacity:'Ёмкость',capacity_hours:'Часы ёмкости',utilization:'Загрузка',utilization_percent:'Загрузка, %',overload:'Перегрузка',overload_hours:'Часы перегрузки',score:'Оценка',progress:'Прогресс',completeness_score:'Оценка полноты',completion_percent:'Полнота, %',availability_percent:'Доступность, %',record_count:'Количество записей',revision:'Ревизия',pages:'Страницы',page_count:'Количество страниц',date:'Дата',is_archived:'В архиве',low_stock:'Мало на складе',critical:'Критический',meta:'Метаданные'},en:{id:'ID',key:'Key',project_id:'Project ID',task_project_id:'Task project ID',linked_project_ids:'Linked projects',project_code:'Project code',base_reference:'Base reference',base_public_id:'Public base ID',table_public_id:'Public table ID',record_public_id:'Public record ID',title:'Title',name:'Name',description:'Description',status:'Status',status_id:'Status ID',is_done:'Completed',is_complete:'Completed',section:'Section',sort_order:'Sort order',created_at:'Created',updated_at:'Updated',due_date:'Due date',deadline:'Deadline',starts_at:'Starts',ends_at:'Ends',url:'URL',diagnostic:'Diagnostics',message:'Message',type:'Type',state:'State',phase:'Phase',health:'Health',email:'Email',username:'Username',role:'Role',permissions:'Permissions',source:'Source',module:'Module',table:'Table',fields:'Fields',value:'Value',stage:'Stage',approval_status:'Approval status',approval_state:'Approval state',priority:'Priority',assignee:'Assignee',owner:'Owner',type:'Type',category:'Category',permissions:'Permissions',permission:'Permission',read:'Read',write:'Write',manage:'Manage',admin:'Admin',view:'View',create:'Create',update:'Update',delete:'Delete',error:'Error',warning:'Warning',message:'Message',path:'Path',link:'Link',amount:'Amount',total:'Total',quantity:'Quantity',available_quantity:'Available quantity',stock:'Stock',planned:'Planned',planned_hours:'Planned hours',capacity:'Capacity',capacity_hours:'Capacity hours',utilization:'Utilization',utilization_percent:'Utilization, %',overload:'Overload',overload_hours:'Overload hours',score:'Score',progress:'Progress',completeness_score:'Completeness score',completion_percent:'Completeness, %',availability_percent:'Availability, %',record_count:'Record count',revision:'Revision',pages:'Pages',page_count:'Page count',date:'Date',is_archived:'Archived',low_stock:'Low stock',critical:'Critical',meta:'Metadata'}}; var FIELD_LABELS={ru:{id:'ID',key:'Ключ',project_id:'ID проекта',task_project_id:'ID проекта задачи',linked_project_ids:'Связанные проекты',project_code:'Код проекта',base_reference:'Ссылка на базу',base_public_id:'Публичный ID базы',table_public_id:'Публичный ID таблицы',record_public_id:'Публичный ID записи',title:'Название',name:'Название',description:'Описание',status:'Статус',status_id:'ID статуса',is_done:'Завершено',is_complete:'Завершено',section:'Раздел',sort_order:'Порядок сортировки',created_at:'Создано',updated_at:'Обновлено',due_date:'Срок',deadline:'Дедлайн',starts_at:'Начало',ends_at:'Окончание',url:'Ссылка',diagnostic:'Диагностика',message:'Сообщение',type:'Тип',state:'Состояние',phase:'Этап',health:'Состояние',email:'Электронная почта',username:'Имя пользователя',role:'Роль',permissions:'Разрешения',source:'Источник',module:'Модуль',table:'Таблица',fields:'Поля',value:'Значение',stage:'Стадия',approval_status:'Статус согласования',approval_state:'Состояние согласования',priority:'Приоритет',assignee:'Исполнитель',owner:'Владелец',type:'Тип',category:'Категория',permissions:'Разрешения',permission:'Разрешение',read:'Чтение',write:'Запись',manage:'Управление',admin:'Администратор',view:'Просмотр',create:'Создание',update:'Изменение',delete:'Удаление',error:'Ошибка',warning:'Предупреждение',message:'Сообщение',path:'Путь',link:'Ссылка',amount:'Сумма',total:'Итого',quantity:'Количество',available_quantity:'Доступное количество',stock:'Остаток',planned:'План',planned_hours:'Плановые часы',capacity:'Ёмкость',capacity_hours:'Часы ёмкости',utilization:'Загрузка',utilization_percent:'Загрузка, %',overload:'Перегрузка',overload_hours:'Часы перегрузки',score:'Оценка',progress:'Прогресс',completeness_score:'Оценка полноты',completion_percent:'Полнота, %',availability_percent:'Доступность, %',record_count:'Количество записей',revision:'Ревизия',pages:'Страницы',page_count:'Количество страниц',date:'Дата',is_archived:'В архиве',low_stock:'Мало на складе',critical:'Критический',meta:'Метаданные'},en:{id:'ID',key:'Key',project_id:'Project ID',task_project_id:'Task project ID',linked_project_ids:'Linked projects',project_code:'Project code',base_reference:'Base reference',base_public_id:'Public base ID',table_public_id:'Public table ID',record_public_id:'Public record ID',title:'Title',name:'Name',description:'Description',status:'Status',status_id:'Status ID',is_done:'Completed',is_complete:'Completed',section:'Section',sort_order:'Sort order',created_at:'Created',updated_at:'Updated',due_date:'Due date',deadline:'Deadline',starts_at:'Starts',ends_at:'Ends',url:'URL',diagnostic:'Diagnostics',message:'Message',type:'Type',state:'State',phase:'Phase',health:'Health',email:'Email',username:'Username',role:'Role',permissions:'Permissions',source:'Source',module:'Module',table:'Table',fields:'Fields',value:'Value',stage:'Stage',approval_status:'Approval status',approval_state:'Approval state',priority:'Priority',assignee:'Assignee',owner:'Owner',type:'Type',category:'Category',permissions:'Permissions',permission:'Permission',read:'Read',write:'Write',manage:'Manage',admin:'Admin',view:'View',create:'Create',update:'Update',delete:'Delete',error:'Error',warning:'Warning',message:'Message',path:'Path',link:'Link',amount:'Amount',total:'Total',quantity:'Quantity',available_quantity:'Available quantity',stock:'Stock',planned:'Planned',planned_hours:'Planned hours',capacity:'Capacity',capacity_hours:'Capacity hours',utilization:'Utilization',utilization_percent:'Utilization, %',overload:'Overload',overload_hours:'Overload hours',score:'Score',progress:'Progress',completeness_score:'Completeness score',completion_percent:'Completeness, %',availability_percent:'Availability, %',record_count:'Record count',revision:'Revision',pages:'Pages',page_count:'Page count',date:'Date',is_archived:'Archived',low_stock:'Low stock',critical:'Critical',meta:'Metadata'}};
var VALUE_LABELS={ru:{Tasks_Status_Todo:'К выполнению',Tasks_Status_Done:'Завершено',Tasks_Status_In_Progress:'В работе',Tasks_Status_Review:'На проверке',Modules_Done:'Завершено',todo:'К выполнению',to_do:'К выполнению','to do':'К выполнению',in_progress:'В работе','in progress':'В работе','in-progress':'В работе',in_progress_status:'В работе',done:'Завершено',completed:'Завершено',complete:'Завершено',closed:'Закрыто',active:'Активно',pending:'Ожидает',review:'На проверке',approved:'Согласовано',rejected:'Отклонено',archived:'В архиве',not_set:'Не задано'},en:{Tasks_Status_Todo:'To do',Tasks_Status_Done:'Done',Tasks_Status_In_Progress:'In progress',Tasks_Status_Review:'In review',Modules_Done:'Done',todo:'To do',to_do:'To do','to do':'To do',in_progress:'In progress','in progress':'In progress','in-progress':'In progress',in_progress_status:'In progress',done:'Done',completed:'Completed',complete:'Complete',closed:'Closed',active:'Active',pending:'Pending',review:'In review',approved:'Approved',rejected:'Rejected',archived:'Archived',not_set:'Not set'}}; var VALUE_LABELS={ru:{Tasks_Status_Todo:'К выполнению',Tasks_Status_Done:'Завершено',Tasks_Status_In_Progress:'В работе',Tasks_Status_Review:'На проверке',Modules_Done:'Завершено',todo:'К выполнению',to_do:'К выполнению','to do':'К выполнению',in_progress:'В работе','in progress':'В работе','in-progress':'В работе',in_progress_status:'В работе',done:'Завершено',completed:'Завершено',complete:'Завершено',closed:'Закрыто',active:'Активно',pending:'Ожидает',review:'На проверке',approved:'Согласовано',rejected:'Отклонено',archived:'В архиве',not_set:'Не задано'},en:{Tasks_Status_Todo:'To do',Tasks_Status_Done:'Done',Tasks_Status_In_Progress:'In progress',Tasks_Status_Review:'In review',Modules_Done:'Done',todo:'To do',to_do:'To do','to do':'To do',in_progress:'In progress','in progress':'In progress','in-progress':'In progress',in_progress_status:'In progress',done:'Done',completed:'Completed',complete:'Complete',closed:'Closed',active:'Active',pending:'Pending',review:'In review',approved:'Approved',rejected:'Rejected',archived:'Archived',not_set:'Not set'}};
@@ -59,7 +59,7 @@
inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']}, inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']},
agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']}, agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']},
'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']}, 'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']},
'project-db':{ru:['Project DB','Каталог таблиц Project DB с просмотром схемы.','Таблица','Обновлено','Записей'],en:['Project DB','Project DB table catalog with schema details.','Table','Updated','Records']}, 'airbase':{ru:['AirBase','Каталог таблиц AirBase с просмотром схемы.','Таблица','Обновлено','Записей'],en:['AirBase','AirBase table catalog with schema details.','Table','Updated','Records']},
notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']}, notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']},
'project-overview':{ru:['Обзор проекта','Сводные данные по разделам выбранного проекта.','Раздел','Обновлено','Элементы'],en:['Project overview','Cross-module records for the selected project.','Section','Updated','Items']}, 'project-overview':{ru:['Обзор проекта','Сводные данные по разделам выбранного проекта.','Раздел','Обновлено','Элементы'],en:['Project overview','Cross-module records for the selected project.','Section','Updated','Items']},
files:{ru:['Файлы','Файлы выбранного проекта с поиском и безопасным просмотром ссылок.','Файл','Обновлено','Размер или тип'],en:['Files','Files from the selected project with search and safe links.','File','Updated','Size or type']}, files:{ru:['Файлы','Файлы выбранного проекта с поиском и безопасным просмотром ссылок.','Файл','Обновлено','Размер или тип'],en:['Files','Files from the selected project with search and safe links.','File','Updated','Size or type']},
@@ -83,7 +83,7 @@
'gitea-board':{ru:['Gitea-доска','Issues по состояниям разрешённого репозитория.','Issue','Состояние','Ссылка'],en:['Gitea board','Issues grouped by state for an allowed repository.','Issue','State','Link']}, 'gitea-board':{ru:['Gitea-доска','Issues по состояниям разрешённого репозитория.','Issue','Состояние','Ссылка'],en:['Gitea board','Issues grouped by state for an allowed repository.','Issue','State','Link']},
'schemes-progress':{ru:['Прогресс схем','Документы схем, ревизии, страницы и completeness.','Схема','Обновлено','Прогресс'],en:['Schemes progress','Scheme documents, revisions, pages and completeness.','Scheme','Updated','Progress']}, 'schemes-progress':{ru:['Прогресс схем','Документы схем, ревизии, страницы и completeness.','Схема','Обновлено','Прогресс'],en:['Schemes progress','Scheme documents, revisions, pages and completeness.','Scheme','Updated','Progress']},
'notes-tree':{ru:['Дерево Notes','Пространства Notes и их иерархия.','Узел','Обновлено','Тип'],en:['Notes tree','Notes spaces and their hierarchy.','Node','Updated','Type']}, 'notes-tree':{ru:['Дерево Notes','Пространства Notes и их иерархия.','Узел','Обновлено','Тип'],en:['Notes tree','Notes spaces and their hierarchy.','Node','Updated','Type']},
'project-db-preview':{ru:['Project DB preview','Предпросмотр записей выбранной таблицы Project DB.','Запись','Обновлено','Поля'],en:['Project DB preview','Preview of records from the selected Project DB table.','Record','Updated','Fields']} 'airbase-preview':{ru:['AirBase preview','Предпросмотр записей выбранной таблицы AirBase.','Запись','Обновлено','Поля'],en:['AirBase preview','Preview of records from the selected AirBase table.','Record','Updated','Fields']}
}; };
var S={ var S={
discussions:{listTool:'shd_list_discussion_topics',listArgs:{limit:100},readTool:'shd_list_discussion_messages',detailKey:'topic_id',detailArgs:{limit:50},paths:['data'],sort:'desc'}, discussions:{listTool:'shd_list_discussion_topics',listArgs:{limit:100},readTool:'shd_list_discussion_messages',detailKey:'topic_id',detailArgs:{limit:50},paths:['data'],sort:'desc'},
@@ -92,7 +92,7 @@
inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'}, inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'},
agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'}, agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'},
'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'}, 'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'},
'project-db':{listTool:'shd_project_db_tables',listArgs:{},readTool:'shd_project_db_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'}, 'airbase':{listTool:'shd_airbase_tables',listArgs:{},readTool:'shd_airbase_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'},
notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'}, notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'},
'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'}, 'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'},
files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'}, files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'},
@@ -116,7 +116,7 @@
'gitea-board':{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],view:'kanban',groupBy:'state',sort:'asc'}, 'gitea-board':{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],view:'kanban',groupBy:'state',sort:'asc'},
'schemes-progress':{listTool:'shd_list_scheme_documents',readTool:'shd_get_scheme_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],view:'progress',contextRequired:true,contextKeys:['project'],sort:'desc'}, 'schemes-progress':{listTool:'shd_list_scheme_documents',readTool:'shd_get_scheme_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],view:'progress',contextRequired:true,contextKeys:['project'],sort:'desc'},
'notes-tree':{listTool:'shd_list_note_spaces',listArgs:{limit:100},readTool:'shd_get_note_space_tree',detailKey:'space_id',detailSourceArgs:[],paths:['data'],view:'tree',sort:'asc'}, 'notes-tree':{listTool:'shd_list_note_spaces',listArgs:{limit:100},readTool:'shd_get_note_space_tree',detailKey:'space_id',detailSourceArgs:[],paths:['data'],view:'tree',sort:'asc'},
'project-db-preview':{listTool:'shd_project_db_records',listArgs:{limit:100,include_fields:true,include_view_meta:true},paths:['data.records','data'],view:'preview',contextRequired:true,contextSets:[['base','project_code'],['table']],sort:'asc'} 'airbase-preview':{listTool:'shd_airbase_records',listArgs:{limit:100,include_fields:true,include_view_meta:true},paths:['data.records','data'],view:'preview',contextRequired:true,contextSets:[['base','project_code'],['table']],sort:'asc'}
}; };
var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false}; var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false};
var e={title:document.getElementById('title'),desc:document.getElementById('desc'),search:document.getElementById('search'),refresh:document.getElementById('refresh'),status:document.getElementById('status'),summary:document.getElementById('summary'),tableWrap:document.querySelector('.table-wrap'),visual:document.getElementById('visual'),rows:document.getElementById('rows'),empty:document.getElementById('empty'),details:document.getElementById('details'),detailTitle:document.getElementById('detail-title'),detailSub:document.getElementById('detail-sub'),grid:document.getElementById('grid'),close:document.getElementById('close'),ht:document.getElementById('head-title'),hs:document.getElementById('head-status'),hd:document.getElementById('head-date'),hv:document.getElementById('head-value')}; var e={title:document.getElementById('title'),desc:document.getElementById('desc'),search:document.getElementById('search'),refresh:document.getElementById('refresh'),status:document.getElementById('status'),summary:document.getElementById('summary'),tableWrap:document.querySelector('.table-wrap'),visual:document.getElementById('visual'),rows:document.getElementById('rows'),empty:document.getElementById('empty'),details:document.getElementById('details'),detailTitle:document.getElementById('detail-title'),detailSub:document.getElementById('detail-sub'),grid:document.getElementById('grid'),close:document.getElementById('close'),ht:document.getElementById('head-title'),hs:document.getElementById('head-status'),hd:document.getElementById('head-date'),hv:document.getElementById('head-value')};
@@ -0,0 +1,20 @@
{
"schemaVersion": 1,
"name": "shd-airbase-preview",
"version": "1.0.0",
"resources": [
{
"file": "index.html",
"bytes": 76344,
"gzipBytes": 20466,
"mediaType": "text/html;profile=mcp-app",
"uri": "ui://shd/airbase-preview/v1.html",
"sha256": "950024eb11a0b54dad7af732d24c44aba4796392ade66bbf6d5f96f9eeab3c35"
}
],
"license": "../../../../../LICENSE",
"source": {
"repository": "https://github.com/bulava92/shd-mcp-plugin",
"path": "plugins/shd-mcp-plugin/widgets/airbase-preview/v1/index.html"
}
}
@@ -0,0 +1 @@
093206d0369e0ce87e779f72cd22aa626b5d27d65fb6e814513534d77d0164f6 index.html
@@ -1,5 +1,5 @@
# Project DB widget # AirBase widget
This artifact is served by the SHD MCP backend as `ui://shd/project-db/v1.html`. This artifact is served by the SHD MCP backend as `ui://shd/airbase/v1.html`.
The HTML is standalone, uses the MCP Apps bridge first, and keeps `window.openai` as a compatibility extension. It has no external script or network dependency. The widget provides table catalog and read-only schema details. The HTML is standalone, uses the MCP Apps bridge first, and keeps `window.openai` as a compatibility extension. It has no external script or network dependency. The widget provides table catalog and read-only schema details.
@@ -37,7 +37,7 @@
</style> </style>
</head> </head>
<body> <body>
<main class="shell" data-widget-module="project-db"><section class="card"> <main class="shell" data-widget-module="airbase"><section class="card">
<div class="eyebrow">SHD MCP</div><h1 id="title">SHD</h1><p class="lede" id="desc"></p><div class="summary" id="summary"></div> <div class="eyebrow">SHD MCP</div><h1 id="title">SHD</h1><p class="lede" id="desc"></p><div class="summary" id="summary"></div>
<div class="toolbar"><input class="search" id="search" type="search" autocomplete="off"><button class="refresh" id="refresh" type="button"></button></div> <div class="toolbar"><input class="search" id="search" type="search" autocomplete="off"><button class="refresh" id="refresh" type="button"></button></div>
<div class="status" id="status" role="status" aria-live="polite"></div> <div class="status" id="status" role="status" aria-live="polite"></div>
@@ -47,7 +47,7 @@
<script> <script>
(function(){ (function(){
'use strict'; 'use strict';
var DEFAULT_MODULE='project-db'; var DEFAULT_MODULE='airbase';
var C={ru:{refresh:'Обновить',search:'Поиск по названию, статусу или ID',loading:'Загрузка…',empty:'Нет данных для отображения.',records:'записей',status:'Статус',date:'Дата',value:'Детали',id:'ID',details:'Детали',close:'Закрыть',load:'Не удалось загрузить данные.',detail:'Не удалось загрузить детали.',context:'Для обновления нужен контекст проекта или базы',yes:'Да',no:'Нет'},en:{refresh:'Refresh',search:'Search by name, status or ID',loading:'Loading…',empty:'No data to display.',records:'records',status:'Status',date:'Date',value:'Details',id:'ID',details:'Details',close:'Close',load:'Could not load data.',detail:'Could not load details.',context:'A project or base context is required to refresh.',yes:'Yes',no:'No'}}; var C={ru:{refresh:'Обновить',search:'Поиск по названию, статусу или ID',loading:'Загрузка…',empty:'Нет данных для отображения.',records:'записей',status:'Статус',date:'Дата',value:'Детали',id:'ID',details:'Детали',close:'Закрыть',load:'Не удалось загрузить данные.',detail:'Не удалось загрузить детали.',context:'Для обновления нужен контекст проекта или базы',yes:'Да',no:'Нет'},en:{refresh:'Refresh',search:'Search by name, status or ID',loading:'Loading…',empty:'No data to display.',records:'records',status:'Status',date:'Date',value:'Details',id:'ID',details:'Details',close:'Close',load:'Could not load data.',detail:'Could not load details.',context:'A project or base context is required to refresh.',yes:'Yes',no:'No'}};
var FIELD_LABELS={ru:{id:'ID',key:'Ключ',project_id:'ID проекта',task_project_id:'ID проекта задачи',linked_project_ids:'Связанные проекты',project_code:'Код проекта',base_reference:'Ссылка на базу',base_public_id:'Публичный ID базы',table_public_id:'Публичный ID таблицы',record_public_id:'Публичный ID записи',title:'Название',name:'Название',description:'Описание',status:'Статус',status_id:'ID статуса',is_done:'Завершено',is_complete:'Завершено',section:'Раздел',sort_order:'Порядок сортировки',created_at:'Создано',updated_at:'Обновлено',due_date:'Срок',deadline:'Дедлайн',starts_at:'Начало',ends_at:'Окончание',url:'Ссылка',diagnostic:'Диагностика',message:'Сообщение',type:'Тип',state:'Состояние',phase:'Этап',health:'Состояние',email:'Электронная почта',username:'Имя пользователя',role:'Роль',permissions:'Разрешения',source:'Источник',module:'Модуль',table:'Таблица',fields:'Поля',value:'Значение',stage:'Стадия',approval_status:'Статус согласования',approval_state:'Состояние согласования',priority:'Приоритет',assignee:'Исполнитель',owner:'Владелец',type:'Тип',category:'Категория',permissions:'Разрешения',permission:'Разрешение',read:'Чтение',write:'Запись',manage:'Управление',admin:'Администратор',view:'Просмотр',create:'Создание',update:'Изменение',delete:'Удаление',error:'Ошибка',warning:'Предупреждение',message:'Сообщение',path:'Путь',link:'Ссылка',amount:'Сумма',total:'Итого',quantity:'Количество',available_quantity:'Доступное количество',stock:'Остаток',planned:'План',planned_hours:'Плановые часы',capacity:'Ёмкость',capacity_hours:'Часы ёмкости',utilization:'Загрузка',utilization_percent:'Загрузка, %',overload:'Перегрузка',overload_hours:'Часы перегрузки',score:'Оценка',progress:'Прогресс',completeness_score:'Оценка полноты',completion_percent:'Полнота, %',availability_percent:'Доступность, %',record_count:'Количество записей',revision:'Ревизия',pages:'Страницы',page_count:'Количество страниц',date:'Дата',is_archived:'В архиве',low_stock:'Мало на складе',critical:'Критический',meta:'Метаданные'},en:{id:'ID',key:'Key',project_id:'Project ID',task_project_id:'Task project ID',linked_project_ids:'Linked projects',project_code:'Project code',base_reference:'Base reference',base_public_id:'Public base ID',table_public_id:'Public table ID',record_public_id:'Public record ID',title:'Title',name:'Name',description:'Description',status:'Status',status_id:'Status ID',is_done:'Completed',is_complete:'Completed',section:'Section',sort_order:'Sort order',created_at:'Created',updated_at:'Updated',due_date:'Due date',deadline:'Deadline',starts_at:'Starts',ends_at:'Ends',url:'URL',diagnostic:'Diagnostics',message:'Message',type:'Type',state:'State',phase:'Phase',health:'Health',email:'Email',username:'Username',role:'Role',permissions:'Permissions',source:'Source',module:'Module',table:'Table',fields:'Fields',value:'Value',stage:'Stage',approval_status:'Approval status',approval_state:'Approval state',priority:'Priority',assignee:'Assignee',owner:'Owner',type:'Type',category:'Category',permissions:'Permissions',permission:'Permission',read:'Read',write:'Write',manage:'Manage',admin:'Admin',view:'View',create:'Create',update:'Update',delete:'Delete',error:'Error',warning:'Warning',message:'Message',path:'Path',link:'Link',amount:'Amount',total:'Total',quantity:'Quantity',available_quantity:'Available quantity',stock:'Stock',planned:'Planned',planned_hours:'Planned hours',capacity:'Capacity',capacity_hours:'Capacity hours',utilization:'Utilization',utilization_percent:'Utilization, %',overload:'Overload',overload_hours:'Overload hours',score:'Score',progress:'Progress',completeness_score:'Completeness score',completion_percent:'Completeness, %',availability_percent:'Availability, %',record_count:'Record count',revision:'Revision',pages:'Pages',page_count:'Page count',date:'Date',is_archived:'Archived',low_stock:'Low stock',critical:'Critical',meta:'Metadata'}}; var FIELD_LABELS={ru:{id:'ID',key:'Ключ',project_id:'ID проекта',task_project_id:'ID проекта задачи',linked_project_ids:'Связанные проекты',project_code:'Код проекта',base_reference:'Ссылка на базу',base_public_id:'Публичный ID базы',table_public_id:'Публичный ID таблицы',record_public_id:'Публичный ID записи',title:'Название',name:'Название',description:'Описание',status:'Статус',status_id:'ID статуса',is_done:'Завершено',is_complete:'Завершено',section:'Раздел',sort_order:'Порядок сортировки',created_at:'Создано',updated_at:'Обновлено',due_date:'Срок',deadline:'Дедлайн',starts_at:'Начало',ends_at:'Окончание',url:'Ссылка',diagnostic:'Диагностика',message:'Сообщение',type:'Тип',state:'Состояние',phase:'Этап',health:'Состояние',email:'Электронная почта',username:'Имя пользователя',role:'Роль',permissions:'Разрешения',source:'Источник',module:'Модуль',table:'Таблица',fields:'Поля',value:'Значение',stage:'Стадия',approval_status:'Статус согласования',approval_state:'Состояние согласования',priority:'Приоритет',assignee:'Исполнитель',owner:'Владелец',type:'Тип',category:'Категория',permissions:'Разрешения',permission:'Разрешение',read:'Чтение',write:'Запись',manage:'Управление',admin:'Администратор',view:'Просмотр',create:'Создание',update:'Изменение',delete:'Удаление',error:'Ошибка',warning:'Предупреждение',message:'Сообщение',path:'Путь',link:'Ссылка',amount:'Сумма',total:'Итого',quantity:'Количество',available_quantity:'Доступное количество',stock:'Остаток',planned:'План',planned_hours:'Плановые часы',capacity:'Ёмкость',capacity_hours:'Часы ёмкости',utilization:'Загрузка',utilization_percent:'Загрузка, %',overload:'Перегрузка',overload_hours:'Часы перегрузки',score:'Оценка',progress:'Прогресс',completeness_score:'Оценка полноты',completion_percent:'Полнота, %',availability_percent:'Доступность, %',record_count:'Количество записей',revision:'Ревизия',pages:'Страницы',page_count:'Количество страниц',date:'Дата',is_archived:'В архиве',low_stock:'Мало на складе',critical:'Критический',meta:'Метаданные'},en:{id:'ID',key:'Key',project_id:'Project ID',task_project_id:'Task project ID',linked_project_ids:'Linked projects',project_code:'Project code',base_reference:'Base reference',base_public_id:'Public base ID',table_public_id:'Public table ID',record_public_id:'Public record ID',title:'Title',name:'Name',description:'Description',status:'Status',status_id:'Status ID',is_done:'Completed',is_complete:'Completed',section:'Section',sort_order:'Sort order',created_at:'Created',updated_at:'Updated',due_date:'Due date',deadline:'Deadline',starts_at:'Starts',ends_at:'Ends',url:'URL',diagnostic:'Diagnostics',message:'Message',type:'Type',state:'State',phase:'Phase',health:'Health',email:'Email',username:'Username',role:'Role',permissions:'Permissions',source:'Source',module:'Module',table:'Table',fields:'Fields',value:'Value',stage:'Stage',approval_status:'Approval status',approval_state:'Approval state',priority:'Priority',assignee:'Assignee',owner:'Owner',type:'Type',category:'Category',permissions:'Permissions',permission:'Permission',read:'Read',write:'Write',manage:'Manage',admin:'Admin',view:'View',create:'Create',update:'Update',delete:'Delete',error:'Error',warning:'Warning',message:'Message',path:'Path',link:'Link',amount:'Amount',total:'Total',quantity:'Quantity',available_quantity:'Available quantity',stock:'Stock',planned:'Planned',planned_hours:'Planned hours',capacity:'Capacity',capacity_hours:'Capacity hours',utilization:'Utilization',utilization_percent:'Utilization, %',overload:'Overload',overload_hours:'Overload hours',score:'Score',progress:'Progress',completeness_score:'Completeness score',completion_percent:'Completeness, %',availability_percent:'Availability, %',record_count:'Record count',revision:'Revision',pages:'Pages',page_count:'Page count',date:'Date',is_archived:'Archived',low_stock:'Low stock',critical:'Critical',meta:'Metadata'}};
var VALUE_LABELS={ru:{Tasks_Status_Todo:'К выполнению',Tasks_Status_Done:'Завершено',Tasks_Status_In_Progress:'В работе',Tasks_Status_Review:'На проверке',Modules_Done:'Завершено',todo:'К выполнению',to_do:'К выполнению','to do':'К выполнению',in_progress:'В работе','in progress':'В работе','in-progress':'В работе',in_progress_status:'В работе',done:'Завершено',completed:'Завершено',complete:'Завершено',closed:'Закрыто',active:'Активно',pending:'Ожидает',review:'На проверке',approved:'Согласовано',rejected:'Отклонено',archived:'В архиве',not_set:'Не задано'},en:{Tasks_Status_Todo:'To do',Tasks_Status_Done:'Done',Tasks_Status_In_Progress:'In progress',Tasks_Status_Review:'In review',Modules_Done:'Done',todo:'To do',to_do:'To do','to do':'To do',in_progress:'In progress','in progress':'In progress','in-progress':'In progress',in_progress_status:'In progress',done:'Done',completed:'Completed',complete:'Complete',closed:'Closed',active:'Active',pending:'Pending',review:'In review',approved:'Approved',rejected:'Rejected',archived:'Archived',not_set:'Not set'}}; var VALUE_LABELS={ru:{Tasks_Status_Todo:'К выполнению',Tasks_Status_Done:'Завершено',Tasks_Status_In_Progress:'В работе',Tasks_Status_Review:'На проверке',Modules_Done:'Завершено',todo:'К выполнению',to_do:'К выполнению','to do':'К выполнению',in_progress:'В работе','in progress':'В работе','in-progress':'В работе',in_progress_status:'В работе',done:'Завершено',completed:'Завершено',complete:'Завершено',closed:'Закрыто',active:'Активно',pending:'Ожидает',review:'На проверке',approved:'Согласовано',rejected:'Отклонено',archived:'В архиве',not_set:'Не задано'},en:{Tasks_Status_Todo:'To do',Tasks_Status_Done:'Done',Tasks_Status_In_Progress:'In progress',Tasks_Status_Review:'In review',Modules_Done:'Done',todo:'To do',to_do:'To do','to do':'To do',in_progress:'In progress','in progress':'In progress','in-progress':'In progress',in_progress_status:'In progress',done:'Done',completed:'Completed',complete:'Complete',closed:'Closed',active:'Active',pending:'Pending',review:'In review',approved:'Approved',rejected:'Rejected',archived:'Archived',not_set:'Not set'}};
@@ -58,7 +58,7 @@
inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']}, inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']},
agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']}, agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']},
'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']}, 'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']},
'project-db':{ru:['Project DB','Каталог таблиц Project DB с просмотром схемы.','Таблица','Обновлено','Записей'],en:['Project DB','Project DB table catalog with schema details.','Table','Updated','Records']}, 'airbase':{ru:['AirBase','Каталог таблиц AirBase с просмотром схемы.','Таблица','Обновлено','Записей'],en:['AirBase','AirBase table catalog with schema details.','Table','Updated','Records']},
notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']} notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']}
}; };
var S={ var S={
@@ -68,7 +68,7 @@
inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'}, inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'},
agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'}, agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'},
'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'}, 'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'},
'project-db':{listTool:'shd_project_db_tables',listArgs:{},readTool:'shd_project_db_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'}, 'airbase':{listTool:'shd_airbase_tables',listArgs:{},readTool:'shd_airbase_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'},
notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'} notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'}
}; };
var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false}; var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false};
@@ -1,20 +1,20 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"name": "shd-schemes", "name": "shd-airbase",
"version": "1.0.0", "version": "1.0.0",
"resources": [ "resources": [
{ {
"file": "index.html", "file": "index.html",
"bytes": 53688, "bytes": 48220,
"gzipBytes": 15718, "gzipBytes": 14235,
"mediaType": "text/html;profile=mcp-app", "mediaType": "text/html;profile=mcp-app",
"uri": "ui://shd/schemes/v1.html", "uri": "ui://shd/airbase/v1.html",
"sha256": "689456f1eb21cb77661d710eb72b42679347a282529a7666839e3522c836ec38" "sha256": "093206d0369e0ce87e779f72cd22aa626b5d27d65fb6e814513534d77d0164f6"
} }
], ],
"license": "../../../../../LICENSE", "license": "../../../../../LICENSE",
"source": { "source": {
"repository": "https://github.com/bulava92/shd-mcp-plugin", "repository": "https://github.com/bulava92/shd-mcp-plugin",
"path": "plugins/shd-mcp-plugin/widgets/schemes/v1/index.html" "path": "plugins/shd-mcp-plugin/widgets/airbase/v1/index.html"
} }
} }
@@ -1 +1 @@
34fa0a294db25af0b4d6c76960c42c12d8d9765360cb8f19eaaf97dcbb840f9d index.html e79d43eb1737d8abe02a7d5c0407def0dbda9eea7af4808130b775e79ce6f42c index.html
@@ -97,7 +97,7 @@
'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'}, 'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'},
files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'}, files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'},
proposals:{listTool:'shd_list_proposals',listArgs:{limit:100},readTool:'shd_get_proposal',detailKey:'proposal_id',detailSourceArgs:[],paths:['data'],sort:'desc'}, proposals:{listTool:'shd_list_proposals',listArgs:{limit:100},readTool:'shd_get_proposal',detailKey:'proposal_id',detailSourceArgs:[],paths:['data'],sort:'desc'},
terms:{listTool:'shd_list_terms_documents',readTool:'shd_get_terms_document',detailKey:'document_id',detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'}, terms:{listTool:'shd_list_pdf_scheme_editor_documents',readTool:'shd_get_terms_document',detailKey:'document_id',detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'},
activity:{listTool:'shd_get_realtime_events',listArgs:{module:'notifications',limit:100},paths:['data.events','events','data'],sort:'desc'}, activity:{listTool:'shd_get_realtime_events',listArgs:{module:'notifications',limit:100},paths:['data.events','events','data'],sort:'desc'},
organizations:{listTool:'shd_admin_list_organizations',listArgs:{limit:100},readTool:'shd_admin_get_organization_members',detailKey:'organization_id',detailSourceArgs:[],paths:['data'],sort:'asc'}, organizations:{listTool:'shd_admin_list_organizations',listArgs:{limit:100},readTool:'shd_admin_get_organization_members',detailKey:'organization_id',detailSourceArgs:[],paths:['data'],sort:'asc'},
gitea:{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],sort:'desc'}, gitea:{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],sort:'desc'},
@@ -108,7 +108,7 @@
'crm-funnel':{listTool:'shd_list_crm',listArgs:{section:'deals',limit:100},readTool:'shd_get_crm_entity',detailKey:'entity_id',detailSourceArgs:['section'],paths:['data'],view:'funnel',groupBy:'stage',sort:'desc'}, 'crm-funnel':{listTool:'shd_list_crm',listArgs:{section:'deals',limit:100},readTool:'shd_get_crm_entity',detailKey:'entity_id',detailSourceArgs:['section'],paths:['data'],view:'funnel',groupBy:'stage',sort:'desc'},
'finance-dashboard':{listTool:'shd_list_finance_documents',listArgs:{limit:100},paths:['data'],view:'dashboard',sort:'desc'}, 'finance-dashboard':{listTool:'shd_list_finance_documents',listArgs:{limit:100},paths:['data'],view:'dashboard',sort:'desc'},
'proposal-approvals':{listTool:'shd_list_proposals',listArgs:{limit:100},readTool:'shd_get_proposal_approval',detailKey:'proposal_id',detailSourceArgs:[],paths:['data'],view:'approval',sort:'desc'}, 'proposal-approvals':{listTool:'shd_list_proposals',listArgs:{limit:100},readTool:'shd_get_proposal_approval',detailKey:'proposal_id',detailSourceArgs:[],paths:['data'],view:'approval',sort:'desc'},
'documents-completeness':{listTool:'shd_list_terms_documents',readTool:'shd_get_terms_document_completeness',detailKey:'document_id',detailSourceArgs:['project_code'],paths:['data'],view:'completeness',contextRequired:true,contextKeys:['project_code'],sort:'desc'}, 'documents-completeness':{listTool:'shd_list_pdf_scheme_editor_documents',readTool:'shd_get_pdf_scheme_editor_document_completeness',detailKey:'document_id',detailSourceArgs:['project_code'],paths:['data'],view:'completeness',contextRequired:true,contextKeys:['project_code'],sort:'desc'},
'agents-health':{listTool:'shd_agents_overview',paths:['data.controllers','data.agents','data.user_agents','data'],view:'health',sort:'asc'}, 'agents-health':{listTool:'shd_agents_overview',paths:['data.controllers','data.agents','data.user_agents','data'],view:'health',sort:'asc'},
'schedule-calendar':{listTool:'shd_get_scheduling_overview',listArgs:{limit:100},readTool:'shd_list_scheduling_bookings',detailKey:'booking_id',detailArgs:{limit:1},paths:['data.bookings','data.upcoming_bookings','data'],view:'calendar',sort:'asc'}, 'schedule-calendar':{listTool:'shd_get_scheduling_overview',listArgs:{limit:100},readTool:'shd_list_scheduling_bookings',detailKey:'booking_id',detailArgs:{limit:1},paths:['data.bookings','data.upcoming_bookings','data'],view:'calendar',sort:'asc'},
'acl-matrix':{listTool:'shd_list_organization_members',listArgs:{limit:100},paths:['data'],view:'matrix',contextRequired:true,contextKeys:['organization_id'],contextAll:true,sort:'asc'}, 'acl-matrix':{listTool:'shd_list_organization_members',listArgs:{limit:100},paths:['data'],view:'matrix',contextRequired:true,contextKeys:['organization_id'],contextAll:true,sort:'asc'},
@@ -5,11 +5,11 @@
"resources": [ "resources": [
{ {
"file": "index.html", "file": "index.html",
"bytes": 77331, "bytes": 77367,
"gzipBytes": 20863, "gzipBytes": 20622,
"mediaType": "text/html;profile=mcp-app", "mediaType": "text/html;profile=mcp-app",
"uri": "ui://shd/documents-completeness/v1.html", "uri": "ui://shd/documents-completeness/v1.html",
"sha256": "34fa0a294db25af0b4d6c76960c42c12d8d9765360cb8f19eaaf97dcbb840f9d" "sha256": "e79d43eb1737d8abe02a7d5c0407def0dbda9eea7af4808130b775e79ce6f42c"
} }
], ],
"license": "../../../../../LICENSE", "license": "../../../../../LICENSE",
@@ -0,0 +1 @@
0dbd016e30afb80069902df828c3bb7f7ac13afe548adcf9a0a492013b31504c index.html
@@ -1,5 +1,5 @@
# Schemes progress widget # PDF Scheme Editor progress widget
This artifact is served by the SHD MCP backend as ui://shd/schemes-progress/v1.html. This artifact is served by the SHD MCP backend as ui://shd/pdf-scheme-editor-progress/v1.html.
The HTML is standalone, uses the MCP Apps bridge first, and keeps window.openai as a compatibility extension. It has no external script or network dependency. The widget provides a read-only scheme document progress dashboard. The HTML is standalone, uses the MCP Apps bridge first, and keeps window.openai as a compatibility extension. It has no external script or network dependency. The widget provides a read-only scheme document progress dashboard.
@@ -59,7 +59,7 @@
inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']}, inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']},
agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']}, agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']},
'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']}, 'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']},
'project-db':{ru:['Project DB','Каталог таблиц Project DB с просмотром схемы.','Таблица','Обновлено','Записей'],en:['Project DB','Project DB table catalog with schema details.','Table','Updated','Records']}, 'airbase':{ru:['AirBase','Каталог таблиц AirBase с просмотром схемы.','Таблица','Обновлено','Записей'],en:['AirBase','AirBase table catalog with schema details.','Table','Updated','Records']},
notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']}, notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']},
'project-overview':{ru:['Обзор проекта','Сводные данные по разделам выбранного проекта.','Раздел','Обновлено','Элементы'],en:['Project overview','Cross-module records for the selected project.','Section','Updated','Items']}, 'project-overview':{ru:['Обзор проекта','Сводные данные по разделам выбранного проекта.','Раздел','Обновлено','Элементы'],en:['Project overview','Cross-module records for the selected project.','Section','Updated','Items']},
files:{ru:['Файлы','Файлы выбранного проекта с поиском и безопасным просмотром ссылок.','Файл','Обновлено','Размер или тип'],en:['Files','Files from the selected project with search and safe links.','File','Updated','Size or type']}, files:{ru:['Файлы','Файлы выбранного проекта с поиском и безопасным просмотром ссылок.','Файл','Обновлено','Размер или тип'],en:['Files','Files from the selected project with search and safe links.','File','Updated','Size or type']},
@@ -83,7 +83,7 @@
'gitea-board':{ru:['Gitea-доска','Issues по состояниям разрешённого репозитория.','Issue','Состояние','Ссылка'],en:['Gitea board','Issues grouped by state for an allowed repository.','Issue','State','Link']}, 'gitea-board':{ru:['Gitea-доска','Issues по состояниям разрешённого репозитория.','Issue','Состояние','Ссылка'],en:['Gitea board','Issues grouped by state for an allowed repository.','Issue','State','Link']},
'schemes-progress':{ru:['Прогресс схем','Документы схем, ревизии, страницы и completeness.','Схема','Обновлено','Прогресс'],en:['Schemes progress','Scheme documents, revisions, pages and completeness.','Scheme','Updated','Progress']}, 'schemes-progress':{ru:['Прогресс схем','Документы схем, ревизии, страницы и completeness.','Схема','Обновлено','Прогресс'],en:['Schemes progress','Scheme documents, revisions, pages and completeness.','Scheme','Updated','Progress']},
'notes-tree':{ru:['Дерево Notes','Пространства Notes и их иерархия.','Узел','Обновлено','Тип'],en:['Notes tree','Notes spaces and their hierarchy.','Node','Updated','Type']}, 'notes-tree':{ru:['Дерево Notes','Пространства Notes и их иерархия.','Узел','Обновлено','Тип'],en:['Notes tree','Notes spaces and their hierarchy.','Node','Updated','Type']},
'project-db-preview':{ru:['Project DB preview','Предпросмотр записей выбранной таблицы Project DB.','Запись','Обновлено','Поля'],en:['Project DB preview','Preview of records from the selected Project DB table.','Record','Updated','Fields']} 'airbase-preview':{ru:['AirBase preview','Предпросмотр записей выбранной таблицы AirBase.','Запись','Обновлено','Поля'],en:['AirBase preview','Preview of records from the selected AirBase table.','Record','Updated','Fields']}
}; };
var S={ var S={
discussions:{listTool:'shd_list_discussion_topics',listArgs:{limit:100},readTool:'shd_list_discussion_messages',detailKey:'topic_id',detailArgs:{limit:50},paths:['data'],sort:'desc'}, discussions:{listTool:'shd_list_discussion_topics',listArgs:{limit:100},readTool:'shd_list_discussion_messages',detailKey:'topic_id',detailArgs:{limit:50},paths:['data'],sort:'desc'},
@@ -92,7 +92,7 @@
inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'}, inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'},
agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'}, agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'},
'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'}, 'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'},
'project-db':{listTool:'shd_project_db_tables',listArgs:{},readTool:'shd_project_db_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'}, 'airbase':{listTool:'shd_airbase_tables',listArgs:{},readTool:'shd_airbase_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'},
notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'}, notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'},
'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'}, 'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'},
files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'}, files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'},
@@ -101,7 +101,7 @@
activity:{listTool:'shd_get_realtime_events',listArgs:{module:'notifications',limit:100},paths:['data.events','events','data'],sort:'desc'}, activity:{listTool:'shd_get_realtime_events',listArgs:{module:'notifications',limit:100},paths:['data.events','events','data'],sort:'desc'},
organizations:{listTool:'shd_admin_list_organizations',listArgs:{limit:100},readTool:'shd_admin_get_organization_members',detailKey:'organization_id',detailSourceArgs:[],paths:['data'],sort:'asc'}, organizations:{listTool:'shd_admin_list_organizations',listArgs:{limit:100},readTool:'shd_admin_get_organization_members',detailKey:'organization_id',detailSourceArgs:[],paths:['data'],sort:'asc'},
gitea:{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],sort:'desc'}, gitea:{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],sort:'desc'},
schemes:{listTool:'shd_list_scheme_documents',readTool:'shd_get_scheme_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],contextRequired:true,sort:'desc'}, schemes:{listTool:'shd_list_pdf_scheme_editor_documents',readTool:'shd_get_pdf_scheme_editor_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],contextRequired:true,sort:'desc'},
'task-kanban':{listTool:'shd_list_tasks',listArgs:{limit:100},readTool:'shd_get_task',detailKey:'task_id',detailSourceArgs:[],paths:['data'],view:'kanban',groupBy:'status',sort:'asc'}, 'task-kanban':{listTool:'shd_list_tasks',listArgs:{limit:100},readTool:'shd_get_task',detailKey:'task_id',detailSourceArgs:[],paths:['data'],view:'kanban',groupBy:'status',sort:'asc'},
'team-workload':{listTool:'shd_get_task_workload',listArgs:{period:'month'},paths:['data.rows','data.workload','data.assignees','data'],view:'workload',sort:'desc'}, 'team-workload':{listTool:'shd_get_task_workload',listArgs:{period:'month'},paths:['data.rows','data.workload','data.assignees','data'],view:'workload',sort:'desc'},
'project-timeline':{listTool:'shd_list_tasks',listArgs:{limit:100},paths:['data'],view:'timeline',sort:'asc'}, 'project-timeline':{listTool:'shd_list_tasks',listArgs:{limit:100},paths:['data'],view:'timeline',sort:'asc'},
@@ -114,9 +114,9 @@
'acl-matrix':{listTool:'shd_list_organization_members',listArgs:{limit:100},paths:['data'],view:'matrix',contextRequired:true,contextKeys:['organization_id'],contextAll:true,sort:'asc'}, 'acl-matrix':{listTool:'shd_list_organization_members',listArgs:{limit:100},paths:['data'],view:'matrix',contextRequired:true,contextKeys:['organization_id'],contextAll:true,sort:'asc'},
'inventory-warnings':{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',detailSourceArgs:[],paths:['data'],view:'warnings',sort:'asc'}, 'inventory-warnings':{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',detailSourceArgs:[],paths:['data'],view:'warnings',sort:'asc'},
'gitea-board':{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],view:'kanban',groupBy:'state',sort:'asc'}, 'gitea-board':{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],view:'kanban',groupBy:'state',sort:'asc'},
'schemes-progress':{listTool:'shd_list_scheme_documents',readTool:'shd_get_scheme_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],view:'progress',contextRequired:true,contextKeys:['project'],sort:'desc'}, 'schemes-progress':{listTool:'shd_list_pdf_scheme_editor_documents',readTool:'shd_get_pdf_scheme_editor_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],view:'progress',contextRequired:true,contextKeys:['project'],sort:'desc'},
'notes-tree':{listTool:'shd_list_note_spaces',listArgs:{limit:100},readTool:'shd_get_note_space_tree',detailKey:'space_id',detailSourceArgs:[],paths:['data'],view:'tree',sort:'asc'}, 'notes-tree':{listTool:'shd_list_note_spaces',listArgs:{limit:100},readTool:'shd_get_note_space_tree',detailKey:'space_id',detailSourceArgs:[],paths:['data'],view:'tree',sort:'asc'},
'project-db-preview':{listTool:'shd_project_db_records',listArgs:{limit:100,include_fields:true,include_view_meta:true},paths:['data.records','data'],view:'preview',contextRequired:true,contextKeys:['base','project_code','table'],contextAll:true,sort:'asc'} 'airbase-preview':{listTool:'shd_airbase_records',listArgs:{limit:100,include_fields:true,include_view_meta:true},paths:['data.records','data'],view:'preview',contextRequired:true,contextKeys:['base','project_code','table'],contextAll:true,sort:'asc'}
}; };
var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false}; var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false};
var e={title:document.getElementById('title'),desc:document.getElementById('desc'),search:document.getElementById('search'),refresh:document.getElementById('refresh'),status:document.getElementById('status'),summary:document.getElementById('summary'),tableWrap:document.querySelector('.table-wrap'),visual:document.getElementById('visual'),rows:document.getElementById('rows'),empty:document.getElementById('empty'),details:document.getElementById('details'),detailTitle:document.getElementById('detail-title'),detailSub:document.getElementById('detail-sub'),grid:document.getElementById('grid'),close:document.getElementById('close'),ht:document.getElementById('head-title'),hs:document.getElementById('head-status'),hd:document.getElementById('head-date'),hv:document.getElementById('head-value')}; var e={title:document.getElementById('title'),desc:document.getElementById('desc'),search:document.getElementById('search'),refresh:document.getElementById('refresh'),status:document.getElementById('status'),summary:document.getElementById('summary'),tableWrap:document.querySelector('.table-wrap'),visual:document.getElementById('visual'),rows:document.getElementById('rows'),empty:document.getElementById('empty'),details:document.getElementById('details'),detailTitle:document.getElementById('detail-title'),detailSub:document.getElementById('detail-sub'),grid:document.getElementById('grid'),close:document.getElementById('close'),ht:document.getElementById('head-title'),hs:document.getElementById('head-status'),hd:document.getElementById('head-date'),hv:document.getElementById('head-value')};
@@ -0,0 +1,20 @@
{
"schemaVersion": 1,
"name": "shd-pdf-scheme-editor-progress",
"version": "1.0.0",
"resources": [
{
"file": "index.html",
"bytes": 77318,
"gzipBytes": 20618,
"mediaType": "text/html;profile=mcp-app",
"uri": "ui://shd/pdf-scheme-editor-progress/v1.html",
"sha256": "0dbd016e30afb80069902df828c3bb7f7ac13afe548adcf9a0a492013b31504c"
}
],
"license": "../../../../../LICENSE",
"source": {
"repository": "https://github.com/bulava92/shd-mcp-plugin",
"path": "plugins/shd-mcp-plugin/widgets/pdf-scheme-editor-progress/v1/index.html"
}
}
@@ -0,0 +1 @@
d1a29380759e80afd5b7c9f9ee90a99c393cbf20f177c4b05596609b7b93ed3f index.html
@@ -1,5 +1,5 @@
# Schemes widget # PDF Scheme Editor widget
This artifact is served by the SHD MCP backend as ui://shd/schemes/v1.html. This artifact is served by the SHD MCP backend as ui://shd/pdf-scheme-editor/v1.html.
The HTML is standalone, uses the MCP Apps bridge first, and keeps window.openai as a compatibility extension. It has no external script or network dependency. The widget provides PDF Scheme Editor document register. The HTML is standalone, uses the MCP Apps bridge first, and keeps window.openai as a compatibility extension. It has no external script or network dependency. The widget provides PDF Scheme Editor document register.
@@ -58,7 +58,7 @@
inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']}, inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']},
agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']}, agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']},
'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']}, 'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']},
'project-db':{ru:['Project DB','Каталог таблиц Project DB с просмотром схемы.','Таблица','Обновлено','Записей'],en:['Project DB','Project DB table catalog with schema details.','Table','Updated','Records']}, 'airbase':{ru:['AirBase','Каталог таблиц AirBase с просмотром схемы.','Таблица','Обновлено','Записей'],en:['AirBase','AirBase table catalog with schema details.','Table','Updated','Records']},
notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']}, notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']},
'project-overview':{ru:['Обзор проекта','Сводные данные по разделам выбранного проекта.','Раздел','Обновлено','Элементы'],en:['Project overview','Cross-module records for the selected project.','Section','Updated','Items']}, 'project-overview':{ru:['Обзор проекта','Сводные данные по разделам выбранного проекта.','Раздел','Обновлено','Элементы'],en:['Project overview','Cross-module records for the selected project.','Section','Updated','Items']},
files:{ru:['Файлы','Файлы выбранного проекта с поиском и безопасным просмотром ссылок.','Файл','Обновлено','Размер или тип'],en:['Files','Files from the selected project with search and safe links.','File','Updated','Size or type']}, files:{ru:['Файлы','Файлы выбранного проекта с поиском и безопасным просмотром ссылок.','Файл','Обновлено','Размер или тип'],en:['Files','Files from the selected project with search and safe links.','File','Updated','Size or type']},
@@ -76,7 +76,7 @@
inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'}, inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'},
agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'}, agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'},
'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'}, 'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'},
'project-db':{listTool:'shd_project_db_tables',listArgs:{},readTool:'shd_project_db_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'}, 'airbase':{listTool:'shd_airbase_tables',listArgs:{},readTool:'shd_airbase_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'},
notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'}, notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'},
'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'}, 'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'},
files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'}, files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'},
@@ -85,7 +85,7 @@
activity:{listTool:'shd_get_realtime_events',listArgs:{module:'notifications',limit:100},paths:['data.events','events','data'],sort:'desc'}, activity:{listTool:'shd_get_realtime_events',listArgs:{module:'notifications',limit:100},paths:['data.events','events','data'],sort:'desc'},
organizations:{listTool:'shd_admin_list_organizations',listArgs:{limit:100},readTool:'shd_admin_get_organization_members',detailKey:'organization_id',detailSourceArgs:[],paths:['data'],sort:'asc'}, organizations:{listTool:'shd_admin_list_organizations',listArgs:{limit:100},readTool:'shd_admin_get_organization_members',detailKey:'organization_id',detailSourceArgs:[],paths:['data'],sort:'asc'},
gitea:{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],sort:'desc'}, gitea:{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],sort:'desc'},
schemes:{listTool:'shd_list_scheme_documents',readTool:'shd_get_scheme_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],contextRequired:true,sort:'desc'} schemes:{listTool:'shd_list_pdf_scheme_editor_documents',readTool:'shd_get_pdf_scheme_editor_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],contextRequired:true,sort:'desc'}
}; };
var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false}; var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false};
var e={title:document.getElementById('title'),desc:document.getElementById('desc'),search:document.getElementById('search'),refresh:document.getElementById('refresh'),status:document.getElementById('status'),summary:document.getElementById('summary'),rows:document.getElementById('rows'),empty:document.getElementById('empty'),details:document.getElementById('details'),detailTitle:document.getElementById('detail-title'),detailSub:document.getElementById('detail-sub'),grid:document.getElementById('grid'),close:document.getElementById('close'),ht:document.getElementById('head-title'),hs:document.getElementById('head-status'),hd:document.getElementById('head-date'),hv:document.getElementById('head-value')}; var e={title:document.getElementById('title'),desc:document.getElementById('desc'),search:document.getElementById('search'),refresh:document.getElementById('refresh'),status:document.getElementById('status'),summary:document.getElementById('summary'),rows:document.getElementById('rows'),empty:document.getElementById('empty'),details:document.getElementById('details'),detailTitle:document.getElementById('detail-title'),detailSub:document.getElementById('detail-sub'),grid:document.getElementById('grid'),close:document.getElementById('close'),ht:document.getElementById('head-title'),hs:document.getElementById('head-status'),hd:document.getElementById('head-date'),hv:document.getElementById('head-value')};
@@ -1,20 +1,20 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"name": "shd-terms", "name": "shd-pdf-scheme-editor",
"version": "1.0.0", "version": "1.0.0",
"resources": [ "resources": [
{ {
"file": "index.html", "file": "index.html",
"bytes": 53686, "bytes": 53686,
"gzipBytes": 15717, "gzipBytes": 15502,
"mediaType": "text/html;profile=mcp-app", "mediaType": "text/html;profile=mcp-app",
"uri": "ui://shd/terms/v1.html", "uri": "ui://shd/pdf-scheme-editor/v1.html",
"sha256": "896211a578da8b838770feee592657fbf14e0afd618d9d97d05b02e0854b8286" "sha256": "d1a29380759e80afd5b7c9f9ee90a99c393cbf20f177c4b05596609b7b93ed3f"
} }
], ],
"license": "../../../../../LICENSE", "license": "../../../../../LICENSE",
"source": { "source": {
"repository": "https://github.com/bulava92/shd-mcp-plugin", "repository": "https://github.com/bulava92/shd-mcp-plugin",
"path": "plugins/shd-mcp-plugin/widgets/terms/v1/index.html" "path": "plugins/shd-mcp-plugin/widgets/pdf-scheme-editor/v1/index.html"
} }
} }
@@ -1 +0,0 @@
5326af598a4d5fdd590e8c65faee54fefbc3ea0657c9e4889e3b46e6faf6112a index.html
@@ -1,5 +0,0 @@
# Project DB preview widget
This artifact is served by the SHD MCP backend as ui://shd/project-db-preview/v1.html.
The HTML is standalone, uses the MCP Apps bridge first, and keeps window.openai as a compatibility extension. It has no external script or network dependency. The widget provides a read-only Project DB table record preview.
@@ -1,20 +0,0 @@
{
"schemaVersion": 1,
"name": "shd-project-db-preview",
"version": "1.0.0",
"resources": [
{
"file": "index.html",
"bytes": 76395,
"gzipBytes": 20728,
"mediaType": "text/html;profile=mcp-app",
"uri": "ui://shd/project-db-preview/v1.html",
"sha256": "5326af598a4d5fdd590e8c65faee54fefbc3ea0657c9e4889e3b46e6faf6112a"
}
],
"license": "../../../../../LICENSE",
"source": {
"repository": "https://github.com/bulava92/shd-mcp-plugin",
"path": "plugins/shd-mcp-plugin/widgets/project-db-preview/v1/index.html"
}
}
@@ -1 +0,0 @@
29fef517516916f60a662396049e8516d8379e8366b81eec62ba5f1d972cbd54 index.html
@@ -1,20 +0,0 @@
{
"schemaVersion": 1,
"name": "shd-project-db",
"version": "1.0.0",
"resources": [
{
"file": "index.html",
"bytes": 48250,
"gzipBytes": 14453,
"mediaType": "text/html;profile=mcp-app",
"uri": "ui://shd/project-db/v1.html",
"sha256": "29fef517516916f60a662396049e8516d8379e8366b81eec62ba5f1d972cbd54"
}
],
"license": "../../../../../LICENSE",
"source": {
"repository": "https://github.com/bulava92/shd-mcp-plugin",
"path": "plugins/shd-mcp-plugin/widgets/project-db/v1/index.html"
}
}
@@ -1 +0,0 @@
f24c4103899ccabba355dd7e5c51b429b74edcdca5645c7672c3b6eb9c6a17e3 index.html
@@ -1,20 +0,0 @@
{
"schemaVersion": 1,
"name": "shd-schemes-progress",
"version": "1.0.0",
"resources": [
{
"file": "index.html",
"bytes": 77319,
"gzipBytes": 20866,
"mediaType": "text/html;profile=mcp-app",
"uri": "ui://shd/schemes-progress/v1.html",
"sha256": "f24c4103899ccabba355dd7e5c51b429b74edcdca5645c7672c3b6eb9c6a17e3"
}
],
"license": "../../../../../LICENSE",
"source": {
"repository": "https://github.com/bulava92/shd-mcp-plugin",
"path": "plugins/shd-mcp-plugin/widgets/schemes-progress/v1/index.html"
}
}
@@ -1 +0,0 @@
689456f1eb21cb77661d710eb72b42679347a282529a7666839e3522c836ec38 index.html
@@ -1 +0,0 @@
896211a578da8b838770feee592657fbf14e0afd618d9d97d05b02e0854b8286 index.html
@@ -1,5 +0,0 @@
# Terms / ТЗ widget
This artifact is served by the SHD MCP backend as ui://shd/terms/v1.html.
The HTML is standalone, uses the MCP Apps bridge first, and keeps window.openai as a compatibility extension. It has no external script or network dependency. The widget provides Terms of Reference document register.
@@ -1,563 +0,0 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SHD MCP</title>
<style>
:root{color-scheme:light dark;--bg:#f8fafc;--surface:#e8edf2;--hover:#e1e8ef;--line:rgba(31,41,55,.16);--ink:#1d1f25;--muted:#616670;--accent:#535963;--soft:rgba(75,85,99,.12);--bad:#b42318;--good:#2f855a;--button:#fff;--shadow:0 10px 26px rgba(31,41,55,.1)}
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.45 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}.shell{max-width:980px;margin:auto;padding:22px}.card{padding:20px;border:1px solid var(--line);border-radius:18px;background:var(--surface);box-shadow:var(--shadow)}
.eyebrow{color:var(--muted);font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}h1{margin:4px 0 5px;font-size:25px;line-height:1.15}.lede{margin:0;color:var(--muted)}.summary{display:flex;gap:8px;flex-wrap:wrap;margin:18px 0 14px}.summary span{padding:5px 9px;border:1px solid var(--line);border-radius:999px;background:var(--hover);color:var(--muted)}.summary strong{color:var(--ink)}
.toolbar{display:flex;gap:8px;margin-bottom:10px}.search{min-width:0;flex:1;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--bg);color:inherit;outline:0}.search:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--soft)}button{cursor:pointer}.refresh{padding:10px 14px;border:1px solid var(--accent);border-radius:10px;background:var(--accent);color:var(--button);font-weight:650}.refresh:disabled{opacity:.6;cursor:wait}.status{min-height:22px;color:var(--muted)}.error{color:var(--bad)}
.table-wrap{max-height:460px;overflow:auto;border:1px solid var(--line);border-radius:12px;background:var(--bg)}table{width:100%;border-collapse:collapse;min-width:560px}th,td{padding:11px 13px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}th{position:sticky;top:0;background:var(--hover);color:var(--muted);font-size:12px;font-weight:650;z-index:1}tbody tr:last-child td{border-bottom:0}.record{cursor:pointer;outline:0}.record:hover,.record:focus{background:var(--soft)}.title{font-weight:650}.sub{display:block;color:var(--muted);font-size:12px;margin-top:2px}.pill{display:inline-block;padding:3px 8px;border-radius:999px;background:var(--soft);color:var(--accent);font-size:12px;white-space:nowrap}.pill.up,.pill.ok,.pill.active{color:var(--good);background:rgba(47,133,90,.14)}.pill.down,.pill.error,.pill.overdue{color:var(--bad);background:rgba(180,35,24,.12)}.empty{padding:24px;text-align:center;color:var(--muted)}
.details{margin-top:14px;padding:16px;border:1px solid var(--line);border-radius:12px;background:var(--bg)}.details[hidden]{display:none}.detail-head{display:flex;justify-content:space-between;gap:12px;align-items:start}.details h2{margin:0;font-size:18px}.close{border:0;background:transparent;color:var(--muted);font-size:20px}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-top:14px}.detail{padding:9px;border-radius:8px;background:var(--surface)}.label{display:block;color:var(--muted);font-size:11px;margin-bottom:3px}.value{overflow-wrap:anywhere;white-space:pre-wrap}@media(max-width:640px){.shell{padding:12px}.card{padding:15px}.toolbar{display:grid;grid-template-columns:minmax(0,1fr) auto}}
@media(prefers-color-scheme:dark){:root{--bg:#202020;--surface:#292929;--hover:#303336;--line:#43474c;--ink:#eaecf0;--muted:#96999d;--accent:#c7b07a;--soft:rgba(199,176,122,.18);--bad:#ff9a93;--good:#83c995;--button:#241f14;--shadow:0 10px 26px rgba(0,0,0,.34)}}
</style>
<style data-shd-widget-write-actions="css">
.shd-widget-actions{margin-top:14px;padding:14px;border:1px solid var(--border,var(--line,rgba(31,41,55,.16)));border-radius:11px;background:var(--surface,var(--panel,#e8edf2));color:var(--text,var(--ink,#1d1f25))}
.shd-widget-actions[hidden]{display:none}
.shd-widget-actions-header{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}
.shd-widget-actions-selection{overflow:hidden;color:var(--muted,#616670);font-size:12px;text-overflow:ellipsis;white-space:nowrap}
.shd-widget-actions-select,.shd-widget-actions-input{width:100%;border:1px solid var(--border,var(--line,rgba(31,41,55,.16)));border-radius:8px;padding:8px 10px;background:var(--bg,#f8fafc);color:var(--text,var(--ink,#1d1f25))}
.shd-widget-actions-select:focus,.shd-widget-actions-input:focus{border-color:var(--accent,#535963);outline:0;box-shadow:0 0 0 3px var(--accent-soft,var(--soft,rgba(75,85,99,.12)))}
.shd-widget-actions-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-top:10px}
.shd-widget-actions-field{display:grid;gap:4px;color:var(--muted,#616670);font-size:11px}
.shd-widget-actions-field:has(textarea){grid-column:span 2}
.shd-widget-actions-field input[type=checkbox]{width:18px;height:18px;accent-color:var(--accent,#535963)}
.shd-widget-actions-confirm{display:flex;grid-column:1/-1;align-items:center;gap:7px;color:var(--text,var(--ink,#1d1f25));font-size:12px}
.shd-widget-actions-warning,.shd-widget-actions-hint{grid-column:1/-1;color:var(--muted,#616670);font-size:12px}
.shd-widget-actions-danger{color:var(--danger,var(--bad,#b42318))}
.shd-widget-actions-status{min-height:18px;margin-top:9px;color:var(--muted,#616670);font-size:12px}
.shd-widget-actions-status-error{color:var(--danger,var(--bad,#b42318))}
.shd-widget-actions-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}
.shd-widget-actions-buttons button{border:1px solid var(--border,var(--line,rgba(31,41,55,.16)));border-radius:8px;padding:8px 11px;background:var(--bg,#f8fafc);color:var(--text,var(--ink,#1d1f25));cursor:pointer}
.shd-widget-actions-buttons button:hover{background:var(--surface-hover,var(--hover,#e1e8ef))}
.shd-widget-actions-buttons button:disabled{cursor:wait;opacity:.62}
@media(max-width:600px){.shd-widget-actions-field:has(textarea){grid-column:auto}.shd-widget-actions-header{display:block}.shd-widget-actions-selection{display:block;margin-top:3px}}
</style>
</head>
<body>
<main class="shell" data-widget-module="notes"><section class="card">
<div class="eyebrow">SHD MCP</div><h1 id="title">SHD</h1><p class="lede" id="desc"></p><div class="summary" id="summary"></div>
<div class="toolbar"><input class="search" id="search" type="search" autocomplete="off"><button class="refresh" id="refresh" type="button"></button></div>
<div class="status" id="status" role="status" aria-live="polite"></div>
<div class="table-wrap"><table><thead><tr><th id="head-title"></th><th id="head-status"></th><th id="head-date"></th><th id="head-value"></th></tr></thead><tbody id="rows"></tbody></table><div class="empty" id="empty" hidden></div></div>
<section class="details" id="details" hidden aria-live="polite"><div class="detail-head"><div><h2 id="detail-title"></h2><div class="sub" id="detail-sub"></div></div><button class="close" id="close" type="button">×</button></div><div class="grid" id="grid"></div></section>
</section></main>
<script>
(function(){
'use strict';
var DEFAULT_MODULE='terms';
var C={ru:{refresh:'Обновить',search:'Поиск по названию, статусу или ID',loading:'Загрузка…',empty:'Нет данных для отображения.',records:'записей',status:'Статус',date:'Дата',value:'Детали',id:'ID',yes:'Да',no:'Нет',details:'Детали',close:'Закрыть',load:'Не удалось загрузить данные.',detail:'Не удалось загрузить детали.',context:'Для обновления нужен контекст проекта или базы'},en:{refresh:'Refresh',search:'Search by name, status or ID',loading:'Loading…',empty:'No data to display.',records:'records',status:'Status',date:'Date',value:'Details',id:'ID',yes:'Yes',no:'No',details:'Details',close:'Close',load:'Could not load data.',detail:'Could not load details.',context:'A project or base context is required to refresh.'}};
var FIELD_LABELS={ru:{id:'ID',key:'Ключ',project_id:'ID проекта',task_project_id:'ID проекта задачи',linked_project_ids:'Связанные проекты',project_code:'Код проекта',base_reference:'Ссылка на базу',base_public_id:'Публичный ID базы',table_public_id:'Публичный ID таблицы',record_public_id:'Публичный ID записи',title:'Название',name:'Название',description:'Описание',status:'Статус',status_id:'ID статуса',is_done:'Завершено',is_complete:'Завершено',section:'Раздел',sort_order:'Порядок сортировки',created_at:'Создано',updated_at:'Обновлено',due_date:'Срок',deadline:'Дедлайн',starts_at:'Начало',ends_at:'Окончание',url:'Ссылка',diagnostic:'Диагностика',message:'Сообщение',type:'Тип',state:'Состояние',phase:'Этап',health:'Состояние',email:'Электронная почта',username:'Имя пользователя',role:'Роль',permissions:'Разрешения',source:'Источник',module:'Модуль',table:'Таблица',fields:'Поля',value:'Значение',stage:'Стадия',approval_status:'Статус согласования',approval_state:'Состояние согласования',priority:'Приоритет',assignee:'Исполнитель',owner:'Владелец',type:'Тип',category:'Категория',permissions:'Разрешения',permission:'Разрешение',read:'Чтение',write:'Запись',manage:'Управление',admin:'Администратор',view:'Просмотр',create:'Создание',update:'Изменение',delete:'Удаление',error:'Ошибка',warning:'Предупреждение',message:'Сообщение',path:'Путь',link:'Ссылка',amount:'Сумма',total:'Итого',quantity:'Количество',available_quantity:'Доступное количество',stock:'Остаток',planned:'План',planned_hours:'Плановые часы',capacity:'Ёмкость',capacity_hours:'Часы ёмкости',utilization:'Загрузка',utilization_percent:'Загрузка, %',overload:'Перегрузка',overload_hours:'Часы перегрузки',score:'Оценка',progress:'Прогресс',completeness_score:'Оценка полноты',completion_percent:'Полнота, %',availability_percent:'Доступность, %',record_count:'Количество записей',revision:'Ревизия',pages:'Страницы',page_count:'Количество страниц',date:'Дата',is_archived:'В архиве',low_stock:'Мало на складе',critical:'Критический',meta:'Метаданные'},en:{id:'ID',key:'Key',project_id:'Project ID',task_project_id:'Task project ID',linked_project_ids:'Linked projects',project_code:'Project code',base_reference:'Base reference',base_public_id:'Public base ID',table_public_id:'Public table ID',record_public_id:'Public record ID',title:'Title',name:'Name',description:'Description',status:'Status',status_id:'Status ID',is_done:'Completed',is_complete:'Completed',section:'Section',sort_order:'Sort order',created_at:'Created',updated_at:'Updated',due_date:'Due date',deadline:'Deadline',starts_at:'Starts',ends_at:'Ends',url:'URL',diagnostic:'Diagnostics',message:'Message',type:'Type',state:'State',phase:'Phase',health:'Health',email:'Email',username:'Username',role:'Role',permissions:'Permissions',source:'Source',module:'Module',table:'Table',fields:'Fields',value:'Value',stage:'Stage',approval_status:'Approval status',approval_state:'Approval state',priority:'Priority',assignee:'Assignee',owner:'Owner',type:'Type',category:'Category',permissions:'Permissions',permission:'Permission',read:'Read',write:'Write',manage:'Manage',admin:'Admin',view:'View',create:'Create',update:'Update',delete:'Delete',error:'Error',warning:'Warning',message:'Message',path:'Path',link:'Link',amount:'Amount',total:'Total',quantity:'Quantity',available_quantity:'Available quantity',stock:'Stock',planned:'Planned',planned_hours:'Planned hours',capacity:'Capacity',capacity_hours:'Capacity hours',utilization:'Utilization',utilization_percent:'Utilization, %',overload:'Overload',overload_hours:'Overload hours',score:'Score',progress:'Progress',completeness_score:'Completeness score',completion_percent:'Completeness, %',availability_percent:'Availability, %',record_count:'Record count',revision:'Revision',pages:'Pages',page_count:'Page count',date:'Date',is_archived:'Archived',low_stock:'Low stock',critical:'Critical',meta:'Metadata'}};
var VALUE_LABELS={ru:{Tasks_Status_Todo:'К выполнению',Tasks_Status_Done:'Завершено',Tasks_Status_In_Progress:'В работе',Tasks_Status_Review:'На проверке',Modules_Done:'Завершено',todo:'К выполнению',to_do:'К выполнению','to do':'К выполнению',in_progress:'В работе','in progress':'В работе','in-progress':'В работе',in_progress_status:'В работе',done:'Завершено',completed:'Завершено',complete:'Завершено',closed:'Закрыто',active:'Активно',pending:'Ожидает',review:'На проверке',approved:'Согласовано',rejected:'Отклонено',archived:'В архиве',not_set:'Не задано',overdue:'Просрочено',blocked:'Заблокировано',error:'Ошибка',warning:'Предупреждение',maintenance:'Техническое обслуживание',low_stock:'Мало на складе',critical:'Критический',out_of_stock:'Нет на складе',available:'Доступно',unavailable:'Недоступно',read:'Чтение',write:'Запись',manage:'Управление',admin:'Администратор',view:'Просмотр',create:'Создание',update:'Изменение',delete:'Удаление',execute:'Выполнение'},en:{Tasks_Status_Todo:'To do',Tasks_Status_Done:'Done',Tasks_Status_In_Progress:'In progress',Tasks_Status_Review:'In review',Modules_Done:'Done',todo:'To do',to_do:'To do','to do':'To do',in_progress:'In progress','in progress':'In progress','in-progress':'In progress',in_progress_status:'In progress',done:'Done',completed:'Completed',complete:'Complete',closed:'Closed',active:'Active',pending:'Pending',review:'In review',approved:'Approved',rejected:'Rejected',archived:'Archived',not_set:'Not set',overdue:'Overdue',blocked:'Blocked',error:'Error',warning:'Warning',maintenance:'Maintenance',low_stock:'Low stock',critical:'Critical',out_of_stock:'Out of stock',available:'Available',unavailable:'Unavailable',read:'Read',write:'Write',manage:'Manage',admin:'Admin',view:'View',create:'Create',update:'Update',delete:'Delete',execute:'Execute'}};
var M={
discussions:{ru:['Обсуждения','Темы обсуждений с поиском и просмотром сообщений.','Тема','Обновлено','Сообщение'],en:['Discussions','Discussion topics with search and message details.','Topic','Updated','Message']},
notifications:{ru:['Уведомления','Последние уведомления и события модулей.','Уведомление','Время','Источник'],en:['Notifications','Recent notifications and module events.','Notification','Time','Source']},
scheduling:{ru:['Расписание','Ближайшие события и записи из расписания.','Событие','Начало','Участник'],en:['Scheduling','Upcoming events and bookings from scheduling.','Event','Starts','Guest']},
inventory:{ru:['Склад','Складские позиции, остатки и статусы.','Позиция','Обновлено','Количество'],en:['Inventory','Stock items, quantities and statuses.','Item','Updated','Quantity']},
agents:{ru:['Агенты и контроллеры','Доступные агенты, контроллеры и их текущее состояние.','Агент или контроллер','Проверено','Тип'],en:['Agents & Controllers','Available agents, controllers and their current state.','Agent or controller','Checked','Type']},
'status-page':{ru:['Status Page','Состояние доступности сервисов и мониторов.','Монитор','Проверено','Доступность'],en:['Status Page','Service availability and monitor state.','Monitor','Checked','Availability']},
'project-db':{ru:['Project DB','Каталог таблиц Project DB с просмотром схемы.','Таблица','Обновлено','Записей'],en:['Project DB','Project DB table catalog with schema details.','Table','Updated','Records']},
notes:{ru:['Заметки','Страницы Notes с поиском и просмотром содержимого.','Страница','Обновлено','Пространство'],en:['Notes','Notes pages with search and content details.','Page','Updated','Space']},
'project-overview':{ru:['Обзор проекта','Сводные данные по разделам выбранного проекта.','Раздел','Обновлено','Элементы'],en:['Project overview','Cross-module records for the selected project.','Section','Updated','Items']},
files:{ru:['Файлы','Файлы выбранного проекта с поиском и безопасным просмотром ссылок.','Файл','Обновлено','Размер или тип'],en:['Files','Files from the selected project with search and safe links.','File','Updated','Size or type']},
proposals:{ru:['Предложения','Предложения и сметы с поиском, статусами и деталями.','Предложение','Обновлено','Сумма или номер'],en:['Proposals','Proposals with search, statuses and details.','Proposal','Updated','Amount or number']},
terms:{ru:['Terms / ТЗ','Документы технического задания и их ревизии.','Документ','Обновлено','Страницы или ревизия'],en:['Terms documents','Terms of Reference documents and revisions.','Document','Updated','Pages or revision']},
activity:{ru:['Активность','Авторизованные realtime-события SHD по выбранному scope.','Событие','Время','Модуль или тип'],en:['Activity','Authenticated SHD realtime events for the selected scope.','Event','Time','Module or type']},
organizations:{ru:['Организации и доступ','Организации, роли и безопасный просмотр участников.','Организация','Обновлено','Роль или тип'],en:['Organizations & access','Organizations, roles and safe membership details.','Organization','Updated','Role or type']},
gitea:{ru:['Gitea Issues','Открытые задачи разрешённого site или project репозитория.','Issue','Обновлено','Состояние'],en:['Gitea Issues','Open issues for an allowed site or project repository.','Issue','Updated','State']},
schemes:{ru:['Схемы','Документы PDF Scheme Editor и их текущее состояние.','Схема','Обновлено','Ревизия или страницы'],en:['Schemes','PDF Scheme Editor documents and their current state.','Scheme','Updated','Revision or pages']}
};
var S={
discussions:{listTool:'shd_list_discussion_topics',listArgs:{limit:100},readTool:'shd_list_discussion_messages',detailKey:'topic_id',detailArgs:{limit:50},paths:['data'],sort:'desc'},
notifications:{listTool:'shd_list_notifications',listArgs:{limit:50,offset:0},paths:['data'],sort:'desc'},
scheduling:{listTool:'shd_get_scheduling_overview',listArgs:{limit:100},readTool:'shd_list_scheduling_bookings',detailKey:'booking_id',detailArgs:{limit:1},paths:['data.bookings','data.upcoming_bookings','data'],sort:'asc'},
inventory:{listTool:'shd_list_inventory_items',listArgs:{limit:100},readTool:'shd_get_inventory_item',detailKey:'item_id',paths:['data'],sort:'desc'},
agents:{listTool:'shd_agents_overview',listArgs:{},paths:['data.controllers','data.agents','data.user_agents','data'],sort:'asc'},
'status-page':{listTool:'shd_get_status_page_monitors',listArgs:{environment:'dev'},readTool:'shd_get_status_page_monitor_history',detailKey:'monitor_id',detailArgs:{limit:20},paths:['data'],nested:'monitors',sort:'asc'},
'project-db':{listTool:'shd_project_db_tables',listArgs:{},readTool:'shd_project_db_schema',detailKey:'table',paths:['data.tables','data'],contextRequired:true,sort:'asc'},
notes:{listTool:'shd_list_note_pages',listArgs:{limit:100},readTool:'shd_get_note_page',detailKey:'page_id',paths:['data'],sort:'desc'},
'project-overview':{listTool:'shd_get_project_context',listArgs:{include:['summary','tasks','discussions','documents','finance','terms','agents'],limit_per_section:100},paths:['data.sections.tasks','data.sections.discussions','data.sections.documents','data.sections.finance','data.sections.terms'],combinePaths:true,contextRequired:true,sort:'desc'},
files:{listTool:'shd_list_files',readTool:'shd_get_file_link',detailKey:'path',detailArgs:{download:false},detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'},
proposals:{listTool:'shd_list_proposals',listArgs:{limit:100},readTool:'shd_get_proposal',detailKey:'proposal_id',detailSourceArgs:[],paths:['data'],sort:'desc'},
terms:{listTool:'shd_list_terms_documents',readTool:'shd_get_terms_document',detailKey:'document_id',detailSourceArgs:['project_code'],paths:['data'],contextRequired:true,sort:'desc'},
activity:{listTool:'shd_get_realtime_events',listArgs:{module:'notifications',limit:100},paths:['data.events','events','data'],sort:'desc'},
organizations:{listTool:'shd_admin_list_organizations',listArgs:{limit:100},readTool:'shd_admin_get_organization_members',detailKey:'organization_id',detailSourceArgs:[],paths:['data'],sort:'asc'},
gitea:{listTool:'shd_list_gitea_issues',listArgs:{target:'site',limit:100},paths:['data'],sort:'desc'},
schemes:{listTool:'shd_list_scheme_documents',readTool:'shd_get_scheme_document',detailKey:'document',detailSourceArgs:['project'],paths:['data'],contextRequired:true,sort:'desc'}
};
var pending=new Map(),nextId=1,rows=[],state={module:DEFAULT_MODULE,config:Object.assign({},S[DEFAULT_MODULE]),lang:'ru',busy:false};
var e={title:document.getElementById('title'),desc:document.getElementById('desc'),search:document.getElementById('search'),refresh:document.getElementById('refresh'),status:document.getElementById('status'),summary:document.getElementById('summary'),rows:document.getElementById('rows'),empty:document.getElementById('empty'),details:document.getElementById('details'),detailTitle:document.getElementById('detail-title'),detailSub:document.getElementById('detail-sub'),grid:document.getElementById('grid'),close:document.getElementById('close'),ht:document.getElementById('head-title'),hs:document.getElementById('head-status'),hd:document.getElementById('head-date'),hv:document.getElementById('head-value')};
function lang(){var x=typeof window!=='undefined'&&window.openai&&window.openai.locale;x=String(x||document.documentElement.lang||'ru').toLowerCase();return x.indexOf('en')===0?'en':'ru'}
function t(k){return(C[state.lang]||C.ru)[k]||k}
function obj(x){return x&&typeof x==='object'&&!Array.isArray(x)}
function merge(a,b){return Object.assign({},a||{},b||{})}
function payload(x){if(!x)return null;if(Object.prototype.hasOwnProperty.call(x,'structuredContent'))return x.structuredContent;if(Object.prototype.hasOwnProperty.call(x,'toolOutput'))return x.toolOutput;return x}
function unwrap(x){if(x&&x.isError)throw Error(t('load'));var p=payload(x)||{};if(p.error)throw Error(String(p.error.message||p.error.detail||p.error));if(p.ok===false&&p.message)throw Error(String(p.message));return p}
function applyConfig(p){p=payload(p)||{};var m=obj(p.meta)?p.meta:{},w=obj(m.widget)?m.widget:{},mod=String(w.module||m.module||state.module||DEFAULT_MODULE);state.module=M[mod]?mod:DEFAULT_MODULE;state.config=merge(S[state.module],w);if(!obj(state.config.sourceArgs)&&obj(m.sourceArgs))state.config.sourceArgs=m.sourceArgs;state.lang=lang();labels()}
function labels(){var m=(M[state.module]||M.discussions)[state.lang]||M.discussions.ru;document.documentElement.lang=state.lang;e.title.textContent=m[0];e.desc.textContent=m[1];e.search.placeholder=t('search');e.refresh.textContent=t('refresh');e.empty.textContent=t('empty');e.close.setAttribute('aria-label',t('close'));e.ht.textContent=m[2];e.hs.textContent=t('status');e.hd.textContent=m[3];e.hv.textContent=m[4]}
function req(method,params){var o=typeof window!=='undefined'&&window.openai;if(method==='tools/call'&&o&&typeof o.callTool==='function')return Promise.resolve(o.callTool(params.name,params.arguments||{}));var id=nextId++;window.parent.postMessage({jsonrpc:'2.0',id:id,method:method,params:params||{}},'*');return new Promise(function(resolve,reject){var timeout=window.setTimeout(function(){pending.delete(id);reject(Error(t('load')))},12000);pending.set(id,{resolve:resolve,reject:reject,timeout:timeout})})}
function notify(method,params){window.parent.postMessage({jsonrpc:'2.0',method:method,params:params||{}},'*')}
function path(x,p){return String(p||'').split('.').reduce(function(v,k){return v&&typeof v==='object'?v[k]:undefined},x)}
function findArray(x,d){if(Array.isArray(x))return x;if(!obj(x)||d>2)return null;var keys=['items','records','bookings','upcoming_bookings','topics','notifications','pages','spaces','controllers','agents','user_agents','tables','monitors','data'];for(var i=0;i<keys.length;i++)if(Array.isArray(x[keys[i]]))return x[keys[i]];for(var k in x)if(Object.prototype.hasOwnProperty.call(x,k)){var a=findArray(x[k],d+1);if(a)return a}return null}
function flatten(a){var n=state.config.nested||state.config.nestedCollection;if(!n)return a;var out=[];a.forEach(function(parent){if(parent&&Array.isArray(parent[n]))parent[n].forEach(function(child){var x=Object.assign({},child);if(parent.name&&!x.group_name)x.group_name=parent.name;out.push(x)});else out.push(parent)});return out}
function list(x){var p=payload(x)||{};if(Array.isArray(p.items))return p.items;var ps=Array.isArray(state.config.paths)?state.config.paths:(Array.isArray(state.config.arrayPaths)?state.config.arrayPaths:[]),combined=[];for(var i=0;i<ps.length;i++){var c=path(p,ps[i]),a=Array.isArray(c)?c:findArray(c,0);if(a){if(state.config.combinePaths)combined=combined.concat(a);else return flatten(a)}}if(state.config.combinePaths&&combined.length)return flatten(combined);var d=p.data===undefined?p:p.data;return flatten(Array.isArray(d)?d:(findArray(d,0)||[]))}
function str(x){if(x===null||x===undefined||x==='')return'';if(typeof x==='object'){try{return JSON.stringify(x)}catch(err){return''}}return String(x)}
function id(x,i){var keys=['id','key','code','uuid','page_id','topic_id','booking_id','item_id','monitor_id','table'];for(var n=0;n<keys.length;n++)if(x&&x[keys[n]]!==undefined&&x[keys[n]]!==null&&x[keys[n]]!=='')return str(x[keys[n]]);return String(i+1)}
function status(x){var v=x&&x.status;if(v&&typeof v==='object')v=v.name||v.label||v.code||v.id;return str(v||(x&&(x.state||x.phase||x.health))||'')}
function title(x,i){return str(x&&(x.title||x.name||x.subject||x.display_name||x.label||x.table_name||x.table||x.key))||(t('records')+' '+(i+1))}
function date(x){return str(x&&(x.starts_at||x.start_at||x.due_date||x.checked_at||x.updated_at||x.created_at||x.sent_at||x.published_at||x.date))}
function value(x){if(!x)return'';if(x.availability_percent!==undefined&&x.availability_percent!==null)return str(x.availability_percent)+'%';if(x.quantity!==undefined&&x.quantity!==null)return str(x.quantity);if(x.record_count!==undefined&&x.record_count!==null)return str(x.record_count);return str(x.value!==undefined?x.value:(x.guest_name||x.space_name||x.group_name||x.controller_type||x.type||x.source||x.module||''))}
function sub(x){return str(x&&(x.subtitle||x.project_code||x.space_name||x.channel_name||x.group_name||x.code||x.email))}
function normalize(x,i){var y=obj(x)?Object.assign({},x):{value:x};y.id=id(x,i);y.title=title(x,i);y.subtitle=sub(x);y.status=status(x);y.date=date(x);y.value=value(x);return y}
function dateText(x){if(!x)return'—';var n=Date.parse(x);if(Number.isNaN(n))return String(x);try{return new Intl.DateTimeFormat(state.lang,{dateStyle:'medium',timeStyle:'short'}).format(new Date(n))}catch(err){return String(x)}}
function make(tag,v,cls){var n=document.createElement(tag);if(cls)n.className=cls;if(v!==undefined)n.textContent=v;return n}
function fieldLabel(key){var raw=String(key||'');var labels=FIELD_LABELS[state.lang]||FIELD_LABELS.ru;return labels[raw]||raw.replace(/[_-]+/g,' ')}
function detailText(x,key){if(x===null||x===undefined||x==='')return'—';if(typeof x==='boolean')return x?t('yes'):t('no');if(Array.isArray(x))return'['+x.map(function(v){return detailText(v,key)}).join(', ')+']';if(obj(x))return'{'+Object.keys(x).map(function(k){return fieldLabel(k)+': '+detailText(x[k],k)}).join(', ')+'}';var raw=String(x),labels=VALUE_LABELS[state.lang]||VALUE_LABELS.ru;return labels[raw]||labels[raw.toLowerCase()]||raw}
function renderSummary(){e.summary.replaceChildren();var n=make('span');n.append(make('strong',String(rows.length)),' '+t('records'));e.summary.append(n);var c={};rows.forEach(function(x){if(x.status)c[x.status]=(c[x.status]||0)+1});Object.keys(c).slice(0,3).forEach(function(k){var n=make('span');n.append(make('strong',String(c[k])),' '+detailText(k,'status'));e.summary.append(n)})}
function renderRows(){var q=e.search.value.trim().toLowerCase(),a=rows.filter(function(x){return!q||[x.title,x.subtitle,x.status,x.id,x.value].map(str).join(' ').toLowerCase().indexOf(q)!==-1});e.rows.replaceChildren();e.empty.hidden=a.length!==0;a.forEach(function(x){var r=document.createElement('tr');r.className='record';r.tabIndex=0;r.setAttribute('role','button');r.setAttribute('aria-label',x.title);var n=make('td');n.append(make('span',x.title,'title'));if(x.subtitle)n.append(make('span',x.subtitle,'sub'));var s=make('span',detailText(x.status,'status'),'pill');if(x.status)s.classList.add(String(x.status).toLowerCase().replace(/[^a-z0-9_-]+/g,'-'));r.append(n,make('td').appendChild(s).parentNode,make('td',dateText(x.date)),make('td',detailText(x.value,'value')||'—'));r.onclick=function(){details(x)};r.onkeydown=function(ev){if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();details(x)}};e.rows.append(r)});renderSummary()}
function render(x){var p=unwrap(x);applyConfig(p);rows=list(p).map(normalize);var dir=state.config.sort==='asc'?1:-1;rows.sort(function(a,b){var x=Date.parse(a.date),y=Date.parse(b.date);if(!Number.isNaN(x)&&!Number.isNaN(y)&&x!==y)return(x-y)*dir;return a.title.localeCompare(b.title,state.lang)*dir});renderRows()}
function setStatus(x,bad){e.status.textContent=x||'';e.status.className=bad?'status error':'status'}
function add(k,v){var d=make('div',undefined,'detail');d.append(make('span',fieldLabel(k),'label'),make('span',detailText(v),'value'));e.grid.append(d)}
function show(x){e.detailTitle.textContent=x.title||'SHD';e.detailSub.textContent=x.subtitle||x.id||'';e.grid.replaceChildren();add(t('id'),x.id);if(x.status)add(t('status'),x.status);if(x.date)add(t('date'),dateText(x.date));if(x.value)add(t('value'),x.value);Object.keys(x).filter(function(k){return['id','title','subtitle','status','date','value','meta'].indexOf(k)===-1}).slice(0,8).forEach(function(k){add(k,x[k])});e.details.hidden=false}
function details(x){show(x);if(!state.config.readTool)return;var k=state.config.detailKey;if(!k)return;var v=x[k]===undefined?x.id:x[k];if(v===undefined||v===null||v==='')return;if(state.module==='status-page'&&!/^\d+$/.test(String(v)))return;var a={};if(Array.isArray(state.config.detailSourceArgs)){state.config.detailSourceArgs.forEach(function(name){if(state.config.sourceArgs&&state.config.sourceArgs[name]!==undefined)a[name]=state.config.sourceArgs[name]})}else a=merge(state.config.sourceArgs,state.config.detailArgs);a=merge(a,state.config.detailArgs);a[k]=k==='table'?String(v):(Number(v)||v);req('tools/call',{name:state.config.readTool,arguments:a}).then(function(result){var p=unwrap(result),d=p.data===undefined?p:p.data;e.grid.replaceChildren();if(Array.isArray(d)){add(t('records'),d.length);d.slice(0,6).forEach(function(q,i){add(String(i+1),q&&(q.message||q.body||q.content||q.title||q))})}else if(obj(d))Object.keys(d).slice(0,12).forEach(function(q){add(q,d[q])});else add(t('details'),d)}).catch(function(err){setStatus(err.message||t('detail'),true)})}
function refresh(){if(state.busy)return;var a=merge(state.config.listArgs,state.config.sourceArgs);if(state.config.contextRequired&&!a.base&&!a.project_code&&!a.project){setStatus(t('context'),true);return}if(!state.config.listTool)return;state.busy=true;e.refresh.disabled=true;setStatus(t('loading'),false);req('tools/call',{name:state.config.listTool,arguments:a}).then(function(x){render(x);setStatus('',false)}).catch(function(err){setStatus(err.message||t('load'),true)}).finally(function(){state.busy=false;e.refresh.disabled=false})}
function init(){return req('ui/initialize',{protocolVersion:'2025-11-25',appInfo:{name:'SHD '+(M[state.module]||M.discussions).ru[0],title:'SHD MCP',version:'1.0.0',websiteUrl:'https://shd.xyz.su'},appCapabilities:{}}).then(function(){notify('ui/notifications/initialized',{})}).catch(function(){})}
window.addEventListener('message',function(ev){if(ev.source!==window.parent)return;var m=ev.data;if(!m||m.jsonrpc!=='2.0')return;if(m.id!==undefined&&pending.has(m.id)){var q=pending.get(m.id);pending.delete(m.id);window.clearTimeout(q.timeout);if(m.error)q.reject(Error(m.error.message||t('load')));else q.resolve(m.result);return}if(m.method==='ui/notifications/tool-input'&&!rows.length){try{render(m.params||{})}catch(err){setStatus(err.message||t('load'),true)}}if(m.method==='ui/notifications/tool-result'){try{render(m.params&&m.params.structuredContent)}catch(err){setStatus(err.message||t('load'),true)}}},{passive:true});
e.search.oninput=renderRows;e.refresh.onclick=refresh;e.close.onclick=function(){e.details.hidden=true};state.lang=lang();labels();void init();var out=typeof window!=='undefined'&&window.openai?window.openai.toolOutput:null;if(out){try{render(out)}catch(err){setStatus(err.message||t('load'),true)}}else{var input=typeof window!=='undefined'&&window.openai?window.openai.toolInput:null;if(input){try{render(input)}catch(err){setStatus(err.message||t('load'),true)}}else refresh()}
}());
</script>
<script data-shd-widget-write-actions="js">
(function () {
'use strict';
if (window.__SHD_WIDGET_WRITE_ACTIONS__) return;
window.__SHD_WIDGET_WRITE_ACTIONS__ = true;
var copy = {
ru: {
actions: 'Действия',
chooseAction: 'Выберите действие',
selectRecord: 'Сначала выберите запись.',
submit: 'Сохранить',
cancel: 'Отмена',
confirm: 'Подтверждаю действие',
warning: 'Проверьте данные перед записью.',
destructive: 'Операция может изменить или удалить данные.',
required: 'Заполните обязательное поле.',
invalidJson: 'Введите корректный JSON.',
success: 'Изменения сохранены.',
failure: 'Не удалось сохранить изменения.',
loading: 'Сохраняю…',
noActions: 'Для этого виджета нет доступных действий.',
refreshed: 'Список обновлён.',
fieldValue: 'Значение',
},
en: {
actions: 'Actions',
chooseAction: 'Choose an action',
selectRecord: 'Select a record first.',
submit: 'Save',
cancel: 'Cancel',
confirm: 'I confirm this action',
warning: 'Review the values before writing.',
destructive: 'This operation may change or remove data.',
required: 'Fill in the required field.',
invalidJson: 'Enter valid JSON.',
success: 'Changes saved.',
failure: 'Could not save changes.',
loading: 'Saving…',
noActions: 'No actions are available for this widget.',
refreshed: 'List refreshed.',
fieldValue: 'Value',
},
};
var state = {
widget: {},
records: [],
selected: null,
action: null,
inputs: {},
busy: false,
lang: String(document.documentElement.lang || 'ru').toLowerCase().indexOf('ru') === 0 ? 'ru' : 'en',
};
var pending = new Map();
var nextRequestId = 1;
var elements = {};
function t(key) {
return (copy[state.lang] && copy[state.lang][key]) || copy.en[key] || key;
}
function object(value) {
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
}
function normalize(value) {
if (!value) return null;
if (value.structuredContent) return normalize(value.structuredContent);
if (value.toolOutput) return normalize(value.toolOutput);
if (value.toolInput) return normalize(value.toolInput);
if (value.arguments && !value.data && !value.items && !value.projects) return normalize(value.arguments);
return value;
}
function widgetFrom(value) {
var payload = normalize(value) || {};
var meta = object(payload.meta) ? payload.meta : {};
return object(meta.widget) ? meta.widget : {};
}
function recordsFrom(value) {
var payload = normalize(value) || {};
var data = Array.isArray(payload.items) ? payload.items : payload.projects;
if (!Array.isArray(data)) data = payload.data;
if (data && !Array.isArray(data) && Array.isArray(data.data)) data = data.data;
return Array.isArray(data) ? data.filter(function (item) { return object(item); }) : [];
}
function readPath(value, path) {
if (!value || path === undefined || path === null) return undefined;
var parts = String(path).split('.');
var current = value;
for (var index = 0; index < parts.length; index += 1) {
if (current === undefined || current === null) return undefined;
current = current[parts[index]];
}
return current;
}
function firstValue(paths) {
var list = Array.isArray(paths) ? paths : [paths];
var sources = [state.selected, state.widget.sourceArgs, state.widget.listArgs];
for (var sourceIndex = 0; sourceIndex < sources.length; sourceIndex += 1) {
var sourceObject = sources[sourceIndex];
if (!sourceObject) continue;
for (var pathIndex = 0; pathIndex < list.length; pathIndex += 1) {
var value = readPath(sourceObject, list[pathIndex]);
if (value !== undefined && value !== null && value !== '') return value;
}
}
return undefined;
}
function text(value) {
if (value === undefined || value === null) return '';
if (typeof value === 'object') return JSON.stringify(value);
return String(value);
}
function label(value) {
if (object(value)) return value[state.lang] || value.ru || value.en || t('fieldValue');
return String(value || t('fieldValue'));
}
function actionLabel(action) {
return label(action && action.label) || action.id || action.tool || t('actions');
}
function hasTargets(action) {
return Boolean(action && ((Array.isArray(action.targets) && action.targets.length) || action.target));
}
function actionList() {
return Array.isArray(state.widget.actions) ? state.widget.actions.filter(function (action) {
return action && action.tool;
}) : [];
}
function request(method, params) {
var openai = typeof window !== 'undefined' ? window.openai : undefined;
if (method === 'tools/call' && openai && typeof openai.callTool === 'function') {
return openai.callTool(params.name, params.arguments || {});
}
var id = nextRequestId++;
window.parent.postMessage({ jsonrpc: '2.0', id: id, method: method, params: params || {} }, '*');
return new Promise(function (resolve, reject) {
var timeout = window.setTimeout(function () {
pending.delete(id);
reject(new Error(t('failure')));
}, 15000);
pending.set(id, { resolve: resolve, reject: reject, timeout: timeout });
});
}
function unwrap(value) {
var payload = normalize(value);
if (value && value.isError) throw new Error(payload && payload.error ? text(payload.error) : t('failure'));
if (payload && payload.error) throw new Error(text(payload.error));
return payload || value;
}
function make(tag, value, className) {
var node = document.createElement(tag);
if (className) node.className = className;
if (value !== undefined) node.textContent = value;
return node;
}
function ensurePanel() {
if (elements.panel) return;
var root = document.querySelector('main') || document.body;
var panel = make('section', undefined, 'shd-widget-actions');
panel.hidden = true;
panel.setAttribute('aria-live', 'polite');
var header = make('div', undefined, 'shd-widget-actions-header');
header.append(make('strong', t('actions')), make('span', '', 'shd-widget-actions-selection'));
var select = document.createElement('select');
select.className = 'shd-widget-actions-select';
select.setAttribute('aria-label', t('actions'));
var form = make('form', undefined, 'shd-widget-actions-form');
var status = make('div', '', 'shd-widget-actions-status');
var buttons = make('div', undefined, 'shd-widget-actions-buttons');
var submit = make('button', t('submit'), 'shd-widget-actions-submit');
submit.type = 'submit';
var cancel = make('button', t('cancel'), 'shd-widget-actions-cancel');
cancel.type = 'button';
buttons.append(submit, cancel);
panel.append(header, select, form, status, buttons);
root.append(panel);
elements = { panel: panel, selection: header.lastChild, select: select, form: form, status: status, submit: submit, cancel: cancel };
select.addEventListener('change', function () {
var selected = actionList().find(function (action) { return action.id === select.value; });
state.action = selected || null;
renderForm();
});
cancel.addEventListener('click', function () {
state.action = null;
select.value = '';
renderForm();
});
form.addEventListener('submit', function (event) {
event.preventDefault();
submitAction();
});
}
function inputValue(fieldConfig) {
var value = firstValue(fieldConfig.source || []);
if (value === undefined && fieldConfig.default !== undefined) value = fieldConfig.default;
return value;
}
function createInput(fieldConfig) {
var type = fieldConfig.type || 'text';
var input;
if (type === 'textarea' || type === 'json') {
input = document.createElement('textarea');
input.rows = type === 'json' ? 4 : 3;
if (type === 'json') input.placeholder = '{ }';
} else if (type === 'select') {
input = document.createElement('select');
(fieldConfig.options || []).forEach(function (option) {
var item = document.createElement('option');
item.value = String(option[0]);
item.textContent = state.lang === 'ru' ? String(option[1]) : String(option[2] || option[1]);
input.append(item);
});
} else {
input = document.createElement('input');
input.type = type === 'number' || type === 'email' ? type : 'text';
}
input.className = 'shd-widget-actions-input';
input.name = fieldConfig.name;
var value = inputValue(fieldConfig);
if (type === 'checkbox') {
input.type = 'checkbox';
input.checked = value === true || value === 'true' || value === 1 || value === '1';
} else if (value !== undefined && value !== null) {
input.value = type === 'json' && typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value);
}
if (fieldConfig.required) input.required = true;
return input;
}
function renderForm() {
ensurePanel();
var selectedActionId = state.action ? state.action.id : '';
elements.select.replaceChildren();
var placeholder = document.createElement('option');
placeholder.value = '';
placeholder.textContent = t('chooseAction');
elements.select.append(placeholder);
actionList().forEach(function (action) {
var option = document.createElement('option');
option.value = action.id;
option.textContent = actionLabel(action);
elements.select.append(option);
});
elements.select.value = selectedActionId;
elements.select.hidden = actionList().length === 0;
elements.form.replaceChildren();
elements.status.textContent = '';
elements.submit.disabled = state.busy;
var action = state.action;
if (!action) {
elements.selection.textContent = state.selected ? text(state.selected.title || state.selected.name || state.selected.id || '') : '';
elements.submit.hidden = true;
elements.cancel.hidden = true;
if (actionList().length && !state.selected && actionList().every(hasTargets)) {
elements.form.append(make('div', t('selectRecord'), 'shd-widget-actions-hint'));
}
return;
}
elements.selection.textContent = state.selected ? text(state.selected.title || state.selected.name || state.selected.id || '') : '';
elements.submit.hidden = false;
elements.cancel.hidden = false;
if (hasTargets(action) && !state.selected) elements.form.append(make('div', t('selectRecord'), 'shd-widget-actions-hint'));
(action.fields || []).forEach(function (fieldConfig) {
if (!fieldConfig || !fieldConfig.name || fieldConfig.generated || fieldConfig.type === 'hidden') return;
var wrapper = make('label', undefined, 'shd-widget-actions-field');
wrapper.append(make('span', label(fieldConfig.label)));
wrapper.append(createInput(fieldConfig));
elements.form.append(wrapper);
});
if (action.confirm) {
var confirmLabel = make('label', undefined, 'shd-widget-actions-confirm');
var confirm = document.createElement('input');
confirm.type = 'checkbox';
confirm.name = '__confirm';
confirm.required = true;
confirmLabel.append(confirm, make('span', t('confirm')));
elements.form.append(confirmLabel);
}
var notice = make('div', action.destructive ? t('destructive') : t('warning'), action.destructive ? 'shd-widget-actions-warning shd-widget-actions-danger' : 'shd-widget-actions-warning');
elements.form.append(notice);
}
function coerce(value, type) {
if (type === 'number') {
var number = Number(value);
return Number.isFinite(number) ? number : value;
}
if (type === 'checkbox') return Boolean(value);
if (type === 'json') {
try { return JSON.parse(value); } catch (error) { throw new Error(t('invalidJson')); }
}
return value;
}
function targetType(name) {
return /^(task|document|contract|booking|item|monitor|proposal|approval|page|notification|topic|membership|organization|space|status|project)_?id$/.test(name) || name === 'issue_number' || name === 'number' ? 'number' : 'text';
}
function targetList(action) {
if (Array.isArray(action.targets)) return action.targets;
return action.target ? [action.target] : [];
}
function collectArguments(action) {
var args = Object.assign({}, action.fixed || {});
(action.context || []).forEach(function (name) {
var value = firstValue([name]);
if (value !== undefined && value !== null && value !== '') args[name] = value;
});
targetList(action).forEach(function (targetConfig) {
var value = firstValue(targetConfig.source || targetConfig.name);
if (value === undefined || value === null || value === '') throw new Error(t('selectRecord'));
args[targetConfig.name] = coerce(value, targetConfig.type || targetType(targetConfig.name));
});
(action.fields || []).forEach(function (fieldConfig) {
if (!fieldConfig || !fieldConfig.name || fieldConfig.generated || fieldConfig.type === 'hidden') return;
var input = Array.prototype.find.call(elements.form.querySelectorAll('[name]'), function (node) {
return node.getAttribute('name') === fieldConfig.name;
});
if (!input) return;
var raw = fieldConfig.type === 'checkbox' ? input.checked : input.value.trim();
if (raw === '' && !input.checked && !fieldConfig.required) return;
if (raw === '' && fieldConfig.required) throw new Error(t('required'));
args[fieldConfig.name] = coerce(raw, fieldConfig.type || 'text');
});
if (action.idempotencyKey) args.idempotency_key = 'shd-widget-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 10);
if (action.confirmArg) args.confirm = true;
return args;
}
function setStatus(message, error) {
elements.status.textContent = message || '';
elements.status.className = 'shd-widget-actions-status' + (error ? ' shd-widget-actions-status-error' : '');
}
function submitAction() {
if (state.busy || !state.action) return;
var action = state.action;
var args;
try { args = collectArguments(action); } catch (error) { setStatus(error.message || t('failure'), true); return; }
state.busy = true;
elements.submit.disabled = true;
elements.cancel.disabled = true;
setStatus(t('loading'), false);
request('tools/call', { name: action.tool, arguments: args }).then(function (result) {
unwrap(result);
setStatus(t('success'), false);
var refresh = document.getElementById('refresh');
if (refresh && typeof refresh.click === 'function') window.setTimeout(function () { refresh.click(); }, 250);
}).catch(function (error) {
setStatus(error && error.message ? error.message : t('failure'), true);
}).finally(function () {
state.busy = false;
elements.submit.disabled = false;
elements.cancel.disabled = false;
});
}
function recordFromNode(node) {
var content = String(node.textContent || '').toLowerCase();
var exact = state.records.find(function (item) {
var id = text(item.id || item.code || item.key || item.number).toLowerCase();
return id && content.indexOf(id) !== -1;
});
if (exact) return exact;
return state.records.find(function (item) {
var title = text(item.title || item.name || item.display_name || item.number).toLowerCase();
return title && content.indexOf(title) !== -1;
}) || null;
}
function update(value) {
var payload = normalize(value) || {};
var widget = widgetFrom(payload);
if (Object.keys(widget).length) state.widget = widget;
var records = recordsFrom(payload);
if (records.length || Array.isArray(payload.data) || Array.isArray(payload.items) || Array.isArray(payload.projects)) state.records = records;
ensurePanel();
var actions = actionList();
elements.panel.hidden = actions.length === 0;
if (actions.length && !state.action) renderForm();
else if (actions.length) renderForm();
}
document.addEventListener('click', function (event) {
var node = event.target && event.target.closest ? event.target.closest('.record,.project-row,.visual-card,.progress-card,.preview-card,.calendar-card,.timeline-card,.kanban-card') : null;
if (!node || (elements.panel && elements.panel.contains(node))) return;
var item = recordFromNode(node);
if (!item) return;
state.selected = item;
ensurePanel();
renderForm();
}, true);
window.addEventListener('message', function (event) {
if (event.source !== window.parent) return;
var message = event.data;
if (!message || message.jsonrpc !== '2.0') return;
if (message.id !== undefined && pending.has(message.id)) {
var requestState = pending.get(message.id);
pending.delete(message.id);
window.clearTimeout(requestState.timeout);
if (message.error) requestState.reject(new Error(message.error.message || t('failure')));
else requestState.resolve(message.result);
return;
}
if (message.method === 'ui/notifications/tool-input' || message.method === 'ui/notifications/tool-result') update(message.params || {});
}, { passive: true });
ensurePanel();
var initial = typeof window !== 'undefined' && window.openai ? (window.openai.toolOutput || window.openai.toolInput) : null;
if (initial) update(initial);
}());
</script>
</body>
</html>