@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 +2 -1
- package/lib/index.js +3 -1
- package/lib/prompt.js +41 -8
- package/lib/runner.js +23 -13
- package/package.json +1 -1
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 `Пользователь хочет
|
|
8
|
+
return `Пользователь хочет настроить запланированную задачу (cron) через DSH Cron.
|
|
9
|
+
Исходный запрос пользователя:
|
|
9
10
|
"${text}"
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
1.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
9
|
+
async execute(task) {
|
|
10
10
|
console.log(`[dsh-cron] executing task "${task.title}" (${task.id})`);
|
|
11
11
|
|
|
12
|
-
// 1.
|
|
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
|
-
//
|
|
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
|
}
|