@goodandready/dsh-cron 0.2.5 → 0.2.6
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 +18 -6
- package/docs/README.ru.md +21 -5
- package/docs/README.zh.md +18 -6
- package/docs/design/DESIGN.md +6 -4
- package/docs/plans/0.2.6-economy-block.md +61 -0
- package/lib/api.js +399 -0
- package/lib/client.js +154 -4
- package/lib/failure-inspector.js +107 -0
- package/lib/http-utils.js +24 -0
- package/lib/index.js +121 -388
- package/lib/llm-ask.js +141 -0
- package/lib/recipes.js +238 -0
- package/lib/runner.js +210 -171
- package/lib/scheduler.js +226 -80
- package/lib/silent-rule.js +100 -0
- package/lib/store.js +11 -0
- package/lib/task-patch.js +81 -0
- package/lib/task-transfer.js +4 -0
- package/lib/templates.js +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,13 +99,15 @@ Autonomous agents can manage schedules directly:
|
|
|
99
99
|
|
|
100
100
|
| Tool | Description |
|
|
101
101
|
|:---|:---|
|
|
102
|
-
| `cron_create_task` | Creates a scheduled task: `title`, `schedule`, `prompt`, optional `type` (`llm`/`script`/`node`/`python`/`http`/`ssh`/`docker`/`skill`/`workflow`), `delivery`, `provider`, `model`, `channels`, `template`, `notifyTelegram`, `onlyOnFailure`, `timeoutSeconds`, `overlapPolicy`, `kanbanMode` |
|
|
102
|
+
| `cron_create_task` | Creates a scheduled task: `title`, `schedule`, `prompt`, `fallbackModel` (one retry on a stronger model when a run fails), optional `type` (`llm`/`script`/`node`/`python`/`http`/`ssh`/`docker`/`skill`/`workflow`), `delivery`, `provider`, `model`, `channels`, `template`, `notifyTelegram`, `onlyOnFailure`, `timeoutSeconds`, `overlapPolicy`, `kanbanMode` |
|
|
103
103
|
| `cron_schedule_task` | Alias of `cron_create_task` kept for compatibility with existing agent prompts |
|
|
104
104
|
| `cron_list_tasks` | Lists tasks with statuses, next run timestamps, token totals, and cost estimates |
|
|
105
105
|
| `cron_pause_task` | Pauses a schedule without deleting its configuration |
|
|
106
106
|
| `cron_resume_task` | Resumes a paused schedule |
|
|
107
107
|
| `cron_delete_task` | Permanently removes a task and its history |
|
|
108
108
|
| `cron_run_task` | Triggers an immediate out-of-band run |
|
|
109
|
+
| `cron_get_task` | Reads the full configuration of one task, including fields the list does not show |
|
|
110
|
+
| `cron_update_task` | Changes an existing task in place (whitelisted fields, same validation as the HTTP route); the model is told to confirm code-executing changes with the user first |
|
|
109
111
|
|
|
110
112
|
Example invocation the model can make during a conversation:
|
|
111
113
|
|
|
@@ -147,12 +149,21 @@ Every task picks its own runtime; non-LLM runtimes need no model and consume no
|
|
|
147
149
|
* **Environment variables** — a per-task `env` map (KEY VALUE per line in the UI) applied to external runtimes; secrets do not belong here.
|
|
148
150
|
* **Workspaces and worktrees** — bind a task to a harness workspace (`workspaceId`) and, for code-modifying agent tasks, run it in an isolated git worktree (`worktree`, `keepWorktree`).
|
|
149
151
|
|
|
150
|
-
### 7.
|
|
152
|
+
### 7. Cost Control: Fallback Model
|
|
153
|
+
A task can run on the cheap model by default and still finish on the strong one: set `fallbackModel` (and optionally `fallbackProvider`) and a failed run — `error` or `timeout` — is retried **once** on that model before the ordinary retry backoff applies. History records which model produced the result and whether the fallback was used, usage and cost of both attempts are summed, and the `{model}` template variable renders the model that finished the run. Only agent-mediated tasks (`llm`, `skill`, `workflow`) can use a fallback.
|
|
154
|
+
|
|
155
|
+
### 8. Session Integration & Permissions
|
|
151
156
|
* **Per-task permission presets** — `default`, `read-only`, `workspace-write`, or `full` are applied to the task's agent session before the prompt runs.
|
|
152
157
|
* **Session auto-archive** — isolated cron sessions are archived after each run (best-effort) so they do not clutter the chat list.
|
|
153
158
|
* **History → session navigation** — every LLM run records its session; open it straight from the run history entry.
|
|
154
159
|
|
|
155
|
-
###
|
|
160
|
+
### 9. Quiet by Rule
|
|
161
|
+
A task with output can carry a **silent rule** written in plain words ("stay silent when no filesystem is above 80%"). On a successful run a cheap model judges the output against that rule and the report is skipped when the verdict is to stay silent, with the reason recorded in the run history. It fails open: no rule, no model, a failed call or an unreadable answer all mean the report is delivered. `silentRuleModel` (plugin setting) picks the model used for the judgement.
|
|
162
|
+
|
|
163
|
+
### 10. Failure Diagnosis
|
|
164
|
+
Agent tasks can ask for a diagnosis: with `inspectOnFailure` set, a failed run (`error` or `timeout`) is read by a model together with the task prompt and truncated output, and the run history stores a short diagnosis plus a concrete prompt change. The history entry offers to load that suggestion into the edit form — nothing is applied automatically. The model is configurable with `inspectorModel`, and `{diagnosis}` is available in message templates. A broken or unavailable model call leaves the failed run exactly as it was.
|
|
165
|
+
|
|
166
|
+
### 11. Notification Channels & Message Templates
|
|
156
167
|
A finished run is delivered to every channel configured for the task — Telegram, dsh-kanban, Discord, Slack, ntfy, Bark, PushPlus, voice via `dsh-tts`, and Gitea issues:
|
|
157
168
|
|
|
158
169
|
* **Per-task channels** — tick the channels in the task form; an explicit selection overrides the legacy `notifyTelegram` / `kanbanMode` switches, and an empty selection falls back to them.
|
|
@@ -168,11 +179,11 @@ A finished run is delivered to every channel configured for the task — Telegra
|
|
|
168
179
|
* **Gitea** — opens an issue with the run report (`giteaBaseUrl`, `giteaRepo`, token credential); failures are labelled `cron`, `bug`, `alert`.
|
|
169
180
|
* **Test dispatch button** — verify Telegram connectivity on the spot before scheduling critical jobs.
|
|
170
181
|
|
|
171
|
-
###
|
|
182
|
+
### 12. Kanban Integration & Cost Meter
|
|
172
183
|
* **Automatic Kanban cards** — with `kanbanMode` set to `on_failure` or `always`, the plugin creates cards in `dsh-kanban` (`on_failure` → *Backlog* on `error`/`timeout`; `always` → *Done*/*Backlog* on completion).
|
|
173
184
|
* **Token & execution cost meter** — token consumption (input, output, cache reads) is tracked per run and per task, with USD estimates from a built-in pricing table and an aggregated analytics bar.
|
|
174
185
|
|
|
175
|
-
###
|
|
186
|
+
### 13. Overlap Policies & Execution Timeout
|
|
176
187
|
Prevent rogue processes from stacking concurrent duplicate executions:
|
|
177
188
|
|
|
178
189
|
* **Execution timeout (`timeoutSeconds`)** — when the limit is reached, shell subprocesses are killed immediately via the abort signal and agent sessions are disposed so they stop consuming tokens. Default: `1800` (30 minutes).
|
|
@@ -183,7 +194,7 @@ Prevent rogue processes from stacking concurrent duplicate executions:
|
|
|
183
194
|
|
|
184
195
|
If the daemon was offline at a scheduled time, the run is recorded as `missed` on startup, so gaps in the history stay visible.
|
|
185
196
|
|
|
186
|
-
###
|
|
197
|
+
### 14. Heartbeat Monitoring (#16-style dead man's switch)
|
|
187
198
|
* Set `heartbeatUrl` and `heartbeatIntervalSec` in the plugin settings and the scheduler pings that URL on schedule — an external monitor alerts when the pings stop.
|
|
188
199
|
* A built-in `GET /dsh-cron/heartbeat` endpoint reports liveness, active task count and the last run time for your own watchdogs.
|
|
189
200
|
|
|
@@ -283,6 +294,7 @@ All endpoints are served by the DSH web server under `/dsh-cron/`. Read endpoint
|
|
|
283
294
|
| `POST` | `/dsh-cron/tasks/:id/resume` | Resume the schedule |
|
|
284
295
|
| `POST` | `/dsh-cron/tasks/:id/toggle` | Toggle active/paused |
|
|
285
296
|
| `POST` | `/dsh-cron/tasks/:id/duplicate` | Creates a paused copy of a task: configuration copied, run state (history, counters, last run) reset |
|
|
297
|
+
| `GET` | `/dsh-cron/recipes` | Built-in recipe catalog: ready-to-use monitoring presets grouped by category, all read-only |
|
|
286
298
|
| `GET` | `/dsh-cron/tasks/export` | Versioned JSON document with task configuration only — no history or counters. Channels reference credentials by name, but a task-level `env` map or HTTP headers you typed in yourself are part of the configuration and therefore appear in the file |
|
|
287
299
|
| `POST` | `/dsh-cron/tasks/import` | Validates a document and applies it with `add`, `replace` or `skip`; supports a `dryRun` summary. Imported tasks always start **paused**, so a restore never fires until reviewed |
|
|
288
300
|
| `PATCH` | `/dsh-cron/tasks/:id` | Partial update (whitelisted fields only: `title`, `schedule`, `prompt`, `type`, `delivery`, `provider`, `model`, runtime settings, `channels`, `template`, notification/timeout/overlap/kanban settings, `status`, `oneShot`) |
|
package/docs/README.ru.md
CHANGED
|
@@ -98,13 +98,15 @@ graph TD
|
|
|
98
98
|
|
|
99
99
|
| Инструмент | Описание |
|
|
100
100
|
|:---|:---|
|
|
101
|
-
| `cron_create_task` | Создаёт задачу: `title`, `schedule`, `prompt`, опционально `type` (`llm`/`script`/`node`/`python`/`http`/`ssh`/`docker`/`skill`/`workflow`), `delivery`, `provider`, `model`, `channels`, `template`, `notifyTelegram`, `onlyOnFailure`, `timeoutSeconds`, `overlapPolicy`, `kanbanMode` |
|
|
101
|
+
| `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` |
|
|
102
102
|
| `cron_schedule_task` | Псевдоним `cron_create_task` для совместимости с существующими промптами |
|
|
103
103
|
| `cron_list_tasks` | Список задач со статусами, временем следующего запуска, токенами и стоимостью |
|
|
104
104
|
| `cron_pause_task` | Приостанавливает расписание без удаления конфигурации |
|
|
105
105
|
| `cron_resume_task` | Возобновляет приостановленное расписание |
|
|
106
106
|
| `cron_delete_task` | Полностью удаляет задачу и её историю |
|
|
107
107
|
| `cron_run_task` | Немедленный внеплановый запуск |
|
|
108
|
+
| `cron_get_task` | Полная конфигурация одной задачи, включая поля, которых нет в списке |
|
|
109
|
+
| `cron_update_task` | Изменяет существующую задачу на месте (whitelisted-поля, та же валидация, что у HTTP-маршрута); модели предписано сперва подтверждать с пользователем изменения, исполняющие код |
|
|
108
110
|
|
|
109
111
|
Пример вызова модели в диалоге:
|
|
110
112
|
|
|
@@ -146,12 +148,21 @@ cron_create_task({
|
|
|
146
148
|
* **Переменные окружения** — карта `env` на задачу (в UI — строки KEY VALUE) для внешних рантаймов; секретам здесь не место.
|
|
147
149
|
* **Workspace и worktree** — привязка задачи к workspace харнесса (`workspaceId`) и, для изменяющих код агентских задач, запуск в изолированном git worktree (`worktree`, `keepWorktree`).
|
|
148
150
|
|
|
149
|
-
### 7.
|
|
151
|
+
### 7. Экономия: fallback-модель
|
|
152
|
+
Задача может идти на дешёвой модели по умолчанию и всё же завершиться на сильной: задайте `fallbackModel` (и при необходимости `fallbackProvider`), и сбойный запуск (`error` или `timeout`) один раз повторится на этой модели, прежде чем включится обычный retry с задержкой. В истории видно, какая модель произвела результат и был ли использован fallback; расход и стоимость обеих попыток суммируются; переменная шаблона `{model}` подставляет модель, завершившую запуск. Fallback доступен только агентским типам (`llm`, `skill`, `workflow`).
|
|
153
|
+
|
|
154
|
+
### 8. Интеграция сессий и права
|
|
150
155
|
* **Permission-пресеты на задачу** — `default`, `read-only`, `workspace-write` или `full` применяются к сессии агента перед запуском промпта.
|
|
151
156
|
* **Автоархивация сессий** — изолированные cron-сессии архивируются после запуска (best-effort), не засоряя список чатов.
|
|
152
157
|
* **История → сессия** — каждый LLM-запуск хранит свою сессию; открыть диалог можно прямо из записи истории.
|
|
153
158
|
|
|
154
|
-
###
|
|
159
|
+
### 9. Тишина по правилу
|
|
160
|
+
У задачи с выводом может быть **правило тишины**, написанное словами («молчи, если ни один раздел не занят больше 80%»). На успешном запуске дешёвая модель сверяет вывод с правилом, и отчёт пропускается, если вердикт — молчать; причина сохраняется в истории запуска. Работает fail-open: нет правила, нет модели, сбой вызова или нечитаемый ответ — отчёт доставляется. Настройка `silentRuleModel` задаёт модель для проверки.
|
|
161
|
+
|
|
162
|
+
### 10. Диагностика сбоев
|
|
163
|
+
Агентские задачи могут заказывать диагноз: с включённым `inspectOnFailure` сбойный запуск (`error` или `timeout`) вместе с промптом задачи и обрезанным выводом читает модель, и в историю запуска попадают короткий диагноз и конкретная правка промпта. В записи истории есть кнопка, подставляющая эту правку в форму редактирования — автоматически ничего не применяется. Модель задаётся настройкой `inspectorModel`, в шаблонах доступна переменная `{diagnosis}`. Недоступная модель оставляет сбойный запуск ровно таким, каким он был.
|
|
164
|
+
|
|
165
|
+
### 11. Каналы доставки и шаблоны сообщений
|
|
155
166
|
Отчёт о завершённом запуске уходит во все каналы, выбранные для задачи — Telegram, dsh-kanban, Discord, Slack, ntfy, Bark, PushPlus, голос через `dsh-tts` и issue в Gitea:
|
|
156
167
|
|
|
157
168
|
* **Перенос задач** — экспорт всей конфигурации в версионированный JSON и импорт с предварительной сводкой; импортированные задачи приходят на паузе.
|
|
@@ -168,11 +179,11 @@ cron_create_task({
|
|
|
168
179
|
* **Gitea** — создаёт issue с отчётом (`giteaBaseUrl`, `giteaRepo`, credential токена); сбойные запуски помечаются метками `cron`, `bug`, `alert`.
|
|
169
180
|
* **Кнопка проверки** — проверьте доставку в Telegram до запуска критичных задач.
|
|
170
181
|
|
|
171
|
-
###
|
|
182
|
+
### 12. Интеграция с Kanban и учёт стоимости
|
|
172
183
|
* **Автоматические карточки Kanban** — при `kanbanMode` = `on_failure` или `always` плагин создаёт карточки в `dsh-kanban` (`on_failure` → *Backlog* при `error`/`timeout`; `always` → *Done*/*Backlog* по завершении).
|
|
173
184
|
* **Счётчик токенов и стоимости** — потребление токенов (ввод, вывод, чтения из кэша) учитывается по запускам и задачам с оценкой в USD по встроенной таблице цен и сводной панелью аналитики.
|
|
174
185
|
|
|
175
|
-
###
|
|
186
|
+
### 13. Политики наложения и таймаут выполнения
|
|
176
187
|
|
|
177
188
|
* **Таймаут (`timeoutSeconds`)** — по достижении лимита shell-процесс немедленно завершается через abort-сигнал, а агентская сессия закрывается, чтобы не расходовать токены. По умолчанию `1800` (30 минут).
|
|
178
189
|
* **Политика наложения (`overlapPolicy`)** — что делать, когда тик срабатывает при ещё активном предыдущем запуске:
|
|
@@ -230,6 +241,10 @@ dsh-cron:
|
|
|
230
241
|
giteaTokenRef: ""
|
|
231
242
|
```
|
|
232
243
|
|
|
244
|
+
### 14. Мониторинг heartbeat (dead man's switch)
|
|
245
|
+
* Задайте `heartbeatUrl` и `heartbeatIntervalSec` в настройках плагина — планировщик будет пинговать этот адрес по расписанию, и внешний монитор сообщит, когда пинги прекратятся.
|
|
246
|
+
* Встроенный эндпоинт `GET /dsh-cron/heartbeat` сообщает живость, число активных задач и время последнего запуска для ваших собственных сторожей.
|
|
247
|
+
|
|
233
248
|
### Параметры
|
|
234
249
|
|
|
235
250
|
| Параметр | Тип | По умолчанию | Описание |
|
|
@@ -276,6 +291,7 @@ dsh-cron:
|
|
|
276
291
|
| `POST` | `/dsh-cron/tasks/:id/resume` | Возобновление расписания |
|
|
277
292
|
| `POST` | `/dsh-cron/tasks/:id/toggle` | Переключение активна/на паузе |
|
|
278
293
|
| `POST` | `/dsh-cron/tasks/:id/duplicate` | Копия задачи в статусе «на паузе»: настройки копируются, история и счётчики сбрасываются |
|
|
294
|
+
| `GET` | `/dsh-cron/recipes` | Встроенный каталог рецептов: готовые мониторинговые пресеты по категориям, все только на чтение |
|
|
279
295
|
| `GET` | `/dsh-cron/tasks/export` | Версионированный JSON только с конфигурацией задач — без истории и счётчиков. Каналы ссылаются на credential по имени, но введённые вручную `env` и HTTP-заголовки задачи являются частью конфигурации и попадают в файл |
|
|
280
296
|
| `POST` | `/dsh-cron/tasks/import` | Проверяет документ и применяет его стратегией `add`, `replace` или `skip`; поддерживает `dryRun`. Импортированные задачи всегда приходят **на паузе** — восстановление не сработает само |
|
|
281
297
|
| `PATCH` | `/dsh-cron/tasks/:id` | Частичное обновление (только whitelisted-поля: `title`, `schedule`, `prompt`, `type`, `delivery`, `provider`, `model`, настройки уведомлений/таймаута/overlap/kanban, `status`, `oneShot`) |
|
package/docs/README.zh.md
CHANGED
|
@@ -98,13 +98,15 @@ graph TD
|
|
|
98
98
|
|
|
99
99
|
| 工具 | 说明 |
|
|
100
100
|
|:---|:---|
|
|
101
|
-
| `cron_create_task` | 创建任务:`title`、`schedule`、`prompt
|
|
101
|
+
| `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` |
|
|
102
102
|
| `cron_schedule_task` | `cron_create_task` 的别名,保持与既有提示词兼容 |
|
|
103
103
|
| `cron_list_tasks` | 列出任务的状态、下次运行时间、token 总量与成本估算 |
|
|
104
104
|
| `cron_pause_task` | 暂停调度而不删除配置 |
|
|
105
105
|
| `cron_resume_task` | 恢复已暂停的调度 |
|
|
106
106
|
| `cron_delete_task` | 永久删除任务及其历史 |
|
|
107
107
|
| `cron_run_task` | 触发一次立即的带外运行 |
|
|
108
|
+
| `cron_get_task` | 读取单个任务的完整配置,包括列表中看不到的字段 |
|
|
109
|
+
| `cron_update_task` | 就地修改现有任务(白名单字段,校验与 HTTP 路由一致);提示模型先与用户确认会执行代码的改动 |
|
|
108
110
|
|
|
109
111
|
会话中模型可进行的调用示例:
|
|
110
112
|
|
|
@@ -146,12 +148,21 @@ cron_create_task({
|
|
|
146
148
|
* **环境变量** —— 按任务的 `env` 映射(界面中每行 KEY VALUE)应用于外部运行时;请勿在此存放密钥。
|
|
147
149
|
* **工作区与 worktree** —— 将任务绑定到 Harness 工作区(`workspaceId`);对会修改代码的智能体任务,可在隔离的 git worktree 中运行(`worktree`、`keepWorktree`)。
|
|
148
150
|
|
|
149
|
-
### 7.
|
|
151
|
+
### 7. 成本控制:回退模型
|
|
152
|
+
任务可以默认使用便宜模型,失败时改用更强模型完成:设置 `fallbackModel`(可选 `fallbackProvider`),失败(`error` 或 `timeout`)的运行会在该模型上重试一次,之后才进入常规重试退避。历史记录会标明最终产出结果的模型以及是否使用了回退,两次尝试的用量与成本都会累计,模板变量 `{model}` 渲染完成运行的模型。回退仅适用于智能体类型(`llm`、`skill`、`workflow`)。
|
|
153
|
+
|
|
154
|
+
### 8. 会话集成与权限
|
|
150
155
|
* **按任务的权限预设** —— `default`、`read-only`、`workspace-write` 或 `full` 在提示词执行前应用于任务会话。
|
|
151
156
|
* **会话自动归档** —— 隔离的 cron 会话在运行后自动归档(尽力而为),不干扰聊天列表。
|
|
152
157
|
* **历史 → 会话** —— 每次 LLM 运行都会记录会话,可直接从历史记录打开对话。
|
|
153
158
|
|
|
154
|
-
###
|
|
159
|
+
### 9. 按规则保持安静
|
|
160
|
+
有输出的任务可以设置用自然语言描述的**静默规则**(例如“当没有分区使用率超过 80% 时保持安静”)。运行成功时,由便宜模型对照该规则判断输出,若结论为保持安静则跳过报告,并在运行历史中记录原因。遵循 fail-open:没有规则、没有模型、调用失败或答案无法解析时都会照常投递报告。插件设置 `silentRuleModel` 指定用于判断的模型。
|
|
161
|
+
|
|
162
|
+
### 10. 失败诊断
|
|
163
|
+
智能体任务可以请求诊断:设置 `inspectOnFailure` 后,失败(`error` 或 `timeout`)的运行会连同任务提示词与截断输出一起交给模型,运行历史中会保存简短诊断与具体的提示词修改建议。历史记录提供按钮把该建议载入编辑表单 —— 不会自动应用。模型由 `inspectorModel` 指定,消息模板中可使用 `{diagnosis}`。模型不可用或调用失败时,失败的运行保持原样。
|
|
164
|
+
|
|
165
|
+
### 11. 通知渠道与消息模板
|
|
155
166
|
运行完成后,报告会发送到该任务配置的所有渠道 —— Telegram、dsh-kanban、Discord、Slack、ntfy、Bark、PushPlus、语音(`dsh-tts`)以及 Gitea issue:
|
|
156
167
|
|
|
157
168
|
* **任务迁移** —— 将全部配置导出为版本化 JSON,并在别处导入(含预览摘要);导入的任务处于暂停状态。
|
|
@@ -168,11 +179,11 @@ cron_create_task({
|
|
|
168
179
|
* **Gitea** —— 创建包含运行报告的 issue(`giteaBaseUrl`、`giteaRepo`、token 凭据);失败运行标记为 `cron`、`bug`、`alert`。
|
|
169
180
|
* **测试发送按钮** —— 在安排关键任务前现场验证 Telegram 连通性。
|
|
170
181
|
|
|
171
|
-
###
|
|
182
|
+
### 12. Kanban 集成与成本统计
|
|
172
183
|
* **自动创建 Kanban 卡片** —— 当 `kanbanMode` 为 `on_failure` 或 `always` 时,插件在 `dsh-kanban` 中创建卡片(`on_failure` → `error`/`timeout` 时进入 *Backlog*;`always` → 完成后进入 *Done*/*Backlog*)。
|
|
173
184
|
* **Token 与执行成本计量** —— 按运行与任务统计 token 消耗(输入、输出、缓存读取),基于内置价格表估算美元成本,并提供汇总分析栏。
|
|
174
185
|
|
|
175
|
-
###
|
|
186
|
+
### 13. 重叠策略与执行超时
|
|
176
187
|
|
|
177
188
|
* **执行超时(`timeoutSeconds`)** —— 达到限制后,shell 子进程通过 abort 信号立即终止,智能体会话被释放以停止消耗 token。默认 `1800`(30 分钟)。
|
|
178
189
|
* **重叠策略(`overlapPolicy`)** —— 上一次运行尚未结束时再次触发调度时的行为:
|
|
@@ -182,7 +193,7 @@ cron_create_task({
|
|
|
182
193
|
|
|
183
194
|
如果守护进程在计划时刻处于离线状态,启动时该次运行会被记录为 `missed`,历史空档始终可见。
|
|
184
195
|
|
|
185
|
-
###
|
|
196
|
+
### 14. 心跳监控(Dead man's switch)
|
|
186
197
|
* 在插件设置中配置 `heartbeatUrl` 与 `heartbeatIntervalSec`,调度器会按间隔 GET 该地址 —— 外部监控可在心跳停止时告警。
|
|
187
198
|
* 内置 `GET /dsh-cron/heartbeat` 端点返回存活状态、活跃任务数与最近运行时间,便于自建看门狗。
|
|
188
199
|
|
|
@@ -280,6 +291,7 @@ dsh-cron:
|
|
|
280
291
|
| `POST` | `/dsh-cron/tasks/:id/resume` | 恢复调度 |
|
|
281
292
|
| `POST` | `/dsh-cron/tasks/:id/toggle` | 切换活跃/暂停 |
|
|
282
293
|
| `POST` | `/dsh-cron/tasks/:id/duplicate` | 创建暂停状态的副本:复制配置,重置运行历史与计数 |
|
|
294
|
+
| `GET` | `/dsh-cron/recipes` | 内置配方目录:按类别分组的现成监控预设,全部为只读操作 |
|
|
283
295
|
| `GET` | `/dsh-cron/tasks/export` | 仅含任务配置的版本化 JSON —— 不含历史与计数。渠道按名称引用凭据,但手动填写在任务中的 `env` 与 HTTP 请求头属于配置,会出现在文件里 |
|
|
284
296
|
| `POST` | `/dsh-cron/tasks/import` | 校验文档并以 `add`、`replace` 或 `skip` 策略导入;支持 `dryRun` 预览。导入的任务始终为**暂停**状态,恢复不会自动触发 |
|
|
285
297
|
| `PATCH` | `/dsh-cron/tasks/:id` | 部分更新(仅白名单字段:`title`、`schedule`、`prompt`、`type`、`delivery`、`provider`、`model`、通知/超时/重叠/Kanban 设置、`status`、`oneShot`) |
|
package/docs/design/DESIGN.md
CHANGED
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
- Табы фильтрации: «Все», «Активные», «На паузе», «Завершённые».
|
|
18
18
|
- Поисковая строка; сводная статистика (активные задачи, запуски, токены, стоимость).
|
|
19
19
|
- Карточки задач: статус-переключатель, название, расписание (человекочитаемое + raw cron), действия (запуск, редактирование, удаление).
|
|
20
|
-
- Блок «Рекомендуемые задачи»:
|
|
20
|
+
- Блок «Рекомендуемые задачи»: подсказки из встроенного каталога рецептов (`lib/recipes.js`, 10 рецептов в 5 категориях), клик открывает форму с заполненными типом, каналом и правилом тишины; ничего не создаётся без сохранения (#48).
|
|
21
21
|
- Карточка настроек в слоте settings.plugin.item, key = namespace `dsh-cron`; отдельный раздел настроек не используется (#102).
|
|
22
|
-
- LLM Tools: cron_create_task (+ alias cron_schedule_task), cron_list_tasks, cron_pause_task, cron_resume_task, cron_delete_task, cron_run_task. Параметры задачи включают рантайм (`type`), `channels` (список каналов доставки) и `template` (шаблон сообщения).
|
|
23
|
-
- API: HTTP эндпоинты /dsh-cron/* (tasks, models, chat/start, settings, telegram/test, kanban/test, tasks/:id/actions, legacy action/:id/:action). Мутирующие эндпоинты отклоняют cross-origin запросы; script-задачи по HTTP требуют заголовок x-dsh-cron-confirm. Настройки доставки принимаются как плоские ключи (webhook URL, топики, base URL) и `channelTemplates` — карта шаблонов по каналам.
|
|
22
|
+
- LLM Tools: cron_create_task (+ alias cron_schedule_task), cron_list_tasks, cron_pause_task, cron_resume_task, cron_delete_task, cron_run_task, cron_get_task (полная конфигурация задачи), cron_update_task (правка существующей задачи; переключение в код-исполняющий тип требует явного `confirmCodeSwitch`) (#49). Параметры задачи включают рантайм (`type`), `channels` (список каналов доставки) и `template` (шаблон сообщения).
|
|
23
|
+
- API: `GET /dsh-cron/recipes` (каталог рецептов) (#48); HTTP эндпоинты /dsh-cron/* (tasks, models, chat/start, settings, telegram/test, kanban/test, tasks/:id/actions, legacy action/:id/:action). Мутирующие эндпоинты отклоняют cross-origin запросы; script-задачи по HTTP требуют заголовок x-dsh-cron-confirm. Настройки доставки принимаются как плоские ключи (webhook URL, топики, base URL) и `channelTemplates` — карта шаблонов по каналам.
|
|
24
24
|
- Chat / Slash Commands: отсутствуют (ранее заявленные /cron-команды не были реализованы и удалены из документации; решение 2026-09-09).
|
|
25
25
|
|
|
26
26
|
## Visual Direction
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
- CronScreen: основной оверлей со списком, табами, статистикой и рекомендациями.
|
|
46
46
|
- CreateDropdown: всплывающее меню выбора способа создания.
|
|
47
47
|
- ManualTaskModal: модальная форма создания/редактирования (вкладки «Параметры» / «История запусков»); блок каналов доставки — сетка чекбоксов (Telegram, dsh-kanban, Discord, Slack, ntfy, Bark, PushPlus, Voice, Gitea) и поле шаблона сообщения с подсказкой по переменным.
|
|
48
|
-
- SettingsModal: настройки доставки с тестами;
|
|
48
|
+
- SettingsModal: настройки доставки с тестами; секции «Credentials (references)», «Delivery channels», «Automation models» (модели для правила тишины и диагностики), «Message templates» — сворачиваемые, шапка-кнопка с aria-expanded.
|
|
49
49
|
- DeliverySettingsForm: общая форма настроек доставки, одна реализация для SettingsModal и CronSettingsCard; секреты вводятся только по имени credential-ссылки.
|
|
50
50
|
- TaskItem: строка задачи с переключателем состояния и действиями (запуск, редактирование, дублирование, удаление); адресуется атрибутом data-task-id для подсветки из сайдбара.
|
|
51
51
|
- ImportModal: сводка по файлу (сколько добавится, заменится, пропустится) и выбор стратегии add/replace/skip до применения (#42).
|
|
@@ -65,6 +65,8 @@
|
|
|
65
65
|
4. Разбор инцидента: история запусков в карточке задачи → статус, длительность, вывод/ошибка.
|
|
66
66
|
|
|
67
67
|
## Locked Design Decisions
|
|
68
|
+
|
|
69
|
+
- 2026-09-11 — Блок B (0.2.6): рецепты (#48), инструменты чтения и правки задачи (#49), каскад моделей (#45), правило тишины (#44), диагностика сбоев (#43), разбивка обработчиков (#97). Модельные вспомогательные вызовы идут через `ctx.llm.stream` с жёстким дедлайном и fail-open: недоступная или неуверенная модель означает «доставить отчёт», а не тишину. Переключение задачи в код-исполняющий тип подтверждается структурно на обеих поверхностях (HTTP-заголовок и `confirmCodeSwitch` инструмента).
|
|
68
70
|
- 2026-09-11 — Доставка вынесена в отдельный слой: сообщение рендерится шаблоном `{var}` (#25), транспорт — адаптеры каналов с чистым builder'ом payload и инжектируемым fetch, маршрутизатор собирает ошибки каналов и не роняет запуск (#26, #20–#23, #28, #47). Явно выбранные каналы задачи перекрывают legacy-флаги `notifyTelegram`/`kanbanMode`.
|
|
69
71
|
- 2026-09-11 — Доставка не может заблокировать планировщик: каждый канал ограничен таймаутом (`deliveryTimeoutMs`, по умолчанию 15 с), каналы отправляются параллельно, а ошибки (включая таймаут) собираются в `failures`. Причина: `protect: true` в croner пропускал бы следующие тики, пока висит незавершённая доставка (находка независимого review PR #114).
|
|
70
72
|
- 2026-09-11 — Блок A (0.2.5): список активных задач в сайдбаре (#34), фильтры по типу/модели/каналу (#40), адаптив до 375 px без скрытия информации (#39), дублирование задачи серверным маршрутом с принудительной паузой и сбросом состояния (#41), экспорт/импорт конфигурации задач в JSON со стратегиями и dry-run (#42), нормализация и нижняя граница таймаута доставки (#115). Экспорт — только JSON: YAML-парсера в проекте нет, а зависимость ради формата не добавляется.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# План: блок B — экономия и меньше шума (0.2.6)
|
|
2
|
+
|
|
3
|
+
Живой план блока. Обновляется по факту работы; источник истины по задачам —
|
|
4
|
+
Gitea (`goodandready/dsh-cron`), milestone `0.2.6`.
|
|
5
|
+
|
|
6
|
+
## Состав блока (согласован владельцем)
|
|
7
|
+
|
|
8
|
+
| Issue | Задача | Сложность |
|
|
9
|
+
|:--|:--|:--|
|
|
10
|
+
| #45 | Каскад моделей Flash → Pro при сбое | H |
|
|
11
|
+
| #44 | «Правило тишины» на базе LLM для задач с внешним выводом | M |
|
|
12
|
+
| #43 | Инспектор сбоев: диагноз и предложение правки промпта | M |
|
|
13
|
+
| #49 | Подстройка задачи через диалог (`cron_get_task`, `cron_update_task`) | M |
|
|
14
|
+
| #48 | Хаб готовых рецептов мониторинга | M |
|
|
15
|
+
| #97 | Техдолг: разбить разросшиеся обработчики (пункт 3 issue) | L |
|
|
16
|
+
|
|
17
|
+
Следующий по согласованию блок C (0.2.7) — #54, #50, #53, #97(остатки), #121.
|
|
18
|
+
|
|
19
|
+
## Границы и инварианты
|
|
20
|
+
|
|
21
|
+
- Один блок → одна ветка `feat/0.2.6-economy-block` → один PR → один релиз 0.2.6.
|
|
22
|
+
- Новых зависимостей блок не добавляет; вызовы модели идут через сервис харнесса.
|
|
23
|
+
- **Все обращения к модели fail-open:** ошибка, таймаут или невалидный ответ LLM
|
|
24
|
+
не приводят к потере отчёта, зависанию запуска или ложной тишине.
|
|
25
|
+
- Секреты — только credential-ссылки. Ключи и токены в рецептах и промптах не
|
|
26
|
+
хранятся.
|
|
27
|
+
- Публичные экспорты `lib/index.js` не ломаются; поведение существующих
|
|
28
|
+
маршрутов не меняется.
|
|
29
|
+
- Рефакторинг (#97) идёт первым коммитом блока: новые фичи ложатся в уже
|
|
30
|
+
разобранную структуру, а не наоборот.
|
|
31
|
+
- `lib/client.js` остаётся single-file (требование загрузчика DSH).
|
|
32
|
+
|
|
33
|
+
## Вне scope
|
|
34
|
+
|
|
35
|
+
- Внешний REST API и декларативный конфиг (блок C).
|
|
36
|
+
- Новые каналы доставки и изменения существующих.
|
|
37
|
+
- Обновление зависимостей (`#117` — отдельная ветка).
|
|
38
|
+
|
|
39
|
+
## План проверки блока
|
|
40
|
+
|
|
41
|
+
- `npm test` до и после каждого пункта; базовый результат на старте — 128/128.
|
|
42
|
+
- Новые тесты: каскад моделей с подставным исполнителем, вердикты правила тишины
|
|
43
|
+
(тихо/громко/ошибка/невалидный JSON), разбор диагноза инспектора, инструменты
|
|
44
|
+
подстройки, валидность всех рецептов и отсутствие деструктивных команд.
|
|
45
|
+
- `bash deploy.sh check` (тесты + гейт размера + кандидат).
|
|
46
|
+
- Приёмка на изолированном MiniPC: установка кандидата, проверка новых полей и
|
|
47
|
+
инструментов через API, отображение в браузере.
|
|
48
|
+
- Независимое ревью PR перед merge.
|
|
49
|
+
|
|
50
|
+
## Журнал
|
|
51
|
+
|
|
52
|
+
- 2026-09-11 — #97 закрыт первым коммитом: `lib/api.js` (диспетчер + обработчики по областям), `http-utils` получил общие `sendJson`/`rejectCrossOrigin`/`readBody`, `runTask` → `beginRun`/`executeOnce`/`completeRun`, `_run` → диспетчер + подготовка/ход/уборка. `index.js` 1024 → 671 строк; полный набор тестов зелёный без правок ожиданий, добавлен тест на контракты item-маршрутов. **Уточнение после ревью:** утверждение «все затронутые функции ≤ 50 строк» на тот момент было неверным — `completeRun` и `buildTaskRecord` превышали ориентир и разбиты отдельным коммитом.
|
|
53
|
+
- 2026-09-11 — #43 готов: `lib/failure-inspector.js` (промпт, разбор диагноза, fail-open), планировщик диагностирует сбой до записи, история хранит `diagnosis`/`suggestion`/`confidence`, в UI — чекбокс, настройка `inspectorModel`, блок диагноза в истории с кнопкой подстановки правки, переменная `{diagnosis}`. 164/164 тестов.
|
|
54
|
+
- 2026-09-11 — #44 готов: `lib/llm-ask.js` (обёртка над `ctx.llm.stream` со сбором текста, таймаутом и fail-open) и `lib/silent-rule.js` (правило словами → вердикт `{notify, reason}`); планировщик решает о доставке до записи запуска, история хранит `silentSkip`/`silentReason`, в UI есть поле правила и маркер в истории, настройка `silentRuleModel`. 156/156 тестов, включая четыре сценария fail-open.
|
|
55
|
+
- 2026-09-11 — #49 готов: инструменты `cron_get_task`/`cron_update_task`, общий модуль `lib/task-patch.js` (один код для HTTP PATCH и инструмента), действие «Настроить с DSH» в строке задачи, которое открывает сессию с контекстом задачи и предписанием подтверждать code-изменения. 145/145 тестов.
|
|
56
|
+
- 2026-09-11 — #48 готов: каталог `lib/recipes.js` (10 рецептов в 5 категориях, только read-only команды), маршрут `GET /dsh-cron/recipes`, панель подсказок переведена на каталог, пресет рецепта заполняет форму вместе с типом и каналами; тест проверяет валидность каждого рецепта и отсутствие деструктивных команд.
|
|
57
|
+
- 2026-09-11 — #45 готов: `fallbackProvider`/`fallbackModel` у задачи, ровно одна повторная попытка на fallback-модели при `error`/`timeout` (только агентские типы), сумма usage и стоимости обеих попыток, `model` и `fallback` в записи истории, переменная шаблона `{model}`, поле в UI. 134/134 тестов.
|
|
58
|
+
- 2026-09-11 — блок согласован (блок B + #97 → 0.2.6), ТЗ по каждой задаче
|
|
59
|
+
записаны в Gitea, все шесть задач переведены в milestone 0.2.6.
|
|
60
|
+
- 2026-09-11 — независимое ревью блока B дало FAIL и нашло: `cron_update_task` обходил подтверждение переключения в код-исполняющий тип (закрыто структурным гейтом `allowCodeSwitch`/`confirmCodeSwitch` с поведенческими тестами), помощники моделей всегда шли на модель харнесса вместо модели задачи (исправлено передачей задачи в `ask`), дедлайн вызова модели держался только на abort-сигнале (добавлена жёсткая гонка в `lib/llm-ask.js`), чёрный список деструктивных команд обходился `find -delete`, `shred`, `apt purge`, `mv /etc/...` и др. (расширен, те же пробы теперь блокируются), две функции превышали ориентир 50 строк (`completeRun`, `buildTaskRecord` — разбиты), документация отстала (DESIGN.md, index.md, AGENTS.md, RU §14 обновлены). Тестов стало 175.
|
|
61
|
+
- 2026-09-11 — релиз `0.2.6`: bump 0.2.5 → 0.2.6, тег `v0.2.6`, npm publish, GitHub Release, установка точной версии в production web-профиль MiniAI и production-проверки; закрыты #43, #44, #45, #48, #49, #97.
|