@goodandready/dsh-cron 0.2.11 → 0.2.12

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 CHANGED
@@ -352,6 +352,13 @@ Developer-facing, no behaviour change. `parseScheduleExpression` was split into
352
352
 
353
353
  ---
354
354
 
355
+ ### 24. Automatic Agent Preset Mounting & Tool Availability (#141 / GH-1, Added in v0.2.12)
356
+ - **Automatic Agent Preset Mounting**: Scheduled autonomous `llm` tasks and on-demand agent runs now automatically resolve and mount the system agent preset (defaulting to user's standard preset via `presets.mount(agentCtx, preset.id)` in `setup`). Scheduled agent turns now possess complete tool access (file editing, workspace exploration, shell commands, etc.) instead of running with bare chat sessions.
357
+ - **Per-Task Preset Override**: Tasks can explicitly configure an `agentPreset` identifier in the task form UI, REST API, or profile jobs (e.g. `coding`, `system`, `minimal`). When left empty, tasks automatically resolve to the harness's default preset.
358
+ - **Graceful Toolset Fallback**: If the `agentPresets` service is absent or an unknown preset ID is provided, the scheduler logs an informative warning and safely proceeds with basic model execution without aborting the scheduled task.
359
+
360
+ ---
361
+
355
362
  ## 📦 Installation
356
363
 
357
364
  Install into your DeepSeek Harness web profile:
package/README.ru.md CHANGED
@@ -228,6 +228,13 @@ cron_create_task({
228
228
 
229
229
  ---
230
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
+
231
238
  ## 📦 Установка
232
239
 
233
240
  ```bash
package/README.zh.md CHANGED
@@ -351,6 +351,13 @@ bash deploy.sh verify [exact-version]
351
351
 
352
352
  ---
353
353
 
354
+ ### 24. 自动挂载智能体预设与工具支持 (#141 / GH-1,v0.2.12 新增)
355
+ - **自动挂载智能体预设**:计划执行的自主 `llm` 任务和交互式启动现在会自动解析并挂载系统智能体预设(默认通过 `setup` 钩子中的 `presets.mount(agentCtx, preset.id)` 挂载用户的标准预设)。计划会话现已具备完整的工具调用能力(文件读写、工作区操作、Shell 终端等),彻底解决此前空会话无工具调用的问题。
356
+ - **单任务预设覆盖**:可在 Web 管理界面、REST API 或配置文件中为具体任务配置独立的 `agentPreset` 标识(例如 `coding`、`system`、`minimal`)。未设置时自动继承系统默认预设。
357
+ - **优雅降级保障**:当未安装 `agentPresets` 服务或指定了未知的预设 ID 时,调度器仅记录友好的警告日志,并安全平稳地继续执行基础模型会话,避免定时任务中断。
358
+
359
+ ---
360
+
354
361
  ## 📦 安装
355
362
 
356
363
  ```bash
package/docs/README.ru.md CHANGED
@@ -228,6 +228,13 @@ cron_create_task({
228
228
 
229
229
  ---
230
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
+
231
238
  ## 📦 Установка
232
239
 
233
240
  ```bash
package/docs/README.zh.md CHANGED
@@ -351,6 +351,13 @@ bash deploy.sh verify [exact-version]
351
351
 
352
352
  ---
353
353
 
354
+ ### 24. 自动挂载智能体预设与工具支持 (#141 / GH-1,v0.2.12 新增)
355
+ - **自动挂载智能体预设**:计划执行的自主 `llm` 任务和交互式启动现在会自动解析并挂载系统智能体预设(默认通过 `setup` 钩子中的 `presets.mount(agentCtx, preset.id)` 挂载用户的标准预设)。计划会话现已具备完整的工具调用能力(文件读写、工作区操作、Shell 终端等),彻底解决此前空会话无工具调用的问题。
356
+ - **单任务预设覆盖**:可在 Web 管理界面、REST API 或配置文件中为具体任务配置独立的 `agentPreset` 标识(例如 `coding`、`system`、`minimal`)。未设置时自动继承系统默认预设。
357
+ - **优雅降级保障**:当未安装 `agentPresets` 服务或指定了未知的预设 ID 时,调度器仅记录友好的警告日志,并安全平稳地继续执行基础模型会话,避免定时任务中断。
358
+
359
+ ---
360
+
354
361
  ## 📦 安装
355
362
 
356
363
  ```bash
package/lib/chat-start.js CHANGED
@@ -40,13 +40,33 @@ export async function chatStartHandler(ctx, req, res, parseJsonBody, sendJson, r
40
40
  const model = body.model || defaultSel?.model;
41
41
 
42
42
  const cwd = process.cwd();
43
+ const presets = ctx.agentPresets || ctx.get?.('agentPresets');
44
+ let preset = null;
45
+ if (presets && typeof presets.resolve === 'function') {
46
+ try {
47
+ preset = await presets.resolve(body.agentPreset || 'standard');
48
+ if (preset && typeof presets.standingKeyFor === 'function') {
49
+ await presets.standingKeyFor(preset.id);
50
+ }
51
+ } catch (presetErr) {
52
+ ctx.logger?.warn?.(`[dsh-cron] could not resolve agentPreset: ${presetErr.message}`);
53
+ }
54
+ }
55
+
43
56
  const handle = await agents.create({
44
57
  sessionId: mintSessionId(),
45
58
  meta: {
46
59
  cwd,
47
- agentPreset: 'standard',
60
+ agentPreset: preset ? preset.id : 'standard',
48
61
  },
49
62
  agentOptions: provider && model ? { provider, model } : undefined,
63
+ ...(preset ? {
64
+ setup: async (agentCtx) => {
65
+ if (typeof presets.mount === 'function') {
66
+ await presets.mount(agentCtx, preset.id);
67
+ }
68
+ }
69
+ } : {}),
50
70
  });
51
71
 
52
72
  const permissions = ctx.get?.('permissionPresets');
package/lib/client.js CHANGED
@@ -323,6 +323,9 @@ window.__ModuleLoader__.load({
323
323
  'form.selfHealingLabel': 'Self-healing runbook command (shell)',
324
324
  'form.selfHealingPlaceholder': 'systemctl restart app || true',
325
325
  'form.autoDiagnoseLabel': 'Auto-diagnose failures with AI agent',
326
+ 'form.agentPresetLabel': 'Agent preset',
327
+ 'form.agentPresetPlaceholder': 'standard (leave empty for configured default)',
328
+ 'form.agentPresetHint': 'Agent preset from dsh-agent-presets (e.g. standard, minimal, cordis, ptc). Mounts workspace and coding tools.',
326
329
  'form.previewSchedule': 'Preview next runs',
327
330
  'form.previewScheduleTitle': 'Next 5 scheduled runs:',
328
331
  },
@@ -396,6 +399,9 @@ window.__ModuleLoader__.load({
396
399
  'form.selfHealingLabel': '故障自愈脚本 (Shell)',
397
400
  'form.selfHealingPlaceholder': 'systemctl restart app || true',
398
401
  'form.autoDiagnoseLabel': '任务失败时启用 AI 智能分析诊断',
402
+ 'form.agentPresetLabel': '智能体预设 (Agent Preset)',
403
+ 'form.agentPresetPlaceholder': 'standard (留空使用全局默认预设)',
404
+ 'form.agentPresetHint': '来自 dsh-agent-presets 的智能体预设(如 standard, minimal, cordis, ptc),挂载工作区工具与文件读写能力。',
399
405
  'form.previewSchedule': '预测下次运行时间',
400
406
  'form.previewScheduleTitle': '未来 5 次计划运行时间:',
401
407
  'search.placeholder': '搜索定时任务',
@@ -1155,6 +1161,7 @@ window.__ModuleLoader__.load({
1155
1161
  const [formMisfirePolicy, setFormMisfirePolicy] = React.useState('skip');
1156
1162
  const [formMaxRetries, setFormMaxRetries] = React.useState(0);
1157
1163
  const [formPermissionPreset, setFormPermissionPreset] = React.useState('default');
1164
+ const [formAgentPreset, setFormAgentPreset] = React.useState('');
1158
1165
  const [formEnv, setFormEnv] = React.useState('');
1159
1166
  const [formCwd, setFormCwd] = React.useState('');
1160
1167
  const [formWorkspaceId, setFormWorkspaceId] = React.useState('');
@@ -1705,6 +1712,7 @@ window.__ModuleLoader__.load({
1705
1712
  setFormMisfirePolicy('skip');
1706
1713
  setFormMaxRetries(0);
1707
1714
  setFormPermissionPreset('default');
1715
+ setFormAgentPreset('');
1708
1716
  setFormEnv('');
1709
1717
  setFormCwd('');
1710
1718
  setFormWorkspaceId('');
@@ -1803,6 +1811,7 @@ window.__ModuleLoader__.load({
1803
1811
  setFormMisfirePolicy(task.misfirePolicy || 'skip');
1804
1812
  setFormMaxRetries(task.maxRetries !== undefined ? task.maxRetries : 0);
1805
1813
  setFormPermissionPreset(task.permissionPreset || 'default');
1814
+ setFormAgentPreset(task.agentPreset || '');
1806
1815
  setFormEnv(formatEnvText(task.env));
1807
1816
  setFormCwd(task.cwd || '');
1808
1817
  setFormWorkspaceId(task.workspaceId || '');
@@ -1860,6 +1869,7 @@ window.__ModuleLoader__.load({
1860
1869
  misfirePolicy: formMisfirePolicy,
1861
1870
  maxRetries: Number(formMaxRetries) || 0,
1862
1871
  permissionPreset: formPermissionPreset,
1872
+ agentPreset: formAgentPreset.trim() || undefined,
1863
1873
  kanbanMode: formKanbanMode,
1864
1874
  onSuccess: formOnSuccess.trim() || undefined,
1865
1875
  onFailure: formOnFailure.trim() || undefined,
@@ -2520,6 +2530,16 @@ window.__ModuleLoader__.load({
2520
2530
  React.createElement('option', { value: 'always' }, T_KEY(t, 'form.kanbanAlways'))
2521
2531
  )
2522
2532
  ),
2533
+ AGENT_FORM_TYPES.includes(formType) && React.createElement('div', { className: 'dsh-cron-form-group' },
2534
+ React.createElement('label', null, T_KEY(t, 'form.agentPresetLabel')),
2535
+ React.createElement('input', {
2536
+ type: 'text',
2537
+ value: formAgentPreset,
2538
+ placeholder: T_KEY(t, 'form.agentPresetPlaceholder'),
2539
+ onChange: (e) => setFormAgentPreset(e.target.value)
2540
+ }),
2541
+ React.createElement('div', { className: 'dsh-cron-hint' }, T_KEY(t, 'form.agentPresetHint'))
2542
+ ),
2523
2543
  AGENT_FORM_TYPES.includes(formType) && React.createElement('div', { className: 'dsh-cron-form-row' },
2524
2544
  React.createElement('div', { className: 'dsh-cron-form-group' },
2525
2545
  React.createElement('label', null, T_KEY(t, 'form.providerLabel')),
package/lib/runner.js CHANGED
@@ -457,10 +457,38 @@ ${prompt}`;
457
457
  async _executeAgentTurn(task, prep) {
458
458
  let handle = null;
459
459
  try {
460
+ // Resolve agent preset (#GH-1): scheduled llm sessions must join an agent preset
461
+ // (default or task-configured), otherwise tools resolve against the empty global layer.
462
+ const presets = this.ctx.agentPresets || (this.ctx.get && this.ctx.get('agentPresets'));
463
+ let preset = null;
464
+ if (presets && typeof presets.resolve === 'function') {
465
+ try {
466
+ preset = await presets.resolve(task.agentPreset || undefined);
467
+ if (preset && typeof presets.standingKeyFor === 'function') {
468
+ await presets.standingKeyFor(preset.id);
469
+ }
470
+ } catch (presetErr) {
471
+ console.warn('[dsh-cron] agent preset unavailable, running without one:', presetErr && presetErr.message);
472
+ preset = null;
473
+ }
474
+ }
475
+
460
476
  handle = await this.ctx.agents.create({
461
477
  sessionId: prep.mintSessionId(),
462
- meta: { cwd: prep.cwd, ephemeral: true, internal: true },
478
+ meta: {
479
+ cwd: prep.cwd,
480
+ ephemeral: true,
481
+ internal: true,
482
+ ...(preset ? { agentPreset: preset.id } : {})
483
+ },
463
484
  agentOptions: prep.provider && prep.model ? { provider: prep.provider, model: prep.model } : undefined,
485
+ ...(preset ? {
486
+ setup: async (agentCtx) => {
487
+ if (typeof presets.mount === 'function') {
488
+ await presets.mount(agentCtx, preset.id);
489
+ }
490
+ }
491
+ } : {}),
464
492
  });
465
493
  this._applyPermissionPreset(task, handle);
466
494
  await prep.raceAbort(handle.agent.whenIdle());
package/lib/store.js CHANGED
@@ -249,6 +249,7 @@ export class TaskStore {
249
249
  priority: task.priority !== undefined ? Number(task.priority) : (prev.priority || 5),
250
250
  selfHealingCommand: task.selfHealingCommand !== undefined ? String(task.selfHealingCommand).trim() : (prev.selfHealingCommand || ''),
251
251
  autoDiagnose: task.autoDiagnose !== undefined ? Boolean(task.autoDiagnose) : (prev.autoDiagnose || false),
252
+ agentPreset: task.agentPreset !== undefined ? String(task.agentPreset).trim() : (prev.agentPreset || ''),
252
253
  totalTokens: prev.totalTokens || 0,
253
254
  totalCostUsd: prev.totalCostUsd || 0,
254
255
  createdAt: prev.createdAt || task.createdAt || now,
@@ -30,6 +30,7 @@ export const PATCHABLE_TASK_FIELDS = [
30
30
  'maxRetries',
31
31
  'retryBackoffMs',
32
32
  'permissionPreset',
33
+ 'agentPreset',
33
34
  'env',
34
35
  'cwd',
35
36
  'workspaceId',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-cron",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "Scheduled cron tasks, background automation and agent execution for DeepSeek Harness.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",