@goodandready/dsh-cron 0.1.8 → 0.1.10

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/lib/chat-start.js CHANGED
@@ -39,9 +39,10 @@ export async function chatStartHandler(ctx, req, res, parseJsonBody, sendJson, r
39
39
  const provider = body.provider || defaultSel?.provider;
40
40
  const model = body.model || defaultSel?.model;
41
41
 
42
+ const cwd = process.cwd();
42
43
  const handle = await agents.create({
43
44
  sessionId: mintSessionId(),
44
- meta: {},
45
+ meta: { cwd },
45
46
  agentOptions: provider && model ? { provider, model } : undefined,
46
47
  });
47
48
 
package/lib/index.js CHANGED
@@ -194,6 +194,7 @@ export function apply(ctx, config) {
194
194
  schedule: { type: 'string', required: true, description: 'Выражение cron или интервал (every 30m, 0 9 * * 1-5, daily)' },
195
195
  prompt: { type: 'string', required: true, description: 'Инструкция для агента при запуске' },
196
196
  delivery: { type: 'string', description: 'Режим запуска: current или isolated' },
197
+ type: { type: 'string', description: 'Тип задачи: "llm" (агент с LLM) или "script" (прямой запуск shell без LLM)' },
197
198
  provider: { type: 'string', description: 'ID провайдера LLM для выполнения задачи' },
198
199
  model: { type: 'string', description: 'ID модели LLM для выполнения задачи' }
199
200
  },
@@ -210,7 +211,7 @@ export function apply(ctx, config) {
210
211
  return [{ type: 'text', text: value.message }];
211
212
  }
212
213
  },
