@goodandready/dsh-cron 0.1.13 → 0.1.14

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/client.js CHANGED
@@ -123,6 +123,20 @@ const React = window.React || require('react');
123
123
  .dsh-cron-card-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
124
124
  .dsh-cron-card-title { font-size: 15px; font-weight: 600; color: var(--dsw-alias-label-primary, #fff); }
125
125
  .dsh-cron-card-desc { font-size: 13px; color: var(--dsw-alias-label-secondary, #888); margin-bottom: 16px; line-height: 1.4; }
126
+
127
+ .dsh-cron-modal-nav { display: flex; gap: 4px; border-bottom: 1px solid #2e2e2e; margin-bottom: 18px; padding-bottom: 2px; }
128
+ .dsh-cron-modal-tab { appearance: none; background: transparent; border: none; border-bottom: 2px solid transparent; padding: 8px 14px; font-size: 13.5px; color: #888; cursor: pointer; font-weight: 500; transition: color 0.15s, border-color 0.15s; }
129
+ .dsh-cron-modal-tab:hover { color: #ccc; }
130
+ .dsh-cron-modal-tab[data-active="true"] { color: #fff; border-bottom-color: #ededed; }
131
+ .dsh-cron-history-list { display: flex; flex-direction: column; gap: 10px; max-height: 420px; overflow-y: auto; padding-right: 4px; }
132
+ .dsh-cron-history-item { background: #161616; border: 1px solid #2a2a2a; border-radius: 8px; padding: 12px 14px; font-size: 12.5px; }
133
+ .dsh-cron-history-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
134
+ .dsh-cron-history-status { font-weight: 600; font-size: 11.5px; text-transform: uppercase; padding: 2px 6px; border-radius: 4px; }
135
+ .dsh-cron-history-status[data-status="success"] { background: rgba(16, 185, 129, 0.15); color: #10b981; }
136
+ .dsh-cron-history-status[data-status="error"] { background: rgba(239, 68, 68, 0.15); color: #ef4444; }
137
+ .dsh-cron-history-time { color: #777; font-size: 12px; }
138
+ .dsh-cron-history-output { background: #0c0c0c; border: 1px solid #222; border-radius: 6px; padding: 8px 10px; font-family: monospace; font-size: 12px; color: #bbb; max-height: 140px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; margin-top: 6px; }
139
+ .dsh-cron-history-empty { text-align: center; padding: 36px 0; color: #666; font-size: 13.5px; }
126
140
  `;
127
141
 
128
142
  function ensureStyles() {
@@ -220,6 +234,9 @@ const React = window.React || require('react');
220
234
  const [formModel, setFormModel] = React.useState('');
221
235
  const [formDelivery, setFormDelivery] = React.useState('isolated');
222
236
  const [selectedTaskMeta, setSelectedTaskMeta] = React.useState(null);
237
+ const [modalTab, setModalTab] = React.useState('params');
238
+ const [taskHistory, setTaskHistory] = React.useState([]);
239
+ const [historyLoading, setHistoryLoading] = React.useState(false);
223
240
 
224
241
  // DSH dialog state
225
242
  const [dshModalOpen, setDshModalOpen] = React.useState(false);
@@ -317,10 +334,26 @@ const React = window.React || require('react');
317
334
  setManualModalOpen(true);
318
335
  };
319
336
 
337
+ const loadTaskHistory = async (taskId) => {
338
+ setHistoryLoading(true);
339
+ try {
340
+ const res = await fetch('/dsh-cron/action/' + encodeURIComponent(taskId) + '/history');
341
+ const data = await res.json();
342
+ if (data.ok) {
343
+ setTaskHistory(data.history || []);
344
+ }
345
+ } catch (e) {
346
+ console.error('[dsh-cron] history load failed:', e);
347
+ } finally {
348
+ setHistoryLoading(false);
349
+ }
350
+ };
351
+
320
352
  const openEditModal = (task) => {
321
353
  setDropdownOpen(false);
322
354
  setFormId(task.id);
323
355
  setSelectedTaskMeta(task);
356
+ setModalTab('params');
324
357
  setFormTitle(task.title || '');
325
358
  setFormSchedule(task.schedule || '');
326
359
  setFormType(task.type || 'llm');
@@ -330,6 +363,7 @@ const React = window.React || require('react');
330
363
  setFormDelivery(task.delivery || 'isolated');
331
364
  if (task.provider) loadModels(task.provider);
332
365
  else if (defaultModelInfo?.provider) loadModels(defaultModelInfo.provider);
366
+ loadTaskHistory(task.id);
333
367
  setManualModalOpen(true);
334
368
  };
335
369
 
@@ -547,7 +581,7 @@ const React = window.React || require('react');
547
581
  style: { maxWidth: '640px' },
548
582
  onClick: (e) => e.stopPropagation()
549
583
  },
550
- React.createElement('div', { className: 'dsh-cron-modal-head', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '18px' } },
584
+ React.createElement('div', { className: 'dsh-cron-modal-head', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: formId ? '12px' : '18px' } },
551
585
  React.createElement('div', { className: 'dsh-cron-modal-title', style: { margin: 0 } }, formId ? 'Редактирование задачи' : 'Новая запланированная задача'),
552
586
  selectedTaskMeta && React.createElement('span', {
553
587
  style: {
@@ -559,6 +593,55 @@ const React = window.React || require('react');
559
593
  }
560
594
  }, selectedTaskMeta.status === 'active' ? '● Активна' : '○ На паузе')
561
595
  ),
596
+
597
+ formId && React.createElement('div', { className: 'dsh-cron-modal-nav' },
598
+ React.createElement('button', {
599
+ type: 'button',
600
+ className: 'dsh-cron-modal-tab',
601
+ 'data-active': modalTab === 'params',
602
+ onClick: () => setModalTab('params')
603
+ }, 'Параметры'),
604
+ React.createElement('button', {
605
+ type: 'button',
606
+ className: 'dsh-cron-modal-tab',
607
+ 'data-active': modalTab === 'history',
608
+ onClick: () => { setModalTab('history'); if (formId) loadTaskHistory(formId); }
609
+ }, 'История запусков (' + (taskHistory.length || 0) + ')')
610
+ ),
611
+
612
+ modalTab === 'history' && formId ? React.createElement('div', null,
613
+ historyLoading ? React.createElement('div', { className: 'dsh-cron-history-empty' }, 'Загрузка истории...') :
614
+ taskHistory.length === 0 ? React.createElement('div', { className: 'dsh-cron-history-empty' }, 'История запусков пока пуста') :
615
+ React.createElement('div', { className: 'dsh-cron-history-list' },
616
+ taskHistory.map((run) => React.createElement('div', { key: run.id, className: 'dsh-cron-history-item' },
617
+ React.createElement('div', { className: 'dsh-cron-history-head' },
618
+ React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
619
+ React.createElement('span', {
620
+ className: 'dsh-cron-history-status',
621
+ 'data-status': run.status
622
+ }, run.status === 'success' ? 'Успешно' : 'Ошибка'),
623
+ React.createElement('span', { className: 'dsh-cron-history-time' }, run.at ? new Date(run.at).toLocaleString() : '')
624
+ ),
625
+ React.createElement('span', { style: { color: '#888', fontSize: '11.5px' } }, (run.durationMs || 0) + ' ms')
626
+ ),
627
+ run.output && React.createElement('div', { className: 'dsh-cron-history-output' }, run.output),
628
+ run.error && React.createElement('div', { className: 'dsh-cron-history-output', style: { color: '#ef4444', borderColor: '#552222' } }, run.error)
629
+ ))
630
+ ),
631
+ React.createElement('div', { className: 'dsh-cron-modal-foot', style: { marginTop: '18px' } },
632
+ React.createElement('button', {
633
+ type: 'button',
634
+ className: 'dsh-cron-btn-secondary',
635
+ onClick: () => { if (formId) loadTaskHistory(formId); }
636
+ }, 'Обновить историю'),
637
+ React.createElement('button', {
638
+ type: 'button',
639
+ className: 'dsh-cron-btn-primary',
640
+ onClick: () => setManualModalOpen(false)
641
+ }, 'Закрыть')
642
+ )
643
+ ) :
644
+
562
645
  React.createElement('form', { onSubmit: handleSaveManual },
563
646
  React.createElement('div', { className: 'dsh-cron-form-group' },
564
647
  React.createElement('label', null, 'Название задачи'),
@@ -645,7 +728,10 @@ const React = window.React || require('react');
645
728
  type: 'button',
646
729
  className: 'dsh-cron-btn-secondary',
647
730
  style: { padding: '4px 10px', fontSize: '12px' },
648
- onClick: () => { handleRunNow(selectedTaskMeta.id); }
731
+ onClick: async () => {
732
+ await handleRunNow(selectedTaskMeta.id);
733
+ if (formId) loadTaskHistory(formId);
734
+ }
649
735
  }, 'Запустить сейчас')
650
736
  ),
651
737
  React.createElement('div', { className: 'dsh-cron-modal-foot' },
package/lib/index.js CHANGED
@@ -177,6 +177,14 @@ export function apply(ctx, config) {
177
177
  return;
178
178
  }
179
179
 
180
+ const historyMatch = pathname.match(/^\/dsh-cron\/action\/([^/]+)\/history$/);
181
+ if (req.method === 'GET' && historyMatch) {
182
+ const taskId = historyMatch[1];
183
+ const history = store.getHistory(taskId, 30);
184
+ sendJson(res, 200, { ok: true, history });
185
+ return;
186
+ }
187
+
180
188
  sendJson(res, 404, { ok: false, error: 'Action not found' });
181
189
  } catch (err) {
182
190
  sendJson(res, 500, { ok: false, error: err.message });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-cron",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Scheduled cron tasks, background automation and agent execution for DeepSeek Harness.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",