<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Posts on 1С Инсайдер</title><link>https://darachubarova.github.io/infostart-agent/posts/</link><description>Recent content in Posts on 1С Инсайдер</description><generator>Hugo</generator><language>ru</language><lastBuildDate>Wed, 27 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://darachubarova.github.io/infostart-agent/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Session not found: почему Claude Desktop теряет сессию при подключении к MCP-серверу Vanessa Automation</title><link>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_mcp-vanessa-claude-session/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_mcp-vanessa-claude-session/</guid><description>&lt;p&gt;Всё выглядит правильно: MCP-сервер поднят, сессия инициализируется, &lt;code&gt;initialize&lt;/code&gt; проходит успешно — а потом первый же реальный запрос (&lt;code&gt;tools/list&lt;/code&gt;, &lt;code&gt;resources/list&lt;/code&gt;, &lt;code&gt;prompts/list&lt;/code&gt;) отвечает 404 «Session not found». Сидишь и смотришь на это сообщение, не понимая, куда делась только что созданная сессия. Это не баг в твоём коде. Это столкновение двух протоколов, которые ещё не договорились, кто из них главный.&lt;/p&gt;
&lt;h2 id="что-происходит-на-самом-деле"&gt;Что происходит на самом деле&lt;/h2&gt;
&lt;p&gt;MCP (Model Context Protocol) существует в двух транспортных режимах: &lt;strong&gt;Streamable HTTP&lt;/strong&gt; (новый, статeful, сессионный) и &lt;strong&gt;SSE&lt;/strong&gt; (старый, Server-Sent Events). Vanessa Automation 1.2.x реализует именно SSE-транспорт — это значит, что сервер ждёт долгоживущего HTTP-соединения, через которое сам толкает события.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Всё выглядит правильно: MCP-сервер поднят, сессия инициализируется, <code>initialize</code> проходит успешно — а потом первый же реальный запрос (<code>tools/list</code>, <code>resources/list</code>, <code>prompts/list</code>) отвечает 404 «Session not found». Сидишь и смотришь на это сообщение, не понимая, куда делась только что созданная сессия. Это не баг в твоём коде. Это столкновение двух протоколов, которые ещё не договорились, кто из них главный.</p>
<h2 id="что-происходит-на-самом-деле">Что происходит на самом деле</h2>
<p>MCP (Model Context Protocol) существует в двух транспортных режимах: <strong>Streamable HTTP</strong> (новый, статeful, сессионный) и <strong>SSE</strong> (старый, Server-Sent Events). Vanessa Automation 1.2.x реализует именно SSE-транспорт — это значит, что сервер ждёт долгоживущего HTTP-соединения, через которое сам толкает события.</p>
<p>Claude Desktop при подключении через <code>mcp-remote</code> по умолчанию пытается использовать Streamable HTTP. Он делает <code>POST /mcp</code> для инициализации, получает session ID, а потом отправляет следующий запрос — снова <code>POST /mcp</code>, уже с этим session ID. Vanessa его не находит, потому что для неё сессии не существует: она ждала, что клиент откроет SSE-стрим и подпишется на события.</p>
<p>Результат: <code>404 Session not found</code> при каждом обращении после <code>initialize</code>.</p>
<h2 id="правильная-схема-подключения">Правильная схема подключения</h2>
<p>Конфигурация в <code>claude_desktop_config.json</code> должна выглядеть так:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;mcpServers&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;vanessa&#34;</span>: {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;command&#34;</span>: <span style="color:#e6db74">&#34;npx&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;args&#34;</span>: [
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;mcp-remote&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;http://127.0.0.1:8080/mcp&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--transport&#34;</span>, <span style="color:#e6db74">&#34;sse&#34;</span>
</span></span><span style="display:flex;"><span>      ]
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Ключ — флаг <code>--transport sse</code>. Без него <code>mcp-remote</code> 0.1.x выбирает Streamable HTTP как дефолт, и именно здесь рассыпается вся цепочка.</p>
<p>Если Vanessa запущена на нестандартном пути, проверь endpoint: в версии 1.2.043 это <code>/mcp</code>, но в более ранних сборках встречался <code>/sse</code>. Загляни в настройки Vanessa в разделе «HTTP-сервер» — там будет точный URL.</p>
<h2 id="дополнительные-причины-той-же-ошибки">Дополнительные причины той же ошибки</h2>
<p><strong>Версия mcp-remote.</strong> В 0.1.37 есть известный баг с переподключением: если SSE-соединение рвётся и клиент переподключается, новый session ID не передаётся обратно корректно. Попробуй 0.1.35 или последний snapshot из репозитория — там это починено.</p>
<p><strong>Firewall и антивирус.</strong> SSE-соединение долгоживущее (минуты и часы), некоторые корпоративные фаерволы режут соединения после 30–60 секунд простоя. Vanessa при этом думает, что клиент отключился, и удаляет сессию. Клиент же при следующем запросе ссылается на уже несуществующий ID. Признак именно этой проблемы — ошибка возникает не сразу, а через некоторое время после успешного старта.</p>
<p><strong>Множественные инстанции.</strong> Claude Desktop иногда запускает несколько воркеров, каждый из которых инициализирует свою сессию. Если они конкурируют за один порт — часть запросов теряется. Проверь, что Vanessa обслуживает несколько одновременных SSE-соединений (настройка «Максимальное число подключений» в HTTP-сервере).</p>
<h2 id="проверка-работоспособности-без-claude">Проверка работоспособности без Claude</h2>
<p>Прежде чем идти дальше, убедись, что MCP-сервер в принципе работает:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -N http://127.0.0.1:8080/mcp/sse
</span></span></code></pre></div><p>Флаг <code>-N</code> отключает буферизацию — ты должен увидеть поток событий в терминале. Если соединение сразу закрывается или возвращает ошибку, проблема в самой Vanessa, а не в mcp-remote.</p>
<p>Если curl работает, а Claude Desktop — нет, вернись к конфигу. Убедись, что <code>node</code> и <code>npx</code> доступны из того пути, откуда запускается Claude Desktop (на Windows это особенно актуально: PATH в системной среде и PATH в терминале могут отличаться).</p>
<p>Если после всего этого ошибка не ушла — посмотри в issues репозитория <code>modelcontextprotocol/mcp-remote</code>. Эта связка Vanessa + Claude Desktop + mcp-remote активно используется и проблемы там отслеживаются. Часто решение уже есть в закрытых issues, просто не задокументировано в readme.</p>
]]></content:encoded></item><item><title>Вставить изображение в Google Sheets из 1С: полный путь от файла до ячейки</title><link>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_google-sheets-image-from-1c/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_google-sheets-image-from-1c/</guid><description>&lt;p&gt;Хочется простого: есть картинка на диске или в 1С, хочу её видеть в ячейке Google Sheets. На практике это три отдельных API-вызова, OAuth2-токен, и функция &lt;code&gt;=IMAGE()&lt;/code&gt;, которая работает совсем не так, как кнопка «Вставить изображение» в интерфейсе браузера. Разберём весь путь за один раз.&lt;/p&gt;
&lt;h2 id="почему-sheets-api-не-умеет-вставлять-картинки-напрямую"&gt;Почему Sheets API не умеет вставлять картинки напрямую&lt;/h2&gt;
&lt;p&gt;Google Sheets API v4 оперирует данными ячеек — текстом, числами, формулами. «Вставить изображение в ячейку» в смысле embedded image (то, что в браузере делается через меню «Вставка → Изображение → В ячейку») через REST API в 2026 году всё ещё &lt;strong&gt;официально не поддерживается&lt;/strong&gt;. Это боль всего сообщества.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Хочется простого: есть картинка на диске или в 1С, хочу её видеть в ячейке Google Sheets. На практике это три отдельных API-вызова, OAuth2-токен, и функция <code>=IMAGE()</code>, которая работает совсем не так, как кнопка «Вставить изображение» в интерфейсе браузера. Разберём весь путь за один раз.</p>
<h2 id="почему-sheets-api-не-умеет-вставлять-картинки-напрямую">Почему Sheets API не умеет вставлять картинки напрямую</h2>
<p>Google Sheets API v4 оперирует данными ячеек — текстом, числами, формулами. «Вставить изображение в ячейку» в смысле embedded image (то, что в браузере делается через меню «Вставка → Изображение → В ячейку») через REST API в 2026 году всё ещё <strong>официально не поддерживается</strong>. Это боль всего сообщества.</p>
<p>Что работает через API:</p>
<ol>
<li><strong>Функция <code>=IMAGE(url)</code></strong> — вставляет изображение по публичному URL. Это не настоящий embedded image, но визуально неотличимо.</li>
<li><strong>Floating image через <code>batchUpdate</code></strong> — вставляет картинку как плавающий объект поверх ячеек (не в ячейку).</li>
</ol>
<p>Самый практичный подход для 1С — загрузить изображение на Google Drive и вставить через <code>=IMAGE()</code>.</p>
<h2 id="шаг-1-получаем-oauth2-токен">Шаг 1: Получаем OAuth2-токен</h2>
<p>Тебе нужен service account (сервисный аккаунт) в Google Cloud Console — это проще, чем OAuth2 для пользователей, потому что не требует браузерного редиректа.</p>
<p>Создаёшь сервисный аккаунт, скачиваешь JSON с ключом, и делишься с этим аккаунтом своим Spreadsheet («Дать доступ» → email сервисного аккаунта).</p>
<p>Получение токена из 1С (через JWT):</p>
<pre tabindex="0"><code class="language-bsl" data-lang="bsl">Функция ПолучитьТокенGoogleServiceAccount(ПутьКJSON)
    
    ДанныеКлюча = ЗначениеИзСтрокиJSON(ПрочитатьФайл(ПутьКJSON));
    
    // Формируем JWT
    Заголовок = БазовоеКодированиеURL(ЗаписатьJSON(Новый Структура(&#34;alg,typ&#34;, &#34;RS256&#34;, &#34;JWT&#34;)));
    ВремяСейчас = ТекущаяУниверсальнаяДатаВМиллисекундах() / 1000;
    
    Payload = Новый Структура();
    Payload.Вставить(&#34;iss&#34;, ДанныеКлюча[&#34;client_email&#34;]);
    Payload.Вставить(&#34;scope&#34;, &#34;https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/spreadsheets&#34;);
    Payload.Вставить(&#34;aud&#34;, &#34;https://oauth2.googleapis.com/token&#34;);
    Payload.Вставить(&#34;exp&#34;, ВремяСейчас + 3600);
    Payload.Вставить(&#34;iat&#34;, ВремяСейчас);
    
    // ... подпись через RSA-SHA256 с PrivateKey из JSON ...
    // Используй компоненту подписи или готовую библиотеку с infostart
    
КонецФункции;
</code></pre><p>Подписать JWT в 1С напрямую непросто — нужна внешняя компонента или готовая библиотека. На infostart есть несколько бесплатных реализаций; ищи по «JWT 1С Google» — найдёшь рабочий код.</p>
<h2 id="шаг-2-загружаем-файл-на-google-drive">Шаг 2: Загружаем файл на Google Drive</h2>
<pre tabindex="0"><code class="language-bsl" data-lang="bsl">Функция ЗагрузитьФайлNaDrive(Токен, ПутьКФайлу, ИмяФайла)
    
    Соединение = Новый HTTPСоединение(&#34;www.googleapis.com&#34;, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());
    
    // Multipart-запрос: метаданные + бинарные данные
    Граница = &#34;boundary_1c_upload&#34;;
    
    ЧастьМета = &#34;--&#34; + Граница + Символы.ПС
        + &#34;Content-Type: application/json; charset=UTF-8&#34; + Символы.ПС + Символы.ПС
        + &#34;{&#34;&#34;name&#34;&#34;: &#34;&#34;&#34; + ИмяФайла + &#34;&#34;&#34;}&#34; + Символы.ПС;
    
    ЧастьДанных = &#34;--&#34; + Граница + Символы.ПС
        + &#34;Content-Type: image/jpeg&#34; + Символы.ПС + Символы.ПС;
    
    Конец = Символы.ПС + &#34;--&#34; + Граница + &#34;--&#34;;
    
    Заголовки = Новый Соответствие();
    Заголовки[&#34;Authorization&#34;] = &#34;Bearer &#34; + Токен;
    Заголовки[&#34;Content-Type&#34;] = &#34;multipart/related; boundary=&#34; + Граница;
    
    // Собираем тело запроса (бинарные данные + текст)
    // ...
    
    Запрос = Новый HTTPЗапрос(&#34;/upload/drive/v3/files?uploadType=multipart&#34;, Заголовки);
    Ответ = Соединение.ОтправитьДляПолучения(Запрос);
    
    ДанныеОтвета = ЗначениеИзСтрокиJSON(Ответ.ПолучитьТелоКакСтроку());
    Возврат ДанныеОтвета[&#34;id&#34;]; // FileId на Drive
    
КонецФункции;
</code></pre><h2 id="шаг-3-открываем-доступ-к-файлу">Шаг 3: Открываем доступ к файлу</h2>
<p>Файл на Drive по умолчанию приватный. Нужно сделать его доступным по ссылке:</p>
<pre tabindex="0"><code class="language-bsl" data-lang="bsl">Процедура УстановитьПубличныйДоступ(Токен, FileId)
    
    Соединение = Новый HTTPСоединение(&#34;www.googleapis.com&#34;, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());
    
    ТелоJSON = &#34;{&#34;&#34;role&#34;&#34;: &#34;&#34;reader&#34;&#34;, &#34;&#34;type&#34;&#34;: &#34;&#34;anyone&#34;&#34;}&#34;;
    
    Заголовки = Новый Соответствие();
    Заголовки[&#34;Authorization&#34;] = &#34;Bearer &#34; + Токен;
    Заголовки[&#34;Content-Type&#34;] = &#34;application/json&#34;;
    
    Запрос = Новый HTTPЗапрос(&#34;/drive/v3/files/&#34; + FileId + &#34;/permissions&#34;, Заголовки);
    Запрос.УстановитьТелоИзСтроки(ТелоJSON);
    Соединение.ОтправитьДляПолучения(Запрос); // POST
    
КонецПроцедуры;
</code></pre><h2 id="шаг-4-вставляем-в-ячейку-через-sheets-api">Шаг 4: Вставляем в ячейку через Sheets API</h2>
<pre tabindex="0"><code class="language-bsl" data-lang="bsl">Процедура ВставитьИзображениеВЯчейку(Токен, SpreadsheetId, Лист, Ячейка, FileId)
    
    URL = &#34;https://lh3.googleusercontent.com/d/&#34; + FileId;
    Формула = &#34;=IMAGE(&#34;&#34;&#34; + URL + &#34;&#34;&#34;)&#34;;
    
    ТелоJSON = &#34;{&#34;&#34;valueInputOption&#34;&#34;:&#34;&#34;USER_ENTERED&#34;&#34;,&#34;&#34;data&#34;&#34;:[{&#34;&#34;range&#34;&#34;:&#34;&#34;&#34; 
        + Лист + &#34;!&#34; + Ячейка + &#34;&#34;&#34;,&#34;&#34;values&#34;&#34;:[[&#34;&#34;&#34; + Формула + &#34;&#34;&#34;]]}]}&#34;;
    
    Соединение = Новый HTTPСоединение(&#34;sheets.googleapis.com&#34;, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());
    
    Заголовки = Новый Соответствие();
    Заголовки[&#34;Authorization&#34;] = &#34;Bearer &#34; + Токен;
    Заголовки[&#34;Content-Type&#34;] = &#34;application/json&#34;;
    
    Запрос = Новый HTTPЗапрос(&#34;/v4/spreadsheets/&#34; + SpreadsheetId + &#34;/values:batchUpdate&#34;, Заголовки);
    Запрос.УстановитьТелоИзСтроки(ТелоJSON);
    Соединение.ОтправитьДляПолучения(Запрос);
    
КонецПроцедуры;
</code></pre><p>URL формата <code>lh3.googleusercontent.com/d/{FileId}</code> — это прямая ссылка на файл в Drive, которую принимает <code>=IMAGE()</code>.</p>
<p>Ограничение: <code>=IMAGE()</code> загружает картинку при открытии таблицы, поэтому изображения при печати и экспорте в PDF могут не отобразиться, если нет интернета. Если нужна именно embedded картинка (для печати) — придётся использовать Google Apps Script, который это делает нативно, но вызвать его из 1С можно только через веб-хук.</p>
]]></content:encoded></item><item><title>Документ Word открывается и сразу закрывается: почему COM-автоматизация из 1С не работает так, как ожидаешь</title><link>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_word-com-open-close-instantly/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_word-com-open-close-instantly/</guid><description>&lt;p&gt;Написал код, запустил — окно Word мелькнуло и пропало. Или вообще не открылось, но файл почему-то изменился. Или открылось, но 1С завис в ожидании чего-то, и пришлось убивать процесс. COM-автоматизация Word из 1С — это один из тех углов платформы, где интуиция подводит почти всегда. Поведение зависит от десятка параметров, которые нигде не описаны вместе.&lt;/p&gt;
&lt;h2 id="корень-проблемы-кто-владеет-объектом"&gt;Корень проблемы: кто владеет объектом&lt;/h2&gt;
&lt;p&gt;Когда ты пишешь &lt;code&gt;СоздатьОбъект(&amp;quot;Word.Application&amp;quot;)&lt;/code&gt;, 1С создаёт COM-объект и держит на него ссылку. Но Word как приложение имеет собственный жизненный цикл. Если ты не сделал его видимым явно, Word работает в &lt;strong&gt;фоновом режиме&lt;/strong&gt; — без окна, без сообщений пользователю. При этом он всё равно может отображать диалоги (например, «Сохранить изменения?»), которые ты не видишь и не можешь закрыть.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Написал код, запустил — окно Word мелькнуло и пропало. Или вообще не открылось, но файл почему-то изменился. Или открылось, но 1С завис в ожидании чего-то, и пришлось убивать процесс. COM-автоматизация Word из 1С — это один из тех углов платформы, где интуиция подводит почти всегда. Поведение зависит от десятка параметров, которые нигде не описаны вместе.</p>
<h2 id="корень-проблемы-кто-владеет-объектом">Корень проблемы: кто владеет объектом</h2>
<p>Когда ты пишешь <code>СоздатьОбъект(&quot;Word.Application&quot;)</code>, 1С создаёт COM-объект и держит на него ссылку. Но Word как приложение имеет собственный жизненный цикл. Если ты не сделал его видимым явно, Word работает в <strong>фоновом режиме</strong> — без окна, без сообщений пользователю. При этом он всё равно может отображать диалоги (например, «Сохранить изменения?»), которые ты не видишь и не можешь закрыть.</p>
<p>Самое частое: код заканчивается, переменная выходит из области видимости, 1С вызывает деструктор COM-объекта — и Word закрывается, не спросив, сохранять ли документ. Если файл был открыт на запись, он или не сохранится, или сохранится в неполном состоянии.</p>
<h2 id="правильная-структура-кода">Правильная структура кода</h2>
<pre tabindex="0"><code class="language-bsl" data-lang="bsl">Перем ПриложениеWord;
Перем Документ;

Попытка
    ПриложениеWord = СоздатьОбъект(&#34;Word.Application&#34;);
    ПриложениеWord.Visible = Истина;  // показываем окно явно
    ПриложениеWord.DisplayAlerts = 0; // wdAlertsNone — убираем диалоги
    
    Документ = ПриложениеWord.Documents.Open(ПутьКФайлу);
    
    // ... работа с документом ...
    
    Документ.Save();
    Документ.Close(0); // 0 = wdDoNotSaveChanges — не спрашиваем про сохранение
    
Исключение
    Сообщить(&#34;Ошибка: &#34; + ОписаниеОшибки());
КонецПопытки;

// Явно закрываем приложение ПОСЛЕ работы с документом
Если ПриложениеWord &lt;&gt; Неопределено Тогда
    ПриложениеWord.Quit();
    ПриложениеWord = Неопределено;
КонецЕсли;
</code></pre><p>Три ключевых момента: <code>Visible = Истина</code> (иначе Word-процесс висит невидимым и может накапливаться), <code>DisplayAlerts = 0</code> (иначе документ застревает на невидимом диалоге), явный <code>Quit()</code> в конце (иначе процесс WINWORD.EXE остаётся в памяти).</p>
<h2 id="почему-документ-мелькает-и-закрывается">Почему документ «мелькает» и закрывается</h2>
<p>Это классика: <code>Visible = Истина</code>, но <code>Quit()</code> вызывается до того, как пользователь что-то сделал. Типичная структура с багом:</p>
<pre tabindex="0"><code class="language-bsl" data-lang="bsl">// НЕПРАВИЛЬНО
Word = СоздатьОбъект(&#34;Word.Application&#34;);
Word.Visible = Истина;
Документ = Word.Documents.Open(Путь);
// ... код заканчивается, Word уничтожается
</code></pre><p>Если цель — показать документ пользователю и не закрывать его немедленно, нужно либо не вызывать <code>Quit()</code> вообще (пользователь закрывает сам), либо дождаться закрытия через цикл проверки:</p>
<pre tabindex="0"><code class="language-bsl" data-lang="bsl">// Ждём, пока пользователь закроет документ
Пока ПриложениеWord.Documents.Count &gt; 0 Цикл
    ОбработкаПрерыванияПользователя();
КонецЦикла;
</code></pre><h2 id="скрытые-диалоги--самая-коварная-проблема">Скрытые диалоги — самая коварная проблема</h2>
<p><code>DisplayAlerts = 0</code> убирает большинство диалогов Word, но не все. Диалог «Файл заблокирован другим пользователем» или «Документ содержит макросы» может всё равно появиться. На сервере это катастрофа: WINWORD.EXE висит и ждёт клика, которого никогда не будет.</p>
<p>Для серверной автоматизации (фоновые задания, регламентные операции) COM-автоматизация Word — <strong>плохой выбор</strong>. Используй вместо этого:</p>
<ul>
<li><strong>OpenDocumentFormat через пакет XML</strong> — 1С умеет работать с .docx как с ZIP напрямую, без Word</li>
<li><strong>Шаблоны с заполнением через XML</strong> — надёжнее и быстрее в 10 раз</li>
<li><strong>Сторонние компоненты</strong> типа Aspose.Words или LibreOffice в headless-режиме</li>
</ul>
<p>Если без COM не обойтись (например, сложное форматирование или макросы), запускай его только в клиентском коде, а на сервере никогда.</p>
<p>Если проблема не воспроизводится у тебя локально, но ломается на сервере — проверь, под каким пользователем запущен агент сервера 1С: COM-объекты Word требуют, чтобы у пользователя была настроена интерактивная сессия Windows. Сервисный аккаунт без профиля просто не умеет запускать Word.</p>
]]></content:encoded></item><item><title>Мы ждали нормальный IDE двадцать лет. Потом взяли его сами</title><link>https://darachubarova.github.io/infostart-agent/posts/trends_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B8_%D0%B8%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B_2026-05-27/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://darachubarova.github.io/infostart-agent/posts/trends_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B8_%D0%B8%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B_2026-05-27/</guid><description>&lt;p&gt;&lt;em&gt;27 мая 2026&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Когда статья без единой строчки кода собирает 158 комментариев за пять дней, это не просто хороший контент. Это диагноз.&lt;/p&gt;
&lt;p&gt;«OneBase и open-source решения в 1C-разработке» — публикация, которая взорвала ленту infostart.ru в конце мая, посвящена проекту на Go с 1С-подобным синтаксисом. YAML-конфигурации вместо XML-дампов. SQLite или PostgreSQL по выбору. Бинарник в двадцать мегабайт. Работает на Raspberry Pi. Кто-то взял и написал альтернативную платформу — не для того чтобы заменить 1С в корпоративном секторе, а чтобы просто попробовать иначе.&lt;/p&gt;</description><content:encoded><![CDATA[<p><em>27 мая 2026</em></p>
<hr>
<p>Когда статья без единой строчки кода собирает 158 комментариев за пять дней, это не просто хороший контент. Это диагноз.</p>
<p>«OneBase и open-source решения в 1C-разработке» — публикация, которая взорвала ленту infostart.ru в конце мая, посвящена проекту на Go с 1С-подобным синтаксисом. YAML-конфигурации вместо XML-дампов. SQLite или PostgreSQL по выбору. Бинарник в двадцать мегабайт. Работает на Raspberry Pi. Кто-то взял и написал альтернативную платформу — не для того чтобы заменить 1С в корпоративном секторе, а чтобы просто попробовать иначе.</p>
<p>Комментарии разделились ровно так, как делятся всегда, когда задет нерв. Starik-2005 трезво заметил: «Бизнес-логика генерирует трудности — то, что просто в 1С, может быть сложнее здесь». Dmpas возразил: «Низкокодовые платформы справляются быстрее, чем стандартный подход 1С». Спор не закончился — он перетёк в следующий пост, потом в следующий. Сто пятьдесят восемь человек пришли поговорить не про OneBase — они пришли поговорить про то, почему им тесно там, где они работают каждый день.</p>
<p>Это первое, что нужно понять про майский срез infostart.ru: за техническими дискуссиями стоит один и тот же подтекст. Сообщество медленно, но верно конструирует инструментарий, который платформа так и не дала.</p>
<p>Второй сигнал — в статьях про AI. Их в топе семь штук, и только ленивый не написал про ChatGPT или Claude в контексте 1С. Но читаешь комментарии — и понимаешь, что интерес неоднородный. Andrew.ab описывает рабочий процесс: «MCP-агенты для анализа метаданных, IDE Cursor с GLM 4.7» — и это звучит не как эксперимент, а как продакшн-workflow. Человек не пользуется конфигуратором для навигации по коду. Он открыл Cursor, подключил языковую модель — и всё заработало лучше.</p>
<p>Kozusenok идёт ещё дальше: «Gemma 4 26B через LM Studio работает с производительностью 7-11 токенов в секунду» на обычном железе без интернета. Ноль подписок. Ноль телеметрии. Полная автономность. Это не гик-развлечение — это ответ на вопрос «что делать с NDA и закрытым кодом клиента», который в другой ветке собрал семьдесят восемь комментариев сам по себе.</p>
<p>Ibrogim, который, кстати, тот самый автор OneBase, в дискуссии про AI написал просто: «Claude и GPT за двадцать долларов в месяц покрывают разные сценарии». Для архитектурных решений — Claude. Для рутины — что подешевле. Практичная, немного усталая формула человека, который давно перестал ждать встроенных инструментов от вендора.</p>
<p>Вот в чём парадокс, который я не могу не назвать своими словами. Мы обсуждаем AI не потому что AI — это захватывающий новый мир. Мы обсуждаем AI потому что он закрывает дыры. Language server для BSL — сообщество. Фреймворк для unit-тестирования YAxUnit — сообщество. Нормальная работа с рефакторингом в большом проекте — через Cursor и языковую модель, то есть опять сообщество плюс сторонний инструмент. В 2026 году Docker-статья по-прежнему бьёт шестьдесят пять комментариев, потому что контейнеризация 1С-сервера для части аудитории всё ещё открытие.</p>
<p>Я не говорю это как упрёк платформе — я говорю это как наблюдение про сообщество. То, что происходит сейчас на infostart.ru, это экосистема, которая взрослеет. Люди перестали ждать. Они берут Go, пишут альтернативную платформу, выкладывают в open-source и получают сто пятьдесят восемь комментариев. Они подключают MCP-сервер к конфигуратору метаданных и автоматизируют то, на что раньше уходили дни. Они запускают двадцатишестимиллиардную модель локально, потому что не хотят отправлять код клиента в облако.</p>
<p>Это не хаос. Это не разбегание в разные стороны. Это — методом проб — складывается новый профиль профессии. Называть его «1С-разработчик» уже немного неточно. Скорее — инженер, который умеет на 1С, но не ограничен ею.</p>
<p>Тренд номер один по майскому срезу — AI-инструменты (trend_score 390 против 76 у DevOps и столько же у инструментария). Но если смотреть честно, это не сигнал про AI. Это сигнал про инструментальный голод, который наконец начали утолять — и не сверху вниз, а снизу вверх.</p>
<p>Один вопрос, который я оставлю без ответа, потому что он стоит того, чтобы ответить самостоятельно: если вы уже работаете в Cursor, запускаете локальные модели, пишете тесты на YAxUnit и деплоите через Docker — что именно в вашем рабочем дне остаётся специфично «1С»? И вас это устраивает или нет?</p>
]]></content:encoded></item><item><title>Резервное копирование высоконагруженной базы 1С: как не останавливать работу и не терять данные</title><link>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_highload-1c-backup/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_highload-1c-backup/</guid><description>&lt;p&gt;Ты открываешь настройки резервного копирования в конфигураторе, видишь кнопку «Выгрузить информационную базу» — и понимаешь, что это не вариант. База 200 ГБ, 150 активных пользователей, окно обслуживания — ноль. Стандартные инструменты платформы сделаны для другого размера задач. Для высоконагруженной базы нужна другая архитектура резервирования.&lt;/p&gt;
&lt;h2 id="почему-стандартный-dt-бэкап-не-работает-при-нагрузке"&gt;Почему стандартный dt-бэкап не работает при нагрузке&lt;/h2&gt;
&lt;p&gt;Выгрузка в .dt делает логическую копию: блокирует базу, читает все объекты, сериализует. При базе больше 20–30 ГБ это занимает часы. Пользователи не могут работать. На файловой базе это вообще единственный способ, но файловая база при высокой нагрузке — это уже само по себе архитектурная проблема.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Ты открываешь настройки резервного копирования в конфигураторе, видишь кнопку «Выгрузить информационную базу» — и понимаешь, что это не вариант. База 200 ГБ, 150 активных пользователей, окно обслуживания — ноль. Стандартные инструменты платформы сделаны для другого размера задач. Для высоконагруженной базы нужна другая архитектура резервирования.</p>
<h2 id="почему-стандартный-dt-бэкап-не-работает-при-нагрузке">Почему стандартный dt-бэкап не работает при нагрузке</h2>
<p>Выгрузка в .dt делает логическую копию: блокирует базу, читает все объекты, сериализует. При базе больше 20–30 ГБ это занимает часы. Пользователи не могут работать. На файловой базе это вообще единственный способ, но файловая база при высокой нагрузке — это уже само по себе архитектурная проблема.</p>
<p>Для клиент-серверного варианта (SQL Server или PostgreSQL) правильный ответ — <strong>бэкап на уровне СУБД</strong>, а не через инструменты 1С.</p>
<h2 id="sql-server-три-уровня-защиты">SQL Server: три уровня защиты</h2>
<p><strong>Full backup</strong> — полная копия, база онлайн, пользователи работают. SQL Server использует теневое копирование, и для базы 200 ГБ это занимает 20–40 минут в зависимости от диска. Делай раз в сутки, ночью.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span>BACKUP <span style="color:#66d9ef">DATABASE</span> [my_1c_base] 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">TO</span> DISK <span style="color:#f92672">=</span> N<span style="color:#e6db74">&#39;D:\Backups\my_1c_base_full.bak&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">WITH</span> COMPRESSION, CHECKSUM, STATS <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>;
</span></span></code></pre></div><p><strong>Differential backup</strong> — только изменения с последнего full. Размер и время: 5–15% от full. Делай каждые 2–4 часа.</p>
<p><strong>Log backup</strong> — бэкап журнала транзакций, при модели восстановления FULL. Позволяет восстановить базу на любой момент времени. Делай каждые 15–30 минут. Это ключ к точечному восстановлению (point-in-time recovery).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#75715e">-- Переключи модель восстановления, если ещё SIMPLE
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">ALTER</span> <span style="color:#66d9ef">DATABASE</span> [my_1c_base] <span style="color:#66d9ef">SET</span> RECOVERY <span style="color:#66d9ef">FULL</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Регулярный бэкап лога
</span></span></span><span style="display:flex;"><span>BACKUP LOG [my_1c_base]
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">TO</span> DISK <span style="color:#f92672">=</span> N<span style="color:#e6db74">&#39;D:\Backups\my_1c_base_log.bak&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">WITH</span> COMPRESSION;
</span></span></code></pre></div><p>Все три типа бэкапа SQL Server делает <strong>без остановки работы пользователей</strong>. Именно поэтому клиент-серверный вариант — единственный правильный выбор для нагруженной базы.</p>
<h2 id="postgresql-аналогичная-схема">PostgreSQL: аналогичная схема</h2>
<p>Для PostgreSQL-варианта:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Физический бэкап через pg_basebackup (онлайн, без остановки)</span>
</span></span><span style="display:flex;"><span>pg_basebackup -D /backup/base -Ft -z -P -Xs -c fast
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># WAL-архивирование для point-in-time recovery</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># В postgresql.conf:</span>
</span></span><span style="display:flex;"><span>archive_mode <span style="color:#f92672">=</span> on
</span></span><span style="display:flex;"><span>archive_command <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;cp %p /backup/wal/%f&#39;</span>
</span></span><span style="display:flex;"><span>wal_level <span style="color:#f92672">=</span> replica
</span></span></code></pre></div><p><code>pg_basebackup</code> создаёт консистентный снимок работающей базы. WAL-архивирование — аналог log backup в SQL Server.</p>
<h2 id="автоматизация-и-контроль">Автоматизация и контроль</h2>
<p>Бэкап без проверки — это не бэкап. Два обязательных элемента:</p>
<p><strong>Проверка целостности.</strong> SQL Server:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span>RESTORE VERIFYONLY <span style="color:#66d9ef">FROM</span> DISK <span style="color:#f92672">=</span> N<span style="color:#e6db74">&#39;D:\Backups\my_1c_base_full.bak&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">WITH</span> CHECKSUM;
</span></span></code></pre></div><p>Добавь в расписание сразу после каждого бэкапа.</p>
<p><strong>Тестовое восстановление.</strong> Раз в месяц разворачивай бэкап на отдельный сервер и проверяй, что 1С запускается и данные на месте. Без этого ты не знаешь, работает ли твоя схема.</p>
<p><strong>Мониторинг.</strong> Создай SQL Agent Job для каждого типа бэкапа и настрой уведомления на провал. Стандартная ошибка — «бэкапы работали полгода, потом диск заполнился, скрипт начал падать, никто не заметил».</p>
<h2 id="когда-нужен-always-on-или-зеркалирование">Когда нужен Always On или зеркалирование</h2>
<p>Если требование — восстановление за минуты (RTO &lt; 5 мин) или потеря данных не более 1 минуты (RPO &lt; 1 мин) — бэкапы не спасут. Нужен SQL Server Always On Availability Groups или репликация PostgreSQL. Это отдельная тема, но знай: Always On — это не замена бэкапам, это добавление к ним.</p>
<p>Если ты на файловом варианте и думаешь «а вдруг и так сойдёт» — переходи на клиент-серверный при первой возможности. Это не просто удобство, это базовая гигиена для любой базы, где работает больше 10 человек. Файловый вариант при нагрузке теряет данные тихо и необратимо.</p>
<p>Если проблема с конкретной реализацией бэкапа на SQL Server — покажи план обслуживания или скрипты, и сообщество поможет. Обычно ошибки прячутся в правах доступа к папке бэкапа или в переполнении диска.</p>
]]></content:encoded></item><item><title>Синхронизация товаров между 1С и Wildberries: как не потерять товар при матчинге</title><link>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_wildberries-product-sync/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://darachubarova.github.io/infostart-agent/posts/forum_forum9_wildberries-product-sync/</guid><description>&lt;p&gt;Задача выглядит просто: есть товары в 1С, есть товары на WB — нужно их связать и синхронизировать. На практике она превращается в головоломку с тремя разными идентификаторами, меняющимся API и тем фактом, что WB понимает «артикул» иначе, чем 1С. Если ты уже потратил день на разбор ответов API и всё ещё не понимаешь, по какому полю матчить — ты не одинок, это путает всех.&lt;/p&gt;
&lt;h2 id="как-wb-идентифицирует-товары"&gt;Как WB идентифицирует товары&lt;/h2&gt;
&lt;p&gt;У Wildberries есть три разных понятия, которые легко перепутать:&lt;/p&gt;</description><content:encoded><![CDATA[<p>Задача выглядит просто: есть товары в 1С, есть товары на WB — нужно их связать и синхронизировать. На практике она превращается в головоломку с тремя разными идентификаторами, меняющимся API и тем фактом, что WB понимает «артикул» иначе, чем 1С. Если ты уже потратил день на разбор ответов API и всё ещё не понимаешь, по какому полю матчить — ты не одинок, это путает всех.</p>
<h2 id="как-wb-идентифицирует-товары">Как WB идентифицирует товары</h2>
<p>У Wildberries есть три разных понятия, которые легко перепутать:</p>
<p><strong>nmId</strong> (числовой, например <code>296729549</code>) — это ID номенклатуры WB, уникальный в рамках всей платформы. Назначается WB автоматически при создании карточки. Менять нельзя, исчезает при удалении карточки.</p>
<p><strong>vendorCode</strong> (строковый, например <code>MY-SKU-001</code>) — это <strong>твой</strong> артикул, который ты сам задаёшь при создании карточки. Это единственный идентификатор, который ты контролируешь и который должен совпадать с артикулом в 1С.</p>
<p><strong>barcode</strong> — штрихкод, может быть несколько на одну позицию.</p>
<p>Золотое правило: матчить 1С ↔ WB нужно по <code>vendorCode</code>. Это поле ты заполнял сам при создании карточки — оно и должно совпадать с полем «Артикул» в номенклатуре 1С.</p>
<h2 id="получение-списка-товаров-с-wb-через-api-v3">Получение списка товаров с WB через API v3</h2>
<p>API Wildberries v3 — актуальная версия на 2026 год. V2 устарел.</p>
<pre tabindex="0"><code class="language-bsl" data-lang="bsl">Функция ПолучитьТоварыWB(Токен)
    
    НТТР = Новый HTTPСоединение(&#34;suppliers-api.wildberries.ru&#34;, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());
    
    Заголовки = Новый Соответствие();
    Заголовки[&#34;Authorization&#34;] = Токен;
    Заголовки[&#34;Content-Type&#34;] = &#34;application/json&#34;;
    
    Тело = Новый Структура();
    Тело.Вставить(&#34;settings&#34;, Новый Структура(
        &#34;cursor,filter&#34;,
        Новый Структура(&#34;limit&#34;, 1000),
        Новый Структура(&#34;withPhoto&#34;, -1)
    ));
    
    Запрос = Новый HTTPЗапрос(&#34;/content/v2/get/cards/list&#34;, Заголовки);
    Запрос.УстановитьТелоИзСтроки(Формат(ЗначениеВСтрокуJSON(Тело)));
    
    Ответ = НТТР.ОтправитьДляПолучения(Запрос);
    
    Если Ответ.КодСостояния = 200 Тогда
        Возврат ЗначениеИзСтрокиJSON(Ответ.ПолучитьТелоКакСтроку());
    КонецЕсли;
    
    Возврат Неопределено;

КонецФункции;
</code></pre><p>В ответе ищи поле <code>vendorCode</code> в каждой карточке — это и есть твой артикул для матчинга.</p>
<h2 id="стратегия-синхронизации-три-сценария">Стратегия синхронизации: три сценария</h2>
<p><strong>Сценарий 1: Первичная загрузка (1С → WB)</strong>
Берёшь номенклатуру из 1С, создаёшь карточки на WB через <code>POST /content/v2/cards/upload</code>. В качестве <code>vendorCode</code> подставляешь артикул из 1С. После создания WB вернёт <code>nmId</code> — его нужно сохранить в дополнительных реквизитах номенклатуры.</p>
<p><strong>Сценарий 2: Обновление остатков и цен (1С → WB)</strong>
Для остатков: <code>PUT /api/v3/stocks/{warehouseId}</code> — принимает массив <code>{sku, amount}</code>. <code>sku</code> здесь — это <strong>barcode</strong>, не vendorCode! Нужно заранее получить маппинг barcode ↔ vendorCode.
Для цен: <code>POST /public/api/v1/prices</code> — принимает <code>{nmId, price, discount}</code>.</p>
<p><strong>Сценарий 3: Обратная синхронизация (WB → 1С)</strong>
Продажи, возвраты, штрафы приходят через <code>GET /api/v3/supplier/orders</code>. В заказе есть <code>article</code> — это vendorCode. По нему находишь номенклатуру в 1С и создаёшь документы.</p>
<h2 id="хранение-связей-в-1с">Хранение связей в 1С</h2>
<p>Не храни nmId в коде — выноси в справочник или дополнительные реквизиты:</p>
<pre tabindex="0"><code>Справочник.НоменклатураWB:
  Номенклатура (ссылка на Номенклатуру)
  nmId (число)
  vendorCode (строка)
  Артикул_WB (строка — barcode для остатков)
  ДатаПоследнейСинхронизации
</code></pre><p>Если у тебя уже есть товары на WB и ты создаёшь 1С сбоку, первый шаг — выгрузи весь каталог WB, пройди по <code>vendorCode</code> и сопоставь с 1С вручную или через загрузку в промежуточную таблицу.</p>
<p>Если что-то не сматчилось — не паникуй. WB позволяет отредактировать <code>vendorCode</code> через API (<code>POST /content/v2/cards/update</code>), но делать это надо осторожно: изменение vendorCode не меняет nmId, но может сломать существующие интеграции.</p>
<p>Когда матчинг налажен, дальнейшая синхронизация — это уже технические детали. Главный источник боли именно здесь, в первичной связке идентификаторов. Если проблема осталась, посмотри в сторону готовых коннекторов: «1С-Битрикс: Маркетплейс» и несколько сторонних разработок на infostart имеют рабочие реализации этой логики.</p>
]]></content:encoded></item></channel></rss>