213
- execute: async ({ title, schedule, prompt, delivery, provider, model }) => {
214
+ execute: async ({ title, schedule, prompt, delivery, provider, model, type }) => {
214
215
  try {
215
216
  const parsed = parseScheduleExpression(schedule);
216
217
  const task = store.set({
@@ -218,6 +219,7 @@ export function apply(ctx, config) {
218
219
  schedule: parsed.cronPattern,
219
220
  scheduleText: parsed.humanText,
220
221
  prompt,
222
+ type: type || (provider || model ? 'llm' : 'llm'),
221
223
  delivery: delivery || 'isolated',
222
224
  provider: provider || undefined,
223
225
  model: model || undefined,
package/lib/prompt.js CHANGED
@@ -5,13 +5,46 @@
5
5
  */
6
6
  export function buildAgentCronPrompt(userText) {
7
7
  const text = (userText || '').trim();
8
- return `Пользователь хочет запланировать cron-задачу через DSH Cron:
8
+ return `Пользователь хочет настроить запланированную задачу (cron) через DSH Cron.
9
+ Исходный запрос пользователя:
9
10
  "${text}"
10
11
 
11
- ИНСТРУКЦИЯ ДЛЯ АГЕНТА:
12
- 1. Твоя цель — помочь пользователю настроить и зарегистрировать запланированную задачу с помощью инструмента \`cron_schedule_task\`.
13
- 2. Предложи подходящую и экономичную LLM-модель для выполнения этого крона (например, \`Qwen/Qwen3.8-Flash\` через Command Code или \`deepseek/deepseek-v4-flash\`), уточни у пользователя, устраивает ли она его или он предпочитает другую подключенную модель.
14
- 3. Уточни и сформулируй точное расписание cron (например, "0 * * * *" или интервал вроде "every 1h").
15
- 4. Примени Silent Rule (правило тишины): если задача мониторинга/проверки не обнаружила проблем, критических изменений или ошибок, агент должен возвращать ПУСТОЙ ответ или короткое уведомление без лишнего шума.
16
- 5. После согласования параметров ОБЯЗАТЕЛЬНО вызови инструмент \`cron_schedule_task\`, передав title, schedule, prompt и delivery ("isolated" или "current").`;
17
- }
12
+ ВАЖНЕЙШИЕ ПРАВИЛА ДЛЯ АГЕНТА:
13
+ 1. СТРОГИЙ ЗАПРЕТ НА СПЕШКУ:
14
+ КАТЕГОРИЧЕСКИ ЗАПРЕЩЕНО вызывать инструмент \`cron_schedule_task\` в первом же ответе!
15
+ Ты НЕ имеешь права создавать задачу, пока не задашь пользователю уточняющие вопросы и не получишь его подтверждение.
16
+
17
+ 2. ЧТО ТЫ ОБЯЗАН УТОЧНИТЬ В ПЕРВОМ ОТВЕТЕ:
18
+ - Тип задачи (LLM или NO-LLM?):
19
+ * LLM-крон: агент запускается по расписанию с языковой моделью, анализирует вывод, делает выводы, парсит неструктурированный текст (расходует токены).
20
+ * NO-LLM крон (скрипт/bash): периодический запуск shell-команды или скрипта (curl, git check, ping, проверка системных служб) БЕЗ участия LLM. Не расходует токены, сообщает только при ненулевом коде возврата или ошибке.
21
+ Спроси пользователя, какой вариант предпочтительнее для его задачи (или аргументированно предложи подходящий).
22
+ - Выбор модели (если выбран LLM-крон):
23
+ * Предложи экономичную и быструю модель (например, \`deepseek/deepseek-v4-flash\` или \`Qwen/Qwen3.8-Flash\`).
24
+ * Спроси, подходит ли эта модель или пользователь хочет использовать другую подключенную модель.
25
+ - Точное расписание (schedule):
26
+ * Предложи конкретное выражение cron (например, "0 */6 * * *" для 4 раз в день или "0 9 * * 1-5" по будням) и понятное текстовое пояснение.
27
+ * Уточни, устраивает ли такое расписание.
28
+ - Silent Rule (Правило тишины / Уведомления):
29
+ * По умолчанию для регулярных проверок действует Silent Rule: если всё в порядке / нет обновлений / сервис работает штатно — агент молчит или возвращает пустой ответ, чтобы не спамить. Оповещение отправляется ТОЛЬКО при обнаружении изменений, обновлений или проблем.
30
+ * Уточни, нужно ли применять Silent Rule или присылать отчёт при каждом запуске.
31
+
32
+ 3. СТРУКТУРА ПЕРВОГО ОТВЕТА:
33
+ - Кратко подтверди суть задачи.
34
+ - Сформулируй проект карточки задачи:
35
+ • Тип: [LLM / NO-LLM]
36
+ • Расписание: [cron-выражение и понятное описание]
37
+ • Модель: [если LLM — предлагаемая модель]
38
+ • Логика проверки и Silent Rule: [кратко]
39
+ - Задай недостающие вопросы (LLM/NO-LLM, модель, расписание, порог алерта).
40
+ - Попроси пользователя подтвердить или скорректировать параметры перед созданием.
41
+
42
+ 4. СОЗДАНИЕ ЗАДАЧИ:
43
+ Только ПОСЛЕ ТОГО, как пользователь ответит и подтвердит параметры, вызови инструмент \`cron_schedule_task\`, передав:
44
+ - title: понятное название задачи
45
+ - schedule: согласованное cron-выражение
46
+ - prompt: финальная подробная инструкция для агента (с обязательным Silent Rule) ИЛИ shell-команда для NO-LLM
47
+ - type: "llm" или "script"
48
+ - provider и model: согласованный провайдер и модель (если type="llm")
49
+ - delivery: "isolated"`;
50
+ }
package/lib/runner.js CHANGED
@@ -6,10 +6,28 @@ export class SessionRunner {
6
6
  this.ctx = ctx;
7
7
  }
8
8
 
9
- async execute(task) {
9
+ async execute(task) {
10
10
  console.log(`[dsh-cron] executing task "${task.title}" (${task.id})`);
11
11
 
12
- // 1. If ctx.agents is available, run through agent session
12
+ // 1. Direct shell / script task fallback (NO-LLM)
13
+ if (task.type === 'script' || task.mode === 'no-llm') {
14
+ const { exec } = await import('node:child_process');
15
+ const { promisify } = await import('node:util');
16
+ const execAsync = promisify(exec);
17
+ try {
18
+ const { stdout, stderr } = await execAsync(task.prompt, {
19
+ timeout: 60000,
20
+ cwd: process.cwd()
21
+ });
22
+ const out = (stdout || stderr || '').trim();
23
+ return out || 'Script completed with code 0';
24
+ } catch (err) {
25
+ console.error(`[dsh-cron] script task failed:`, err.message);
26
+ throw err;
27
+ }
28
+ }
29
+
30
+ // 2. If ctx.agents is available, run through agent session (LLM)
13
31
  if (this.ctx && this.ctx.agents && typeof this.ctx.agents.create === 'function') {
14
32
  try {
15
33
  const { randomUUID } = await import('node:crypto');
@@ -34,9 +52,10 @@ export class SessionRunner {
34
52
  const provider = task.provider || defaultSel?.provider;
35
53
  const model = task.model || defaultSel?.model;
36
54
 
55
+ const cwd = process.cwd();
37
56
  const handle = await this.ctx.agents.create({
38
57
  sessionId: mintSessionId(),
39
- meta: {},
58
+ meta: { cwd },
40
59
  agentOptions: provider && model ? { provider, model } : undefined,
41
60
  });
42
61
 
@@ -53,7 +72,7 @@ export class SessionRunner {
53
72
  }
54
73
  }
55
74
 
56
- // 2. Check if legacy session service is present
75
+ // 3. Check if legacy session service is present
57
76
  if (this.ctx && this.ctx.session && typeof this.ctx.session.create === 'function') {
58
77
  try {
59
78
  const session = await this.ctx.session.create({
@@ -71,15 +90,6 @@ export class SessionRunner {
71
90
  }
72
91
  }
73
92
 
74
- // 3. Direct shell / script task fallback
75
- if (task.type === 'script' && task.prompt) {
76
- const { exec } = await import('node:child_process');
77
- const { promisify } = await import('node:util');
78
- const execAsync = promisify(exec);
79
- const { stdout, stderr } = await execAsync(task.prompt, { timeout: 60000 });
80
- return stdout || stderr || 'Script completed with code 0';
81
- }
82
-
83
93
  return `[dsh-cron] Prompt triggered: "${task.prompt.slice(0, 100)}..."`;
84
94
  }
85
95
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-cron",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Scheduled cron tasks, background automation and agent execution for DeepSeek Harness.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",