@syncended/dsh-automations 0.1.2 → 0.2.1
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 +2 -2
- package/docs/architecture.md +5 -1
- package/lib/client.js +287 -7
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A DeepSeek Harness plugin for durable, configurable cron jobs. Each occurrence s
|
|
|
8
8
|
|
|
9
9
|
- Standard five-field cron expressions with `UTC` or IANA timezones.
|
|
10
10
|
- Per-job project directory, provider/model, reasoning effort, agent preset, permission preset, and timeout.
|
|
11
|
-
- Enable/disable, Run now, edit, delete, cancel, and recent run history
|
|
11
|
+
- Enable/disable, Run now, edit, delete, cancel, and recent run history from the main **Automations** sidebar action or **Settings → Automations**.
|
|
12
12
|
- Overlap policies:
|
|
13
13
|
- `skip` — record and skip an occurrence while the job has queued/running work.
|
|
14
14
|
- `queue` — serialize occurrences for the same job.
|
|
@@ -42,7 +42,7 @@ pnpm build
|
|
|
42
42
|
dsh plugin --profile web add .
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
The package declares a DSH bundle, so `dsh plugin` appends it to the Web profile automatically. Restart the running Web Harness after the initial install, then refresh the page. Open **Settings → Automations**.
|
|
45
|
+
The package declares a DSH bundle, so `dsh plugin` appends it to the Web profile automatically. Restart the running Web Harness after the initial install, then refresh the page. Open **Automations** from the main sidebar, or use **Settings → Automations**.
|
|
46
46
|
|
|
47
47
|
To remove it:
|
|
48
48
|
|
package/docs/architecture.md
CHANGED
|
@@ -15,7 +15,7 @@ Non-goals for the first release:
|
|
|
15
15
|
## Components
|
|
16
16
|
|
|
17
17
|
```text
|
|
18
|
-
Settings UI / HTTP API
|
|
18
|
+
Sidebar / Settings UI / HTTP API
|
|
19
19
|
│
|
|
20
20
|
▼
|
|
21
21
|
AutomationService ─── ProjectPolicy
|
|
@@ -28,6 +28,10 @@ Settings UI / HTTP API
|
|
|
28
28
|
└── HarnessAgentExecutor (MVP)
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
### Browser surfaces
|
|
32
|
+
|
|
33
|
+
The same automation page is available through two additive DSH extension points: `settings.section` keeps the configuration page inside Settings, while `sidebar.footer.action` opens a frame-wide `shell.overlay`. A small client-only disclosure store coordinates the sidebar trigger and overlay; neither surface owns scheduler state, and both read the same package HTTP API.
|
|
34
|
+
|
|
31
35
|
### AutomationService
|
|
32
36
|
|
|
33
37
|
Cordis service `ctx.automations`. It owns input validation, canonical project authorization, metadata discovery, the Web route, and the public executor-registration seam.
|
package/lib/client.js
CHANGED
|
@@ -12,7 +12,7 @@ window.__ModuleLoader__.load({
|
|
|
12
12
|
// x-dsh-automation-client fence header plus an application/json body.
|
|
13
13
|
const React = require("react");
|
|
14
14
|
const h = React.createElement;
|
|
15
|
-
const { useCallback, useEffect, useRef, useState } = React;
|
|
15
|
+
const { useCallback, useEffect, useId, useRef, useState, useSyncExternalStore } = React;
|
|
16
16
|
const inject = ["slots"];
|
|
17
17
|
|
|
18
18
|
const API_PREFIX = "/api/automations";
|
|
@@ -66,6 +66,31 @@ window.__ModuleLoader__.load({
|
|
|
66
66
|
return error instanceof Error ? error.message : String(error);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
const CJK_LABEL_PATTERN = /[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\uac00-\ud7af]/;
|
|
70
|
+
const BUILTIN_AGENT_PRESET_LABELS = {
|
|
71
|
+
standard: "Standard mode",
|
|
72
|
+
code: "PTC mode",
|
|
73
|
+
minimal: "Minimal mode",
|
|
74
|
+
cordis: "Creator mode",
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
function humanizePresetId(id) {
|
|
78
|
+
return id
|
|
79
|
+
.split(/[-_]+/)
|
|
80
|
+
.filter(Boolean)
|
|
81
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
82
|
+
.join(" ");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function agentPresetDisplayLabel(preset) {
|
|
86
|
+
const id = preset && typeof preset.id === "string" ? preset.id.trim() : "";
|
|
87
|
+
const name = preset && typeof preset.name === "string" ? preset.name.trim() : "";
|
|
88
|
+
if (id === "") return name !== "" && !CJK_LABEL_PATTERN.test(name) ? name : "Unknown preset";
|
|
89
|
+
if (name !== "" && name !== id && !CJK_LABEL_PATTERN.test(name)) return name + " (" + id + ")";
|
|
90
|
+
const readableId = BUILTIN_AGENT_PRESET_LABELS[id] || humanizePresetId(id) || id;
|
|
91
|
+
return readableId === id ? id : readableId + " (" + id + ")";
|
|
92
|
+
}
|
|
93
|
+
|
|
69
94
|
function browserTimezone() {
|
|
70
95
|
return BROWSER_TIMEZONE;
|
|
71
96
|
}
|
|
@@ -443,7 +468,7 @@ window.__ModuleLoader__.load({
|
|
|
443
468
|
h(
|
|
444
469
|
"option",
|
|
445
470
|
{ key: preset.id, value: preset.id },
|
|
446
|
-
preset
|
|
471
|
+
agentPresetDisplayLabel(preset) + (preset.broken ? " (broken: " + preset.broken + ")" : ""),
|
|
447
472
|
),
|
|
448
473
|
),
|
|
449
474
|
),
|
|
@@ -559,7 +584,10 @@ window.__ModuleLoader__.load({
|
|
|
559
584
|
? meta.agentPresets.find((preset) => preset.id === job.execution.agentPreset)
|
|
560
585
|
: undefined;
|
|
561
586
|
const presetLabel = job.execution.agentPreset
|
|
562
|
-
? (agentPreset
|
|
587
|
+
? agentPresetDisplayLabel(agentPreset || {
|
|
588
|
+
id: job.execution.agentPreset,
|
|
589
|
+
name: job.execution.agentPreset,
|
|
590
|
+
})
|
|
563
591
|
: "";
|
|
564
592
|
|
|
565
593
|
return h(
|
|
@@ -1139,7 +1167,242 @@ window.__ModuleLoader__.load({
|
|
|
1139
1167
|
);
|
|
1140
1168
|
}
|
|
1141
1169
|
|
|
1170
|
+
function createDisclosureStore() {
|
|
1171
|
+
let open = false;
|
|
1172
|
+
let disposed = false;
|
|
1173
|
+
const listeners = new Set();
|
|
1174
|
+
const publish = (next) => {
|
|
1175
|
+
if (disposed || open === next) return;
|
|
1176
|
+
open = next;
|
|
1177
|
+
for (const listener of Array.from(listeners)) listener();
|
|
1178
|
+
};
|
|
1179
|
+
return {
|
|
1180
|
+
getSnapshot: () => open,
|
|
1181
|
+
subscribe: (listener) => {
|
|
1182
|
+
if (disposed) return () => {};
|
|
1183
|
+
listeners.add(listener);
|
|
1184
|
+
return () => listeners.delete(listener);
|
|
1185
|
+
},
|
|
1186
|
+
open: () => publish(true),
|
|
1187
|
+
close: () => publish(false),
|
|
1188
|
+
toggle: () => publish(!open),
|
|
1189
|
+
dispose: () => {
|
|
1190
|
+
disposed = true;
|
|
1191
|
+
open = false;
|
|
1192
|
+
listeners.clear();
|
|
1193
|
+
},
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
const MODAL_FOCUS_SELECTOR = [
|
|
1198
|
+
"a[href]",
|
|
1199
|
+
"button:not([disabled])",
|
|
1200
|
+
"input:not([disabled])",
|
|
1201
|
+
"select:not([disabled])",
|
|
1202
|
+
"textarea:not([disabled])",
|
|
1203
|
+
"[contenteditable=\"true\"]",
|
|
1204
|
+
"[tabindex]:not([tabindex=\"-1\"])",
|
|
1205
|
+
].join(",");
|
|
1206
|
+
|
|
1207
|
+
function modalFocusables(panel) {
|
|
1208
|
+
if (!panel) return [];
|
|
1209
|
+
return Array.from(panel.querySelectorAll(MODAL_FOCUS_SELECTOR)).filter((element) =>
|
|
1210
|
+
!element.hasAttribute("hidden") &&
|
|
1211
|
+
element.getAttribute("aria-hidden") !== "true" &&
|
|
1212
|
+
element.getClientRects().length > 0,
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
function trapModalTab(event, panel) {
|
|
1217
|
+
if (
|
|
1218
|
+
event.key !== "Tab" ||
|
|
1219
|
+
event.defaultPrevented ||
|
|
1220
|
+
event.altKey ||
|
|
1221
|
+
event.ctrlKey ||
|
|
1222
|
+
event.metaKey
|
|
1223
|
+
) return;
|
|
1224
|
+
const focusables = modalFocusables(panel);
|
|
1225
|
+
if (focusables.length === 0) {
|
|
1226
|
+
event.preventDefault();
|
|
1227
|
+
panel?.focus();
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
const first = focusables[0];
|
|
1231
|
+
const last = focusables[focusables.length - 1];
|
|
1232
|
+
const active = panel.ownerDocument.activeElement;
|
|
1233
|
+
if (event.shiftKey) {
|
|
1234
|
+
if (active === first || !panel.contains(active)) {
|
|
1235
|
+
event.preventDefault();
|
|
1236
|
+
last.focus();
|
|
1237
|
+
}
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (active === last || !panel.contains(active)) {
|
|
1241
|
+
event.preventDefault();
|
|
1242
|
+
first.focus();
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
function AutomationGlyph({ size = 18 }) {
|
|
1247
|
+
return h(
|
|
1248
|
+
"svg",
|
|
1249
|
+
{
|
|
1250
|
+
width: size,
|
|
1251
|
+
height: size,
|
|
1252
|
+
viewBox: "0 0 24 24",
|
|
1253
|
+
fill: "none",
|
|
1254
|
+
stroke: "currentColor",
|
|
1255
|
+
strokeWidth: "1.7",
|
|
1256
|
+
strokeLinecap: "round",
|
|
1257
|
+
strokeLinejoin: "round",
|
|
1258
|
+
"aria-hidden": "true",
|
|
1259
|
+
focusable: "false",
|
|
1260
|
+
},
|
|
1261
|
+
h("rect", { x: "3.5", y: "5.5", width: "17", height: "15", rx: "3" }),
|
|
1262
|
+
h("path", { d: "M8 3.5v4M16 3.5v4M3.5 10h17" }),
|
|
1263
|
+
h("circle", { cx: "12", cy: "15.25", r: "2.75" }),
|
|
1264
|
+
h("path", { d: "M12 13.8v1.65l1.15.7" }),
|
|
1265
|
+
);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
function CloseGlyph() {
|
|
1269
|
+
return h(
|
|
1270
|
+
"svg",
|
|
1271
|
+
{
|
|
1272
|
+
width: "16",
|
|
1273
|
+
height: "16",
|
|
1274
|
+
viewBox: "0 0 16 16",
|
|
1275
|
+
fill: "none",
|
|
1276
|
+
stroke: "currentColor",
|
|
1277
|
+
strokeWidth: "1.5",
|
|
1278
|
+
strokeLinecap: "round",
|
|
1279
|
+
"aria-hidden": "true",
|
|
1280
|
+
focusable: "false",
|
|
1281
|
+
},
|
|
1282
|
+
h("path", { d: "M3.5 3.5l9 9M12.5 3.5l-9 9" }),
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
function AutomationsSidebarAction({ wide, disclosure }) {
|
|
1287
|
+
const open = useSyncExternalStore(
|
|
1288
|
+
disclosure.subscribe,
|
|
1289
|
+
disclosure.getSnapshot,
|
|
1290
|
+
disclosure.getSnapshot,
|
|
1291
|
+
);
|
|
1292
|
+
const triggerRef = useRef(null);
|
|
1293
|
+
const previousOpenRef = useRef(open);
|
|
1294
|
+
|
|
1295
|
+
useEffect(() => {
|
|
1296
|
+
const previous = previousOpenRef.current;
|
|
1297
|
+
previousOpenRef.current = open;
|
|
1298
|
+
if (!previous || open) return undefined;
|
|
1299
|
+
const frame = window.requestAnimationFrame(() => triggerRef.current?.focus());
|
|
1300
|
+
return () => window.cancelAnimationFrame(frame);
|
|
1301
|
+
}, [open]);
|
|
1302
|
+
|
|
1303
|
+
return h(
|
|
1304
|
+
"div",
|
|
1305
|
+
{ className: "dsh-auto-sidebar-action" + (wide ? "" : " dsh-auto-sidebar-action-rail") },
|
|
1306
|
+
h(
|
|
1307
|
+
"button",
|
|
1308
|
+
{
|
|
1309
|
+
ref: triggerRef,
|
|
1310
|
+
type: "button",
|
|
1311
|
+
className: "dsh-auto-sidebar-trigger",
|
|
1312
|
+
title: wide ? undefined : "Automations",
|
|
1313
|
+
"aria-label": "Automations",
|
|
1314
|
+
"aria-haspopup": "dialog",
|
|
1315
|
+
"aria-expanded": open,
|
|
1316
|
+
"data-active": open ? "true" : undefined,
|
|
1317
|
+
"data-dsh-automations-trigger": "true",
|
|
1318
|
+
onClick: disclosure.toggle,
|
|
1319
|
+
},
|
|
1320
|
+
h(AutomationGlyph, { size: wide ? 16 : 18 }),
|
|
1321
|
+
wide ? h("span", { className: "dsh-auto-sidebar-label" }, "Automations") : null,
|
|
1322
|
+
),
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
function AutomationsOverlay({ disclosure }) {
|
|
1327
|
+
const open = useSyncExternalStore(
|
|
1328
|
+
disclosure.subscribe,
|
|
1329
|
+
disclosure.getSnapshot,
|
|
1330
|
+
disclosure.getSnapshot,
|
|
1331
|
+
);
|
|
1332
|
+
const closeRef = useRef(null);
|
|
1333
|
+
const panelRef = useRef(null);
|
|
1334
|
+
const titleId = useId();
|
|
1335
|
+
|
|
1336
|
+
useEffect(() => {
|
|
1337
|
+
if (!open) return undefined;
|
|
1338
|
+
const frame = window.requestAnimationFrame(() => closeRef.current?.focus());
|
|
1339
|
+
return () => window.cancelAnimationFrame(frame);
|
|
1340
|
+
}, [open]);
|
|
1341
|
+
|
|
1342
|
+
if (!open) return null;
|
|
1343
|
+
return h(
|
|
1344
|
+
"div",
|
|
1345
|
+
{ className: "dsh-auto-overlay", "data-dsh-automations-overlay": "true" },
|
|
1346
|
+
h("div", { className: "dsh-auto-overlay-mask", "aria-hidden": "true", onClick: disclosure.close }),
|
|
1347
|
+
h(
|
|
1348
|
+
"section",
|
|
1349
|
+
{
|
|
1350
|
+
ref: panelRef,
|
|
1351
|
+
className: "dsh-auto-overlay-panel",
|
|
1352
|
+
role: "dialog",
|
|
1353
|
+
tabIndex: -1,
|
|
1354
|
+
"aria-modal": "true",
|
|
1355
|
+
"aria-labelledby": titleId,
|
|
1356
|
+
onKeyDownCapture: (event) => {
|
|
1357
|
+
if (event.key === "Escape") {
|
|
1358
|
+
event.preventDefault();
|
|
1359
|
+
disclosure.close();
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1362
|
+
trapModalTab(event, panelRef.current);
|
|
1363
|
+
},
|
|
1364
|
+
},
|
|
1365
|
+
h(
|
|
1366
|
+
"header",
|
|
1367
|
+
{ className: "dsh-auto-overlay-header" },
|
|
1368
|
+
h("span", { id: titleId, className: "dsh-auto-sr-only" }, "Automations"),
|
|
1369
|
+
h(
|
|
1370
|
+
"button",
|
|
1371
|
+
{
|
|
1372
|
+
ref: closeRef,
|
|
1373
|
+
type: "button",
|
|
1374
|
+
className: "dsh-auto-overlay-close",
|
|
1375
|
+
"aria-label": "Close Automations",
|
|
1376
|
+
title: "Close",
|
|
1377
|
+
onClick: disclosure.close,
|
|
1378
|
+
},
|
|
1379
|
+
h(CloseGlyph),
|
|
1380
|
+
),
|
|
1381
|
+
),
|
|
1382
|
+
h("div", { className: "dsh-auto-overlay-body" }, h(AutomationsSection)),
|
|
1383
|
+
),
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1142
1387
|
const STYLE_CSS = [
|
|
1388
|
+
".dsh-auto-sidebar-action{box-sizing:border-box;width:100%;height:42px;flex:none;display:flex;align-items:center;margin:4px 0 0;}",
|
|
1389
|
+
".dsh-auto-sidebar-trigger{box-sizing:border-box;appearance:none;width:calc(100% + 4px);height:42px;margin:0 -2px;padding:0 10px 0 8px;border:0;border-radius:12px;background:transparent;color:var(--dsw-alias-label-primary,#0f1115);display:flex;align-items:center;gap:8px;overflow:hidden;font:14px/22px inherit;cursor:pointer;}",
|
|
1390
|
+
".dsh-auto-sidebar-trigger:hover,.dsh-auto-sidebar-trigger[data-active=\"true\"]{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));}",
|
|
1391
|
+
".dsh-auto-sidebar-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:-2px;}",
|
|
1392
|
+
".dsh-auto-sidebar-trigger svg{flex:none;}",
|
|
1393
|
+
".dsh-auto-sidebar-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
1394
|
+
".dsh-auto-sidebar-action-rail{width:36px;height:36px;margin:0;}",
|
|
1395
|
+
".dsh-auto-sidebar-action-rail .dsh-auto-sidebar-trigger{width:36px;height:36px;margin:0;padding:0;justify-content:center;gap:0;border-radius:50%;}",
|
|
1396
|
+
".dsh-auto-overlay{z-index:1000;pointer-events:auto;position:fixed;inset:0;display:flex;align-items:center;justify-content:center;}",
|
|
1397
|
+
".dsh-auto-overlay-mask{position:absolute;inset:0;background:var(--dsw-alias-bg-mask-1,rgba(0,0,0,.46));backdrop-filter:var(--dsw-mask-blur,blur(2px));}",
|
|
1398
|
+
".dsh-auto-overlay-panel{box-sizing:border-box;z-index:1;position:relative;width:900px;max-width:calc(100vw - 48px);height:min(800px,calc(100vh - 48px));border:0;border-radius:24px;background:var(--dsw-alias-bg-layer-2,#fff);box-shadow:var(--dsw-shadow-lv3,0 18px 60px rgba(0,0,0,.3));color:var(--dsw-alias-label-primary,#0f1115);display:flex;flex-direction:column;overflow:hidden;}",
|
|
1399
|
+
".dsh-auto-overlay-header{box-sizing:border-box;height:52px;flex:none;display:flex;align-items:center;justify-content:flex-end;padding:10px 16px;}",
|
|
1400
|
+
".dsh-auto-overlay-close{appearance:none;width:30px;height:30px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--dsw-alias-label-secondary,#4f5661);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;}",
|
|
1401
|
+
".dsh-auto-overlay-close:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-label-primary,#0f1115);}",
|
|
1402
|
+
".dsh-auto-overlay-close:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px;}",
|
|
1403
|
+
".dsh-auto-overlay-body{box-sizing:border-box;min-height:0;flex:1;padding:0 28px 28px;overflow-y:auto;overscroll-behavior:contain;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);}",
|
|
1404
|
+
".dsh-auto-overlay-body>.dsh-auto-root{width:100%;margin:0 auto;padding-top:0;}",
|
|
1405
|
+
".dsh-auto-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important;}",
|
|
1143
1406
|
".dsh-auto-root{--dsh-auto-border:var(--dsw-alias-border-l2,rgba(15,17,21,.14));--dsh-auto-border-strong:var(--dsw-alias-border-l3,rgba(15,17,21,.2));--dsh-auto-surface:var(--dsw-alias-bg-layer-3,#fff);--dsh-auto-surface-active:var(--dsw-alias-bg-layer-2,#fff);--dsh-auto-input-bg:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1,#fff));--dsh-auto-text:var(--dsw-alias-label-primary,#0f1115);--dsh-auto-text-secondary:var(--dsw-alias-label-secondary,#4f5661);--dsh-auto-muted:var(--dsw-alias-label-tertiary,#81858c);--dsh-auto-caption:var(--dsw-alias-label-caption,#adb2b8);--dsh-auto-accent:var(--dsw-alias-state-business-primary,#4176e6);--dsh-auto-primary-fill:var(--dsw-alias-button-primary-fill,#0f1115);--dsh-auto-primary-hover:var(--dsw-alias-button-primary-hover,#34415b);--dsh-auto-on-primary:var(--dsw-alias-label-primary-foreground,#fff);--dsh-auto-danger:var(--dsw-alias-state-error-primary,#ec1313);--dsh-auto-success:var(--dsw-alias-state-success-primary,#22c55e);--dsh-auto-warning:var(--dsw-alias-state-warn-primary,#f59e0b);box-sizing:border-box;max-width:820px;padding-top:12px;display:flex;flex-direction:column;gap:16px;font-family:inherit;color:var(--dsh-auto-text);}",
|
|
1144
1407
|
"body:not([data-ds-dark-theme]) .dsh-auto-root{color-scheme:light;}",
|
|
1145
1408
|
"body[data-ds-dark-theme] .dsh-auto-root{color-scheme:dark;}",
|
|
@@ -1225,12 +1488,13 @@ window.__ModuleLoader__.load({
|
|
|
1225
1488
|
"@keyframes dsh-auto-pulse{0%,100%{opacity:1}50%{opacity:.35}}",
|
|
1226
1489
|
".dsh-auto-empty,.dsh-auto-loading,.dsh-auto-error{padding:22px 16px;text-align:center;border:1px dashed var(--dsh-auto-border);border-radius:12px;font-size:13px;color:var(--dsh-auto-text-secondary);}",
|
|
1227
1490
|
".dsh-auto-error{color:var(--dsh-auto-danger);display:flex;flex-direction:column;gap:10px;align-items:center;}",
|
|
1228
|
-
"@media (max-width:640px){.dsh-auto-formgrid{grid-template-columns:1fr;}.dsh-auto-card-head{flex-direction:column;align-items:flex-start;}.dsh-auto-run-name{max-width:150px;}}",
|
|
1491
|
+
"@media (max-width:640px){.dsh-auto-overlay-panel{max-width:calc(100vw - 16px);height:calc(100vh - 16px);border-radius:16px;}.dsh-auto-overlay-header{height:46px;padding:8px 10px;}.dsh-auto-overlay-body{padding:0 16px 16px;}.dsh-auto-formgrid{grid-template-columns:1fr;}.dsh-auto-card-head{flex-direction:column;align-items:flex-start;}.dsh-auto-run-name{max-width:150px;}}",
|
|
1229
1492
|
].join("\n");
|
|
1230
1493
|
|
|
1231
1494
|
function apply(ctx) {
|
|
1232
|
-
|
|
1233
|
-
//
|
|
1495
|
+
const disclosure = createDisclosureStore();
|
|
1496
|
+
// All package-owned surfaces share one style element and one disclosure
|
|
1497
|
+
// store; both are released with the client-plugin fiber.
|
|
1234
1498
|
ctx.effect(() => {
|
|
1235
1499
|
const tag = document.createElement("style");
|
|
1236
1500
|
tag.setAttribute("data-plugin", "@syncended/dsh-automations");
|
|
@@ -1239,15 +1503,31 @@ window.__ModuleLoader__.load({
|
|
|
1239
1503
|
return () => {
|
|
1240
1504
|
tag.remove();
|
|
1241
1505
|
};
|
|
1242
|
-
}, "@syncended/dsh-automations:
|
|
1506
|
+
}, "@syncended/dsh-automations: client styles");
|
|
1507
|
+
ctx.effect(() => () => disclosure.dispose(), "@syncended/dsh-automations: disclosure store");
|
|
1243
1508
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
1244
1509
|
name: "settings.section",
|
|
1245
1510
|
id: "automations",
|
|
1246
1511
|
order: 25,
|
|
1247
1512
|
label: "Automations",
|
|
1248
1513
|
}, AutomationsSection));
|
|
1514
|
+
ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
|
|
1515
|
+
name: "sidebar.footer.action",
|
|
1516
|
+
id: "automations",
|
|
1517
|
+
order: 50,
|
|
1518
|
+
label: "Automations",
|
|
1519
|
+
inject: () => ({ disclosure }),
|
|
1520
|
+
}, AutomationsSidebarAction));
|
|
1521
|
+
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
1522
|
+
name: "shell.overlay",
|
|
1523
|
+
id: "automations",
|
|
1524
|
+
order: 50,
|
|
1525
|
+
label: "Automations",
|
|
1526
|
+
inject: () => ({ disclosure }),
|
|
1527
|
+
}, AutomationsOverlay));
|
|
1249
1528
|
}
|
|
1250
1529
|
|
|
1530
|
+
exports.agentPresetDisplayLabel = agentPresetDisplayLabel;
|
|
1251
1531
|
exports.inject = inject;
|
|
1252
1532
|
exports.apply = apply;
|
|
1253
1533
|
return module.exports;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncended/dsh-automations",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Durable cron automations for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
"client": {
|
|
30
30
|
"inject": [
|
|
31
31
|
"@deepseek-ai/dsh-client-runtime",
|
|
32
|
+
"@deepseek-ai/dsh-client-ui-layout",
|
|
33
|
+
"@deepseek-ai/dsh-client-ui-sidebar",
|
|
32
34
|
"@deepseek-ai/dsh-client-ui-settings"
|
|
33
35
|
],
|
|
34
36
|
"platform": "web"
|
|
@@ -80,7 +82,9 @@
|
|
|
80
82
|
"@deepseek-ai/dsh-agent-default-model": "^0.1.1-rc.2",
|
|
81
83
|
"@deepseek-ai/dsh-agent-presets": "^0.1.1-rc.2",
|
|
82
84
|
"@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-layout": "^0.1.1-rc.2",
|
|
83
86
|
"@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
|
|
87
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "^0.1.1-rc.2",
|
|
84
88
|
"@deepseek-ai/dsh-host-webserver": "^0.1.1-rc.2",
|
|
85
89
|
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
|
|
86
90
|
"@deepseek-ai/dsh-permission-presets": "^0.1.1-rc.2",
|
|
@@ -93,7 +97,9 @@
|
|
|
93
97
|
"@deepseek-ai/dsh-agent-default-model": "0.1.1-rc.2",
|
|
94
98
|
"@deepseek-ai/dsh-agent-presets": "0.1.1-rc.2",
|
|
95
99
|
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
100
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.1.1-rc.2",
|
|
96
101
|
"@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
|
|
102
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "0.1.1-rc.2",
|
|
97
103
|
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
98
104
|
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
99
105
|
"@deepseek-ai/dsh-permission-presets": "0.1.1-rc.2",
|