@goodandready/dsh-cron 0.2.14 → 0.2.16
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.md +17 -0
- package/README.ru.md +17 -0
- package/README.zh.md +17 -0
- package/lib/api.js +3 -1
- package/lib/channels.js +3 -13
- package/lib/chat-start.js +6 -2
- package/lib/client.js +121 -5
- package/lib/failure-inspector.js +2 -8
- package/lib/index.js +18 -0
- package/lib/recipes.js +1 -1
- package/lib/runtimes.js +2 -2
- package/lib/scheduler.js +2 -2
- package/lib/silent-rule.js +4 -1
- package/lib/telegram.js +1 -1
- package/lib/updater.js +237 -0
- package/package.json +5 -4
- package/docs/README.ru.md +0 -512
- package/docs/README.zh.md +0 -512
package/docs/README.ru.md
DELETED
|
@@ -1,512 +0,0 @@
|
|
|
1
|
-
# 📦 @goodandready/dsh-cron
|
|
2
|
-
|
|
3
|
-
<div align="center">
|
|
4
|
-
|
|
5
|
-
<h3>Планировщик cron-задач, фоновая автоматизация и выполнение сценариев агентом для DeepSeek Harness</h3>
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
<a href="https://www.npmjs.com/package/@goodandready/dsh-cron"><img src="https://img.shields.io/npm/v/@goodandready/dsh-cron.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>
|
|
9
|
-
<a href="../LICENSE"><img src="https://img.shields.io/github/license/GooDAnDReaDY/dsh-cron.svg?style=for-the-badge&color=10b981&labelColor=064e3b" alt="license"></a>
|
|
10
|
-
<a href="https://github.com/topics/dsh-plugin"><img src="https://img.shields.io/badge/DSH-Plugin-8b5cf6.svg?style=for-the-badge&labelColor=2e1065" alt="DSH Plugin"></a>
|
|
11
|
-
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node-20%2B-f59e0b.svg?style=for-the-badge&labelColor=451a03" alt="Node version"></a>
|
|
12
|
-
</p>
|
|
13
|
-
|
|
14
|
-
<p align="center">
|
|
15
|
-
<a href="https://goodandready.app/"><img src="https://img.shields.io/badge/Все_проекты_автора-goodandready.app-ff4500.svg?style=for-the-badge&logo=rocket&logoColor=white&labelColor=1a1a2e" alt="Все проекты автора"></a>
|
|
16
|
-
</p>
|
|
17
|
-
|
|
18
|
-
<p align="center">
|
|
19
|
-
<a href="README.md"><b>🇬🇧 English</b></a> •
|
|
20
|
-
<a href="README.ru.md"><b>🇷🇺 Русский</b></a> •
|
|
21
|
-
<a href="README.zh.md"><b>🇨🇳 中文说明</b></a>
|
|
22
|
-
</p>
|
|
23
|
-
|
|
24
|
-
<table align="center">
|
|
25
|
-
<tr>
|
|
26
|
-
<td align="center">
|
|
27
|
-
⭐ <strong>Если вам нравится этот плагин, поставьте ему звезду на GitHub</strong> — это покажет мне, что плагин вам полезен, и будет мотивировать меня развивать его дальше.
|
|
28
|
-
<br><br>
|
|
29
|
-
🐛 <strong>Если вы нашли баг или хотите предложить новый функционал</strong>, создайте issue на GitHub на любом языке — я рассмотрю ваше предложение и реализую полезные идеи в одной из следующих версий плагина.
|
|
30
|
-
</td>
|
|
31
|
-
</tr>
|
|
32
|
-
</table>
|
|
33
|
-
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## ⚡ Обзор и проблема
|
|
39
|
-
|
|
40
|
-
Автономным AI-агентам регулярно нужны повторяющиеся действия: утренние сводки, разбор трекеров задач, проверка доступности API, синхронизация баз данных, периодическая гигиена Git. Без штатного планировщика внутри харнесса приходится использовать внешние обёртки над crontab, сложные webhook-схемы или ручной запуск.
|
|
41
|
-
|
|
42
|
-
**`@goodandready/dsh-cron`** — нативный полноформатный плагин планирования и фоновой автоматизации для DeepSeek Harness. Он связывает стандартные cron-выражения и естественные интервалы с автономным исполнением агентами:
|
|
43
|
-
|
|
44
|
-
1. **Развитый визуальный менеджер задач** — кнопка в сайдбаре со сворачиваемым списком активных задач (следующий запуск или живой статус, с ограничением и запоминанием состояния) и полноценная панель: фильтры по типу, модели и каналу, пауза, немедленный запуск, дублирование, экспорт/импорт и создание задач.
|
|
45
|
-
2. **Интерактивный сценарий «Создать с DSH»** — опишите задачу словами, агент уточнит детали и оформит расписание.
|
|
46
|
-
3. **Автономный tool calling** — нативные инструменты `cron_*` позволяют агентам планировать собственные последующие действия прямо в диалоге.
|
|
47
|
-
4. **Надёжный планировщик и атомарное хранилище** — на базе `croner`: интервалы, разовые задачи с задержкой, атомарная запись, история запусков, учёт стоимости.
|
|
48
|
-
5. **Шесть рантаймов исполнения** — shell, Node.js, Python, HTTP/webhook, удалённый SSH и Docker, плюс переменные окружения на задачу, привязка workspace и изолированные git worktree для изменяющих код агентских задач.
|
|
49
|
-
6. **Многоканальная доставка с шаблонами** — один запуск расходится в Telegram, dsh-kanban, Discord, Slack, ntfy, Bark, PushPlus, голос (`dsh-tts`) и Gitea, с шаблонами сообщений `{переменные}` и секретами по имени credential в DSH.
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## 🏗️ Архитектура
|
|
54
|
-
|
|
55
|
-
```mermaid
|
|
56
|
-
graph TD
|
|
57
|
-
subgraph Client ["Клиентская поверхность (DSH UI)"]
|
|
58
|
-
SidebarBtn["Кнопка-часы в сайдбаре<br/>(слот DSH Client UI)"]
|
|
59
|
-
Overlay["Панель управления задачами<br/>(табы: Все, Активные, На паузе, Завершённые)"]
|
|
60
|
-
CreateWithDSH["Диалог «Создать с DSH»<br/>(задача на естественном языке)"]
|
|
61
|
-
ManualForm["Ручная форма задачи<br/>(рантайм, cron, таймаут, overlap, каналы)"]
|
|
62
|
-
SettingsCard["Карточка настроек<br/>(каналы, шаблоны, credentials)"]
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
subgraph Server ["Серверная часть (Cordis и сервисы DSH)"]
|
|
66
|
-
HttpRoutes["HTTP REST API<br/>(/dsh-cron/*)"]
|
|
67
|
-
AgentTools["Шлюз tool calling<br/>(cron_create_task, cron_list_tasks, ...)"]
|
|
68
|
-
Scheduler["Движок TaskScheduler<br/>(экземпляры Croner + таймеры one-shot)"]
|
|
69
|
-
Store["Атомарный TaskStore<br/>(tasks.json, атомарная запись)"]
|
|
70
|
-
AgentRunner["Диспетчер агентских сессий<br/>(запуск промпта выбранной моделью)"]
|
|
71
|
-
Runtimes["Рантаймы исполнения<br/>(shell, node, python, http, ssh, docker)"]
|
|
72
|
-
Notify["Маршрутизатор доставки<br/>(шаблоны + 9 каналов)"]
|
|
73
|
-
Secrets["Credential-ссылки<br/>(DSH credentials / ENV)"]
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
SidebarBtn --> Overlay
|
|
77
|
-
Overlay --> CreateWithDSH
|
|
78
|
-
Overlay --> ManualForm
|
|
79
|
-
SettingsCard --> HttpRoutes
|
|
80
|
-
CreateWithDSH -->|POST /chat/start| HttpRoutes
|
|
81
|
-
ManualForm -->|POST /tasks| HttpRoutes
|
|
82
|
-
HttpRoutes --> Scheduler
|
|
83
|
-
AgentTools --> Scheduler
|
|
84
|
-
Scheduler --> Store
|
|
85
|
-
Scheduler -->|Запуск по интервалу/one-shot| AgentRunner
|
|
86
|
-
Scheduler --> Notify
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## ✨ Возможности
|
|
92
|
-
|
|
93
|
-
### 1. Визуальный менеджер задач
|
|
94
|
-
Нажмите на иконку-часы в сайдбаре DSH (рядом с кнопкой новой сессии), чтобы открыть панель:
|
|
95
|
-
* **Табы фильтрации**: **Все**, **Активные**, **На паузе**, **Завершённые**.
|
|
96
|
-
* **Мгновенные действия**: немедленный запуск (**Запустить**), пауза/возобновление расписания, удаление с подтверждением.
|
|
97
|
-
* **Готовые шаблоны в один клик**: *Ежедневная сводка*, *Еженедельный обзор*, *Мониторинг дальнейших действий*.
|
|
98
|
-
* **История запусков**: в карточке задачи — время, длительность и статусы предыдущих запусков (успех / сбой / таймаут / пропуск / пропущен по простою), вывод и ошибки.
|
|
99
|
-
* **Сводная статистика**: активные задачи, всего запусков, израсходованные токены и оценочная стоимость в долларах.
|
|
100
|
-
|
|
101
|
-
### 2. Диалог «Создать с DSH»
|
|
102
|
-
Превратите естественный язык в задачу без подбора cron-синтаксиса:
|
|
103
|
-
1. Нажмите **Создать ⌄** ➔ **Создать с DSH**.
|
|
104
|
-
2. Опишите, что нужно автоматизировать (например: *«Проверяй открытые PR по будням в 9:00 и готовь черновики комментариев»*).
|
|
105
|
-
3. Плагин создаст отдельную агентскую сессию с системными инструкциями планировщика. Агент уточнит детали — LLM или NO-LLM shell-задача, точное cron-выражение, экономичная модель из доступных в вашей установке DSH, нужно ли «правило тишины» (алерт только при новых событиях или сбоях) — и создаст задачу через инструмент `cron_create_task` только после вашего подтверждения.
|
|
106
|
-
|
|
107
|
-
### 3. Инструменты агентов (tool calling)
|
|
108
|
-
|
|
109
|
-
| Инструмент | Описание |
|
|
110
|
-
|:---|:---|
|
|
111
|
-
| `cron_create_task` | Создаёт задачу: `title`, `schedule`, `prompt`, `fallbackModel` (одна повторная попытка на сильной модели при сбое), опционально `type` (`llm`/`script`/`node`/`python`/`http`/`ssh`/`docker`/`skill`/`workflow`), `delivery`, `provider`, `model`, `channels`, `template`, `notifyTelegram`, `onlyOnFailure`, `timeoutSeconds`, `overlapPolicy`, `kanbanMode` |
|
|
112
|
-
| `cron_schedule_task` | Псевдоним `cron_create_task` для совместимости с существующими промптами |
|
|
113
|
-
| `cron_list_tasks` | Список задач со статусами, временем следующего запуска, токенами и стоимостью |
|
|
114
|
-
| `cron_pause_task` | Приостанавливает расписание без удаления конфигурации |
|
|
115
|
-
| `cron_resume_task` | Возобновляет приостановленное расписание |
|
|
116
|
-
| `cron_delete_task` | Полностью удаляет задачу и её историю |
|
|
117
|
-
| `cron_run_task` | Немедленный внеплановый запуск |
|
|
118
|
-
| `cron_get_task` | Полная конфигурация одной задачи, включая поля, которых нет в списке |
|
|
119
|
-
| `cron_update_task` | Изменяет существующую задачу на месте (whitelisted-поля, та же валидация, что у HTTP-маршрута); модели предписано сперва подтверждать с пользователем изменения, исполняющие код |
|
|
120
|
-
|
|
121
|
-
Пример вызова модели в диалоге:
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
cron_create_task({
|
|
125
|
-
"title": "Утренняя сводка",
|
|
126
|
-
"schedule": "0 8 * * 1-5",
|
|
127
|
-
"prompt": "Подготовь короткую утреннюю сводку активных задач и открытых тикетов.",
|
|
128
|
-
"type": "llm",
|
|
129
|
-
"delivery": "isolated"
|
|
130
|
-
})
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### 4. Синтаксис расписаний
|
|
134
|
-
На базе `croner`: стандартные 5-полевые cron-выражения и дружелюбные алиасы:
|
|
135
|
-
|
|
136
|
-
* `0 9 * * 1-5` — по будням в 09:00
|
|
137
|
-
* `*/15 * * * *` — каждые 15 минут
|
|
138
|
-
* `0 0 * * 0` — каждое воскресенье в полночь
|
|
139
|
-
* `every 10m` / `every 2h` / `every 30s` — естественные интервалы
|
|
140
|
-
* алиасы `daily` / `hourly` / `weekdays`, а также стандартные `@hourly` / `@daily` / `@weekly` / `@monthly` / `@yearly` и `@every 30m`
|
|
141
|
-
* **Часовые пояса** — для задачи можно указать IANA-зону (например, `Europe/Berlin`); без неё расписание живёт в серверном времени
|
|
142
|
-
* **Разовые задачи**: `at: 2026-09-05T15:00:00Z` (точный ISO-таймстемп) или относительные задержки `in 20m` / `in 2h` (принимаются и русские варианты вроде `через 15 минут`). После единственного запуска задача автоматически переходит в `completed` и отображается на табе **Завершённые**.
|
|
143
|
-
|
|
144
|
-
### 5. Надёжность исполнения
|
|
145
|
-
* **Автоповторы** — `maxRetries` и база `retryBackoffMs` на задачу: упавшие запуски (error/timeout) повторяются с экспоненциальной задержкой, счётчик сбрасывается после успеха.
|
|
146
|
-
* **Misfire-политики** — что делать с пропущенным за время простоя запуском: `skip` (по умолчанию — записать пропуск), `runOnce` (выполнить один раз с опозданием) или `catchUpAll` (выполнить и зафиксировать пропуск). Пропущенный one-shot при `skip` уходит в `completed` без выполнения.
|
|
147
|
-
* **Лимит параллельности** — настройка `maxConcurrent` ограничивает число одновременных запусков; лишние помечаются `skipped` с причиной.
|
|
148
|
-
* **Живой индикатор** — в списке задач пульсирует статус и идёт таймер текущего запуска.
|
|
149
|
-
|
|
150
|
-
### 6. Рантаймы исполнения
|
|
151
|
-
Каждая задача выбирает собственный рантайм; не-LLM рантаймы не используют модель и не тратят токены:
|
|
152
|
-
|
|
153
|
-
* **Shell** (`script`) — команда или скрипт через shell харнесса, с `env` и `cwd`.
|
|
154
|
-
* **Node.js** (`node`) и **Python** (`python`) — запуск сниппета с указанием интерпретатора (`nodePath`, `pythonPath`); для Python определяется виртуальное окружение проекта.
|
|
155
|
-
* **HTTP** (`http`) — GET/POST/… по URL с собственными заголовками и телом; статус и вывод ответа попадают в историю запуска.
|
|
156
|
-
* **SSH** (`ssh`) — выполнение команды на удалённом хосте через профиль `dsh-remote-workspace` (`sshProfileId`) или отдельные поля host/key.
|
|
157
|
-
* **Docker** (`docker`) — выполнение команды в контейнере образа (`dockerImage`).
|
|
158
|
-
* **Переменные окружения** — карта `env` на задачу (в UI — строки KEY VALUE) для внешних рантаймов; секретам здесь не место.
|
|
159
|
-
* **Workspace и worktree** — привязка задачи к workspace харнесса (`workspaceId`) и, для изменяющих код агентских задач, запуск в изолированном git worktree (`worktree`, `keepWorktree`).
|
|
160
|
-
|
|
161
|
-
### 7. Экономия: fallback-модель
|
|
162
|
-
Задача может идти на дешёвой модели по умолчанию и всё же завершиться на сильной: задайте `fallbackModel` (и при необходимости `fallbackProvider`), и сбойный запуск (`error` или `timeout`) один раз повторится на этой модели, прежде чем включится обычный retry с задержкой. В истории видно, какая модель произвела результат и был ли использован fallback; расход и стоимость обеих попыток суммируются; переменная шаблона `{model}` подставляет модель, завершившую запуск. Fallback доступен только агентским типам (`llm`, `skill`, `workflow`).
|
|
163
|
-
|
|
164
|
-
### 8. Интеграция сессий и права
|
|
165
|
-
* **Permission-пресеты на задачу** — `default`, `read-only`, `workspace-write` или `full` применяются к сессии агента перед запуском промпта.
|
|
166
|
-
* **Автоархивация сессий** — изолированные cron-сессии архивируются после запуска (best-effort), не засоряя список чатов.
|
|
167
|
-
* **История → сессия** — каждый LLM-запуск хранит свою сессию; открыть диалог можно прямо из записи истории.
|
|
168
|
-
|
|
169
|
-
### 9. Тишина по правилу
|
|
170
|
-
У задачи с выводом может быть **правило тишины**, написанное словами («молчи, если ни один раздел не занят больше 80%»). На успешном запуске дешёвая модель сверяет вывод с правилом, и отчёт пропускается, если вердикт — молчать; причина сохраняется в истории запуска. Работает fail-open: нет правила, нет модели, сбой вызова или нечитаемый ответ — отчёт доставляется. Настройка `silentRuleModel` задаёт модель для проверки.
|
|
171
|
-
|
|
172
|
-
### 10. Диагностика сбоев
|
|
173
|
-
Агентские задачи могут заказывать диагноз: с включённым `inspectOnFailure` сбойный запуск (`error` или `timeout`) вместе с промптом задачи и обрезанным выводом читает модель, и в историю запуска попадают короткий диагноз и конкретная правка промпта. В записи истории есть кнопка, подставляющая эту правку в форму редактирования — автоматически ничего не применяется. Модель задаётся настройкой `inspectorModel`, в шаблонах доступна переменная `{diagnosis}`. Недоступная модель оставляет сбойный запуск ровно таким, каким он был.
|
|
174
|
-
|
|
175
|
-
### 11. Каналы доставки и шаблоны сообщений
|
|
176
|
-
Отчёт о завершённом запуске уходит во все каналы, выбранные для задачи — Telegram, dsh-kanban, Discord, Slack, ntfy, Bark, PushPlus, голос через `dsh-tts` и issue в Gitea:
|
|
177
|
-
|
|
178
|
-
* **Перенос задач** — экспорт всей конфигурации в версионированный JSON и импорт с предварительной сводкой; импортированные задачи приходят на паузе.
|
|
179
|
-
* **Каналы на задачу** — отметьте каналы в форме задачи; явный выбор перекрывает legacy-переключатели `notifyTelegram`/`kanbanMode`, а пустой выбор возвращается к ним.
|
|
180
|
-
* **Изоляция сбоев** — недоступный канал фиксируется в логе планировщика, остальные каналы получают отчёт; сломанный webhook не поглощает доставку целиком.
|
|
181
|
-
* **Шаблоны сообщений** — глобальный шаблон, переопределения по каналам или шаблон на задачу с переменными `{title} {id} {status} {output} {error} {duration} {schedule} {time} {tokens} {cost}`. Неизвестные плейсхолдеры остаются как есть, для сбойных запусков по умолчанию используется шаблон ошибки.
|
|
182
|
-
* **`onlyOnFailure`** — глобально или на задачу: успешные запуски молчат, уходят только `error`/`timeout`.
|
|
183
|
-
* **Креденшелы по ссылке** — токены webhook'ов и токен Telegram вводятся как ИМЯ credential в DSH (`botTokenRef`, `ntfyTokenRef`, `pushplusTokenRef`, `giteaTokenRef`); значение резолвится в момент отправки через credentials-сервис DSH с фолбэком на переменную окружения и никогда не проходит через настройки плагина. Webhook-URL и ключ устройства Bark содержат секрет внутри, поэтому хранятся в настройках плагина, но всегда отдаются в браузер замаскированными, а замаскированное значение из UI никогда не перезаписывает сохранённое.
|
|
184
|
-
* **Таймаут доставки** — каждый запрос канала ограничен (`deliveryTimeoutMs`, по умолчанию 15000 мс, задаётся в панели настроек или `settings.yaml`), каналы отправляются параллельно: недоступный endpoint фиксируется как сбой и не задерживает остальные каналы и следующий тик расписания. Ограничение действует на весь обработчик канала, включая резолв credential'ов, который не поддерживает abort-сигнал.
|
|
185
|
-
* **Telegram** — Markdown-отчёт со статусными значками (✅ / ❌), длительностью, описанием расписания и monospace-блоком вывода; динамические значения экранируются. Креденшелы можно ввести напрямую или унаследовать из секции `dsh-messenger-gateway` вашего DSH `settings.yaml` (best-effort).
|
|
186
|
-
* **Discord / Slack** — доставка через webhook: Discord получает embed с цветом по статусу запуска, Slack — обычный текст.
|
|
187
|
-
* **ntfy / Bark / PushPlus** — мобильные пуши: тема/ключ устройства и опциональный bearer-токен; у Bark заголовок и текст идут в пути запроса, у PushPlus endpoint настраивается (self-hosted прокси).
|
|
188
|
-
* **Голос** — `dsh-tts` озвучивает отчёт через свой HTTP-маршрут (`ttsBaseUrl`, по умолчанию `http://127.0.0.1:3080`).
|
|
189
|
-
* **Gitea** — создаёт issue с отчётом (`giteaBaseUrl`, `giteaRepo`, credential токена); сбойные запуски помечаются метками `cron`, `bug`, `alert`.
|
|
190
|
-
* **Кнопка проверки** — проверьте доставку в Telegram до запуска критичных задач.
|
|
191
|
-
|
|
192
|
-
### 12. Интеграция с Kanban и учёт стоимости
|
|
193
|
-
* **Автоматические карточки Kanban** — при `kanbanMode` = `on_failure` или `always` плагин создаёт карточки в `dsh-kanban` (`on_failure` → *Backlog* при `error`/`timeout`; `always` → *Done*/*Backlog* по завершении).
|
|
194
|
-
* **Счётчик токенов и стоимости** — потребление токенов (ввод, вывод, чтения из кэша) учитывается по запускам и задачам с оценкой в USD по встроенной таблице цен и сводной панелью аналитики.
|
|
195
|
-
|
|
196
|
-
### 13. Политики наложения и таймаут выполнения
|
|
197
|
-
|
|
198
|
-
* **Таймаут (`timeoutSeconds`)** — по достижении лимита shell-процесс немедленно завершается через abort-сигнал, а агентская сессия закрывается, чтобы не расходовать токены. По умолчанию `1800` (30 минут).
|
|
199
|
-
* **Политика наложения (`overlapPolicy`)** — что делать, когда тик срабатывает при ещё активном предыдущем запуске:
|
|
200
|
-
* **`skip`** (по умолчанию): накладывающийся запуск отбрасывается, в истории появляется запись `skipped`;
|
|
201
|
-
* **`queue`**: следующий запуск ставится в очередь и стартует по завершении активного;
|
|
202
|
-
* **`replace`**: активный запуск прерывается через `AbortController`, запускается свежий.
|
|
203
|
-
|
|
204
|
-
Если сервис был выключен в момент планового запуска, при старте в истории появится запись `missed` — пробелы в истории остаются видимыми.
|
|
205
|
-
|
|
206
|
-
### 21. Пакет производительности и изоляции процессов (v0.2.9, #134)
|
|
207
|
-
- **Изоляция дерева процессов**: Shell и Script задачи запускаются в отдельной группе процессов (POSIX `detached: true`); при отмене или таймауте сигнал `-child.pid SIGTERM -> SIGKILL` завершает всё дерево, исключая зомби-процессы.
|
|
208
|
-
- **Троттлинг параллелизма**: Безопасный лимит `maxConcurrent = 2` по умолчанию предотвращает всплески нагрузки на CPU и RAM.
|
|
209
|
-
- **Повторы транзиентных сбоев**: Экспоненциальный backoff для ошибок 429 и 5xx (до 3 попыток).
|
|
210
|
-
- **Сетевая и UI-оптимизация**: `GET /dsh-cron/tasks` поддерживает `ETag` и `304 Not Modified`; адаптивный опрос UI (30с в фоне, 8с на активной вкладке).
|
|
211
|
-
- **Ротация истории и архив**: В памяти удерживается до 100 последних запусков на задачу, остальные архивируются в `tasks-history-archive.json`.
|
|
212
|
-
- **Рецепт автономного PR-ревьюера (#33)**: Готовый шаблон в Template Hub и тумблер `prReviewerEnabled`.
|
|
213
|
-
|
|
214
|
-
### 22. Автоматизация, цепочки задач и наблюдаемость (v0.2.10, #137)
|
|
215
|
-
- **Двухсторонний интерактивный Telegram**: Кнопки действий под уведомлениями (`🚀 Run Now`, `⏸️ Pause`, `📋 Last Output`), вебхук `POST /dsh-cron/telegram/webhook` с валидацией прав по Chat ID и откликом `answerCallbackQuery`.
|
|
216
|
-
- **Цепочки задач и конвейеры**: Триггеры `onSuccess` и `onFailure` для связывания задач. Передача вывода родительской задачи в переменную `$DSH_PREV_OUTPUT` (для shell) и `{{prevOutput}}` (для LLM). Ограничение глубины (максимум 5 уровней) против зацикливания.
|
|
217
|
-
- **Структурированные действия LLM**: Парсер директив модели (`trigger_task`, `notify`, `create_issue`) под опцией `llmActionsEnabled: false`.
|
|
218
|
-
- **Архивация и задержка в UI**: REST API `/dsh-cron/tasks/:id/archive` с пагинацией и статистика `/stats`. Бейджи латентности на карточках задач (<5с зелёный, <30с жёлтый, ≥30с красный).
|
|
219
|
-
- **Расширенные Prometheus-метрики**: Gauge `dsh_cron_concurrent_running`, счетчики токенов и стоимости в USD на задачу.
|
|
220
|
-
|
|
221
|
-
### 23. Расширенная надёжность, самовосстановление, Heartbeat и UX (v0.2.11, #139)
|
|
222
|
-
- **Мониторинг тишины (Heartbeat / Dead Man's Snitch)**: Эндпоинты `/dsh-cron/heartbeat/:id` и `/dsh-cron/api/heartbeat/:id` для приёма внешних пингов от бэкапов и демонов. При отсутствии пинга в пределах `heartbeatIntervalSeconds` + `gracePeriodSeconds` фиксируется статус `missed`, рассылается тревога и запускается `onFailure`.
|
|
223
|
-
- **Pre-flight проверки (условный запуск)**: Предварительная проверка HTTP-статуса 2xx, exit-кода команды или свободного места на диске. При непрохождении задача переходит в `skipped` без траты токенов LLM.
|
|
224
|
-
- **Dry-Run и симулятор расписания**: Тестовый запуск `POST /dsh-cron/tasks/:id/dry-run` и кнопка `🧪 Dry Run` в UI без записи в историю и без отправки в каналы; расчет следующих тиков через `POST /dsh-cron/schedule/preview`.
|
|
225
|
-
- **Очереди с приоритетами**: При достижении лимита параллелизма задачи упорядочиваются по полю `priority` (1 — наивысший, 10 — низший).
|
|
226
|
-
- **Команды самоисцеления и авто-диагностика (Self-Healing)**: Автоматический запуск компенсирующей команды `selfHealingCommand` при падении задачи; опция `autoDiagnose` для генерации AI-диагностики причин сбоя.
|
|
227
|
-
- **Интерактивный архив логов в UI**: Модальное окно просмотра истории с пагинацией и полным выводом логов, визуальные ссылки конвейеров `➜ onSuccess` и `↳ onFailure`.
|
|
228
|
-
|
|
229
|
-
---
|
|
230
|
-
|
|
231
|
-
### 24. Автоматическое подключение пресетов агента и инструментов (#141 / GH-1, добавлено в v0.2.12)
|
|
232
|
-
- **Автоматическое монтирование пресета агента**: Запланированные автономные `llm`-задачи и интерактивные запуски агента теперь автоматически определяют и подключают пресет агента системы (по умолчанию используется стандартный пресет пользователя через `presets.mount(agentCtx, preset.id)` внутри хука `setup`). Автономные сессии по расписанию получают полный доступ к инструментам (файлы, рабочее окружение, терминал и т.д.) вместо изолированного чата без инструментов.
|
|
233
|
-
- **Индивидуальный пресет для задачи**: Для каждой задачи можно явно задать идентификатор `agentPreset` в веб-интерфейсе, через REST API или в декларативных задачах профиля (например, `coding`, `system`, `minimal`). Если поле не заполнено, автоматически применяется пресет по умолчанию из настроек харнесса.
|
|
234
|
-
- **Безопасная деградация**: Если сервис `agentPresets` недоступен или указан несуществующий пресет, планировщик выводит информативное предупреждение и штатно продолжает выполнение модели без аварийной остановки задачи.
|
|
235
|
-
|
|
236
|
-
---
|
|
237
|
-
|
|
238
|
-
### 25. Долговременные сессии и непрерывность контекста (`targetSessionId`, добавлено в v0.2.13, #143)
|
|
239
|
-
- **Непрерывный контекст диалога**: Для задач можно задать `targetSessionId`. При наличии этого идентификатора планировщик возобновляет существующую сессию через `agents.resume()` вместо создания одноразовой сессии (`cron-exec-${id}-${uuid}`) на каждом тике. Агент сохраняет память предыдущих ходов и может ссылаться на ранее обнаруженные данные и выводы.
|
|
240
|
-
- **Защита от переполнения контекста и ротация (`targetSessionReset`)**: Чтобы контекстное окно и расход токенов не разрастались бесконечно при частых запусках, предусмотрены политики автоматической ротации:
|
|
241
|
-
- `never`: единая непрерывная сессия без сброса.
|
|
242
|
-
- `daily`: ежедневная автоматическая ротация (`<id>-YYYY-MM-DD`).
|
|
243
|
-
- `weekly`: еженедельная автоматическая ротация (`<id>-YYYY-Www`).
|
|
244
|
-
- Шаблоны дат: в `targetSessionId` поддерживается плейсхолдер `{{date}}`, который автоматически заменяется на текущую дату `YYYY-MM-DD`.
|
|
245
|
-
- **Видимость в списке чатов DSH**: Долговременные сессии не помечаются как `ephemeral`/`internal` и исключены из автоматической архивации (`sessions.archive()`), поэтому они остаются доступны для чтения и прямого диалога в веб-интерфейсе DSH.
|
|
246
|
-
- **Совместимость с пресетами и инструментами**: При возобновлении сессии автоматически подключаются инструменты пресета `agentPreset`, гарантируя доступ к терминалу, файлам и командам.
|
|
247
|
-
- *Благодарность*: концепция вдохновлена разработкой [@RaulLazaro](https://github.com/RaulLazaro).
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
### 26. Пакет надежности, отказоустойчивости и самовосстановления (v0.2.14, #145)
|
|
252
|
-
- **Автоматический сброс бюджета повторов**: Исправлена «амнезия повторов». Когда задача исчерпывает лимит попыток (`maxRetries`), счётчик `attempts` автоматически обнуляется, поэтому следующий плановый запуск по расписанию получает полный бюджет повторов с нуля. Любой регулярный или ручной запуск гарантированно начинает выполнение со сброшенным счётчиком попыток.
|
|
253
|
-
- **Устранение «зомби»-задач в очереди**: Задачи, приостановленные через интерфейс/API или удалённые, мгновенно вычищаются из очереди ожидания параллелизма (`this.queue`). При освобождении слотов очереди неактивные или удалённые задачи безопасно пропускаются.
|
|
254
|
-
- **Ограничение архива истории**: В длительно работающих инсталляциях с высокочастотными cron-задачами файл архива `tasks-history-archive.json` теперь надёжно ограничен последними 1 000 запусками на задачу, предотвращая неконтролируемый рост диска и синхронные задержки сериализации JSON.
|
|
255
|
-
- **Аварийное восстановление и авто-бэкап хранилища**: `TaskStore` автоматически поддерживает атомарную резервную копию `tasks.json.bak` при каждом успешном сохранении. В случае сбоя или повреждения файла хранилище делает снимок `tasks.json.corrupted.<timestamp>` для диагностики и бесшовно восстанавливается из резервной копии.
|
|
256
|
-
- **Самовосстановление при переполнении контекстного окна**: Если в долговременной сессии (`targetSessionId`) очередной ход агента завершается ошибкой переполнения контекста модели (`context_length_exceeded`), раннер распознаёт переполнение, архивирует исчерпанную сессию, автоматически выполняет ротацию на свежую сессию и прозрачно повторяет выполнение без срыва задачи.
|
|
257
|
-
- **Корректное завершение дерева процессов в Windows**: На платформе Windows отмена или таймаут внешних скриптовых задач теперь вызывают `taskkill /pid <pid> /T /F`, гарантируя полное уничтожение всех дочерних процессов и оболочек без зависания зомби-процессов в системе.
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
## 📦 Установка
|
|
263
|
-
|
|
264
|
-
```bash
|
|
265
|
-
dsh plugin --profile web add @goodandready/dsh-cron
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
Перезапустите DeepSeek Harness и обновите страницу в браузере.
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
## ⚙️ Конфигурация (`settings.yaml`)
|
|
273
|
-
|
|
274
|
-
Конфигурацию можно задать в `settings.yaml` или интерактивно через карточку настроек плагина в DSH:
|
|
275
|
-
|
|
276
|
-
```yaml
|
|
277
|
-
# settings.yaml
|
|
278
|
-
dsh-cron:
|
|
279
|
-
botToken: "" # токен Telegram Bot API (секретное поле)
|
|
280
|
-
chatId: "" # ID чата Telegram для отчётов
|
|
281
|
-
notifyTelegram: false # глобально отправлять отчёты о всех задачах
|
|
282
|
-
onlyOnFailure: false # отправлять отчёты только при сбоях
|
|
283
|
-
kanbanBaseUrl: "http://127.0.0.1:3000" # базовый URL HTTP API dsh-kanban
|
|
284
|
-
defaultTimezone: "" # IANA-зона по умолчанию (пусто = серверное время)
|
|
285
|
-
maxConcurrent: 0 # максимум параллельных запусков (0 = без лимита)
|
|
286
|
-
heartbeatUrl: "" # URL dead man's snitch, пингуется по интервалу
|
|
287
|
-
heartbeatIntervalSec: 0 # интервал heartbeat-пинга в секундах (0 = выключено)
|
|
288
|
-
# --- каналы доставки ---
|
|
289
|
-
botTokenRef: "" # ИМЯ credential для токена Telegram-бота
|
|
290
|
-
template: "" # глобальный шаблон сообщения, напр. "⏰ {title} — {status}"
|
|
291
|
-
channelTemplates: {} # переопределения шаблонов по каналам
|
|
292
|
-
deliveryTimeoutMs: 15000 # таймаут доставки на канал; медленный канал = сбой, остальные не ждут
|
|
293
|
-
discordWebhookUrl: "" # webhook Discord
|
|
294
|
-
slackWebhookUrl: "" # incoming webhook Slack
|
|
295
|
-
ntfyUrl: "https://ntfy.sh" # сервер ntfy; ntfyTopic / ntfyTokenRef
|
|
296
|
-
ntfyTopic: ""
|
|
297
|
-
ntfyTokenRef: ""
|
|
298
|
-
barkServerUrl: "https://api.day.app" # сервер Bark; barkKey — ключ устройства
|
|
299
|
-
barkKey: ""
|
|
300
|
-
pushplusUrl: "https://www.pushplus.plus/send" # pushplusTokenRef
|
|
301
|
-
pushplusTokenRef: ""
|
|
302
|
-
ttsBaseUrl: "http://127.0.0.1:3080" # базовый URL dsh-tts
|
|
303
|
-
giteaBaseUrl: "" # giteaRepo = owner/repo, giteaTokenRef = ИМЯ credential
|
|
304
|
-
giteaRepo: ""
|
|
305
|
-
giteaTokenRef: ""
|
|
306
|
-
# --- внешний REST API (#54) ---
|
|
307
|
-
apiToken: "" # bearer-токен внешнего префикса /dsh-cron/api/* (маскируется; пусто = 503)
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
### 14. Мониторинг heartbeat (dead man's switch)
|
|
311
|
-
* Задайте `heartbeatUrl` и `heartbeatIntervalSec` в настройках плагина — планировщик будет пинговать этот адрес по расписанию, и внешний монитор сообщит, когда пинги прекратятся.
|
|
312
|
-
* Встроенный эндпоинт `GET /dsh-cron/heartbeat` сообщает живость, число активных задач и время последнего запуска для ваших собственных сторожей.
|
|
313
|
-
|
|
314
|
-
### 15. Задачи из конфига профиля (#50)
|
|
315
|
-
Долгоживущие эксплуатационные задачи можно объявлять в конфиге профиля, а не пересоздавать руками в интерфейсе. Владелец объявленных задач — файл конфига: при каждом старте плагина они создаются или обновляются, а задача, исчезнувшая из файла, удаляется.
|
|
316
|
-
|
|
317
|
-
Добавьте список `jobs` в секцию плагина конфига профиля (`cordis.patch.yml`):
|
|
318
|
-
|
|
319
|
-
```yaml
|
|
320
|
-
dsh-cron:
|
|
321
|
-
jobs:
|
|
322
|
-
- id: nightly-backup
|
|
323
|
-
title: Nightly backup
|
|
324
|
-
schedule: "0 3 * * *"
|
|
325
|
-
type: script
|
|
326
|
-
prompt: "bash /path/to/backup.sh"
|
|
327
|
-
channels: ["telegram"]
|
|
328
|
-
timeoutSeconds: 3600
|
|
329
|
-
- id: morning-digest
|
|
330
|
-
title: Morning digest
|
|
331
|
-
schedule: "0 8 * * 1-5"
|
|
332
|
-
type: llm
|
|
333
|
-
prompt: "Prepare a brief morning digest of active tasks."
|
|
334
|
-
provider: my-provider
|
|
335
|
-
model: provider-id/model-id
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
* Обязательные поля записи: `id`, `title`, `schedule`; типам, у которых полезная нагрузка — это промпт (`script`, `node`, `python`, `ssh`, `docker`, `llm`, `skill`, `workflow`), нужен ещё непустой `prompt`. `http` — исключение: цель задаётся `httpUrl` (или `prompt`).
|
|
339
|
-
* Остальные поля задачи проходят как есть с той же валидацией, что и в API: `channels`, `model`, `provider`, `fallbackModel`, `silentRule`, `inspectOnFailure`, `timezone`, `timeoutSeconds`, `template`, `env`, `cwd` и рантайм-поля (`nodePath`, `pythonPath`, `httpUrl`, `httpMethod`, `httpHeaders`, `httpBody`, `sshProfileId`, `sshTarget`, `dockerImage`, `workspaceId`, `worktree`, `keepWorktree`, `skillName`, `workflowName`).
|
|
340
|
-
* Объявленные задачи помечаются как **управляемые конфигом**; в панели вместо действий правки и удаления выводится метка источника.
|
|
341
|
-
* Правка, пауза, возобновление, переключение и удаление конфиг-задачи отклоняются с `409` в панели и по API, и создание-обновление через `POST /dsh-cron/tasks` с существующим `id` конфиг-задачи отклоняется так же — источник правды файл конфига. **Запустить сейчас** остаётся доступным.
|
|
342
|
-
* Задача с тем же `id`, созданная через UI, API или инструмент агента, никогда не перезаписывается: запись пропускается, конфликт пишется в лог.
|
|
343
|
-
* Код-исполняющие типы активируются как обычные объявленные задачи, но при старте плагин пишет предупреждение в лог — путь исполнения кода, добавленный правкой конфига, остаётся видимым.
|
|
344
|
-
* Записи валидируются по одной с указанием индекса (`config.jobs[i]: …`); одна плохая запись пропускается и не может остановить остальные задачи или профиль.
|
|
345
|
-
|
|
346
|
-
### 16. Внешний REST API (`/dsh-cron/api/*`, #54)
|
|
347
|
-
Внешние системы (CI, cron хоста, `curl`) могут управлять планировщиком без открытия панели. Это единственная поверхность за bearer-токеном; маршруты панели остаются локальными и защищёнными от cross-origin.
|
|
348
|
-
|
|
349
|
-
Токен задаётся настройкой плагина `apiToken` (маскируется, как любой секрет). Аутентификация и ошибки:
|
|
350
|
-
* токен не задан → вся поверхность отвечает `503`;
|
|
351
|
-
* нет заголовка `Authorization: Bearer <token>` или токен неверный → `401`; сравнение постоянное по времени.
|
|
352
|
-
|
|
353
|
-
| Метод | Путь | Описание |
|
|
354
|
-
|:---|:---|:---|
|
|
355
|
-
| `GET` | `/dsh-cron/api/tasks` | Список задач (фильтры `status` / `query`, как в панели) |
|
|
356
|
-
| `GET` | `/dsh-cron/api/tasks/:id` | Чтение одной задачи |
|
|
357
|
-
| `POST` | `/dsh-cron/api/tasks` | Создание задачи или обновление существующей при наличии `id` |
|
|
358
|
-
| `DELETE` | `/dsh-cron/api/tasks/:id` | Удаление задачи |
|
|
359
|
-
| `POST` | `/dsh-cron/api/tasks/:id/run` | Принудительный немедленный запуск |
|
|
360
|
-
|
|
361
|
-
Операции переиспользуют обработчики панели, поэтому гейт `x-dsh-cron-confirm: script` для код-исполняющих типов и отказ `409` для конфиг-задач действуют здесь так же, как в UI.
|
|
362
|
-
|
|
363
|
-
```bash
|
|
364
|
-
BASE="http://127.0.0.1:3080"
|
|
365
|
-
TOKEN="<API_TOKEN>"
|
|
366
|
-
|
|
367
|
-
# список
|
|
368
|
-
curl -s -H "Authorization: Bearer $TOKEN" "$BASE/dsh-cron/api/tasks"
|
|
369
|
-
|
|
370
|
-
# создание или обновление, если в теле есть id
|
|
371
|
-
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
372
|
-
-d '{"id":"cleanup","title":"Cleanup","schedule":"0 4 * * *","prompt":"Remove stale temporary files."}' \
|
|
373
|
-
"$BASE/dsh-cron/api/tasks"
|
|
374
|
-
|
|
375
|
-
# принудительный запуск
|
|
376
|
-
curl -s -X POST -H "Authorization: Bearer $TOKEN" "$BASE/dsh-cron/api/tasks/cleanup/run"
|
|
377
|
-
|
|
378
|
-
# удаление
|
|
379
|
-
curl -s -X DELETE -H "Authorization: Bearer $TOKEN" "$BASE/dsh-cron/api/tasks/cleanup"
|
|
380
|
-
|
|
381
|
-
# код-исполняющей задаче нужен ещё заголовок подтверждения
|
|
382
|
-
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "x-dsh-cron-confirm: script" \
|
|
383
|
-
-H "Content-Type: application/json" \
|
|
384
|
-
-d '{"title":"Disk check","schedule":"0 * * * *","type":"script","prompt":"df -h"}' \
|
|
385
|
-
"$BASE/dsh-cron/api/tasks"
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
### 17. Метрики Prometheus (#53)
|
|
389
|
-
`GET /dsh-cron/metrics` отдаёт текст в формате Prometheus, поэтому планировщик можно снимать scrape'ом без новых зависимостей:
|
|
390
|
-
|
|
391
|
-
* `dsh_cron_tasks_total{status}` — число задач по статусам (gauge).
|
|
392
|
-
* `dsh_cron_task_last_duration_seconds{task}` — длительность последнего завершённого запуска задачи в секундах (gauge).
|
|
393
|
-
* `dsh_cron_runs_total{status}` — завершённые запуски с момента старта процесса плагина (counter); статусы `success`, `error`, `timeout`, `skipped`, `missed`.
|
|
394
|
-
* `dsh_cron_run_records` — число записей о запусках, хранимых в памяти (gauge).
|
|
395
|
-
|
|
396
|
-
В экспозицию попадают только счётчики, статусы и длительности; промпты, вывод запусков и конфигурация задач в неё не входят.
|
|
397
|
-
|
|
398
|
-
```yaml
|
|
399
|
-
scrape_configs:
|
|
400
|
-
- job_name: dsh-cron
|
|
401
|
-
static_configs:
|
|
402
|
-
- targets: ["127.0.0.1:3080"]
|
|
403
|
-
metrics_path: /dsh-cron/metrics
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
### 18. Строгая проверка каналов (#121)
|
|
407
|
-
Создание или обновление задачи с неизвестным идентификатором канала теперь отклоняется с `400`, а виновники перечисляются в ответе:
|
|
408
|
-
|
|
409
|
-
```json
|
|
410
|
-
{ "ok": false, "error": "Unknown channel ids: email_ping", "unknownChannels": ["email_ping"] }
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
Changed in v0.2.7: раньше неизвестный идентификатор молча отбрасывался, поэтому клиент с опечаткой получал `ok: true` и задачу, которая никуда не доставляет.
|
|
414
|
-
|
|
415
|
-
Импорт намеренно остаётся терпимым (файл может быть из старой версии): неизвестные идентификаторы отбрасываются у импортируемой задачи, но перечисляются в ответе (`unknownChannels`) и пишутся в лог планировщика, а не исчезают молча.
|
|
416
|
-
|
|
417
|
-
### 19. Проверка после установки (#126)
|
|
418
|
-
У `deploy.sh` есть режим только-проверки уже установленного профиля, ничего не устанавливающий:
|
|
419
|
-
|
|
420
|
-
```bash
|
|
421
|
-
bash deploy.sh verify [exact-version]
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
Он проверяет, что профиль сообщает нужную версию (по умолчанию — версия из `package.json`), аутентифицируется в web UI, затем скачивает клиентский бандл и убеждается, что имя пакета в нём присутствует.
|
|
425
|
-
|
|
426
|
-
Зачем это нужно: web-профиль может стоять за плагином аутентификации и отвечать `401` на анонимный запрос, а клиентский бандл плагина отдаётся только по точному combined-URL вида `??` из аутентифицированного индекса — голый `/plugins/<name>/client.js` отвечает `404`. Поэтому проверка сначала строит аутентифицированную сессию.
|
|
427
|
-
|
|
428
|
-
Переменные окружения проверки: `DSH_WEB_BASE` (по умолчанию `http://127.0.0.1:3080`), `DSH_WEB_TOKEN` (токен; если не задан, скрипт берёт последний из журнала юнита), `DSH_WEB_UNIT` (по умолчанию `dsh-web.service`). Секретов в скрипте нет.
|
|
429
|
-
|
|
430
|
-
### 20. Внутренняя разбивка: разбор расписания и постановка (#97)
|
|
431
|
-
Только для разработчиков, поведение не меняется. `parseScheduleExpression` разбит на маленькие функции с тем же порядком ветвей — `parseAtExpression`, `parseRelativeOneShot`, `parseIntervalExpression`, `parseAliasExpression`, `parseCronExpression`, — а `scheduleTask` — на `clearScheduled`, `scheduleOneShot` и `scheduleCron`. Прежний набор тестов прошёл без правок, добавлены точечные тесты на приоритет ветвей и ошибки.
|
|
432
|
-
|
|
433
|
-
### Параметры
|
|
434
|
-
|
|
435
|
-
| Параметр | Тип | По умолчанию | Описание |
|
|
436
|
-
|:---|:---|:---|:---|
|
|
437
|
-
| `botToken` | `string` | `""` | Токен Telegram Bot API. Если пусто, плагин пытается унаследовать бота, настроенного для `dsh-messenger-gateway` в настройках DSH (best-effort). Секретное поле: в интерфейсе отображается только замаскированное значение |
|
|
438
|
-
| `chatId` | `string` | `""` | ID чата Telegram для отчётов. Пустое значение — откат к первому разрешённому чату `dsh-messenger-gateway` |
|
|
439
|
-
| `notifyTelegram` | `boolean` | `false` | Глобальный выключатель доставки отчётов в Telegram |
|
|
440
|
-
| `onlyOnFailure` | `boolean` | `false` | Глобальный режим «только при сбоях» (`error`/`timeout`) |
|
|
441
|
-
| `kanbanBaseUrl` | `string` | `"http://127.0.0.1:3000"` | Базовый URL HTTP API `dsh-kanban` для автоматических карточек |
|
|
442
|
-
| `defaultTimezone` | `string` | `""` | IANA-зона по умолчанию для расписаний; пусто = серверное время |
|
|
443
|
-
| `maxConcurrent` | `number` | `0` | Лимит параллельных запусков; лишние помечаются `skipped` (0 = без лимита) |
|
|
444
|
-
| `heartbeatUrl` | `string` | `""` | URL dead man's snitch, пингуемый каждый `heartbeatIntervalSec`, пока жив планировщик |
|
|
445
|
-
| `heartbeatIntervalSec` | `number` | `0` | Интервал heartbeat-пинга в секундах (0 = выключено) |
|
|
446
|
-
| `botTokenRef` | `string` | `""` | Имя credential DSH с токеном Telegram-бота; резолвится при отправке (фолбэк: `botToken` → настройки messenger-gateway → переменная окружения `CRON_TELEGRAM_BOT_TOKEN`) |
|
|
447
|
-
| `template` | `string` | `""` | Глобальный шаблон сообщения с плейсхолдерами `{title}`/`{status}`/`{duration}`/…; пусто = встроенный текст |
|
|
448
|
-
| `channelTemplates` | `object` | `{}` | Переопределения шаблонов по каналам (`telegram`, `discord`, …) |
|
|
449
|
-
| `deliveryTimeoutMs` | `number` | `15000` | Таймаут доставки на канал; более медленный endpoint фиксируется как сбой и не задерживает остальные каналы и следующий тик |
|
|
450
|
-
| `discordWebhookUrl` / `slackWebhookUrl` | `string` | `""` | Webhook-URL каналов Discord и Slack |
|
|
451
|
-
| `ntfyUrl` / `ntfyTopic` / `ntfyTokenRef` | `string` | `"https://ntfy.sh"` / `""` / `""` | Сервер ntfy, тема и опциональное имя credential токена (`Authorization: Bearer …`) |
|
|
452
|
-
| `barkServerUrl` / `barkKey` | `string` | `"https://api.day.app"` / `""` | Сервер Bark и ключ устройства (ключ, заголовок и текст идут в пути запроса) |
|
|
453
|
-
| `pushplusUrl` / `pushplusTokenRef` | `string` | `"https://www.pushplus.plus/send"` / `""` | Endpoint PushPlus (переопределяется для self-hosted прокси) и имя credential токена |
|
|
454
|
-
| `ttsBaseUrl` | `string` | `"http://127.0.0.1:3080"` | Базовый URL плагина `dsh-tts` для голосовых объявлений |
|
|
455
|
-
| `giteaBaseUrl` / `giteaRepo` / `giteaTokenRef` | `string` | `""` | Канал Gitea: базовый URL, `owner/repo` и имя credential API-токена |
|
|
456
|
-
| `apiToken` | `string` | `""` | Bearer-токен внешней поверхности `/dsh-cron/api/*`. Секретное поле, отдаётся замаскированным; пусто отключает поверхность (503), неверное значение — 401 |
|
|
457
|
-
|
|
458
|
-
Примечания:
|
|
459
|
-
|
|
460
|
-
* История запусков ограничена **50 записями на задачу** (фиксировано); в записи хранится до 4000 символов вывода.
|
|
461
|
-
* Задачи выполняются в **локальном часовом поясе сервера**, если для задачи не указана своя IANA-зона; cron-выражения вычисляет `croner` по часам хоста.
|
|
462
|
-
* Задачи сохраняются в каталоге данных DSH (`cron/tasks.json`) и переживают перезапуск; пропущенные one-shot запуски обнаруживаются при старте.
|
|
463
|
-
|
|
464
|
-
---
|
|
465
|
-
|
|
466
|
-
## 🔌 HTTP API
|
|
467
|
-
|
|
468
|
-
Все эндпоинты обслуживаются веб-сервером DSH под `/dsh-cron/`. Чтение открыто локальному интерфейсу; **мутирующие эндпоинты отклоняют cross-origin запросы** и принимают тела до 1 МБ. Для создания `script`-задач по HTTP дополнительно требуется заголовок `x-dsh-cron-confirm: script`, который подделанный межсайтовый запрос приложить не может.
|
|
469
|
-
|
|
470
|
-
| Метод | Путь | Описание |
|
|
471
|
-
|:---|:---|:---|
|
|
472
|
-
| `GET` | `/dsh-cron/tasks` | Список задач; параметры `status` (`all/active/paused/completed`), `query` (подстрока). Возвращает задачи, шаблоны рекомендаций и сводную статистику |
|
|
473
|
-
| `POST` | `/dsh-cron/tasks` | Создание или обновление задачи (при наличии `id` — обновление). Обязательны `title`, `schedule`, `prompt` |
|
|
474
|
-
| `GET` | `/dsh-cron/tasks/:id/history` | История запусков, `?limit=20` |
|
|
475
|
-
| `POST` | `/dsh-cron/tasks/:id/run` | Немедленный ручной запуск |
|
|
476
|
-
| `POST` | `/dsh-cron/tasks/:id/pause` | Пауза расписания |
|
|
477
|
-
| `POST` | `/dsh-cron/tasks/:id/resume` | Возобновление расписания |
|
|
478
|
-
| `POST` | `/dsh-cron/tasks/:id/toggle` | Переключение активна/на паузе |
|
|
479
|
-
| `POST` | `/dsh-cron/tasks/:id/duplicate` | Копия задачи в статусе «на паузе»: настройки копируются, история и счётчики сбрасываются |
|
|
480
|
-
| `GET` | `/dsh-cron/recipes` | Встроенный каталог рецептов: готовые мониторинговые пресеты по категориям, все только на чтение |
|
|
481
|
-
| `GET` | `/dsh-cron/tasks/export` | Версионированный JSON только с конфигурацией задач — без истории и счётчиков. Каналы ссылаются на credential по имени, но введённые вручную `env` и HTTP-заголовки задачи являются частью конфигурации и попадают в файл |
|
|
482
|
-
| `POST` | `/dsh-cron/tasks/import` | Проверяет документ и применяет его стратегией `add`, `replace` или `skip`; поддерживает `dryRun`. Импортированные задачи всегда приходят **на паузе** — восстановление не сработает само |
|
|
483
|
-
| `PATCH` | `/dsh-cron/tasks/:id` | Частичное обновление (только whitelisted-поля: `title`, `schedule`, `prompt`, `type`, `delivery`, `provider`, `model`, настройки уведомлений/таймаута/overlap/kanban, `status`, `oneShot`) |
|
|
484
|
-
| `DELETE` | `/dsh-cron/tasks/:id` | Удаление задачи |
|
|
485
|
-
| `GET` | `/dsh-cron/models` | Список LLM-провайдеров; `?provider=<id>` — модели |
|
|
486
|
-
| `POST` | `/dsh-cron/chat/start` | Старт агентской сессии «Создать с DSH» с инструкциями планировщика |
|
|
487
|
-
| `GET` | `/dsh-cron/settings` | Настройки для клиента (токен замаскирован) |
|
|
488
|
-
| `POST` | `/dsh-cron/settings` | Обновление настроек интеграций (через службу настроек) |
|
|
489
|
-
| `GET` | `/dsh-cron/heartbeat` | Probe живости: число активных задач, время последнего запуска |
|
|
490
|
-
| `POST` | `/dsh-cron/telegram/test` | Тестовое сообщение в Telegram |
|
|
491
|
-
| `POST` | `/dsh-cron/kanban/test` | Тестовая карточка в Kanban |
|
|
492
|
-
| `*` | `/dsh-cron/action/:id/:action` | Legacy-алиас действий над задачей (`run`, `toggle`, `delete`, `history`) |
|
|
493
|
-
| `GET` | `/dsh-cron/metrics` | Текст в формате Prometheus: счётчики задач и запусков — без промптов и вывода (#53) |
|
|
494
|
-
| `GET` / `POST` | `/dsh-cron/api/tasks` | Внешняя поверхность под токеном: список / создание-обновление (#54) |
|
|
495
|
-
| `GET` / `DELETE` | `/dsh-cron/api/tasks/:id` | Внешняя поверхность под токеном: чтение / удаление (#54) |
|
|
496
|
-
| `POST` | `/dsh-cron/api/tasks/:id/run` | Внешняя поверхность под токеном: принудительный запуск (#54) |
|
|
497
|
-
|
|
498
|
-
---
|
|
499
|
-
|
|
500
|
-
## 🧪 Тестирование
|
|
501
|
-
|
|
502
|
-
```bash
|
|
503
|
-
npm test
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
Набор покрывает разбор расписаний, движок планировщика, атомарное хранилище, HTTP-хелперы, уведомления и контракт инструментов.
|
|
507
|
-
|
|
508
|
-
---
|
|
509
|
-
|
|
510
|
-
## 📄 Лицензия
|
|
511
|
-
|
|
512
|
-
MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY)
|