The notes described a machine that no longer matches: the runtime paths they hardcoded do not exist on this one, and three of their claims turned out to be wrong when the plugin was actually installed. What was wrong, and what is true: 1. Runtime paths. `~/.dsh/dsh-runtimes/...` is only where a downloaded runtime lives; this install carries it in the application. The notes now probe both locations and take the one that exists. 2. "You cannot install into the desktop profile from the CLI". The launcher refuses `desktop` only for booting and for --dump-config; `dsh plugin --profile desktop ...` is allowed because the Desktop carrier passes manageDesktopProfile. Verified: install, list, remove all work, and each one keeps dsh.profile.bundles in sync by itself. 3. "An application restart is required". Not on Desktop. The base bundle enables hmr whenever profileContext is supplied, and the application supplies it, so editing the profile manifest recomposes the tree live and the client half reaches an open page over the HMR transport. The application had started at 16:36 and the pill appeared in that same process after the 16:41 install. Also documented, because it decides whether an edit reaches the harness: `file:` on Windows produces hardlinks out of the pnpm store, so an in-place write is visible immediately but an atomic replace silently breaks the link; `link:` is a junction and always sees edits. The plugin is now installed as `link:` for that reason. The design note keeps its original text and carries dated corrections plus a table of what was actually verified, so the next install does not repeat the probing.
11 KiB
Установка на другое устройство
Плагин — один файл: dist/dsh-session-cost-0.1.0.tgz. Перенесите его на другую машину любым способом (флешка, облако, scp).
Что нужно на той машине
-
DeepSeek Harness 0.2.x (проверено на
0.2.1-rc.3). Точную версию печатаетruntime.json, полеdesktopVersion— файл лежит в одном из двух мест, смотря как установлен харнесс:$runtimeJson = @( "$env:USERPROFILE\.dsh\dsh-runtimes\dsh-primary-runtime\runtime.json", "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\primary-runtime\runtime.json" ) | Where-Object { Test-Path $_ } | Select-Object -First 1 (Get-Content $runtimeJson -Raw | ConvertFrom-Json).desktopVersionПервый путь — рантайм, скачанный харнессом отдельно; второй — рантайм, вложенный в установленное приложение (так на машине, где плагин писался). Второй путь ищется от
$env:LOCALAPPDATA, поэтому при установке в другое место подставьте свой. -
Модель должна идти через routerai: стоимость приходит в ответе провайдера, другие провайдеры её не отдают, и ячейка просто молчит.
-
Ничего больше: ключ
ROUTERAI_API_KEYплагину не нужен. Он читает стоимость из ответа, который харнесс и так получает, и сам никуда не ходит.
Установка
Ставим в профиль desktop — это профиль, который поднимает приложение.
Самый короткий путь — одна команда dsh plugin: она и ставит пакет, и дописывает его в список бандлов профиля (проверено: после неё dsh-session-cost уже в dsh.profile.bundles).
# dsh.cmd лежит рядом с установленным приложением; ищем, не угадывая путь
$dsh = @(
"$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd",
"C:\Program Files\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd"
) | Where-Object { Test-Path $_ } | Select-Object -First 1
$tgz = "C:\путь\к\dsh-session-cost-0.1.0.tgz"
& $dsh plugin --profile desktop add "file:$tgz"
Оба пути — рядом с DeepSeek Harness.exe: установщик кладёт приложение либо в %LOCALAPPDATA%\Programs, либо в C:\Program Files, смотря как ставили.
Профиль desktop принадлежит приложению, поэтому обычный запуск и дамп конфигурации по нему закрыты: dsh --profile desktop --dump-config отвечает error: profile "desktop" is managed exclusively by the Electron application. Это ограничение на запуск, а не на управление пакетами: dsh plugin --profile desktop ... в поставке десктопа разрешён и работает.
Если ставите pnpm напрямую
Штатный dsh plugin — обёртка над pnpm, и разница только в одном: он же ведёт список бандлов. Голый pnpm список не трогает, поэтому после него шаг со списком обязателен.
$node = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\primary-runtime\dependencies\node\bin\node.exe"
$pnpm = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\primary-runtime\dependencies\pnpm\bin\pnpm.mjs"
$profile = "$env:USERPROFILE\.dsh\profiles\desktop"
$tgz = "C:\путь\к\dsh-session-cost-0.1.0.tgz"
# 1. поставить пакет в профиль
& $node $pnpm add "file:$tgz" --dir $profile
# 2. дописать плагин в список бандлов (голый pnpm этого не делает)
$manifestPath = Join-Path $profile 'package.json'
$m = Get-Content $manifestPath -Raw | ConvertFrom-Json
if ($m.dsh.profile.bundles -notcontains 'dsh-session-cost') {
$m.dsh.profile.bundles += 'dsh-session-cost'
}
$m | ConvertTo-Json -Depth 10 | Set-Content $manifestPath -Encoding utf8
Без шага 2 пакет лежит в профиле и не загружается. Ровно в таком состоянии на машине, где плагин писался, оказался dsh-bottom-info-bar: установлен, но не активен.
Тумблером это тоже делается: Plugins в боковой панели → dsh-session-cost → включить. Страница правит тот же список бандлов (её host-половина plugin-manager на десктопе включена, потому что он передаёт profileContext).
file: и link: — чем отличаются на Windows
Формат записи в package.json профиля решает, как пакет попадёт в node_modules, и от этого зависит, что будет при правке исходника.
-
file:(так ставится.tgzи так стояло на машине-источнике изначально). pnpm кладёт содержимое в свой store и делает хардлинки вnode_modulesпрофиля. Это не копия: у файлов один и тот же File ID, поэтому правка на месте видна в профиле сразу, без переустановки. Но атомарная замена файла (сохранение через временный файл иrename— так делают многие редакторы,pnpm packи инструменты вроде нашего) рвёт хардлинк: в профиле остаётся старая версия, и нужна переустановка. Проверить, жив ли ещё линк:fsutil hardlink list "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-session-cost\lib\index.js"Два пути в выводе — линк цел; один — в профиле уже отдельная копия.
-
link:— junction на папку с исходником. Правки видны всегда, чем бы их ни делали, переустановка не нужна вовсе. Цена: pnpm предупреждает, чтоpeerDependencies(у плагина этоreact) из целевой папки не разрешатся, — для клиентской половины это неважно,reactподставляет модульная система браузера. Плагин в профилеdesktopстоит именно так, чтобы правкиlib/доезжали до харнесса без переустановки.
Живой линк ставится так (именно так плагин стоит на машине-источнике сейчас):
& $node $pnpm add "link:C:\Users\anton\src\dsh-cost-plugin" --dir $profile
Нужен ли перезапуск
На десктопе — нет. Базовый бандл включает hmr, когда приложение передаёт profileContext, а dsh-hmr следит за манифестом профиля и обоими файлами патчей: правка dsh.profile.bundles пересобирает дерево на ходу, и клиентская половина подхватывается открытой страницей через HMR-транспорт. Проверено: приложение стартовало в 16:36, пакет встал в 16:41, ячейка появилась в том же процессе.
Перезапуск нужен, если HMR выключен — в бандлах headless, sdk и acp он погашен в YAML, и там же, где профиль правили руками без пересборки. Перезагрузки одной страницы в этом случае недостаточно: плагины собираются при старте хоста.
Проверка
Открыть любой диалог, отправить сообщение. В нижнем ряду, сразу после родных ячеек, должна появиться сумма вида ₽ 0,1234.
Если пусто, открыть консоль (F12) и посмотреть строки [dsh-session-cost]:
session id: ...— какой id определился;cannot read ...— не дошёл запрос до хостовой половины.
Оба сообщения печатаются один раз на каждую новую причину, а не на каждый опрос.
Что переносится, а что нет
Переносится: сам плагин — код, страница состояния, расчёт.
Не переносится: накопленный реестр. Стоимость хранится на каждой машине отдельно, в ~/.dsh/dsh-session-cost/state.json. Это сделано намеренно: суммы относятся к сессиям конкретной установки, и чужие сессии в новом реестре всё равно не к чему привязать.
Если всё же нужно перенести историю — скопируйте этот файл в ту же папку на новой машине. Формат переносимый, идентификаторы генераций глобально уникальны.
Как обновить плагин
Собрать новый архив здесь (pnpm pack --pack-destination dist), перенести, повторить установку.
Если плагин стоит ссылкой (link:), обновление не нужно: правится исходник, и после ближайшей пересборки дерева подхватывается новое. Если он стоит через file:, правка исходника доедет только при записи на месте — после атомарной замены файла переустановите пакет.
Как удалить
& $dsh plugin --profile desktop remove dsh-session-cost
Штатная команда убирает и пакет, и запись из dsh.profile.bundles (проверено). Если ставили голым pnpm — уберите dsh-session-cost из списка вручную или выключите тумблером в Plugins.
Реестр ~/.dsh/dsh-session-cost/ при удалении остаётся, как и у dsh-bottom-info-bar; удалите папку вручную, если хотите чистый лист.