dsh-composer-plus 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +69 -16
- package/README.es.md +69 -16
- package/README.fr.md +69 -16
- package/README.hi.md +69 -16
- package/README.id.md +69 -16
- package/README.ja.md +69 -16
- package/README.ko.md +69 -16
- package/README.md +69 -16
- package/README.pt-BR.md +69 -16
- package/README.ru.md +69 -16
- package/README.tr.md +69 -16
- package/README.vi.md +69 -16
- package/README.zh.md +69 -16
- package/assets/features/autoBackup.webp +0 -0
- package/assets/features/backup.webp +0 -0
- package/assets/features/branchTree.webp +0 -0
- package/assets/features/changesPanel.webp +0 -0
- package/assets/features/idleSwitch.webp +0 -0
- package/assets/features/projectMemory.webp +0 -0
- package/assets/features/questionFit.webp +0 -0
- package/assets/features/queueEdit.webp +0 -0
- package/assets/features/rescueConsole.webp +0 -0
- package/assets/features/sessionDoctor.webp +0 -0
- package/assets/features/stopSendFirst.webp +0 -0
- package/backup.mjs +1069 -0
- package/client.js +1278 -182
- package/index.js +1602 -37
- package/package.json +3 -2
- package/tether/gateway/server.mjs +1 -1
package/README.ru.md
CHANGED
|
@@ -29,7 +29,7 @@ dsh plugin --profile web add dsh-composer-plus
|
|
|
29
29
|
|
|
30
30
|
Затем перезапустите dsh. (CLI не может устанавливать плагины в профиль настольного приложения: им управляет само приложение.)
|
|
31
31
|
|
|
32
|
-
> pnpm в dsh пропускает версии, которые вышли меньше 24 часов назад. Сразу после выпуска укажите версию: `dsh-composer-plus@1.
|
|
32
|
+
> pnpm в dsh пропускает версии, которые вышли меньше 24 часов назад. Сразу после выпуска укажите версию: `dsh-composer-plus@1.16.0`.
|
|
33
33
|
|
|
34
34
|
## Функции
|
|
35
35
|
|
|
@@ -37,7 +37,7 @@ dsh plugin --profile web add dsh-composer-plus
|
|
|
37
37
|
|
|
38
38
|
| Функция | Как пользоваться | Снимок экрана |
|
|
39
39
|
|---|---|---|
|
|
40
|
-
| **Панель изменений** | <a id="feature-changespanel"></a>Правая боковая панель → `+` → **Изменения**.
|
|
40
|
+
| **Панель изменений** | <a id="feature-changespanel"></a>Правая боковая панель → `+` → **Изменения**. Страница открывается в режиме **Дерево**: это карта веток репозитория чата. Три карточки считают ветки: все, слитые и те, что ожидают слияния. Нажмите на карточку, чтобы показать только эти ветки; нажмите на неё ещё раз, чтобы показать все. Каждая ветка — это блок с её последним коммитом: зелёный, если её работа есть в основной ветке, оранжевый, если нет, синий для основной ветки. От каждой ветки идёт стрелка к ветке, которая её приняла (✅ **Слито**), или к ветке, от которой она началась (⏳ **Ожидает**, пунктир). Нажмите на блок, чтобы увидеть коммиты ветки, затем нажмите на коммит, чтобы увидеть его файлы и их diff. Нажмите **Слито**, чтобы увидеть файлы коммита слияния, или **Ожидает**, чтобы увидеть файлы, которые ветка приносит в свою целевую ветку. Удалённая ветка показывается, только если нет локальной ветки с таким же именем. В меню режимов выберите **Незафиксированные**, **Непроиндексированные**, **Проиндексированные** или **Ветка**: вы увидите изменённые файлы со счётчиками `+/-`. Нажмите на файл, чтобы открыть его diff. **Последний ход** открывает встроенный обзор dsh для последнего хода. **Этот чат** показывает только файлы, которые записали файловые инструменты открытого чата (write, edit) во всех его ходах, и их общий diff с первого сообщения. Кнопка **␣** скрывает изменения пробелов (`git diff -w`): строки, в которых изменились только отступы или концы строк, не показываются. Меню **…** файла → **Чаты, которые изменили этот файл** показывает чаты того же репозитория, инструменты записи или правки которых изменили этот файл, сначала самые новые, вместе с запросом, который это сделал; щелчок открывает этот чат на этом запросе. | <a href="assets/features/changesPanel.webp"><img src="assets/features/changesPanel.webp" width="160" alt="Снимок экрана: Панель изменений"></a> |
|
|
41
41
|
| **Идеи функций** | <a id="feature-featureideas"></a>Правая боковая панель → `+` → **Идеи функций** → **Предложить функции**. Модель чата читает краткую сводку проекта этого чата (файлы верхнего уровня, начало README и манифеста, структуру остальной части README, заголовки последних коммитов) и предлагает до 8 функций. Они появляются стопкой карточек на языке интерфейса dsh. Смахните карточку вправо (или нажмите **✓**, или клавишу `→`; в любом случае карточка улетает в свою сторону), чтобы начать новый чат в том же проекте. Чат начинается в режиме плана, а идея становится запросом, поэтому до одобрения плана ничего не меняется. Чтобы обойтись без плана, нажмите **▶ Создать сразу** (или клавишу `↑`; карточка улетает вверх): новый чат сразу начинается с идеей как обычным запросом, и модель вносит изменение и запускает свои проверки (одобрения действуют как обычно). Смахните влево (или **✕**, или `←`), чтобы пропустить карточку. **Отменить** (или `Z`) возвращает пропущенную карточку. Нажмите **↓** (или клавишу `↓`), чтобы отложить хорошую идею: она попадает в список проекта **На потом**. Этот список виден в каждом чате из той же папки проекта (и после перезапуска). **На потом (N)** открывает список. **Спланировать** начинает для идеи такой же чат в режиме плана, а **Создать сразу** — чат без плана; обе кнопки убирают её из списка. **Спланировать все (N)** начинает один чат в режиме плана для всех идей из списка, поэтому общие части планируются один раз. **Убрать из списка** удаляет её. **Копировать как чек-лист** копирует весь список в буфер обмена как чек-лист Markdown (`- [ ] Title — Summary`, по одной строке на идею) для трекера задач или файла TODO; сетевых запросов при этом нет. **Открыть issue на GitHub** у идеи открывает issue с её названием и кратким описанием (и тем, почему она важна) в репозитории проекта на GitHub через ваш собственный вход в GitHub CLI (`gh`); затем рядом с идеей появляется ссылка **Issue #N**, которая открывает issue. **Ещё идеи** добавляет карточки. Чтобы получить идеи только по одной области, введите короткую тему в поле **Тема** рядом с **Предложить функции** (не более 80 символов; `Enter` тоже запускает предложение) или нажмите одну из готовых тем под ним: **Производительность**, **Доступность**, **Тесты**, **Безопасность**, **Удобство** или **Документация** (повторное нажатие очищает тему). Тогда модель предлагает только функции по этой теме; пустое поле означает любые функции. В одном проекте идея не предлагается дважды: каждая предложенная идея (пропущенная, отложенная или начатая) попадает в список проекта **История**, модель получает указание больше не предлагать эти идеи, а идея с повторным заголовком отбрасывается. **История** показывает их с пометкой **Начата** или **Предложена**; **Забыть** (или **Забыть все**) позволяет идее появиться снова; идея, которая ещё есть в списке **На потом**, не попадает в предложения, пока вы не уберёте её оттуда. Модель запускается, только когда вы нажимаете кнопку. | <a href="assets/features/featureIdeas.webp"><img src="assets/features/featureIdeas.webp" width="160" alt="Снимок экрана: Идеи функций"></a> |
|
|
42
42
|
| **Поиск по содержимому** | <a id="feature-contentsearch"></a>Встроенный поиск dsh на боковой панели (лупа рядом с **Рабочие области**; `Cmd+K` в настольном приложении, `Cmd+Alt+K` в браузере) находит чаты не только по названию, но и по словам из ваших сообщений и ответов. Под чатом он показывает совпавший текст. Такой поиск в dsh уже есть, но выключен. Эта функция включает его и хранит поисковый индекс в файле на вашем компьютере. Индекс создаётся при первом поиске после запуска (около 15 с для 250 чатов, см. «Ограничения») и сохраняется для следующих запусков. Включено по умолчанию. Изменение действует после перезапуска dsh. | <a href="assets/features/contentSearch.webp"><img src="assets/features/contentSearch.webp" width="160" alt="Снимок экрана: Поиск по содержимому"></a> |
|
|
43
43
|
| **Откат хода** | <a id="feature-turnrollback"></a>Наведите указатель на своё сообщение и нажмите **↶** (рядом с кнопкой «Копировать»). **Только чат** убирает это сообщение и всё, что было после него (ответы, вызовы инструментов), из чата и из контекста модели. Само сообщение возвращается в поле ввода: измените его и отправьте снова. **Чат и файлы** сначала показывает файлы проекта, которые изменились после этого сообщения, а затем возвращает и их в прежнее состояние. Это касается и изменений, сделанных командами (`bash`), а не только инструментами редактирования dsh. Если ход выполняется, он сначала останавливается. Журнал чата никогда не переписывается: отозванную часть прячет одна скрытая метка, так же как встроенная команда dsh `/compact` прячет старые сообщения. Если установлен [dsh-rewind-plugin](https://www.npmjs.com/package/dsh-rewind-plugin), эту работу делает он, и Composer Plus не показывает вторую кнопку. После отката над полем ввода появляется панель **Повторить**. Она начинает новый чат с момента непосредственно перед откатом (те же сообщения и контекст), а в режиме **Чат и файлы** также возвращает файлы. Файл, который вы изменили после отката, попадает в список и сохраняется, если вы не отметите флажок, который его перезаписывает. | <a href="assets/features/turnRollback.webp"><img src="assets/features/turnRollback.webp" width="160" alt="Снимок экрана: Откат хода"></a> |
|
|
@@ -46,10 +46,12 @@ dsh plugin --profile web add dsh-composer-plus
|
|
|
46
46
|
| **История ввода** | <a id="feature-inputhistory"></a>В пустом поле ввода нажимайте `↑` / `↓`, чтобы листать отправленные сообщения, как в терминале. | <a href="assets/features/inputHistory.webp"><img src="assets/features/inputHistory.webp" width="160" alt="Снимок экрана: История ввода"></a> |
|
|
47
47
|
| **Режим плана по Shift+Tab** | <a id="feature-plantoggle"></a>`Shift+Tab` добавляет `/plan ` в начало черновика (нажмите ещё раз, чтобы убрать). Если чат уже в режиме плана, `Shift+Tab` выходит из него. | <a href="assets/features/planToggle.webp"><img src="assets/features/planToggle.webp" width="160" alt="Снимок экрана: Режим плана по Shift+Tab"></a> |
|
|
48
48
|
| **Сохранять фокус в поле ввода** | <a id="feature-keepfocus"></a>После отправки команды `/` или навыка курсор остаётся в поле ввода, и можно сразу печатать дальше. Это работает и для клавиатурных макросов, которые вводят команду и нажимают `Enter`. Пока dsh обрабатывает команду, поле ввода доступно только для чтения, и браузер снимает с него фокус. Эта функция возвращает фокус, если он не занят меню, диалогом или другим полем. | <a href="assets/features/keepFocus.webp"><img src="assets/features/keepFocus.webp" width="160" alt="Снимок экрана: Сохранять фокус в поле ввода"></a> |
|
|
49
|
+
| **Подгонять карточку вопроса под окно** | <a id="feature-questionfit"></a>Когда агент задаёт вам вопрос, вопрос и ответы прокручиваются в карточке вместе, а **Пропустить** и **Отправить** остаются видны внизу. Карточка занимает высоту окна (минус 200 px на заголовок чата и полосу чата), поэтому растёт и уменьшается вместе с окном. Без этой функции dsh ограничивает карточку 60% окна (не больше 520 px) и прокручивает только ответы: длинный вопрос может вытолкнуть из карточки свой конец, ответы и кнопки. | <a href="assets/features/questionFit.webp"><img src="assets/features/questionFit.webp" width="160" alt="Снимок экрана: Подгонять карточку вопроса под окно"></a> |
|
|
49
50
|
| **Продолжение в один клик** | <a id="feature-continuebutton"></a>После остановленного, завершившегося сбоем или оборванного хода в пустом поле ввода появляется **▶**. Один щелчок продолжает работу с текущего разговора. Ничего не нужно писать в поле ввода, и в чате не появляется новое сообщение. (Модель получает короткую скрытую заметку «продолжи с того места, где остановился», потому что некоторые провайдеры, например Claude, отклоняют запрос, который заканчивается ответом ассистента.) Сообщения в очереди остаются в ней: ▶ продолжает только остановленную задачу, а потом выполняется очередь. После завершённого хода остаётся обычная кнопка отправки. | <a href="assets/features/continueButton.webp"><img src="assets/features/continueButton.webp" width="160" alt="Снимок экрана: Продолжение в один клик"></a> |
|
|
50
51
|
| **Продолжать после перезапуска** | <a id="feature-resumeafterrestart"></a>По умолчанию выключено: включите функцию в **Настройки → Composer Plus**. Если выйти из dsh (или он закроется), пока чат работает, этот чат сам продолжит работу, когда вы снова откроете dsh. Он получает ту же скрытую заметку, что и при продолжении в один клик. Если выполнялся раунд цели (`/goal`), цель продолжается со следующего раунда (при каждом запуске dsh приостанавливает цели, пока вы их не возобновите). Чаты, которые вы остановили, которые завершились или завершились сбоем, не продолжаются. В самом dsh такой настройки нет: он только помечает такой ход как прерванный. | <a href="assets/features/resumeAfterRestart.webp"><img src="assets/features/resumeAfterRestart.webp" width="160" alt="Снимок экрана: Продолжать после перезапуска"></a> |
|
|
51
52
|
| **Перетаскивание в очереди** | <a id="feature-queuereorder"></a>У сообщений в очереди появляется маркер (⠿). Перетащите его, чтобы изменить порядок, или переведите на него фокус и нажмите `↑` / `↓`. `Esc` отменяет перемещение. | <a href="assets/features/queueReorder.webp"><img src="assets/features/queueReorder.webp" width="160" alt="Снимок экрана: Перетаскивание в очереди"></a> |
|
|
52
|
-
| **Правка сообщения в очереди на месте** | <a id="feature-queueedit"></a>Дважды щёлкните по сообщению в
|
|
53
|
+
| **Правка сообщения в очереди на месте** | <a id="feature-queueedit"></a>Дважды щёлкните по сообщению в очереди или нажмите его кнопку «Изменить» (**Изменить сообщение в очереди**). В строке открывается редактор: измените текст, удалите изображение или файл его кнопкой ✕ или добавьте новые скрепкой (**Добавить изображения или файлы**) или вставкой изображения. `Enter` сохраняет, `Esc` отменяет, `Shift+Enter` добавляет строку. Сообщение остаётся на своём месте в очереди, а изображения и файлы, которые вы оставили, не меняются. Пока редактор открыт, порядок очереди изменить нельзя. В Tether: меню сообщения в очереди → Edit. | <a href="assets/features/queueEdit.webp"><img src="assets/features/queueEdit.webp" width="160" alt="Снимок экрана: Правка сообщения в очереди на месте"></a> |
|
|
54
|
+
| **Приоритет сообщения после остановки** | <a id="feature-stopsendfirst"></a>Включено по умолчанию. Остановите чат, пока в его очереди ждут сообщения, и отправьте новое сообщение: оно сразу выполняется отдельно. Сообщения в очереди сохраняют порядок и выполняются после него, по одному за ход. Без этой функции dsh добавляет новое сообщение в конец очереди и вместо него выполняет первое сообщение из очереди, так что новое выполняется последним. Сообщение, отправленное, пока чат работает, по-прежнему ждёт в конце очереди. | <a href="assets/features/stopSendFirst.webp"><img src="assets/features/stopSendFirst.webp" width="160" alt="Снимок экрана: Приоритет сообщения после остановки"></a> |
|
|
53
55
|
| **Копировать ссылку на сеанс** | <a id="feature-copydeeplink"></a>Правый щелчок по чату на боковой панели → **Копировать ссылку на сеанс**. Вставьте ссылку `dsh-session:…` в другой чат, чтобы прикрепить этот чат как контекст только для чтения. В dsh 0.2.1 есть свой пункт **Копировать ID сеанса**, но он копирует только сам идентификатор. Пункт плагина стоит сразу после него. | <a href="assets/features/copyDeeplink.webp"><img src="assets/features/copyDeeplink.webp" width="160" alt="Снимок экрана: Копировать ссылку на сеанс"></a> |
|
|
54
56
|
| **Копировать ссылку на сообщение** | <a id="feature-copymessagelink"></a>Наведите указатель на сообщение и нажмите **🔗** (в строке действий сообщения; у ответа — рядом со временем). Ссылка — это ссылка на сеанс плюс номер сообщения: `dsh-session:…#42`. Вставьте её в сообщение и отправьте. В dsh 0.2.1 и новее ссылка показывается как значок. Щелчок по нему открывает тот чат, прокручивает его до сообщения и подсвечивает сообщение на 2 секунды. Как и ссылка на сеанс, она также прикрепляет тот чат как контекст только для чтения. | <a href="assets/features/copyMessageLink.webp"><img src="assets/features/copyMessageLink.webp" width="160" alt="Снимок экрана: Копировать ссылку на сообщение"></a> |
|
|
55
57
|
| **Экспорт чата в Markdown** | <a id="feature-exportmarkdown"></a>Правый щелчок по чату на боковой панели (или его меню **…**) → **Экспорт в Markdown…**. Диалог показывает, сколько сообщений в чате. **Копировать в буфер обмена** копирует чат как Markdown, а **Сохранить файл .md** сохраняет его как `<chat title>.md` через загрузку браузера (в настольном dsh — в папку «Загрузки» или через диалог сохранения, как настроено в системе). В файле есть название чата, название проекта и дата, а затем по одному разделу `## Вы` или `## Ассистент` на каждое сообщение. Блоки кода остаются как есть; блок кода, который сообщение оставило открытым, закрывается. | <a href="assets/features/exportMarkdown.webp"><img src="assets/features/exportMarkdown.webp" width="160" alt="Снимок экрана: Экспорт чата в Markdown"></a> |
|
|
@@ -57,23 +59,30 @@ dsh plugin --profile web add dsh-composer-plus
|
|
|
57
59
|
| **Поиск проекта в новом чате** | <a id="feature-projectpicker"></a>Новый чат → кнопка проекта над полем ввода. Проекты показаны в порядке A–Z, а сверху есть поле **Поиск проектов**. Введите часть названия (регистр и диакритические знаки не важны) и нажмите `Enter`, чтобы выбрать первое совпадение. Если ничего не подходит, появляется **Нет подходящих проектов**. Сохранённый порядок проектов dsh на боковой панели не меняется. | <a href="assets/features/projectPicker.webp"><img src="assets/features/projectPicker.webp" width="160" alt="Снимок экрана: Поиск проекта в новом чате"></a> |
|
|
58
60
|
| **Рабочая область по умолчанию для нового сеанса** | <a id="feature-defaultworkspace"></a>Настройки → Composer Plus → **Рабочая область по умолчанию для нового сеанса** → **Открывать «Новый сеанс» в**: выберите проект или **Общая папка (default-workspace)** (по умолчанию: собственная папка dsh `Documents/deepseek-harness/default-workspace`, которая создаётся при первом использовании). После этого **Новый сеанс** вверху боковой панели (и его сочетание клавиш) всегда открывает новый чат там, даже когда открыт чат другого проекта. Кнопка `+` рядом с проектом по-прежнему открывает этот проект, а кнопка проекта над полем ввода нового чата по-прежнему меняет проект. | <a href="assets/features/defaultWorkspace.webp"><img src="assets/features/defaultWorkspace.webp" width="160" alt="Снимок экрана: Рабочая область по умолчанию для нового сеанса"></a> |
|
|
59
61
|
| **Поиск в чате** | <a id="feature-findinchat"></a>Нажмите `Cmd+F` на Mac (`Ctrl+F` в Windows и Linux) в чате: над ним откроется поле поиска. Введите слово: все совпадения в сообщениях и ответах на экране выделяются, текущее — более ярким цветом, а поле показывает n / всего. `Enter` или `↓` переходит к следующему совпадению, а `Shift+Enter` или `↑` — к предыдущему (также кнопки со стрелками); чат прокручивает совпадение к середине. Регистр, диакритические знаки и турецкая ı без точки не важны. `Esc` закрывает поле и возвращает курсор туда, где он был. Поиск следует за чатом, пока приходит ответ. | <a href="assets/features/findInChat.webp"><img src="assets/features/findInChat.webp" width="160" alt="Снимок экрана: Поиск в чате"></a> |
|
|
60
|
-
| **Ветка для каждого чата** | <a id="feature-worktreechats"></a
|
|
62
|
+
| **Ветка для каждого чата** | <a id="feature-worktreechats"></a>На экране нового чата кнопка ветки (значок ветки) между кнопкой проекта и кнопкой режима по умолчанию показывает **Новая ветка**. Введите первое сообщение и отправьте его. Чтобы остаться в текущей ветке, выберите в той же кнопке «Текущая ветка (main)». К первому сообщению можно приложить изображения и файлы. В режиме плана новый чат тоже начинается в режиме плана: отправьте сообщение как `/plan <сообщение>` (Shift+Tab) или сначала включите режим плана на экране нового чата. ИИ называет ветку (`feat/…`, `fix/…`) по этому сообщению, Composer Plus создаёт для неё git worktree в `<project>/.worktrees/`, копирует игнорируемые файлы из списка `.worktreeinclude` (например, `.env` и `node_modules/`) и открывает там новый чат с вашим сообщением. Заголовок открытого чата показывает ⑂ ветка · изменений: N · ↑ ↓ (или **не отправлена**); нажмите на него, чтобы открыть **Изменения**. В том же меню есть список открытых worktree: выберите один, чтобы начать в нём чат. Чтобы видеть папки веток внутри их проекта на боковой панели, выберите в dsh **Параметры просмотра** → **Дерево рабочих областей**. | <a href="assets/features/worktreeChats.webp"><img src="assets/features/worktreeChats.webp" width="160" alt="Снимок экрана: Ветка для каждого чата"></a> |
|
|
63
|
+
| **Ветки в дереве рабочих областей** | <a id="feature-branchtree"></a>Настройки → Composer Plus → **Ветки в дереве рабочих областей** (по умолчанию выключено). Каждая ветка с папкой worktree в `<project>/.worktrees/` показывается как проект внутри своего проекта; выберите в dsh **Параметры просмотра** → **Дерево рабочих областей**, чтобы видеть вложенность. Ветка, чью папку удалили, уходит из списка, а dsh показывает её чаты в **Без группы**. Когда агент чата в папке проекта создаёт ветку и переключается на неё (`git switch -c`, `git checkout -b`), а в папке нет незакоммиченных изменений, папка проекта возвращается на прежнюю ветку, ветка получает свою папку, и чат переходит туда: копия открывается в проекте ветки и продолжает задачу, а старый чат архивируется. Список проверяется при запуске, каждые 30 секунд, после каждого хода и когда вы возвращаетесь в окно. | <a href="assets/features/branchTree.webp"><img src="assets/features/branchTree.webp" width="160" alt="Снимок экрана: Ветки в дереве рабочих областей"></a> |
|
|
61
64
|
| **Предсказание следующего сообщения** | <a id="feature-nextprediction"></a>По умолчанию включено: выключить функцию можно в **Настройки → Composer Plus**. Когда агент завершает ход (не остановленный и не завершившийся сбоем), пустое поле ввода серым текстом показывает предположение о вашем следующем сообщении и подсказку **Tab — принять**. `Tab` вставляет текст в поле ввода, но не отправляет его. `Esc` скрывает предположение до конца этого хода. Ввод текста тоже скрывает его, а новый ход заменяет его новым. Меню **Модель** под переключателем показывает собственные модели dsh (тот же список, что и в меню моделей dsh). По умолчанию выбран пункт **По умолчанию в dsh**: он следует модели dsh по умолчанию. Каждый завершённый ход стоит один короткий вызов модели. В Tether предположение появляется над пустым полем ввода: коснитесь его, чтобы вставить текст в поле. | <a href="assets/features/nextPrediction.webp"><img src="assets/features/nextPrediction.webp" width="160" alt="Снимок экрана: Предсказание следующего сообщения"></a> |
|
|
62
65
|
| **Дополнение при вводе** | <a id="feature-typingcompletion"></a>По умолчанию выключено: включить функцию можно в **Настройки → Composer Plus**. Пока вы печатаете, серый текст сразу после курсора показывает, как может продолжиться ваше сообщение. `Tab` добавляет его в сообщение, но не отправляет. `Esc` скрывает его. Функция предлагает только ваши собственные следующие слова: никогда не ответ вам и без выдуманных текстов ошибок или имён. Если сообщение выглядит законченным или модель не уверена, ничего не появляется. Если вы набираете следующие буквы серого текста, он остаётся, без нового вызова модели. Под её переключателем есть своё меню **Модель**. Первый пункт, **Как у предсказания следующего сообщения**, использует модель **Предсказание следующего сообщения** (выбран по умолчанию). Выберите другую модель, чтобы у каждой функции была своя, например более быстрая модель для дополнений. Она делает один вызов модели при каждой паузе в наборе, поэтому расходует намного больше токенов, чем предсказание: выберите быструю и недорогую модель. Она не работает для слеш-команды, для сообщения со значком файла и когда курсор стоит не в конце. В Tether остаток текста появляется над полем, пока вы печатаете: коснитесь его, чтобы добавить. | <a href="assets/features/typingCompletion.webp"><img src="assets/features/typingCompletion.webp" width="160" alt="Снимок экрана: Дополнение при вводе"></a> |
|
|
63
66
|
| **Улучшить промпт** | <a id="feature-promptimprove"></a>Напишите черновой запрос, затем нажмите волшебную палочку (**Улучшить промпт**) рядом с меню моделей. Один вызов модели переписывает его в более понятный промпт: сначала цель, короткие пронумерованные шаги, если частей несколько, и проверка, которую нужно запустить. Функция читает этот чат (без сообщений, убранных откатом), README, AGENTS.md и манифест проекта, изменённые файлы и файлы, имена которых совпадают с вашими словами, и сохраняет ваш язык. Она никогда не выдумывает имена файлов. Новый текст заменяет ваш черновик, но не отправляется: прочитайте его, отредактируйте, затем нажмите `Enter`. `Cmd/Ctrl+Z` возвращает ваш текст за один шаг, как и кнопка (**Отменить улучшение**). Если вы печатаете, пока она работает, ваш новый текст остаётся. `Esc` или повторное нажатие отменяет. У неё есть своё меню **Модель** в настройках (по умолчанию: **Как модель чата**). Не работает для слеш-команд и для сообщения со значком файла. В Tether палочка находится рядом с полем. | <a href="assets/features/promptImprove.webp"><img src="assets/features/promptImprove.webp" width="160" alt="Снимок экрана: Улучшить промпт"></a> |
|
|
64
67
|
| **Проверка цели** | <a id="feature-goalcheck"></a>Начните цель командой `/goal`. Когда агент в автоматическом раунде отмечает цель как выполненную, цель закрывается только после двух проверок. Сначала тестовая команда проекта запускается в папке чата, в режиме песочницы этого чата. Это ваша собственная команда или команда, найденная в `package.json`, `Makefile`, `Cargo.toml`, `go.mod` или pytest. Если последним шагом самого агента был успешный запуск этого теста, повторно он не запускается. Затем независимый вызов модели без инструментов читает цель, этот чат, `git status` и результат теста. Если проверка не пройдена, цель остаётся активной, агент читает причину, и начинается следующий раунд. Строка под панелью цели (**Проверка цели**) показывает тест и последний результат. **Изменить** задаёт вашу собственную тестовую команду и лимит времени или токенов; при превышении лимита цель становится заблокированной. **Запустить сейчас** запускает проверку, не закрывая цель. У функции есть своё меню **Модель** в настройках (по умолчанию: **Как модель чата**). Когда вы сами завершаете цель, ничего не проверяется. | <a href="assets/features/goalCheck.webp"><img src="assets/features/goalCheck.webp" width="160" alt="Снимок экрана: Проверка цели"></a> |
|
|
68
|
+
| **Память проекта** | <a id="feature-projectmemory"></a>По умолчанию выключено: включите функцию в **Настройки → Composer Plus**. У каждой папки проекта своя память, которую читают следующие чаты этого проекта, так же как DS Bot хранит память для каждого бота. После каждого завершённого хода один вызов модели чата читает новые сообщения (без отменённых откатом), сохраняет ваши постоянные предпочтения, решения и факты как короткие заметки и изменяет или удаляет старые. Агент также может сам сохранять, удалять и искать заметки (`memory_remember`, `memory_forget`, `memory_recall`). Заметка может быть и глобальной: её читают все проекты. Новый чат получает заметки в системном промпте; заметка, сохранённая позже, появляется со следующего чата. Файлы хранятся в формате Markdown в домашней папке dsh (`storages/dsh-composer-plus/memory/`), никогда в папке проекта. | <a href="assets/features/projectMemory.webp"><img src="assets/features/projectMemory.webp" width="160" alt="Снимок экрана: Память проекта"></a> |
|
|
65
69
|
| **Разрешить для этого чата** | <a id="feature-allowforchat"></a>Когда автопроверка спрашивает вас, на карточке одобрения появляется кнопка **Разрешить для этого чата**. После этого тот же инструмент в том же чате разрешён с любыми аргументами, пока не истечёт лимит времени (по умолчанию 1 час; выберите его в **Настройки → Composer Plus → Разрешить для этого чата**). Затем агент снова спрашивает. Значок в заголовке показывает список разрешений со временем их окончания и позволяет их отозвать. Разрешения сохраняются после перезапуска. | <a href="assets/features/allowForChat.webp"><img src="assets/features/allowForChat.webp" width="160" alt="Снимок экрана: Разрешить для этого чата"></a> |
|
|
66
|
-
| **Статус проекта** | <a id="feature-projectstatus"></a>Строка проекта на боковой панели показывает ту же метку, что и его чаты: индикатор выполнения, ожидание или «готово». Поэтому даже свёрнутый проект сообщает, что чат внутри работает или ждёт вас. Сначала показывается чат, который ждёт вас, затем завершённый чат, который вы ещё не открыли (зелёная точка, даже пока другой чат ещё выполняется), затем индикатор выполнения. Наведите на метку указатель, чтобы увидеть подробности. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="Снимок экрана: Статус проекта"></a> |
|
|
67
|
-
| **Ветка Git в строках чатов** | <a id="feature-sessionbranch"></a>Каждая строка чата на боковой панели показывает маленькую серую метку с веткой git, на которой была папка проекта чата в его последнем ходе (например, `main` или `feature/login`; при отсоединённом HEAD в скобках показывается короткий ID коммита). Два чата одного проекта на разных ветках больше не выглядят одинаково, и вы сразу видите, если собираетесь продолжить чат не на той ветке. Наведите указатель на метку, чтобы увидеть полное имя. Host-часть читает ветку (`git branch --show-current`, только чтение), когда ход начинается и когда заканчивается; у чата без хода с момента установки этой функции или у папки, которая не является репозиторием git, метки нет. | <a href="assets/features/sessionBranch.webp"><img src="assets/features/sessionBranch.webp" width="160" alt="Снимок экрана: Ветка Git в строках чатов"></a> |
|
|
70
|
+
| **Статус проекта** | <a id="feature-projectstatus"></a>Строка проекта на боковой панели показывает ту же метку, что и его чаты: индикатор выполнения, ожидание или «готово». Поэтому даже свёрнутый проект сообщает, что чат внутри работает или ждёт вас. Сначала показывается чат, который ждёт вас, затем завершённый чат, который вы ещё не открыли (зелёная точка, даже пока другой чат ещё выполняется), затем индикатор выполнения. Наведите на метку указатель, чтобы увидеть подробности. В режиме **Дерево рабочих областей** строка родительской папки также показывает чаты каждого проекта внутри неё (например, каждой папки ветки в `.worktrees/`), даже когда папка свёрнута. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="Снимок экрана: Статус проекта"></a> |
|
|
71
|
+
| **Ветка Git в строках чатов** | <a id="feature-sessionbranch"></a>Каждая строка чата на боковой панели показывает маленькую серую метку с веткой git, на которой была папка проекта чата в его последнем ходе (например, `main` или `feature/login`; при отсоединённом HEAD в скобках показывается короткий ID коммита). Два чата одного проекта на разных ветках больше не выглядят одинаково, и вы сразу видите, если собираетесь продолжить чат не на той ветке. Наведите указатель на метку, чтобы увидеть полное имя. Host-часть читает ветку (`git branch --show-current`, только чтение), когда ход начинается и когда заканчивается; у чата без хода с момента установки этой функции или у папки, которая не является репозиторием git, метки нет. Если строка проекта над чатом называется так же, как ветка (например, папка «Ветка для каждого чата»), строка чата не показывает метку, но в режиме «Одним списком» метка по-прежнему видна. | <a href="assets/features/sessionBranch.webp"><img src="assets/features/sessionBranch.webp" width="160" alt="Снимок экрана: Ветка Git в строках чатов"></a> |
|
|
68
72
|
| **Отметить все как прочитанные** | <a id="feature-markprojectread"></a>На боковой панели нажмите кнопку **…** проекта → **Отметить все как прочитанные**. У всех чатов этого проекта сразу пропадает зелёная точка непрочитанного. У других проектов точки остаются. Если в проекте нет непрочитанных чатов, пункт показан серым (**Нет непрочитанных чатов**). | <a href="assets/features/markProjectRead.webp"><img src="assets/features/markProjectRead.webp" width="160" alt="Снимок экрана: Отметить все как прочитанные"></a> |
|
|
69
73
|
| **Активные проекты сверху** | <a id="feature-activeprojectsfirst"></a>Когда чат начинает работать или ждёт вас, его проект перемещается в начало боковой панели со встроенной анимацией строк dsh (так же, как при перетаскивании). Завершённые проекты остаются на месте; их можно перетаскивать как обычно. Перемещения сохраняются в порядке проектов dsh, поэтому при отключении функции текущий порядок остаётся. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="Снимок экрана: Активные проекты сверху"></a> |
|
|
70
|
-
| **Фильтр недавних проектов** | <a id="feature-recentprojects"></a>Боковая панель → параметры просмотра (значок с ползунками) → **Активные за последние 2 часа**. Пока этот пункт выбран, боковая панель показывает только проекты с чатом, активным за последние 2 часа. Это чат, обновлённый за это время, выполняющийся или ожидающий чат, открытый чат или завершённый чат, который вы ещё не открыли (зелёная точка dsh «готово»), — такой чат оставляет проект на виду и после 2 часов. Проекты без такого чата скрыты, в том числе новые и пустые. Выберите пункт ещё раз, чтобы показать все проекты. Выбор сохраняется на этом устройстве. | <a href="assets/features/recentProjects.webp"><img src="assets/features/recentProjects.webp" width="160" alt="Снимок экрана: Фильтр недавних проектов"></a> |
|
|
74
|
+
| **Фильтр недавних проектов** | <a id="feature-recentprojects"></a>Боковая панель → параметры просмотра (значок с ползунками) → **Активные за последние 2 часа**. Пока этот пункт выбран, боковая панель показывает только проекты с чатом, активным за последние 2 часа. Это чат, обновлённый за это время, выполняющийся или ожидающий чат, открытый чат или завершённый чат, который вы ещё не открыли (зелёная точка dsh «готово»), — такой чат оставляет проект на виду и после 2 часов. Проекты без такого чата скрыты, в том числе новые и пустые. В режиме **Дерево рабочих областей** родительская папка остаётся на виду, пока активен проект внутри неё, а чаты, которые не были активны за последние 2 часа, тоже скрыты, поэтому видны только недавние чаты. Выберите пункт ещё раз, чтобы показать все проекты. Выбор сохраняется на этом устройстве. | <a href="assets/features/recentProjects.webp"><img src="assets/features/recentProjects.webp" width="160" alt="Снимок экрана: Фильтр недавних проектов"></a> |
|
|
71
75
|
| **Свернуть все проекты** | <a id="feature-collapseprojects"></a>Пока на боковой панели открыт хотя бы один проект, рядом с параметрами просмотра (значок с ползунками) есть кнопка. Нажмите её, чтобы сразу закрыть все открытые проекты, например 3 открытых из 5. Когда открытых проектов нет, кнопка снова скрывается. | <a href="assets/features/collapseProjects.webp"><img src="assets/features/collapseProjects.webp" width="160" alt="Снимок экрана: Свернуть все проекты"></a> |
|
|
72
76
|
| **Сортировка по состоянию** | <a id="feature-statusorder"></a>Боковая панель → параметры просмотра → **Сортировать** → **По состоянию** (вместе с **Одним списком**). Сначала идут завершённые чаты (с точкой dsh «готово»; её получает и ход, который закончился ошибкой), затем выполняющиеся или ожидающие чаты, затем чаты с активной автоматизацией (расписанием), затем остальные в порядке dsh. Когда вы открываете завершённый чат, он опускается ниже. Меняется только вид: чтобы вернуться, выберите **Вручную** или **По дате изменения**. | <a href="assets/features/statusOrder.webp"><img src="assets/features/statusOrder.webp" width="160" alt="Снимок экрана: Сортировка по состоянию"></a> |
|
|
73
77
|
| **Фоновые уведомления** | <a id="feature-notifications"></a>Пока dsh работает в фоне, вы получаете уведомление, когда ход завершён (первая строка ответа) или когда чат действительно ждёт вас: одобрения (имя инструмента), ответа (сам вопрос) или проверки плана. Запрос должен оставаться открытым и через 1,5 с. Поэтому одобрения, на которые ответили автоматически (разрешения автопроверки, другие плагины), не вызывают уведомлений. Уведомление убирается, как только на его запрос ответили. Значок в Dock или на панели задач показывает число ожидающих чатов. Щелчок по уведомлению открывает этот чат. | <a href="assets/features/notifications.webp"><img src="assets/features/notifications.webp" width="160" alt="Снимок экрана: Фоновые уведомления"></a> |
|
|
78
|
+
| **Открывать ожидающий чат при бездействии** | <a id="feature-idleswitch"></a>Когда чат задаёт вопрос или ждёт одобрения или проверки плана (оранжевая точка), а вы не пользуетесь dsh 30 секунд, dsh открывает этот чат. Если ждут несколько чатов, первым открывается тот, что ждёт дольше всех; следующий открывается ещё через 30 секунд бездействия. Нажатие клавиши, щелчок, движение мыши, колесо прокрутки или касание запускают отсчёт 30 секунд заново. Текст в поле с фокусом, выделенный текст или открытое меню либо диалог тоже не дают переключиться. Пока ожидающий чат на экране, ничего не меняется. Если вы ушли из ожидающего чата, не ответив, он может открыться снова после следующих 30 секунд бездействия. Функция работает и когда dsh в фоне, но окно dsh не выходит на передний план. | <a href="assets/features/idleSwitch.webp"><img src="assets/features/idleSwitch.webp" width="160" alt="Снимок экрана: Открывать ожидающий чат при бездействии"></a> |
|
|
74
79
|
| **Язык приложения** | <a id="feature-language"></a>Настройки → Composer Plus → **Язык приложения** переключает весь интерфейс dsh на Türkçe, Español, Português (Brasil), Français, Deutsch, Русский, 日本語, 한국어, Bahasa Indonesia, Tiếng Việt или हिन्दी (см. ниже). | <a href="assets/features/language.webp"><img src="assets/features/language.webp" width="160" alt="Снимок экрана: Язык приложения"></a> |
|
|
75
80
|
| **Мобильное подключение (iPhone)** | <a id="feature-mobileconnect"></a>Работайте с dsh на iPhone через приложение [Tether](tether/) в той же сети Wi-Fi или через [Tailscale](https://tailscale.com). Включите функцию в **Настройки → Composer Plus** (по умолчанию она выключена, потому что открывает сетевой порт на этом Mac). Затем нажмите **Мобильное подключение** внизу слева на боковой панели, отсканируйте QR-код камерой iPhone (коснитесь **Open in Tether**) или кнопкой **Scan code** в Tether, коснитесь **Connect** и нажмите **Approve**. Сначала установите Tether: без него камера не сможет открыть код. Телефон показывает ваши чаты, отправляет сообщения (с фото: **+** в поле ввода → Camera, Photos или Paste image), отвечает на запросы одобрения и вопросы, переключает модели и агентов. Можно связать сколько угодно Mac: имя Mac вверху слева в приложении переключает между ними. Панель **Мобильное подключение** показывает связанные iPhone и время их последнего подключения: **Remove** сразу отключает любой из них. «Tailscale only» отклоняет подключения из локальной сети (для общей сети Wi-Fi), а журнал доступа показывает, кто пытался подключиться. В Tether «Settings → Privacy» блокирует приложение с помощью Face ID. | <a href="assets/features/mobileConnect.webp"><img src="assets/features/mobileConnect.webp" width="160" alt="Снимок экрана: Мобильное подключение (iPhone)"></a> |
|
|
76
81
|
| **Автоматические обновления** | <a id="feature-autoupdate"></a>При запуске dsh плагин проверяет [последний выпуск на GitHub](https://github.com/furkancak1r/dsh-composer-plus/releases/latest). Если он новее и уже есть в npm, плагин устанавливает именно эту версию через встроенный менеджер плагинов dsh (тем же путём, что и Настройки → Плагины) и уведомляет вас. Перезапустите dsh, чтобы загрузить её. **Настройки → Composer Plus → Обновления Composer Plus** показывает версию и кнопки **Проверить обновления** / **Обновить сейчас**. При первом запуске dsh с новой версией окно **Что нового в Composer Plus N** один раз показывает примечания к этой версии (из той же проверки обновлений, без нового сетевого запроса); **Закрыть** или `Esc` закрывает его. | <a href="assets/features/autoUpdate.webp"><img src="assets/features/autoUpdate.webp" width="160" alt="Снимок экрана: Автоматические обновления"></a> |
|
|
82
|
+
| **Резервное копирование** | <a id="feature-backup"></a>Настройки → Composer Plus → **Резервное копирование** → **Создать копию сейчас** записывает всю домашнюю папку dsh (чаты, настройки, плагины, MCP, навыки) в один архив в `~/Desktop/dsh-backups` вместе с контрольной суммой. Секреты в архиве скрыты: файлы учётных данных, файлы ключей (`.pem`, `.key`) и значения token, secret и password в настройках yml остаются только на этом компьютере, в `vault` этой папки. `cache/`, `dsh-runtimes/` и `node_modules` в архив не входят (dsh создаёт их заново). У каждой резервной копии в списке есть **Проверить** (читает её целиком), **Для другого компьютера** (папка для копирования на новый компьютер, вместе с аварийной консолью) и **Удалить**. Архивы dsh-backup в той же папке тоже показываются и работают. Чтобы восстановить данные, выйдите из dsh и используйте аварийную консоль. | <a href="assets/features/backup.webp"><img src="assets/features/backup.webp" width="160" alt="Снимок экрана: Резервное копирование"></a> |
|
|
83
|
+
| **Автоматическое резервное копирование** | <a id="feature-autobackup"></a>Включите **Автоматическое резервное копирование** (по умолчанию выключено: каждая копия занимает примерно столько же места, сколько ваша домашняя папка dsh без кеша). Выберите, как часто создавать копии (**Каждые**: от 6 часов до 7 дней, по умолчанию 24 часа), и сколько резервных копий хранить (**Хранить**: от 3 до 14, по умолчанию 7). Время следующей копии показано под переключателем; неудачная копия тоже показывается там, и через 30 минут будет новая попытка. Когда dsh или Composer Plus запускается с новой версией, вскоре после запуска создаётся снимок, пока новая версия ещё недолго работала с вашими данными (хранятся два самых новых, с пометкой **Перед обновлением**). | <a href="assets/features/autoBackup.webp"><img src="assets/features/autoBackup.webp" width="160" alt="Снимок экрана: Автоматическое резервное копирование"></a> |
|
|
84
|
+
| **Проверка журналов сеансов** | <a id="feature-sessiondoctor"></a>**Проверить журналы сеансов** читает журнал каждого чата и показывает те, которые dsh не может открыть (повреждённый фрейм, обрезанная запись, неверный порядковый номер). Оборванный конец журнала в список не попадает: dsh исправляет его сам. **Исправить из резервных копий** возвращает копию из самой новой резервной копии, где она не повреждена, и оставляет повреждённый файл рядом (`.corrupt-<время>`). Сообщений, написанных после этой резервной копии, в копии нет. Чат, открытый в этом dsh, здесь не исправляется: выйдите из dsh и исправьте его в аварийной консоли. | <a href="assets/features/sessionDoctor.webp"><img src="assets/features/sessionDoctor.webp" width="160" alt="Снимок экрана: Проверка журналов сеансов"></a> |
|
|
85
|
+
| **Аварийная консоль** | <a id="feature-rescueconsole"></a>Каждая резервная копия также кладёт аварийную консоль в папку резервных копий. Когда dsh закрыт или не запускается, откройте `Composer Plus Rescue` в этой папке (macOS: `Composer Plus Rescue.command`): меню в окне терминала показывает, проверяет и восстанавливает резервные копии, а также проверяет и исправляет журналы сеансов. Консоль не открывает сетевой порт. При восстановлении нужно ввести `RESTORE`; текущая домашняя папка dsh сохраняется как `.dsh.pre-restore-<время>`, скрытые секреты возвращаются из vault, а `cache/`, `dsh-runtimes/` и `node_modules` переносятся из старой папки. Консоль работает без dsh: она использует Node.js или само приложение DeepSeek Harness. На новом компьютере скопируйте папку из **Для другого компьютера** и откройте там `Composer Plus Rescue`. | <a href="assets/features/rescueConsole.webp"><img src="assets/features/rescueConsole.webp" width="160" alt="Снимок экрана: Аварийная консоль"></a> |
|
|
77
86
|
|
|
78
87
|
<!-- END GENERATED FEATURES -->
|
|
79
88
|
|
|
@@ -117,7 +126,7 @@ English · 中文 · Türkçe · Español · Português (Brasil) · Français ·
|
|
|
117
126
|
| `Esc` | пустое поле ввода с предсказанием | скрыть предсказание |
|
|
118
127
|
| `Cmd/Ctrl+Z` | поле ввода, после **Улучшить промпт** | вернуть текст, который вы ввели |
|
|
119
128
|
| `Esc` | поле ввода, пока работает **Улучшить промпт** | отменить улучшение |
|
|
120
|
-
| `Enter` / `Esc` |
|
|
129
|
+
| `Enter` / `Esc` | редактор сообщения в очереди | сохранить / отменить правку |
|
|
121
130
|
| `Cmd+F` на Mac, `Ctrl+F` в Windows и Linux | открытый чат | открыть **Поиск в чате** |
|
|
122
131
|
| `Enter` / `Shift+Enter`, `↓` / `↑` | поле **Поиск в чате** | следующее / предыдущее совпадение |
|
|
123
132
|
| `Esc` | поле **Поиск в чате** | закрыть поле |
|
|
@@ -151,6 +160,9 @@ English · 中文 · Türkçe · Español · Português (Brasil) · Français ·
|
|
|
151
160
|
- **Дополнение при вводе:** выключено, пока вы его не включите. Когда оно включено, при каждой паузе в наборе Host-часть отправляет уже набранный текст, а также ваши собственные сообщения в чате и текстовые ответы агента (без вывода инструментов, скрытого контекста и рассуждений), не более примерно 3 000 символов чата, модели, выбранной для **Дополнение при вводе** (по умолчанию это модель **Предсказание следующего сообщения**). Новая пауза останавливает предыдущий запрос. В чате ничего не сохраняется. Переключатель хранится в `$DSH_HOME/storages/dsh-composer-plus/complete.json` (файл доступен только владельцу).
|
|
152
161
|
- **Улучшить промпт:** ничего не запускается, пока вы не нажмёте волшебную палочку. Затем Host-часть одним запросом отправляет модели, выбранной для **Улучшить промпт** (по умолчанию это модель самого чата), ваш черновик, ваши собственные сообщения в чате и текстовые ответы агента (без вывода инструментов, скрытого контекста, рассуждений и сообщений, убранных откатом; не более примерно 6 000 символов, самую новую часть), ту же сводку проекта, что и **Идеи функций** (с теми же правилами для файлов: без `.env*` и файлов ключей, без символических ссылок за пределы папки, без FIFO), пути, которые `git status` показывает как изменённые, и до 30 отслеживаемых или неотслеживаемых (не игнорируемых) путей, в именах которых есть слова из вашего черновика. Другое содержимое файлов, кроме этой сводки, не отправляется. В чат и в проект ничего не записывается: ответ только заменяет ваш черновик в поле ввода, а отправлять ли его, решаете вы. Выбранная модель хранится в `$DSH_HOME/storages/dsh-composer-plus/improve.json` (файл доступен только владельцу).
|
|
153
162
|
- **Проверка цели:** запускается, только когда агент в автоматическом раунде отмечает `/goal` как выполненную (или когда вы нажимаете **Запустить сейчас**). Host-часть запускает тестовую команду в папке чата в режиме песочницы этого чата (как собственный инструмент `bash` в dsh: та же политика доступа к файлам; если эта песочница не может запуститься, тест не запускается и проверка не пройдена). Чтобы найти команду, она читает только `package.json`, `Makefile`, `Cargo.toml`, `go.mod`, `pyproject.toml` и `pytest.ini`, как обычные файлы внутри папки (без символических ссылок за пределы папки, без FIFO). Затем она одним запросом без инструментов отправляет модели, выбранной для **Проверка цели** (по умолчанию это модель самого чата), цель, чат с момента начала цели (ваши сообщения, ответы агента, вызовы инструментов, обрезанные до 1 000 символов, и последние 2 000 символов каждого результата инструмента; без рассуждений и шагов, убранных откатом; не более примерно 60 000 символов, самую новую часть), `git status --short` и конец вывода теста. Вывод инструментов может содержать то, что прочитал агент, поэтому в этом запросе могут быть части ваших файлов, как и в самом чате. В чат и в проект ничего не записывается. Ваша тестовая команда, лимиты, последний результат (с концом его вывода) и выбранная модель хранятся в `$DSH_HOME/storages/dsh-composer-plus/goal-check.json` (файл доступен только владельцу, последние 500 чатов).
|
|
163
|
+
- **Память проекта:** выключена, пока вы её не включите. Когда она включена, после каждого завершённого хода чата верхнего уровня часть Host отправляет новые сообщения этого чата с момента последнего разбора (ваши сообщения и текстовые ответы агента; без вывода инструментов, рассуждений, скрытого контекста и сообщений, убранных откатом; в ответвлённом чате копия родительского чата не учитывается; не больше примерно 16 000 символов) и сохранённые заметки модели этого чата, одним запросом без инструментов. Заметки — это файлы Markdown в `$DSH_HOME/storages/dsh-composer-plus/memory/` (доступны только владельцу): `projects/<id>/` для каждой папки проекта (`<id>` — хеш реального пути папки; `project.json` указывает папку), `global/`, `journal.jsonl` (каждое изменение со строкой до и после) и `reviewed.json` (до какого места прочитан каждый чат). В папку проекта ничего не записывается. Заметки, похожие на ключ, токен, пароль или номер документа, отклоняются. Заметки проекта попадают в системный промпт каждого нового чата в этой папке, поэтому уходят модели с каждым запросом этого чата. Переключатель хранится в `memory.json` там же.
|
|
164
|
+
- **Резервное копирование:** ничего не покидает ваш компьютер. Архивы сохраняются в `~/Desktop/dsh-backups` (файлы доступны только владельцу). Секретов в архиве нет: файлы учётных данных (`.credentials.yaml`, `.env`), файлы ключей (`.pem`, `.key`, `.p12`, `.pfx`) и значения настроек token, secret, password и API-ключей в файлах yml скрыты; их настоящие копии остаются в `composer-plus-vault/<archive>/` в той же папке (доступно только владельцу) и только на этом компьютере. **Для другого компьютера** не копирует vault: введите эти секреты там заново. Ваши журналы чатов, настройки и остальное содержимое домашней папки dsh лежат в архиве как есть: держите папку закрытой, как и сам `$DSH_HOME`. Резервное копирование читает файлы с `O_NOFOLLOW | O_NONBLOCK`; символическая ссылка сохраняется как ссылка (переход по ней не выполняется), а FIFO или устройство пропускается. Переключатель и настройки автоматического резервного копирования хранятся в `$DSH_HOME/storages/dsh-composer-plus/auto-backup.json`, переключатель аварийной консоли — в `rescue-console.json`, а пока dsh работает, `running/host-<pid>.json` указывает каждый процесс dsh (аварийная консоль читает эти файлы, чтобы отказать в восстановлении).
|
|
165
|
+
- **Аварийная консоль:** меню в терминале; она не открывает сетевой порт. Восстановление пишет только в новую папку рядом с домашней папкой dsh (файлы — с `O_EXCL | O_NOFOLLOW`, символические ссылки — в последнюю очередь и без перехода по ним) и отклоняет архив с небезопасным именем (`..`, абсолютный путь), устройством или FIFO, более чем одной папкой верхнего уровня или записью внутри ссылки.
|
|
154
166
|
|
|
155
167
|
## Устранение неполадок
|
|
156
168
|
|
|
@@ -165,11 +177,15 @@ English · 中文 · Türkçe · Español · Português (Brasil) · Français ·
|
|
|
165
177
|
- **При удалении появляется сообщение, что этот чат открыт в другом dsh:** второй dsh с той же домашней папкой dsh удерживает блокировку чата. Закройте это окно или dsh и удалите чат снова. До этого чат остаётся в архиве.
|
|
166
178
|
- **iPhone не подключается после включения «Tailscale only»:** Tailscale должен быть включён и на Mac, и на iPhone. Панель «Мобильное подключение» предупреждает, если на Mac он выключен. Журнал доступа показывает каждую отклонённую попытку и её причину.
|
|
167
179
|
- **Чат не продолжился после перезапуска:** функция «Продолжать после перезапуска» была выключена, когда dsh завершил работу; вы сами остановили этот ход; ход уже закончился (готово или сбой); чат был в архиве; или работало больше 20 чатов (продолжаются 20 самых новых).
|
|
180
|
+
- **После перезапуска очередь пуста:** очередь очищает сам dsh при завершении. Функция «Продолжать после перезапуска» возвращает её только в чате, который продолжается; в других чатах отправьте сообщения снова. Сообщение, удалённое прямо перед выходом, может вернуться: удалите его снова.
|
|
168
181
|
- **Открыть issue на GitHub сообщает «gh could not open the issue»:** это первая строка вывода самого `gh`. Выполните `gh auth status` в терминале и войдите с помощью `gh auth login`; у папки чата должен быть удалённый репозиторий GitHub (`git remote -v`). «not installed or not on the PATH of dsh» означает, что dsh не нашёл `gh`: установите его или запустите dsh из терминала, в котором `gh` работает.
|
|
169
182
|
- **На строке чата нет метки ветки:** у чата не было хода с момента установки этой версии, его папка не является репозиторием git, или функция **Ветка Git в строках чатов** выключена. После обновления перезапустите dsh (ветку записывает Host-часть).
|
|
170
183
|
- **Проверка цели сообщает, что тест завершился с кодом 127 или «not found»:** у dsh, запущенного из Finder или Dock, PATH может быть короче, чем в вашем терминале, поэтому он не находит `npm`, `pnpm` или `cargo`. Запустите dsh из терминала или задайте свою тестовую команду с полным путём в **Проверка цели** → **Изменить**. **Запустить сейчас** сразу показывает результат.
|
|
171
184
|
- **Цель не закрывается, и агент продолжает работать:** **Проверка цели** нашла непройденный тест или недоделанную работу; строка под целью показывает причину (наведите указатель на результат, чтобы увидеть подробности). Исправьте причину или тестовую команду либо завершите цель сами командой `/goal` или через панель цели (это не проверяется).
|
|
172
|
-
- **Установка не удаётся сразу после выпуска:** укажите версию (`dsh-composer-plus@1.
|
|
185
|
+
- **Установка не удаётся сразу после выпуска:** укажите версию (`dsh-composer-plus@1.16.0`), см. примечание об установке выше.
|
|
186
|
+
- **Кнопка «Создать копию сейчас» сообщает «Уже выполняется другое действие с резервными копиями»:** действие выполняется в другом окне dsh или в аварийной консоли (они используют общий файл блокировки `.composer-plus.lock` в папке резервных копий). Дождитесь его окончания. Если никакое действие не выполняется, блокировку закрытого процесса перехватит следующее нажатие.
|
|
187
|
+
- **Аварийная консоль сообщает «dsh is running»:** сначала выйдите из dsh. Если dsh действительно закрыт, файл, названный в сообщении, остался после сбоя: удалите его и повторите попытку.
|
|
188
|
+
- **После восстановления dsh не запускается или не хватает плагина:** пакеты плагинов профиля нужно установить заново. Аварийная консоль предлагает это после восстановления; или выполните `pnpm install` в каждой папке внутри `$DSH_HOME/profiles/`, которую она перечисляет. Секреты, которых не было в vault (другой компьютер), нужно ввести заново: консоль перечисляет их.
|
|
173
189
|
|
|
174
190
|
## Ограничения
|
|
175
191
|
|
|
@@ -177,6 +193,7 @@ English · 中文 · Türkçe · Español · Português (Brasil) · Français ·
|
|
|
177
193
|
- **Идеи функций** хранит карточки в памяти для каждого чата, пока не перезагрузится dsh или страница. После этого **Предложить функции** снова обращается к модели. Карточки приходят на том языке интерфейса dsh, который выбран в момент нажатия. Если вы смените язык, карточки, которые уже лежат в стопке, сохранят свой язык, а **Ещё идеи** использует новый. Модель видит только краткую сводку проекта, а не код, поэтому идея может повторять то, что в проекте уже есть: просто пропустите её. Новый чат запускается в режиме плана, только если в профиле есть команда dsh `/plan`; иначе идея уходит как обычное первое сообщение. Список **На потом** привязан к пути папки чата: та же папка, открытая через символическую ссылку, получает свой список. В нём хранится не более 50 идей на проект (удалите одну, чтобы добавить новые), и каждый заголовок только один раз. Перетаскивание карточки решает только «влево» или «вправо»; чтобы отложить её, используйте **↓**, а чтобы создать её сразу — **▶**. Повтор определяется только по заголовку: модель всё равно может предложить прежнюю идею под новым названием; пропустите её. Если модель отвечает только прежними идеями, ничего нового не появляется: нажмите ещё раз. Узкая тема делает это более вероятным: выберите тему шире или очистите её. Тема остаётся в поле для каждого чата, пока не перезагрузится dsh или страница.
|
|
178
194
|
- **Экспорт чата в Markdown** включает только ваши сообщения и текстовые ответы ассистента. Вызовы инструментов и их вывод, рассуждения, изображения (их отмечает строка `[image]`), скрытый контекст и сообщения, которые убрал откат хода или dsh-rewind-plugin, в экспорт не попадают. Ответы одного хода объединяются в один раздел. В один экспорт входит не более примерно 4 миллионов символов; для более длинного чата экспорт содержит его первую часть и примечание.
|
|
179
195
|
- **Продолжать после перезапуска** продолжает ход, а не повторяет его. Вызов инструмента, который выполнялся в момент выхода, завершается результатом dsh «outcome unknown» (результат неизвестен). Модели сообщается, что не нужно повторять сделанную работу, но команда, которую небезопасно запускать дважды, может выполниться снова. Субагенты, одобрения и вопросы, которые были открыты, не восстанавливаются: их родительский чат продолжает работу и спрашивает снова. За один запуск продолжается не более 20 чатов.
|
|
196
|
+
- **Продолжать после перезапуска** и очередь: при завершении dsh очищает очередь чата. Плагин возвращает ваши сообщения из очереди по журналу чата, с их порядком, правками, изображениями и файлами; они выполняются после продолженного хода. Очередь возвращается только в чатах, которые продолжаются (переключатель включён, выход во время хода). Ваше собственное удаление последних сообщений из очереди dsh записывает так же: если вы удалили их и dsh завершил работу до начала следующего шага, они вернутся.
|
|
180
197
|
|
|
181
198
|
- **Поиск по содержимому** — это встроенный поиск dsh, поэтому у него те же ограничения. Он ищет только в сообщениях пользователя и ассистента: не в выводе инструментов (команды, содержимое файлов, результаты) и не в рассуждениях. Фильтра по сообщениям пользователя, ассистента или инструментов нет. Он находит целые слова, а не части слов (`deploy` не находит `deployment`); буквы с диакритикой совпадают с буквами без неё (`seker` находит `şeker`). На каждый чат одна строка с фрагментом dsh длиной 240 символов, всего не более 20 строк.
|
|
182
199
|
- **Поиск по содержимому**: затраты измерены на копии 247 реальных журналов чатов (159 МБ, dsh 0.2.1-rc.2, Apple Silicon, 32 ГБ). Первый поиск после запуска строит индекс примерно за 15 с. В это время Host dsh около 7 с ничего не отвечает, поэтому другие чаты на этот момент перестают выводить ответ (сама страница не зависает). Память Host на пике вырастает примерно на 1,1 ГБ; через минуту она всё ещё примерно на 0,5–0,6 ГБ выше начальной и остаётся такой до выхода из dsh. Файл индекса занимает около 165 МБ. Следующие поиски занимают около 0,5 с. После перезапуска первый поиск занимает около 1 с (добавляются только новые или изменённые чаты) и добавляет около 70 МБ. Если на компьютере мало памяти, выключите эту функцию.
|
|
@@ -187,19 +204,25 @@ English · 中文 · Türkçe · Español · Português (Brasil) · Français ·
|
|
|
187
204
|
- dsh 0.2.1 загружает обновление сразу, если новая версия не меняет никаких настроек dsh; в остальных случаях, а также в dsh 0.2.0, перезапустите dsh, чтобы загрузить его. Плагин никогда не перезапускает dsh за вас. Профили Web/CLI без менеджера плагинов dsh только сообщают о новой версии.
|
|
188
205
|
- **Разрешить для этого чата** отсчитывает лимит времени с момента выдачи разрешения. Новый лимит времени сразу применяется к действующим разрешениям, поэтому более короткий лимит может сразу их завершить. У разрешений из версии 1.12 и более ранних нет времени: после обновления агент ещё раз спросит об этих инструментах.
|
|
189
206
|
- **Сохранять фокус в поле ввода** возвращает фокус только после команды `/` или навыка. Пока dsh обрабатывает команду, поле ввода несколько миллисекунд доступно только для чтения, поэтому клавиши, нажатые в это время, теряются. Если меню `/` в dsh ещё открыто, `Enter` выбирает выделенную строку и ничего не отправляет.
|
|
190
|
-
-
|
|
207
|
+
- **Подгонять карточку вопроса под окно** меняет только карточку вопроса dsh, а не карточку проверки плана. Она находит карточку по разметке dsh (`data-question-key`, `data-question-scroll`); если обновление dsh изменит эту разметку, карточка будет выглядеть так, как её рисует dsh. Высота карточки следует за окном, а не за чатом: в чате в узкой боковой панели высокая карточка всё ещё может выходить выше чата.
|
|
208
|
+
- **Мобильное подключение** работает только в macOS (оно использует `en0`, `openssl`, `swift` и `dns-sd`). Оно использует фиксированные порты 19390 и 19391, поэтому на каждом Mac его может одновременно запускать только один dsh (каждый Mac — одна запись в списке Mac на телефоне). Телефон получает уведомления, только пока Tether открыт или только что ушёл в фон (сервиса push-уведомлений нет). Tether отправляет их только после того, как вы включите в Tether «Settings → Notifications → Send notifications». По умолчанию этот переключатель выключен, а разрешение iOS запрашивает в момент включения. Приложения для iOS пока нет в App Store: соберите его из `tether/ios` в Xcode. «Tailscale only» всё равно требует адрес Wi-Fi или Ethernet на Mac (шлюз запускается только при таком адресе). Журнал доступа у каждого Mac свой и хранит только 200 самых новых попыток; повторная попытка в течение минуты увеличивает счётчик той же строки на один. Блокировка приложения Tether не скрывает превью уведомлений на экране блокировки iPhone: выключите их в настройках iOS. Зелёные точки в Tether следуют за Mac: у чата, который вы открыли в dsh, точка пропадает и на телефоне. У чата, который вы открыли в Tether, точка пропадает только на телефонах. Собственная точка dsh на Mac остаётся, пока вы не откроете чат на Mac.
|
|
191
209
|
- Ссылка на сеанс работает внутри чатов; щелчок по ней не открывает чат. Ссылка, созданная через **Копировать ссылку на сообщение**, открывает своё сообщение только в dsh 0.2.1 и новее и только из сообщения в чате (в dsh 0.2.0 нет правил для пользовательского текста, поэтому там ссылка копируется, но показывается как обычный текст). Сообщение, которое убрал откат или которое сжатие удалило из истории, загружаемой dsh, показать нельзя: ссылка тогда сообщает об этом. Кнопки 🔗 привязаны к строкам сообщений dsh; если обновление dsh изменит эту разметку, они не появятся.
|
|
192
210
|
- **Отметить все как прочитанные** меняет собственные точки непрочитанного dsh через часть dsh, которая не является публичным API (список `completionUnread` в состоянии сеансов dsh). Если обновление dsh переименует его, пункт не появится. Пункт добавляется в меню «…» проекта в dsh, где нет места для плагинов; если dsh изменит это меню, пункт тоже не появится.
|
|
193
|
-
- **Правка сообщения в очереди на месте**
|
|
211
|
+
- **Правка сообщения в очереди на месте** не меняет сообщение, которое тем временем начало отправляться, и не перезаписывает сообщение, которое тем временем изменилось (например, в Tether на iPhone): об этом сообщает уведомление. Для нового изображения нужна модель, которая принимает изображения (действуют собственные ограничения dsh на изображения), а новый файл должен загрузиться до того, как вы сможете сохранить. Изменять можно только свои сообщения в очереди: раунд цели или ответ на вопрос в очереди изменить нельзя. После обновления плагина сразу работает только правка текста: перезапустите dsh, прежде чем сохранять сообщение с изображениями или файлами (Host-часть загружается при запуске).
|
|
194
212
|
- **Повторить** никогда не меняет откаченный чат: кнопка начинает новый чат с момента непосредственно перед откатом (встроенное ответвление dsh, тот же контекст модели), поэтому у нового чата новый id и новое название. Повторить можно только самый новый откат чата, один раз и только пока после него ничего не было (новое сообщение убирает эту возможность). Файл, который вы изменили после отката, сохраняется, если вы не отметите флажок, который его перезаписывает. Для повтора нужен снимок, который сохранил откат (то же окно из 50 записей); откат, сделанный до этой версии или с вариантом **Только чат**, возвращает только сообщения.
|
|
213
|
+
- Карта веток в режиме **Дерево** угадывает, куда идёт каждая стрелка, потому что git не сохраняет, в какую ветку слита ветка. Слитая ветка указывает на ветку, коммит слияния которой первым принял её. Ожидающая ветка указывает на ближайшую ветку, от которой она началась (в первую очередь на основную ветку); если две ветки начались от одного коммита, карта может выбрать не ту. У ветки, которая продвинулась перемоткой вперёд (fast-forward), нет коммита слияния, поэтому её метка **Слито** ничего не открывает. Основная ветка — это ветка по умолчанию у `origin`, иначе `main` или `master`, иначе открытая ветка. Карта читает последние 20 000 коммитов и показывает не больше 60 веток; если история длиннее, она сообщает, что некоторые стрелки могут быть неверными. Ветка, слитая через squash или rebase (например, на GitHub), показывается как **Ожидает**: git не хранит связи с её коммитами.
|
|
195
214
|
- **Этот чат** учитывает только файлы, которые записали файловые инструменты dsh (`write`, `edit`, `str_replace_editor`). Файлов, которые изменила команда (`bash`), в этом представлении нет; они показаны в разделе **Незафиксированные**. Без снимка отката хода для чата (откат хода выключен, установлен dsh-rewind-plugin или чат старше плагина) представление сравнивает с последним коммитом и сообщает об этом. Откат хода хранит 50 последних снимков чата: в более длинном чате представление сравнивает с самым старым сохранённым снимком, сообщает, с какого сообщения, и не учитывает более ранние изменения. **Скрыть изменения пробелов** — это `git diff -w`: строка, в которой изменились только пробелы внутри неё, тоже скрывается.
|
|
196
215
|
- **Открыть issue на GitHub** требует GitHub CLI (`gh`) в PATH dsh и удалённый репозиторий GitHub в папке чата. Команда работает не дольше 60 с; если `gh` работает дольше, issue может уже существовать на GitHub без ссылки в списке (прежде чем нажать ещё раз, проверьте GitHub: список читает ссылку только из завершённого запуска, поэтому новое нажатие может открыть вторую issue). Папка с несколькими удалёнными репозиториями GitHub использует значение по умолчанию самого `gh` (`gh repo set-default`).
|
|
197
216
|
- **Чаты, которые изменили этот файл**, как и **Этот чат**, знают только файловые инструменты dsh (`write`, `edit`, `str_replace_editor`): изменение, сделанное командой (`bash`), в списке не появляется. Список читает 300 самых новых чатов репозитория (по времени создания) и сообщает, если их больше; он показывает не более 100 строк. Переименованный файл показан под тем именем, которое записал инструмент. Чат, папка которого находится вне репозитория (в том числе через другой путь к тем же файлам), не учитывается. Первое открытие после запуска dsh читает все журналы чатов репозитория (около 4 с для 275 чатов); последующие открытия читают только чаты, изменившиеся с тех пор.
|
|
198
|
-
- **Ветка Git в строках чатов** показывает ветку папки чата на момент начала или конца его последнего хода, а не текущую ветку: переключение ветки вне хода появится после следующего хода. У чатов, созданных до этой версии, метки нет до их следующего хода. Метка встроена в разметку строк чатов dsh (в dsh нет для неё отдельного места); если обновление dsh изменит эту разметку, метка не появится.
|
|
217
|
+
- **Ветка Git в строках чатов** показывает ветку папки чата на момент начала или конца его последнего хода, а не текущую ветку: переключение ветки вне хода появится после следующего хода. У чатов, созданных до этой версии, метки нет до их следующего хода. Метка встроена в разметку строк чатов dsh (в dsh нет для неё отдельного места); если обновление dsh изменит эту разметку, метка не появится. Если строка проекта над чатом называется так же, как ветка (например, папка «Ветка для каждого чата»), строка чата не показывает метку, но в режиме «Одним списком» метка по-прежнему видна.
|
|
218
|
+
- **Ветка для каждого чата** в режиме плана: dsh отправляет `/plan <сообщение>` как команду, а не как сообщение, поэтому Composer Plus перехватывает отправку команды в поле ввода dsh (это не публичный API). Если обновление dsh это изменит, `/plan <сообщение>` при выбранном пункте **Новая ветка** выполнится на открытом экране нового чата как собственная команда dsh. Если Host не может включить режим плана в новом чате, папка ветки остаётся, а сообщение не отправляется, поэтому новый чат не меняет файлы в режиме по умолчанию.
|
|
219
|
+
- **Ветка для каждого чата**: когда папка ветки чата (`<project>/.worktrees/<name>`) удалена, например когда агент самого чата удаляет worktree и ветку, следующий шаг чата выводит чат из этой папки. Проект папки ветки исчезает с боковой панели, а чат появляется в разделе «Без группы» и остаётся открытым. В dsh 0.2.1 и новее чат продолжается в основной папке проекта, и модель получает заметку о новой папке. В dsh 0.2.0 чат остаётся в удалённой папке: команда там завершается с ошибкой, пока вы не начнёте новый чат. Перенос происходит только на следующем шаге чата, поэтому проект удалённой ветки, который не использует ни один чат, остаётся на боковой панели: удалите его через меню проекта dsh. Пока чат переносится, **Новая ветка** в том же репозитории отвечает «попробуйте ещё раз». Если переключатель выключен, снова показывается собственная ошибка dsh («working-directory: directory does not exist»).
|
|
220
|
+
- **Ветки в дереве рабочих областей** пишет в git без клика: при переносе чата он возвращает папку проекта на прежнюю ветку (`git switch`) и добавляет worktree (`git worktree add`). Он никогда не удаляет ветку, worktree или файл. dsh не может сменить папку чата, поэтому перенесённый чат — это копия (собственный форк dsh с новым id), а старый чат архивируется. Копия продолжает остановленную задачу; вызов инструмента, который шёл в момент появления ветки, завершается отказом, и агент запускает его снова в новой папке. Цель старого чата не переносится. Переносится только чат, чья папка — главная папка репозитория, и только ради ветки, которую он создал и на которую переключился в этом ходе (`git switch -c`, `git checkout -b`): ветка, созданная только через `git branch`, папка с незакоммиченными изменениями, связанный worktree или подпапка ничего не переносят. В дереве показываются только worktree прямо в `<project>/.worktrees/` с веткой; отсоединённый (detached) worktree или worktree в другом месте не показывается. Копия открывается сама, только если её чат был открытым (плагин читает это из строки боковой панели dsh); иначе она находится в проекте ветки.
|
|
199
221
|
- **Поиск в чате** ищет только в том, что показывает страница: в загруженных сообщениях и ответах (для более старых прокрутите вверх или нажмите **Загрузить более ранние**), но не в закрытых шагах инструментов и не в свёрнутом тексте вывода инструмента. Он считает не более 2 000 совпадений (дальше — «2000+»). Он использует API подсветки браузера (Chromium 105 и новее; в настольном приложении он есть): в более старом браузере счётчик и переходы работают без цвета. `Cmd+F` на Mac (`Ctrl+F` в Windows и Linux) открывает его, только пока на экране есть чат; в других местах встроенный поиск браузера работает как раньше. На Mac `Ctrl+F` сохраняет своё действие macOS в текстовых полях (курсор сдвигается на один символ вперёд).
|
|
222
|
+
- **Открывать ожидающий чат при бездействии** знает только то, что видит окно dsh: работа в другом приложении не считается, поэтому, когда dsh в фоне, функция может открыть ожидающий чат через 30 секунд. Окно dsh при этом не выходит на передний план. Чтение без нажатия клавиш, щелчков и движений мыши считается бездействием. Функция смотрит только на чаты с оранжевой точкой dsh (вопрос, одобрение или проверка плана); запрос субагента показывается в его родительском чате. Пока ожидающий чат на экране, другой не открывается; чат, из которого вы ушли без ответа, может открыться снова после следующих 30 секунд бездействия. 30 секунд изменить нельзя.
|
|
200
223
|
- Уведомление, отправленное до перезапуска, при щелчке только выводит dsh на передний план.
|
|
201
224
|
- Активные проекты перемещаются через сохранённый порядок проектов dsh, поэтому новый порядок сохраняется после перезапуска. Чаты вне проектов («Без группы») перемещать нельзя; dsh всегда показывает их последними.
|
|
202
|
-
- В меню параметров просмотра на боковой панели у dsh нет точки расширения, поэтому пункт фильтра недавних проектов добавляется во встроенное меню dsh. Если обновление dsh изменит это меню, пункт не появится, и все проекты останутся видны. Фильтр работает со строками проектов, поэтому режим **Одним списком** не фильтруется.
|
|
225
|
+
- В меню параметров просмотра на боковой панели у dsh нет точки расширения, поэтому пункт фильтра недавних проектов добавляется во встроенное меню dsh. Если обновление dsh изменит это меню, пункт не появится, и все проекты останутся видны. Фильтр работает со строками проектов, поэтому режим **Одним списком** не фильтруется. В режиме **Дерево рабочих областей** родительская папка остаётся видна, пока активен проект внутри неё, а строки чатов, которые не были активны за последние 2 часа, тоже скрываются; в режиме **По рабочей области** фильтруются только строки проектов. Фильтр узнаёт текущий вид dsh из сохранённой настройки вида dsh (это не публичный API); если обновление dsh её переименует, **Дерево рабочих областей** фильтруется как **По рабочей области**. Функция «Статус проекта» читает ту же настройку: в режиме **Дерево рабочих областей** строка родительской папки учитывает и чаты проектов внутри неё; если dsh переименует настройку, каждая строка показывает только свои чаты. У **По состоянию** ограничение того же рода: в dsh нет места для своего порядка сортировки, поэтому пункт и порядок строк привязаны к разметке меню и списка dsh.
|
|
203
226
|
- В dsh нет ни меню строки проекта, ни места в заголовке «Рабочие области». **Копировать путь** находит строку проекта по разметке строк dsh, а **Свернуть все проекты** встраивается в заголовок dsh и закрывает каждый открытый проект тем же щелчком, что и строка проекта. Если обновление dsh изменит эту разметку, правый щелчок покажет меню браузера, а кнопка не появится.
|
|
204
227
|
- В меню проектов нового чата у dsh тоже нет точки расширения, поэтому поле **Поиск проектов** и порядок A–Z привязаны к разметке меню dsh. Если обновление dsh изменит эту разметку, меню будет выглядеть так, как его рисует dsh: в сохранённом порядке и без поля поиска. Порядок A–Z — только способ показа: он не меняет сохранённый порядок проектов dsh.
|
|
205
228
|
- В dsh также нет точки расширения, которая выбирает, где открывается **Новый сеанс**. **Рабочая область по умолчанию для нового сеанса** оборачивает метод dsh, который не является публичным API (`startSession` службы рабочих областей dsh). Если обновление dsh его переименует, **Новый сеанс** откроется там, где выберет dsh (открытый или последний проект). Каждый вызов без проекта использует значение по умолчанию: кнопка на боковой панели, её сочетание клавиш, логотип, а также **Создать** на странице **Задачи автоматизации**. При запуске dsh по-прежнему открывает последний чат. Общая папка создаётся и добавляется в ваши проекты при первом использовании; в Windows или Linux с перемещённой папкой Documents она может отличаться от папки самого dsh.
|
|
@@ -207,6 +230,12 @@ English · 中文 · Türkçe · Español · Português (Brasil) · Français ·
|
|
|
207
230
|
- **Дополнение при вводе** показывает свой текст через собственную подсказку поля ввода dsh (стиль `--dsh-composer-hint`, который dsh использует для подсказки аргумента слеш-команды). Функция не работает для слеш-команды, для сообщения со значком файла или символа и когда курсор стоит не в конце сообщения. Если обновление dsh изменит этот стиль, дополнение не появится. Каждая пауза в наборе стоит один вызов модели.
|
|
208
231
|
- **Улучшить промпт** видит только краткую сводку проекта, изменённые пути и пути, имена которых совпадают с вашими словами, но не сам код. Поэтому функция может пропустить нужный файл и называет только те пути, которые получила. Прочитайте новый текст перед отправкой. Она не работает для слеш-команды и для сообщения со значком файла или символа (новый текст — обычный текст, поэтому значок бы потерялся), а в сообщении может быть не более 8 000 символов. Изображения остаются прикреплёнными: меняется только текст. Каждое нажатие стоит один вызов модели; сильной модели может понадобиться минута (`Esc` отменяет).
|
|
209
232
|
- **Проверка цели** проверяет только выполнение, которое агент отмечает в автоматическом раунде цели: выполнение, о котором вы просите в чате, `/goal` и панель цели не проверяются. Агент может сам изменить тесты или файлы тестовой команды; верификатор читает чат и может это увидеть, но может ошибиться в обе стороны (ошибочное «не выполнено» стоит ещё одного раунда; ошибочное «выполнено» закрывает цель). Верификатор видит чат и `git status`, но не сам код. Запуск тестов используется повторно, только если последним шагом агента, который может менять файлы, был его собственный успешный запуск `bash` точно той же команды в той же папке; команда с конвейером (`| tail`) или `&&` повторно не используется. Бюджет измеряется, когда заканчивается ход, поэтому один ход может его превысить. Учитываются только вызовы модели самого чата (не его субагентов). `update_goal` ждёт, пока идёт проверка (тест не более 15 минут, верификатор не более 3 минут). Ответвление получает новый id чата, поэтому начинает без собственной тестовой команды и лимитов родительского чата. Каждое выполнение, которое доходит до верификатора, стоит одного вызова модели.
|
|
233
|
+
- **Приоритет сообщения после остановки** работает только после того, как вы остановили чат (или после хода с ошибкой, или когда вы открываете чат, у которого ещё есть очередь): сообщение, отправленное во время хода, по-прежнему ждёт в конце очереди. Оно обгоняет только ваши собственные сообщения в очереди: если в очереди ждёт раунд цели или ответ на вопрос, остаётся порядок dsh. Функция читает часть dsh, которая не является публичным API (завершается ли ещё остановленный ход); если обновление dsh её переименует, сообщение встанет первым только после завершения этого хода. Чаты субагентов сохраняют порядок dsh.
|
|
234
|
+
- **Память проекта** принадлежит первой папке чата (папке проекта dsh): чат, который меняет папку командой `cd`, сохраняет память своего первого проекта, а та же папка, открытая по другому пути к тем же файлам, использует ту же память. Чат замораживает свой раздел памяти при запуске, поэтому заметка, сохранённая позже, появляется со следующего чата (`memory_recall` находит её сразу). Разбор сохраняет только то, что решила сохранить модель: он может пропустить факт или сохранить неверный; откройте файлы, чтобы проверить их, и правьте или удаляйте их вручную, когда dsh закрыт. Каждый завершённый ход с вашим сообщением стоит одного вызова модели; неудачный вызов перечитывает те же сообщения после следующего хода. Чаты субагентов не разбираются. Идея и формат файлов взяты из [DS Bot](https://github.com/Fei2411/DS-Bot) (Apache-2.0); Composer Plus не использует его код и никогда не читает и не записывает собственную память DS Bot.
|
|
235
|
+
- **Резервное копирование** использует одну постоянную папку, `~/Desktop/dsh-backups` (папку dsh-backup по умолчанию, поэтому его архивы остаются пригодными); настройки для другой папки нет. Архив примерно такого же размера, как домашняя папка dsh без `cache/` и `dsh-runtimes/` (измерено: из 1,6 ГБ файлов получился архив 830 МБ примерно за 30 с на Apple Silicon; dsh при этом отвечал). Файл, который меняется во время чтения, сохраняется в том виде, в каком он был, когда резервное копирование его открыло, поэтому журнал открытого чата может заканчиваться обрезанной записью, которую dsh исправляет при следующей записи. Скрытие находит секрет в файле yml по имени ключа в одной строке (`token:`, `apiKey:`, …); секрет в потоковом словаре (`{token: x}`), в списке под таким ключом, в файле JSON (например, `apiKey` сервера MCP в файле `.json`) или под другим именем остаётся в архиве. Архивы dsh-backup по типам (`dsh-t-…`) не показываются в списке. **Для другого компьютера** копирует архив (в APFS — клон, без дополнительного места); vault с ним не копируется. **Создать копию сейчас** не удаляет ни одной резервной копии. Автоматическое резервное копирование хранит самые новые резервные копии, которые создал Composer Plus (настройка **Хранить** функции **Автоматическое резервное копирование**), и удаляет более старые из них; снимки перед обновлением считаются отдельно (остаются 2 самых новых). Архивы dsh-backup не удаляются никогда: уберите их кнопкой **Удалить**. Пока dsh-backup ещё установлен, он учитывает архивы Composer Plus в своём лимите хранимых копий и может их удалить.
|
|
236
|
+
- **Восстановить** можно только в аварийной консоли, пока dsh закрыт: восстановление заменяет всю домашнюю папку dsh. Старая остаётся рядом как `.dsh.pre-restore-<time>`, пока вы её не удалите, поэтому на диске нужно место для обеих. Чаты сохраняют пути своих проектов: на другом компьютере проект по другому пути показывается как отсутствующий, пока вы не добавите его снова. Символические ссылки, которые указывают за пределы домашней папки dsh (например, навыки, подключённые ссылкой из другой папки), возвращаются как ссылки; их цели должны существовать на том компьютере.
|
|
237
|
+
- **Проверка журналов сеансов** читает самый новый журнал каждого чата по собственным правилам dsh о том, что открывается: строка, которая не является JSON или стоит не по порядку, считается повреждением, только когда после неё идёт конец хода (иначе dsh открывает чат без строк начиная с этой, поэтому чат не попадает в список). Она не сверяет события журнала с собственными правилами событий dsh, поэтому журнал, который она считает исправным, всё равно может не открыться после обновления dsh. Исправление берёт копию из резервной копии: сообщения после этой резервной копии из чата пропадают (повреждённый файл остаётся рядом). Чат, открытый в этом dsh, в Настройках не исправляется: его удерживает dsh.
|
|
238
|
+
- **Автоматическое резервное копирование** работает, только пока работает dsh: копия, срок которой наступил, пока dsh был закрыт, создаётся примерно через 45 с после следующего запуска. Снимок для новой версии создаётся после этого запуска, а не перед обновлением.
|
|
210
239
|
- Встроенную поддержку запросили у разработчиков dsh: `move` для очереди в [#773](https://github.com/deepseek-ai/deepseek-harness/discussions/773), состояние «Продолжить» в [#9269](https://github.com/deepseek-ai/deepseek-harness/discussions/9269).
|
|
211
240
|
|
|
212
241
|
## Частые вопросы
|
|
@@ -235,9 +264,19 @@ English · 中文 · Türkçe · Español · Português (Brasil) · Français ·
|
|
|
235
264
|
|
|
236
265
|
**Можно ли сделать так, чтобы агент сам не отмечал свою работу как выполненную, как в циклах с верификатором из loop engineering?** Да, с функцией **Проверка цели** (включена по умолчанию): начните цель командой `/goal`. Когда агент говорит, что цель выполнена, запускаются тесты проекта, а независимый вызов модели сверяет цель с чатом; если что-то не пройдено, цель остаётся открытой, а агент читает причину. Свою тестовую команду, лимит времени или лимит токенов задайте кнопкой **Изменить** в строке **Проверка цели** под целью.
|
|
237
266
|
|
|
267
|
+
**Может ли агент помнить мои предпочтения между чатами, как память DS Bot?** Да, с функцией **Память проекта** (по умолчанию выключена): включите её в **Настройки → Composer Plus**. После каждого хода ваши постоянные предпочтения и решения сохраняются короткими заметками для проекта чата, и каждый новый чат этого проекта их читает. Попросите агента что-то запомнить, и он сразу сохранит это.
|
|
268
|
+
|
|
269
|
+
**Может ли dsh создавать резервные копии моих чатов и настроек, как dsh-backup?** Да: **Настройки → Composer Plus → Резервное копирование → Создать копию сейчас**. Он записывает архив того же формата в ту же папку (`~/Desktop/dsh-backups`), поэтому архивы dsh-backup тоже показываются и восстанавливаются, а dsh-backup можно удалить. Чтобы копии создавались по расписанию, включите **Автоматическое резервное копирование**.
|
|
270
|
+
|
|
271
|
+
**dsh больше не запускается. Как восстановить резервную копию?** Откройте папку резервных копий (`~/Desktop/dsh-backups`) и дважды щёлкните `Composer Plus Rescue.command` (Linux: `composer-plus-rescue.sh`, Windows: `Composer Plus Rescue.cmd`). Выберите `3) Restore a backup`, выберите копию и введите `RESTORE`. Это работает без dsh.
|
|
272
|
+
|
|
273
|
+
**Как перенести dsh на новый компьютер?** На старом: **Резервное копирование** → **Для другого компьютера** рядом с резервной копией. Скопируйте эту папку на новый компьютер, установите там dsh, выйдите из него, откройте `Composer Plus Rescue` в скопированной папке и выполните восстановление. Введите свои API-ключи заново (они остаются на старом компьютере).
|
|
274
|
+
|
|
275
|
+
**Чат не открывается после сбоя. Можно ли его исправить?** **Настройки → Composer Plus → Проверка журналов сеансов → Проверить журналы сеансов**. Повреждённый чат возвращается из самой новой резервной копии кнопкой **Исправить из резервных копий** (сообщения после этой резервной копии теряются).
|
|
276
|
+
|
|
238
277
|
**Как изменить порядок сообщений в очереди dsh?** Перетащите маркер ⠿ на сообщении в очереди или переведите на него фокус и нажмите `↑` / `↓`.
|
|
239
278
|
|
|
240
|
-
**Как исправить опечатку в сообщении в очереди?** Дважды щёлкните сообщение в очереди, измените текст и нажмите `Enter` (`Esc` отменяет). Сообщение остаётся на своём месте в очереди.
|
|
279
|
+
**Как исправить опечатку в сообщении в очереди?** Дважды щёлкните сообщение в очереди, измените текст и нажмите `Enter` (`Esc` отменяет). Сообщение остаётся на своём месте в очереди. Там же можно удалить его изображения и файлы или добавить новые.
|
|
241
280
|
|
|
242
281
|
**Как сразу убрать все точки непрочитанного в проекте?** Боковая панель → кнопка **…** проекта → **Отметить все как прочитанные**.
|
|
243
282
|
|
|
@@ -265,13 +304,17 @@ English · 中文 · Türkçe · Español · Português (Brasil) · Français ·
|
|
|
265
304
|
|
|
266
305
|
**Как получать уведомления macOS / Windows, когда задача dsh завершилась или ждёт одобрения?** Оставьте включёнными **Фоновые уведомления** (по умолчанию) и разрешите уведомления для DeepSeek Harness в настройках ОС.
|
|
267
306
|
|
|
307
|
+
**Может ли dsh сам открыть чат, который задаёт мне вопрос?** Да, с функцией **Открывать ожидающий чат при бездействии** (включена по умолчанию): когда чат ждёт ответа, одобрения или проверки плана, а вы не пользуетесь dsh 30 секунд, dsh открывает его. Пока вы печатаете, прокручиваете или двигаете мышь, функция ждёт.
|
|
308
|
+
|
|
268
309
|
**Как переключить интерфейс DeepSeek Harness на турецкий, испанский, японский…?** Настройки → Composer Plus → **Язык приложения**.
|
|
269
310
|
|
|
270
311
|
**Как пользоваться dsh с iPhone?** Соберите приложение Tether из `tether/ios` (Xcode), включите **Настройки → Composer Plus → Мобильное подключение (iPhone)**, нажмите **Мобильное подключение** внизу слева, отсканируйте QR-код (камерой iPhone или кнопкой **Scan code** в Tether), коснитесь **Connect** и нажмите **Approve**. Вне дома используйте Tailscale на обоих устройствах.
|
|
271
312
|
|
|
272
313
|
**Как сделать, чтобы Новый сеанс всегда открывался в одном проекте?** Настройки → Composer Plus → **Рабочая область по умолчанию для нового сеанса** → **Открывать «Новый сеанс» в** → выберите проект. «`+`» рядом с другим проектом по-прежнему открывает этот проект.
|
|
273
314
|
|
|
274
|
-
**Как работать над несколькими функциями одного проекта одновременно, каждой в своей ветке?** С функцией **Ветка для каждого чата**:
|
|
315
|
+
**Как работать над несколькими функциями одного проекта одновременно, каждой в своей ветке?** С функцией **Ветка для каждого чата**: на экране нового чата кнопка ветки по умолчанию показывает **Новая ветка**: отправьте первое сообщение. Каждый чат получает свою ветку и папку worktree, а также ваши `.env` и `node_modules`, если они перечислены в `.worktreeinclude`. Заголовок чата показывает, в какой ветке вы находитесь.
|
|
316
|
+
|
|
317
|
+
**Может ли боковая панель показывать каждую ветку проекта и переносить мой чат, когда агент создаёт ветку?** Да, с помощью **Ветки в дереве рабочих областей** (по умолчанию выключено): включите его в Настройки → Composer Plus, затем выберите в dsh **Параметры просмотра** → **Дерево рабочих областей**. Каждая ветка с worktree в `<project>/.worktrees/` показывается внутри своего проекта. Если вы попросите агента в папке проекта создать ветку и работать в ней, а в папке нет незакоммиченных изменений, чат сам перейдёт в эту ветку. Удалите папку ветки — и она уйдёт из списка; её чаты окажутся в **Без группы**.
|
|
275
318
|
|
|
276
319
|
**Можно ли отправить фото с iPhone?** Да. В чате Tether коснитесь **+** рядом с полем сообщения → Camera, Photos (до 4) или Paste image. Фотографии попадают в чат на Mac как вложения вашего сообщения, поэтому модель их видит.
|
|
277
320
|
|
|
@@ -287,6 +330,7 @@ PLAYWRIGHT=/path/to/playwright node scripts/capture-screenshots.mjs /path/to/dsh
|
|
|
287
330
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-sidebar-projects.mjs /path/to/dsh/lib/bin.js
|
|
288
331
|
# recent filter + a finished chat older than 2 hours (fake model): the project stays until you open the chat
|
|
289
332
|
PLAYWRIGHT=/path/to/playwright node test/browser-recent-finished.mjs /path/to/dsh/lib/bin.js
|
|
333
|
+
PLAYWRIGHT=/path/to/playwright node test/browser-recent-tree.mjs /path/to/dsh/lib/bin.js
|
|
290
334
|
# Order by status (fake model + Schedule): real-app test + its thumbnail
|
|
291
335
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-status-order.mjs /path/to/dsh/lib/bin.js
|
|
292
336
|
# every Settings feature row shows a loading screenshot and a ? link to its README row
|
|
@@ -297,10 +341,14 @@ PLAYWRIGHT=/path/to/playwright node test/browser-whats-new.mjs /path/to/dsh/lib/
|
|
|
297
341
|
PLAYWRIGHT=/path/to/playwright node test/browser-readme-anchors.mjs
|
|
298
342
|
# Keep composer focus (fake model + demo skill): typing goes on after a / command + its thumbnail
|
|
299
343
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-keep-focus.mjs /path/to/dsh/lib/bin.js
|
|
344
|
+
# Fit question card to window (fake model asks a long question at 1280 × 820): question, answers, Skip and Submit readable, height follows the window + its thumbnail
|
|
345
|
+
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-question-fit.mjs /path/to/dsh/lib/bin.js
|
|
300
346
|
# Mobile connect: switch on, QR popover, a fake iPhone pairs and calls dsh through the gateway, switch off + its thumbnail
|
|
301
347
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-mobile-connect.mjs /path/to/dsh/lib/bin.js
|
|
302
348
|
# Resume after restart (fake slow model, real quit and start): a running chat and a goal continue, a stopped chat does not
|
|
303
349
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-resume-restart.mjs /path/to/dsh/lib/bin.js
|
|
350
|
+
# Resume after restart with a queue (fake model, real quit and start): text, image, file, a drag and an edit come back in order
|
|
351
|
+
PLAYWRIGHT=/path/to/playwright node test/browser-resume-queue.mjs /path/to/dsh/lib/bin.js
|
|
304
352
|
# Feature ideas (fake model, made-up project): suggest, drag left, Undo, ✓ starts a new chat in plan mode, ▶ Build now one without, Plan all one for the Later list, a focus topic chip, Copy as checklist + its thumbnail
|
|
305
353
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-feature-ideas.mjs /path/to/dsh/lib/bin.js
|
|
306
354
|
# Export chat as Markdown (fake model, made-up project): right-click → Export as Markdown…, copy and save keep the code blocks, switch off + its thumbnail
|
|
@@ -315,8 +363,10 @@ SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-prompt-improve.mjs /path
|
|
|
315
363
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-goal-check.mjs /path/to/dsh/lib/bin.js
|
|
316
364
|
# Mark all as read, Copy message link, Edit queued message in place, Redo, Changes → This chat and Hide whitespace (fake model, made-up git projects) + their thumbnails
|
|
317
365
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-six-features.mjs /path/to/dsh/lib/bin.js
|
|
318
|
-
# Changes Tree (fake model, made-up git history): branch
|
|
366
|
+
# Changes Tree (fake model, made-up git history): the branch map (counts, colors, arrows), a branch's commits, commit files and diffs, Merged and Waiting files, back marks the box + its thumbnail
|
|
319
367
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-changes-tree.mjs /path/to/dsh/lib/bin.js
|
|
368
|
+
# Branches in the workspace tree (fake model, made-up git project): a worktree becomes a project, the agent's new branch moves the chat, a deleted folder leaves the tree + its thumbnail
|
|
369
|
+
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-branch-tree.mjs /path/to/dsh/lib/bin.js
|
|
320
370
|
# Allow for this chat with a time limit (fake model that is also the Auto Review reviewer): the grant ends after 1 hour
|
|
321
371
|
PLAYWRIGHT=/path/to/playwright node test/browser-grant-ttl.mjs /path/to/dsh/lib/bin.js
|
|
322
372
|
# Next message prediction and Complete while typing (fake models): calls, Tab, Esc, model choice + their thumbnails
|
|
@@ -327,6 +377,9 @@ SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-project-picker.mjs /path
|
|
|
327
377
|
# Queue drag-and-drop and Continue with a queued message (slow fake model)
|
|
328
378
|
PLAYWRIGHT=/path/to/playwright node test/browser-queue-drag.mjs /path/to/dsh/lib/bin.js
|
|
329
379
|
PLAYWRIGHT=/path/to/playwright node test/browser-continue-queue.mjs /path/to/dsh/lib/bin.js
|
|
380
|
+
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-stop-send.mjs /path/to/dsh/lib/bin.js
|
|
381
|
+
# Edit queued message in place with images and files (slow fake model) + its thumbnail
|
|
382
|
+
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-edit.mjs /path/to/dsh/lib/bin.js
|
|
330
383
|
```
|
|
331
384
|
|
|
332
385
|
```sh
|