@goodandready/dsh-cron 0.1.0 → 0.1.2

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.
Files changed (2) hide show
  1. package/lib/client.js +188 -83
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -1,9 +1,7 @@
1
- // Браузерная половина @goodandready/dsh-cron
2
- window.__ModuleLoader__.load({
3
- id: '@goodandready/dsh-cron',
4
- factory: (require) => {
5
- var module = { exports: {} };
6
- var exports = module.exports;
1
+ (function () {
2
+ 'use strict';
3
+
4
+ function dshCronModule(require, exports, module) {
7
5
  const React = require('react');
8
6
  const ReactDOM = require('react-dom/client');
9
7
 
@@ -16,6 +14,7 @@ window.__ModuleLoader__.load({
16
14
  const COLUMN_SELECTOR = '[data-pane=conversation], [class*=centerCol]';
17
15
  const SESSION_ROW_SELECTOR = '[class*="sessionRow"], [class*="projectRow"], [class*="searchResultRow"], [class*="newSession"]';
18
16
 
17
+ const BACK_ICON = '<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 3.5 5.5 8l4.5 4.5"/></svg>';
19
18
  const ICON_TIMER = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>';
20
19
  const ICON_PLAY = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 21"></polygon></svg>';
21
20
  const ICON_PAUSE = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>';
@@ -26,12 +25,25 @@ window.__ModuleLoader__.load({
26
25
  const ICON_ACTIVITY = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>';
27
26
 
28
27
  const STYLES = `
29
- html[${ACTIVE_ATTR}] [data-dsh-cron-view] { display: flex !important; }
30
- html[${ACTIVE_ATTR}] [data-pane=conversation]>:not([data-dsh-cron-view]),
31
- html[${ACTIVE_ATTR}] [class*=centerCol]>:not([data-dsh-cron-view]) { display: none !important; }
32
-
33
- .dsh-cron-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; background: var(--dsw-alias-bg-layer-2, #171717); color: var(--dsw-alias-label-primary, #ededed); overflow-y: auto; padding: 40px 48px; z-index: 100; }
28
+ [data-pane=conversation],[class*=centerCol]{position:relative;}
29
+ [data-dsh-cron-view]{z-index:60;background:var(--dsw-alias-bg-base,#171717);display:none;position:absolute;inset:0;}
30
+ html[${ACTIVE_ATTR}]:not([data-dsh-ssh-active]) [data-dsh-cron-view]{display:block !important;}
31
+ html[${ACTIVE_ATTR}]:not([data-dsh-ssh-active]) [data-pane=conversation]>:not([data-dsh-cron-view]),
32
+ html[${ACTIVE_ATTR}]:not([data-dsh-ssh-active]) [class*=centerCol]>:not([data-dsh-cron-view]){display:none !important;}
33
+
34
+ .dsh-cron-entry-clone { align-items: center; gap: 8px; display: flex; }
35
+ .dsh-cron-entry-clone[data-active] { font-weight: 600; }
36
+ .dsh-cron-entry-icon { flex: none; justify-content: center; align-items: center; display: inline-flex; }
37
+ .dsh-cron-entry-label { text-overflow: ellipsis; overflow: hidden; }
38
+ [data-dsh-frame][data-sidebar-collapsed] .dsh-cron-entry-label { display: none; }
39
+
40
+ .dsh-cron-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; background: var(--dsw-alias-bg-base, #171717); color: var(--dsw-alias-label-primary, #ededed); overflow-y: auto; padding: 32px 48px; z-index: 100; box-sizing: border-box; }
34
41
  .dsh-cron-container { max-width: 860px; width: 100%; margin: 0 auto; }
42
+
43
+ .dsh-cron-top-bar { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
44
+ .dsh-cron-back-btn { appearance: none; font: inherit; cursor: pointer; color: var(--dsw-alias-label-secondary, #9ca3af); background: 0 0; border: 1px solid var(--dsw-alias-border-l2, #383838); border-radius: 8px; align-items: center; gap: 6px; padding: 4px 12px; font-size: 13px; display: inline-flex; flex: none; height: 32px; box-sizing: border-box; }
45
+ .dsh-cron-back-btn:hover { color: var(--dsw-alias-label-primary, #ededed); background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,0.06)); }
46
+
35
47
  .dsh-cron-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 24px; }
36
48
  .dsh-cron-title { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 6px; }
37
49
  .dsh-cron-subtitle { font-size: 14px; color: var(--dsw-alias-label-secondary, #9ca3af); }
@@ -41,7 +53,7 @@ window.__ModuleLoader__.load({
41
53
  .dsh-cron-dropdown-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 12px; background: transparent; border: none; border-radius: 8px; color: #ededed; font-size: 13.5px; text-align: left; cursor: pointer; }
42
54
  .dsh-cron-dropdown-item:hover { background: var(--dsw-alias-bg-layer-4, #2a2a2a); }
43
55
  .dsh-cron-search-bar { position: relative; margin-bottom: 20px; }
44
- .dsh-cron-search-input { width: 100%; background: var(--dsw-alias-bg-layer-3, #1f1f1f); border: 1px solid var(--dsw-alias-border-l2, #333); border-radius: 10px; padding: 10px 14px 10px 38px; color: inherit; font-size: 14px; outline: none; }
56
+ .dsh-cron-search-input { width: 100%; background: var(--dsw-alias-bg-layer-3, #1f1f1f); border: 1px solid var(--dsw-alias-border-l2, #333); border-radius: 10px; padding: 10px 14px 10px 38px; color: inherit; font-size: 14px; outline: none; box-sizing: border-box; }
45
57
  .dsh-cron-search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: #666; }
46
58
  .dsh-cron-tabs { display: flex; gap: 8px; margin-bottom: 24px; }
47
59
  .dsh-cron-tab { appearance: none; background: transparent; border: none; padding: 6px 14px; border-radius: 9999px; color: #9ca3af; font-size: 13.5px; cursor: pointer; }
@@ -49,39 +61,45 @@ window.__ModuleLoader__.load({
49
61
  .dsh-cron-task-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 40px; }
50
62
  .dsh-cron-task-item { display: flex; align-items: center; gap: 16px; padding: 14px 18px; background: var(--dsw-alias-bg-layer-3, #1e1e1e); border: 1px solid var(--dsw-alias-border-l2, #2e2e2e); border-radius: 12px; }
51
63
  .dsh-cron-task-item:hover { border-color: #444; }
52
- .dsh-cron-task-status-btn { width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--dsw-alias-bg-layer-4, #2a2a2a); color: #9ca3af; border: 1px solid #333; cursor: pointer; flex-shrink: 0; }
53
- .dsh-cron-task-status-btn[data-active="true"] { color: #10b981; border-color: rgba(16,185,129,0.3); }
64
+ .dsh-cron-task-status-btn { background: none; border: 1px solid #444; border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; color: #888; cursor: pointer; flex-shrink: 0; }
65
+ .dsh-cron-task-status-btn[data-active="true"] { color: #10b981; border-color: #10b981; }
54
66
  .dsh-cron-task-info { flex: 1; min-width: 0; }
55
- .dsh-cron-task-title { font-size: 14.5px; font-weight: 500; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
56
- .dsh-cron-task-sched { font-size: 12.5px; color: #9ca3af; }
57
- .dsh-cron-task-actions { display: flex; align-items: center; gap: 8px; }
58
- .dsh-cron-icon-action { appearance: none; background: transparent; border: 1px solid transparent; border-radius: 8px; padding: 6px 10px; color: #9ca3af; font-size: 12px; cursor: pointer; }
59
- .dsh-cron-icon-action:hover { background: #2a2a2a; color: #fff; }
60
- .dsh-cron-rec-section { margin-top: 32px; }
61
- .dsh-cron-rec-title { font-size: 15px; font-weight: 600; margin-bottom: 16px; }
62
- .dsh-cron-rec-list { display: flex; flex-direction: column; gap: 12px; }
63
- .dsh-cron-rec-item { display: flex; align-items: flex-start; gap: 14px; padding: 14px 18px; background: var(--dsw-alias-bg-layer-3, #1e1e1e); border: 1px solid #2e2e2e; border-radius: 12px; cursor: pointer; }
64
- .dsh-cron-rec-item:hover { border-color: #444; background: #232323; }
65
- .dsh-cron-rec-item-title { font-size: 14px; font-weight: 500; margin-bottom: 4px; }
66
- .dsh-cron-rec-item-sched { font-size: 12.5px; color: #9ca3af; margin-left: 6px; font-weight: normal; }
67
- .dsh-cron-rec-item-desc { font-size: 13px; color: #888; line-height: 1.4; }
68
- .dsh-cron-modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; z-index: 500; }
69
- .dsh-cron-modal { width: 480px; background: var(--dsw-alias-bg-layer-3, #212121); border: 1px solid #383838; border-radius: 14px; padding: 24px; box-shadow: 0 20px 40px rgba(0,0,0,0.6); }
70
- .dsh-cron-modal-title { font-size: 18px; font-weight: 600; margin-bottom: 16px; }
71
- .dsh-cron-field { margin-bottom: 14px; }
72
- .dsh-cron-label { display: block; font-size: 12.5px; color: #aaa; margin-bottom: 6px; }
73
- .dsh-cron-input, .dsh-cron-textarea { width: 100%; background: #2a2a2a; border: 1px solid #383838; border-radius: 8px; padding: 8px 12px; color: inherit; font-size: 13.5px; outline: none; }
74
- .dsh-cron-textarea { height: 80px; resize: vertical; }
67
+ .dsh-cron-task-title { font-size: 15px; font-weight: 500; margin-bottom: 3px; }
68
+ .dsh-cron-task-sched { font-size: 13px; color: #9ca3af; }
69
+ .dsh-cron-task-actions { display: flex; gap: 8px; }
70
+ .dsh-cron-icon-btn { background: transparent; border: 1px solid #333; border-radius: 8px; padding: 6px 12px; font-size: 12.5px; color: #aaa; cursor: pointer; }
71
+ .dsh-cron-icon-btn:hover { background: #2a2a2a; color: #fff; }
72
+ .dsh-cron-recs-title { font-size: 17px; font-weight: 600; margin-bottom: 14px; }
73
+ .dsh-cron-recs-list { display: flex; flex-direction: column; gap: 10px; }
74
+ .dsh-cron-rec-card { display: flex; align-items: center; gap: 16px; padding: 16px 20px; background: var(--dsw-alias-bg-layer-3, #1c1c1c); border: 1px solid var(--dsw-alias-border-l1, #282828); border-radius: 12px; cursor: pointer; transition: background 0.15s; }
75
+ .dsh-cron-rec-card:hover { background: var(--dsw-alias-bg-layer-4, #242424); border-color: #383838; }
76
+ .dsh-cron-rec-icon { width: 36px; height: 36px; border-radius: 10px; background: rgba(255,255,255,0.03); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
77
+ .dsh-cron-rec-content { flex: 1; min-width: 0; }
78
+ .dsh-cron-rec-title { font-size: 14.5px; font-weight: 500; margin-bottom: 4px; }
79
+ .dsh-cron-rec-time { font-size: 13px; color: #9ca3af; font-weight: normal; margin-left: 8px; }
80
+ .dsh-cron-rec-desc { font-size: 13px; color: #71717a; }
81
+
82
+ .dsh-cron-modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.7); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1000; }
83
+ .dsh-cron-modal { background: var(--dsw-alias-bg-layer-2, #1f1f1f); border: 1px solid var(--dsw-alias-border-l2, #333); border-radius: 16px; width: 100%; max-width: 520px; padding: 24px; box-shadow: 0 20px 40px rgba(0,0,0,0.6); }
84
+ .dsh-cron-modal-title { font-size: 18px; font-weight: 600; margin-bottom: 18px; }
85
+ .dsh-cron-form-group { margin-bottom: 16px; }
86
+ .dsh-cron-form-group label { display: block; font-size: 13px; color: #aaa; margin-bottom: 6px; }
87
+ .dsh-cron-form-group input, .dsh-cron-form-group textarea { width: 100%; background: #141414; border: 1px solid #333; border-radius: 8px; padding: 9px 12px; color: #fff; font-size: 13.5px; outline: none; box-sizing: border-box; }
88
+ .dsh-cron-form-group textarea { min-height: 80px; resize: vertical; }
75
89
  .dsh-cron-modal-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }
76
90
  .dsh-cron-btn-primary { background: #ededed; color: #111; border: none; border-radius: 8px; padding: 7px 16px; font-size: 13.5px; font-weight: 500; cursor: pointer; }
77
91
  .dsh-cron-btn-secondary { background: transparent; color: #999; border: 1px solid #383838; border-radius: 8px; padding: 7px 16px; font-size: 13.5px; cursor: pointer; }
78
92
  `;
79
93
 
80
- if (typeof document !== 'undefined' && !document.getElementById('dsh-cron-styles')) {
81
- const styleEl = document.createElement('style');
82
- styleEl.id = 'dsh-cron-styles';
83
- styleEl.textContent = STYLES;
84
- document.head.appendChild(styleEl);
94
+ function ensureStyles() {
95
+ if (typeof document === 'undefined') return;
96
+ let el = document.getElementById('dsh-cron-styles');
97
+ if (!el) {
98
+ el = document.createElement('style');
99
+ el.id = 'dsh-cron-styles';
100
+ document.head.appendChild(el);
101
+ }
102
+ el.textContent = STYLES;
85
103
  }
86
104
 
87
105
  function createToggle() {
@@ -89,14 +107,24 @@ window.__ModuleLoader__.load({
89
107
  const listeners = new Set();
90
108
  return {
91
109
  isOpen: () => open,
92
- set: (v) => { open = !!v; for (const fn of listeners) fn(open); },
93
- toggle: () => { open = !open; for (const fn of listeners) fn(open); },
94
- subscribe: (fn) => { listeners.add(fn); return () => listeners.delete(fn); }
110
+ set: (v) => {
111
+ if (open === v) return;
112
+ open = !!v;
113
+ for (const fn of listeners) fn(open);
114
+ },
115
+ toggle: () => {
116
+ open = !open;
117
+ for (const fn of listeners) fn(open);
118
+ },
119
+ subscribe: (fn) => {
120
+ listeners.add(fn);
121
+ return () => listeners.delete(fn);
122
+ }
95
123
  };
96
124
  }
97
125
 
98
126
  function CronScreen(props) {
99
- const { toggle } = props;
127
+ const { toggle, onClose } = props;
100
128
  const [tab, setTab] = React.useState('all');
101
129
  const [query, setQuery] = React.useState('');
102
130
  const [tasks, setTasks] = React.useState([]);
@@ -107,6 +135,17 @@ window.__ModuleLoader__.load({
107
135
  const [formSchedule, setFormSchedule] = React.useState('');
108
136
  const [formPrompt, setFormPrompt] = React.useState('');
109
137
 
138
+ React.useEffect(() => {
139
+ const onKey = (e) => {
140
+ if (e.key !== 'Escape') return;
141
+ if (modalOpen) { setModalOpen(false); return; }
142
+ if (dropdownOpen) { setDropdownOpen(false); return; }
143
+ if (onClose) onClose();
144
+ };
145
+ document.addEventListener('keydown', onKey);
146
+ return () => document.removeEventListener('keydown', onKey);
147
+ }, [modalOpen, dropdownOpen, onClose]);
148
+
110
149
  const fetchTasks = async () => {
111
150
  try {
112
151
  const res = await fetch('/dsh-cron/tasks?status=' + tab + '&query=' + encodeURIComponent(query));
@@ -138,7 +177,7 @@ window.__ModuleLoader__.load({
138
177
  const handleDelete = async (id) => {
139
178
  if (!confirm('Удалить эту задачу?')) return;
140
179
  try {
141
- await fetch('/dsh-cron/action/' + id + '/delete', { method: 'DELETE' });
180
+ await fetch('/dsh-cron/action/' + id + '/delete', { method: 'POST' });
142
181
  fetchTasks();
143
182
  } catch (err) {}
144
183
  };
@@ -160,11 +199,14 @@ window.__ModuleLoader__.load({
160
199
  const handleSave = async (e) => {
161
200
  e.preventDefault();
162
201
  try {
163
- const payload = { title: formTitle, schedule: formSchedule, prompt: formPrompt };
164
202
  const res = await fetch('/dsh-cron/tasks', {
165
203
  method: 'POST',
166
204
  headers: { 'Content-Type': 'application/json' },
167
- body: JSON.stringify(payload)
205
+ body: JSON.stringify({
206
+ title: formTitle,
207
+ schedule: formSchedule,
208
+ prompt: formPrompt
209
+ })
168
210
  });
169
211
  const data = await res.json();
170
212
  if (!data.ok) { alert(data.error || 'Ошибка'); return; }
@@ -175,7 +217,8 @@ window.__ModuleLoader__.load({
175
217
 
176
218
  const handleCreateWithDSH = () => {
177
219
  setDropdownOpen(false);
178
- toggle.set(false);
220
+ if (onClose) onClose();
221
+ else toggle.set(false);
179
222
  setTimeout(() => {
180
223
  const textarea = document.querySelector('textarea[placeholder*="message"], textarea[class*="prompt"]');
181
224
  if (textarea) {
@@ -187,6 +230,20 @@ window.__ModuleLoader__.load({
187
230
 
188
231
  return React.createElement('div', { className: 'dsh-cron-overlay' },
189
232
  React.createElement('div', { className: 'dsh-cron-container' },
233
+ React.createElement('div', { className: 'dsh-cron-top-bar' },
234
+ React.createElement('button', {
235
+ type: 'button',
236
+ className: 'dsh-cron-back-btn',
237
+ title: 'Назад к чату',
238
+ onClick: () => { if (onClose) onClose(); else toggle.set(false); }
239
+ },
240
+ React.createElement('span', {
241
+ style: { display: 'flex', alignItems: 'center' },
242
+ dangerouslySetInnerHTML: { __html: BACK_ICON }
243
+ }),
244
+ React.createElement('span', null, 'Назад к чату')
245
+ )
246
+ ),
190
247
  React.createElement('div', { className: 'dsh-cron-header' },
191
248
  React.createElement('div', null,
192
249
  React.createElement('div', { className: 'dsh-cron-title' }, 'Запланированные задачи'),
@@ -239,49 +296,78 @@ window.__ModuleLoader__.load({
239
296
  React.createElement('div', { className: 'dsh-cron-task-sched' }, task.scheduleText || task.schedule)
240
297
  ),
241
298
  React.createElement('div', { className: 'dsh-cron-task-actions' },
242
- React.createElement('button', { className: 'dsh-cron-icon-action', onClick: () => handleRunNow(task.id) }, 'Запустить сейчас'),
243
- React.createElement('button', { className: 'dsh-cron-icon-action', onClick: () => handleDelete(task.id) }, 'Удалить')
299
+ React.createElement('button', { className: 'dsh-cron-icon-btn', onClick: () => handleRunNow(task.id) }, 'Запустить'),
300
+ React.createElement('button', { className: 'dsh-cron-icon-btn', onClick: () => handleDelete(task.id) }, 'Удалить')
244
301
  )
245
302
  )
246
303
  )
247
304
  ),
248
- React.createElement('div', { className: 'dsh-cron-rec-section' },
249
- React.createElement('div', { className: 'dsh-cron-rec-title' }, 'Рекомендации'),
250
- React.createElement('div', { className: 'dsh-cron-rec-list' },
251
- recs.map((rec) =>
252
- React.createElement('div', { key: rec.id, className: 'dsh-cron-rec-item', onClick: () => openCreateModal(rec) },
253
- React.createElement('div', {
254
- className: 'dsh-cron-rec-icon',
255
- dangerouslySetInnerHTML: { __html: rec.icon === 'bell' ? ICON_BELL : rec.icon === 'clipboard' ? ICON_CLIPBOARD : ICON_ACTIVITY }
256
- }),
257
- React.createElement('div', null,
258
- React.createElement('div', { className: 'dsh-cron-rec-item-title' }, rec.title, React.createElement('span', { className: 'dsh-cron-rec-item-sched' }, rec.scheduleText)),
259
- React.createElement('div', { className: 'dsh-cron-rec-item-desc' }, rec.description)
260
- )
305
+ React.createElement('div', { className: 'dsh-cron-recs-title' }, 'Рекомендации'),
306
+ React.createElement('div', { className: 'dsh-cron-recs-list' },
307
+ recs.map((rec) =>
308
+ React.createElement('div', {
309
+ key: rec.id,
310
+ className: 'dsh-cron-rec-card',
311
+ onClick: () => openCreateModal(rec)
312
+ },
313
+ React.createElement('div', {
314
+ className: 'dsh-cron-rec-icon',
315
+ dangerouslySetInnerHTML: {
316
+ __html: rec.icon === 'bell' ? ICON_BELL : rec.icon === 'clipboard' ? ICON_CLIPBOARD : ICON_ACTIVITY
317
+ }
318
+ }),
319
+ React.createElement('div', { className: 'dsh-cron-rec-content' },
320
+ React.createElement('div', { className: 'dsh-cron-rec-title' },
321
+ rec.title,
322
+ React.createElement('span', { className: 'dsh-cron-rec-time' }, rec.scheduleText)
323
+ ),
324
+ React.createElement('div', { className: 'dsh-cron-rec-desc' }, rec.description)
261
325
  )
262
326
  )
263
327
  )
264
328
  )
265
329
  ),
266
- modalOpen && React.createElement('div', { className: 'dsh-cron-modal-backdrop', onClick: () => setModalOpen(false) },
330
+ modalOpen && React.createElement('div', { className: 'dsh-cron-modal-overlay', onClick: () => setModalOpen(false) },
267
331
  React.createElement('div', { className: 'dsh-cron-modal', onClick: (e) => e.stopPropagation() },
268
- React.createElement('div', { className: 'dsh-cron-modal-title' }, 'Настройка задачи вручную'),
332
+ React.createElement('div', { className: 'dsh-cron-modal-title' }, 'Настройка запланированной задачи'),
269
333
  React.createElement('form', { onSubmit: handleSave },
270
- React.createElement('div', { className: 'dsh-cron-field' },
271
- React.createElement('label', { className: 'dsh-cron-label' }, 'Название задачи'),
272
- React.createElement('input', { className: 'dsh-cron-input', required: true, value: formTitle, onChange: (e) => setFormTitle(e.target.value) })
334
+ React.createElement('div', { className: 'dsh-cron-form-group' },
335
+ React.createElement('label', null, 'Название задачи'),
336
+ React.createElement('input', {
337
+ required: true,
338
+ value: formTitle,
339
+ placeholder: 'Например: Ежедневный утренний отчет',
340
+ onChange: (e) => setFormTitle(e.target.value)
341
+ })
273
342
  ),
274
- React.createElement('div', { className: 'dsh-cron-field' },
275
- React.createElement('label', { className: 'dsh-cron-label' }, 'Расписание (cron или interval)'),
276
- React.createElement('input', { className: 'dsh-cron-input', required: true, value: formSchedule, onChange: (e) => setFormSchedule(e.target.value) })
343
+ React.createElement('div', { className: 'dsh-cron-form-group' },
344
+ React.createElement('label', null, 'Расписание (cron или "every 30m")'),
345
+ React.createElement('input', {
346
+ required: true,
347
+ value: formSchedule,
348
+ placeholder: '0 9 * * 1-5 или every 2h',
349
+ onChange: (e) => setFormSchedule(e.target.value)
350
+ })
277
351
  ),
278
- React.createElement('div', { className: 'dsh-cron-field' },
279
- React.createElement('label', { className: 'dsh-cron-label' }, 'Инструкция для агента (промпт)'),
280
- React.createElement('textarea', { className: 'dsh-cron-textarea', required: true, value: formPrompt, onChange: (e) => setFormPrompt(e.target.value) })
352
+ React.createElement('div', { className: 'dsh-cron-form-group' },
353
+ React.createElement('label', null, 'Промпт / Инструкция для агента'),
354
+ React.createElement('textarea', {
355
+ required: true,
356
+ value: formPrompt,
357
+ placeholder: 'Опишите, что именно агент должен сделать...',
358
+ onChange: (e) => setFormPrompt(e.target.value)
359
+ })
281
360
  ),
282
361
  React.createElement('div', { className: 'dsh-cron-modal-foot' },
283
- React.createElement('button', { type: 'button', className: 'dsh-cron-btn-secondary', onClick: () => setModalOpen(false) }, 'Отмена'),
284
- React.createElement('button', { type: 'submit', className: 'dsh-cron-btn-primary' }, 'Сохранить')
362
+ React.createElement('button', {
363
+ type: 'button',
364
+ className: 'dsh-cron-btn-secondary',
365
+ onClick: () => setModalOpen(false)
366
+ }, 'Отмена'),
367
+ React.createElement('button', {
368
+ type: 'submit',
369
+ className: 'dsh-cron-btn-primary'
370
+ }, 'Сохранить задачу')
285
371
  )
286
372
  )
287
373
  )
@@ -290,9 +376,21 @@ window.__ModuleLoader__.load({
290
376
  }
291
377
 
292
378
  function nativeButton() {
293
- const nodes = document.querySelectorAll('button[class*="newSession"]');
294
- for (const node of nodes) {
295
- if (String(node.className).indexOf('newSessionLabel') === -1) return node;
379
+ const candidates = [
380
+ 'nav button[class*="sidebar-entry"]',
381
+ 'aside button[class*="sidebar-entry"]',
382
+ '[class*="sidebar"] button[class*="sidebar-entry"]',
383
+ 'nav button',
384
+ 'aside button',
385
+ '[class*="sidebar"] button'
386
+ ];
387
+ for (const sel of candidates) {
388
+ const found = document.querySelectorAll(sel);
389
+ for (const el of found) {
390
+ if (el.hasAttribute(ENTRY_ATTR)) continue;
391
+ if (el.dataset && el.dataset.dshPart === 'sidebar-entry') continue;
392
+ if (el.offsetWidth > 0 || el.offsetHeight > 0) return el;
393
+ }
296
394
  }
297
395
  return undefined;
298
396
  }
@@ -309,7 +407,6 @@ window.__ModuleLoader__.load({
309
407
 
310
408
  const icon = document.createElement('span');
311
409
  icon.className = 'dsh-cron-entry-icon';
312
- icon.style.marginRight = '8px';
313
410
  icon.innerHTML = ICON_TIMER;
314
411
  entry.appendChild(icon);
315
412
 
@@ -329,12 +426,12 @@ window.__ModuleLoader__.load({
329
426
  function placeEntry(target, entry) {
330
427
  let anchor = target;
331
428
  let next = target.nextElementSibling;
332
- while (next !== null && next.tagName === 'BUTTON' && String(next.className).indexOf('sidebar-entry') >= 0) {
429
+ while (next !== null && next.tagName === 'BUTTON'
430
+ && (String(next.className).indexOf('sidebar-entry') >= 0 || next.hasAttribute('data-dsh-part'))) {
333
431
  anchor = next;
334
432
  next = next.nextElementSibling;
335
433
  }
336
434
  anchor.insertAdjacentElement('afterend', entry);
337
- return true;
338
435
  }
339
436
 
340
437
  function mountSidebarEntry(toggle, label) {
@@ -375,7 +472,7 @@ window.__ModuleLoader__.load({
375
472
  let container;
376
473
 
377
474
  const ensure = () => {
378
- if (container !== undefined) return;
475
+ if (container !== undefined && container.isConnected) return;
379
476
  const column = document.querySelector(COLUMN_SELECTOR);
380
477
  if (column === null) return;
381
478
  container = document.createElement('div');
@@ -426,6 +523,7 @@ window.__ModuleLoader__.load({
426
523
  }
427
524
 
428
525
  function apply(ctx) {
526
+ ensureStyles();
429
527
  const toggle = createToggle();
430
528
  ctx.effect(() => {
431
529
  const off = [
@@ -439,4 +537,11 @@ window.__ModuleLoader__.load({
439
537
  module.exports = { apply, inject: ['slots', 'locale', 'settingsScope'] };
440
538
  return module.exports;
441
539
  }
442
- });
540
+
541
+ if (typeof window !== 'undefined' && window.__ModuleLoader__) {
542
+ window.__ModuleLoader__.load({
543
+ id: '@goodandready/dsh-cron',
544
+ factory: dshCronModule
545
+ });
546
+ }
547
+ })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-cron",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Scheduled cron tasks, background automation and agent execution for DeepSeek Harness.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",