@syncended/dsh-automations 0.2.2 → 0.3.0
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 +2 -2
- package/lib/client.js +157 -158
- package/package.json +4 -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 from the main **Automations** sidebar action or **Settings → Automations**.
|
|
11
|
+
- Enable/disable, Run now, edit, delete, cancel, and recent run history from a full center workspace opened by the main **Automations** sidebar action, or from **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 **Automations** from the main sidebar, or use **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 the full **Automations** workspace 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
|
-
Sidebar / Settings UI / HTTP API
|
|
18
|
+
Sidebar / Center workspace / Settings UI / HTTP API
|
|
19
19
|
│
|
|
20
20
|
▼
|
|
21
21
|
AutomationService ─── ProjectPolicy
|
|
@@ -30,7 +30,7 @@ Sidebar / Settings UI / HTTP API
|
|
|
30
30
|
|
|
31
31
|
### Browser surfaces
|
|
32
32
|
|
|
33
|
-
The same automation page is available through
|
|
33
|
+
The same automation page is available through Settings and a dedicated center workspace. `settings.section` keeps configuration available inside Settings; `sidebar.footer.action` activates a temporary, higher-priority `conversation` entry that replaces the current center occupant. This provides a split-screen-like full-center experience while using the single-slot election directly rather than Split Screen's internal view contributions. Closing Automations disposes its entry immediately, revealing whichever center surface was previously active. A small client-only disclosure store coordinates the sidebar trigger and dynamic registration; neither surface owns scheduler state, and both read the same package HTTP API.
|
|
34
34
|
|
|
35
35
|
Interactive chrome uses the ambient `@deepseek-ai/dsh-client-ui-primitives` `Button`, `Menu`, and icon components. Package CSS is limited to the automation-specific layout and composes only public DSH semantic tokens, so theme, menu, focus, and button behavior stay aligned with the host UI.
|
|
36
36
|
|
package/lib/client.js
CHANGED
|
@@ -21,7 +21,7 @@ window.__ModuleLoader__.load({
|
|
|
21
21
|
IconBrowseOutline16,
|
|
22
22
|
IconCheckOutline16,
|
|
23
23
|
IconChevronDownOutline14,
|
|
24
|
-
|
|
24
|
+
IconChevronLeftOutline14,
|
|
25
25
|
IconEditOutline16,
|
|
26
26
|
IconPlayOutline16,
|
|
27
27
|
IconPlusOutline16,
|
|
@@ -327,12 +327,12 @@ window.__ModuleLoader__.load({
|
|
|
327
327
|
|
|
328
328
|
function focusAfterPickerTab(trigger, backwards) {
|
|
329
329
|
requestAnimationFrame(() => {
|
|
330
|
-
const
|
|
331
|
-
if (!
|
|
330
|
+
const focusBoundary = trigger?.closest(".dsh-auto-form") || trigger?.closest('[role="dialog"]');
|
|
331
|
+
if (!focusBoundary) {
|
|
332
332
|
trigger?.focus();
|
|
333
333
|
return;
|
|
334
334
|
}
|
|
335
|
-
const focusables =
|
|
335
|
+
const focusables = visibleFocusables(focusBoundary);
|
|
336
336
|
const index = focusables.indexOf(trigger);
|
|
337
337
|
const target = index < 0 ? trigger : focusables[index + (backwards ? -1 : 1)];
|
|
338
338
|
(target || trigger)?.focus();
|
|
@@ -406,10 +406,14 @@ window.__ModuleLoader__.load({
|
|
|
406
406
|
});
|
|
407
407
|
});
|
|
408
408
|
const onKeyDown = (event) => {
|
|
409
|
-
if (event.key !== "Tab") return;
|
|
410
409
|
const dialog = riskDialog();
|
|
411
410
|
if (!dialog) return;
|
|
412
|
-
|
|
411
|
+
if (event.key === "Escape" && dialog.contains(event.target)) {
|
|
412
|
+
event.__dshAutomationsNested = true;
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (event.key !== "Tab") return;
|
|
416
|
+
const focusables = visibleFocusables(dialog);
|
|
413
417
|
if (focusables.length === 0) return;
|
|
414
418
|
const index = focusables.indexOf(event.target);
|
|
415
419
|
const next = event.shiftKey
|
|
@@ -607,6 +611,8 @@ window.__ModuleLoader__.load({
|
|
|
607
611
|
: ["workspace-write"];
|
|
608
612
|
const agentPresets = meta && Array.isArray(meta.agentPresets) ? meta.agentPresets : [];
|
|
609
613
|
const creating = editing === null;
|
|
614
|
+
const formPrefix = "dsh-auto-form-" + String(useId()).replace(/[^A-Za-z0-9_-]/g, "");
|
|
615
|
+
const fieldId = (name) => formPrefix + "-" + name;
|
|
610
616
|
|
|
611
617
|
return h(
|
|
612
618
|
"form",
|
|
@@ -622,9 +628,9 @@ window.__ModuleLoader__.load({
|
|
|
622
628
|
{ className: "dsh-auto-formgrid" },
|
|
623
629
|
h(
|
|
624
630
|
Field,
|
|
625
|
-
{ label: "Name", htmlFor: "
|
|
631
|
+
{ label: "Name", htmlFor: fieldId("name"), required: true },
|
|
626
632
|
h("input", {
|
|
627
|
-
id: "
|
|
633
|
+
id: fieldId("name"),
|
|
628
634
|
className: "dsh-auto-input",
|
|
629
635
|
type: "text",
|
|
630
636
|
value: draft.name,
|
|
@@ -636,9 +642,9 @@ window.__ModuleLoader__.load({
|
|
|
636
642
|
creating
|
|
637
643
|
? h(
|
|
638
644
|
Field,
|
|
639
|
-
{ label: "Job id", htmlFor: "
|
|
645
|
+
{ label: "Job id", htmlFor: fieldId("id"), hint: "Lowercase letters, digits and hyphens; auto-derived from the name. Leave blank to let the server generate one." },
|
|
640
646
|
h("input", {
|
|
641
|
-
id: "
|
|
647
|
+
id: fieldId("id"),
|
|
642
648
|
className: "dsh-auto-input",
|
|
643
649
|
type: "text",
|
|
644
650
|
value: draft.id,
|
|
@@ -652,9 +658,9 @@ window.__ModuleLoader__.load({
|
|
|
652
658
|
)
|
|
653
659
|
: h(
|
|
654
660
|
Field,
|
|
655
|
-
{ label: "Job id", htmlFor: "
|
|
661
|
+
{ label: "Job id", htmlFor: fieldId("id"), hint: "Fixed after creation." },
|
|
656
662
|
h("input", {
|
|
657
|
-
id: "
|
|
663
|
+
id: fieldId("id"),
|
|
658
664
|
className: "dsh-auto-input",
|
|
659
665
|
type: "text",
|
|
660
666
|
value: draft.id,
|
|
@@ -664,9 +670,9 @@ window.__ModuleLoader__.load({
|
|
|
664
670
|
),
|
|
665
671
|
h(
|
|
666
672
|
Field,
|
|
667
|
-
{ label: "Cron", htmlFor: "
|
|
673
|
+
{ label: "Cron", htmlFor: fieldId("cron"), required: true, hint: "Five-field cron (minute hour day-of-month month day-of-week)." },
|
|
668
674
|
h("input", {
|
|
669
|
-
id: "
|
|
675
|
+
id: fieldId("cron"),
|
|
670
676
|
className: "dsh-auto-input",
|
|
671
677
|
type: "text",
|
|
672
678
|
value: draft.cron,
|
|
@@ -676,30 +682,30 @@ window.__ModuleLoader__.load({
|
|
|
676
682
|
),
|
|
677
683
|
h(
|
|
678
684
|
Field,
|
|
679
|
-
{ label: "Timezone", htmlFor: "
|
|
685
|
+
{ label: "Timezone", htmlFor: fieldId("timezone"), required: true },
|
|
680
686
|
h("input", {
|
|
681
|
-
id: "
|
|
687
|
+
id: fieldId("timezone"),
|
|
682
688
|
className: "dsh-auto-input",
|
|
683
689
|
type: "text",
|
|
684
|
-
list: "
|
|
690
|
+
list: fieldId("timezone-list"),
|
|
685
691
|
value: draft.timezone,
|
|
686
692
|
spellCheck: false,
|
|
687
693
|
onChange: (event) => onChange("timezone", event.target.value),
|
|
688
694
|
}),
|
|
689
695
|
h(
|
|
690
696
|
"datalist",
|
|
691
|
-
{ id: "
|
|
697
|
+
{ id: fieldId("timezone-list") },
|
|
692
698
|
TIMEZONES.map((zone) => h("option", { key: zone, value: zone })),
|
|
693
699
|
),
|
|
694
700
|
),
|
|
695
701
|
h(
|
|
696
702
|
Field,
|
|
697
|
-
{ label: "Enabled", htmlFor: "
|
|
703
|
+
{ label: "Enabled", htmlFor: fieldId("enabled") },
|
|
698
704
|
h(
|
|
699
705
|
"label",
|
|
700
706
|
{ className: "dsh-auto-check" },
|
|
701
707
|
h("input", {
|
|
702
|
-
id: "
|
|
708
|
+
id: fieldId("enabled"),
|
|
703
709
|
type: "checkbox",
|
|
704
710
|
checked: draft.enabled,
|
|
705
711
|
onChange: (event) => onChange("enabled", event.target.checked),
|
|
@@ -709,9 +715,9 @@ window.__ModuleLoader__.load({
|
|
|
709
715
|
),
|
|
710
716
|
h(
|
|
711
717
|
Field,
|
|
712
|
-
{ label: "Timeout (ms)", htmlFor: "
|
|
718
|
+
{ label: "Timeout (ms)", htmlFor: fieldId("timeout"), required: true, hint: "Wall-clock limit for each run (1s to 24h)." },
|
|
713
719
|
h("input", {
|
|
714
|
-
id: "
|
|
720
|
+
id: fieldId("timeout"),
|
|
715
721
|
className: "dsh-auto-input",
|
|
716
722
|
type: "number",
|
|
717
723
|
min: MIN_TIMEOUT_MS,
|
|
@@ -723,12 +729,12 @@ window.__ModuleLoader__.load({
|
|
|
723
729
|
),
|
|
724
730
|
h(
|
|
725
731
|
Field,
|
|
726
|
-
{ label: "Provider", htmlFor: "
|
|
732
|
+
{ label: "Provider", htmlFor: fieldId("provider"), hint: "Blank uses the current Harness default. You may type an unlisted provider route." },
|
|
727
733
|
h("input", {
|
|
728
|
-
id: "
|
|
734
|
+
id: fieldId("provider"),
|
|
729
735
|
className: "dsh-auto-input",
|
|
730
736
|
type: "text",
|
|
731
|
-
list: "
|
|
737
|
+
list: fieldId("provider-list"),
|
|
732
738
|
value: draft.provider,
|
|
733
739
|
spellCheck: false,
|
|
734
740
|
placeholder: "Harness default",
|
|
@@ -736,7 +742,7 @@ window.__ModuleLoader__.load({
|
|
|
736
742
|
}),
|
|
737
743
|
h(
|
|
738
744
|
"datalist",
|
|
739
|
-
{ id: "
|
|
745
|
+
{ id: fieldId("provider-list") },
|
|
740
746
|
providers.map((provider) => h("option", { key: provider.id, value: provider.id })),
|
|
741
747
|
),
|
|
742
748
|
),
|
|
@@ -744,17 +750,17 @@ window.__ModuleLoader__.load({
|
|
|
744
750
|
Field,
|
|
745
751
|
{
|
|
746
752
|
label: "Model",
|
|
747
|
-
htmlFor: "
|
|
753
|
+
htmlFor: fieldId("model"),
|
|
748
754
|
required: draft.provider !== "",
|
|
749
755
|
hint: draft.provider === ""
|
|
750
756
|
? "Set a provider first, or leave both blank for the Harness default."
|
|
751
757
|
: "Choose a discovered model or type an adapter-supported model id.",
|
|
752
758
|
},
|
|
753
759
|
h("input", {
|
|
754
|
-
id: "
|
|
760
|
+
id: fieldId("model"),
|
|
755
761
|
className: "dsh-auto-input",
|
|
756
762
|
type: "text",
|
|
757
|
-
list: "
|
|
763
|
+
list: fieldId("model-list"),
|
|
758
764
|
value: draft.model,
|
|
759
765
|
spellCheck: false,
|
|
760
766
|
placeholder: draft.provider === "" ? "Harness default" : "Model id",
|
|
@@ -763,18 +769,18 @@ window.__ModuleLoader__.load({
|
|
|
763
769
|
}),
|
|
764
770
|
h(
|
|
765
771
|
"datalist",
|
|
766
|
-
{ id: "
|
|
772
|
+
{ id: fieldId("model-list") },
|
|
767
773
|
models.map((model) => h("option", { key: model, value: model })),
|
|
768
774
|
),
|
|
769
775
|
),
|
|
770
776
|
h(
|
|
771
777
|
Field,
|
|
772
|
-
{ label: "Reasoning effort", htmlFor: "
|
|
778
|
+
{ label: "Reasoning effort", htmlFor: fieldId("effort"), hint: "Blank uses the provider default." },
|
|
773
779
|
h("input", {
|
|
774
|
-
id: "
|
|
780
|
+
id: fieldId("effort"),
|
|
775
781
|
className: "dsh-auto-input",
|
|
776
782
|
type: "text",
|
|
777
|
-
list: "
|
|
783
|
+
list: fieldId("effort-list"),
|
|
778
784
|
value: draft.reasoningEffort,
|
|
779
785
|
spellCheck: false,
|
|
780
786
|
placeholder: "e.g. medium",
|
|
@@ -782,15 +788,15 @@ window.__ModuleLoader__.load({
|
|
|
782
788
|
}),
|
|
783
789
|
h(
|
|
784
790
|
"datalist",
|
|
785
|
-
{ id: "
|
|
791
|
+
{ id: fieldId("effort-list") },
|
|
786
792
|
REASONING_EFFORTS.map((effort) => h("option", { key: effort, value: effort })),
|
|
787
793
|
),
|
|
788
794
|
),
|
|
789
795
|
h(
|
|
790
796
|
Field,
|
|
791
|
-
{ label: "Agent preset", htmlFor: "
|
|
797
|
+
{ label: "Agent preset", htmlFor: fieldId("preset"), hint: "Uses the current Harness default when not explicitly selected." },
|
|
792
798
|
h(AgentPresetPicker, {
|
|
793
|
-
id: "
|
|
799
|
+
id: fieldId("preset"),
|
|
794
800
|
value: draft.agentPreset,
|
|
795
801
|
presets: agentPresets,
|
|
796
802
|
onChange: (value) => onChange("agentPreset", value),
|
|
@@ -800,12 +806,12 @@ window.__ModuleLoader__.load({
|
|
|
800
806
|
Field,
|
|
801
807
|
{
|
|
802
808
|
label: "Permission preset",
|
|
803
|
-
htmlFor: "
|
|
809
|
+
htmlFor: fieldId("permission"),
|
|
804
810
|
required: true,
|
|
805
811
|
hint: permissionPresetPresentation(draft.permissionPreset).detail,
|
|
806
812
|
},
|
|
807
813
|
h(PermissionPresetPicker, {
|
|
808
|
-
id: "
|
|
814
|
+
id: fieldId("permission"),
|
|
809
815
|
value: draft.permissionPreset,
|
|
810
816
|
presets: permissionPresets,
|
|
811
817
|
onChange: (value) => onChange("permissionPreset", value),
|
|
@@ -813,11 +819,11 @@ window.__ModuleLoader__.load({
|
|
|
813
819
|
),
|
|
814
820
|
h(
|
|
815
821
|
Field,
|
|
816
|
-
{ label: "Overlap policy", htmlFor: "
|
|
822
|
+
{ label: "Overlap policy", htmlFor: fieldId("overlap"), full: true, hint: "What happens when a scheduled run fires while another run for the same job is still active." },
|
|
817
823
|
h(
|
|
818
824
|
"select",
|
|
819
825
|
{
|
|
820
|
-
id: "
|
|
826
|
+
id: fieldId("overlap"),
|
|
821
827
|
className: "dsh-auto-select",
|
|
822
828
|
value: draft.overlap,
|
|
823
829
|
onChange: (event) => onChange("overlap", event.target.value),
|
|
@@ -827,11 +833,11 @@ window.__ModuleLoader__.load({
|
|
|
827
833
|
),
|
|
828
834
|
h(
|
|
829
835
|
Field,
|
|
830
|
-
{ label: "Misfire policy", htmlFor: "
|
|
836
|
+
{ label: "Misfire policy", htmlFor: fieldId("misfire"), hint: "How a missed occurrence is handled after the scheduler is back." },
|
|
831
837
|
h(
|
|
832
838
|
"select",
|
|
833
839
|
{
|
|
834
|
-
id: "
|
|
840
|
+
id: fieldId("misfire"),
|
|
835
841
|
className: "dsh-auto-select",
|
|
836
842
|
value: draft.misfire,
|
|
837
843
|
onChange: (event) => onChange("misfire", event.target.value),
|
|
@@ -841,9 +847,9 @@ window.__ModuleLoader__.load({
|
|
|
841
847
|
),
|
|
842
848
|
h(
|
|
843
849
|
Field,
|
|
844
|
-
{ label: "Working directory", htmlFor: "
|
|
850
|
+
{ label: "Working directory", htmlFor: fieldId("cwd"), required: true, full: true, hint: "Absolute project directory the agent runs in." },
|
|
845
851
|
h("input", {
|
|
846
|
-
id: "
|
|
852
|
+
id: fieldId("cwd"),
|
|
847
853
|
className: "dsh-auto-input",
|
|
848
854
|
type: "text",
|
|
849
855
|
value: draft.cwd,
|
|
@@ -854,9 +860,9 @@ window.__ModuleLoader__.load({
|
|
|
854
860
|
),
|
|
855
861
|
h(
|
|
856
862
|
Field,
|
|
857
|
-
{ label: "Prompt", htmlFor: "
|
|
863
|
+
{ label: "Prompt", htmlFor: fieldId("prompt"), required: true, full: true, hint: "Instructions for the agent run. Prompts are never shown in run history." },
|
|
858
864
|
h("textarea", {
|
|
859
|
-
id: "
|
|
865
|
+
id: fieldId("prompt"),
|
|
860
866
|
className: "dsh-auto-textarea",
|
|
861
867
|
value: draft.prompt,
|
|
862
868
|
placeholder: "Summarize yesterday's progress and list today's priorities\u2026",
|
|
@@ -1141,7 +1147,7 @@ window.__ModuleLoader__.load({
|
|
|
1141
1147
|
);
|
|
1142
1148
|
}
|
|
1143
1149
|
|
|
1144
|
-
function AutomationsSection() {
|
|
1150
|
+
function AutomationsSection({ centerMode = false } = {}) {
|
|
1145
1151
|
const [meta, setMeta] = useState(null);
|
|
1146
1152
|
const [snapshot, setSnapshot] = useState(null);
|
|
1147
1153
|
const [loading, setLoading] = useState(true);
|
|
@@ -1418,14 +1424,17 @@ window.__ModuleLoader__.load({
|
|
|
1418
1424
|
|
|
1419
1425
|
return h(
|
|
1420
1426
|
"section",
|
|
1421
|
-
{
|
|
1427
|
+
{
|
|
1428
|
+
className: "dsh-auto-root" + (centerMode ? " dsh-auto-root-workspace" : ""),
|
|
1429
|
+
"aria-busy": loading ? "true" : null,
|
|
1430
|
+
},
|
|
1422
1431
|
h(
|
|
1423
1432
|
"div",
|
|
1424
1433
|
{ className: "dsh-auto-head" },
|
|
1425
1434
|
h(
|
|
1426
1435
|
"div",
|
|
1427
1436
|
null,
|
|
1428
|
-
h("h2",
|
|
1437
|
+
h("h2", { className: centerMode ? "dsh-auto-sr-only" : undefined }, "Automations"),
|
|
1429
1438
|
h(
|
|
1430
1439
|
"p",
|
|
1431
1440
|
{ className: "dsh-auto-sub" },
|
|
@@ -1547,7 +1556,7 @@ window.__ModuleLoader__.load({
|
|
|
1547
1556
|
};
|
|
1548
1557
|
}
|
|
1549
1558
|
|
|
1550
|
-
const
|
|
1559
|
+
const FOCUSABLE_SELECTOR = [
|
|
1551
1560
|
"a[href]",
|
|
1552
1561
|
"button:not([disabled])",
|
|
1553
1562
|
"input:not([disabled])",
|
|
@@ -1557,45 +1566,15 @@ window.__ModuleLoader__.load({
|
|
|
1557
1566
|
"[tabindex]:not([tabindex=\"-1\"])",
|
|
1558
1567
|
].join(",");
|
|
1559
1568
|
|
|
1560
|
-
function
|
|
1569
|
+
function visibleFocusables(panel) {
|
|
1561
1570
|
if (!panel) return [];
|
|
1562
|
-
return Array.from(panel.querySelectorAll(
|
|
1571
|
+
return Array.from(panel.querySelectorAll(FOCUSABLE_SELECTOR)).filter((element) =>
|
|
1563
1572
|
!element.hasAttribute("hidden") &&
|
|
1564
1573
|
element.getAttribute("aria-hidden") !== "true" &&
|
|
1565
1574
|
element.getClientRects().length > 0,
|
|
1566
1575
|
);
|
|
1567
1576
|
}
|
|
1568
1577
|
|
|
1569
|
-
function trapModalTab(event, panel) {
|
|
1570
|
-
if (
|
|
1571
|
-
event.key !== "Tab" ||
|
|
1572
|
-
event.defaultPrevented ||
|
|
1573
|
-
event.altKey ||
|
|
1574
|
-
event.ctrlKey ||
|
|
1575
|
-
event.metaKey
|
|
1576
|
-
) return;
|
|
1577
|
-
const focusables = modalFocusables(panel);
|
|
1578
|
-
if (focusables.length === 0) {
|
|
1579
|
-
event.preventDefault();
|
|
1580
|
-
panel?.focus();
|
|
1581
|
-
return;
|
|
1582
|
-
}
|
|
1583
|
-
const first = focusables[0];
|
|
1584
|
-
const last = focusables[focusables.length - 1];
|
|
1585
|
-
const active = panel.ownerDocument.activeElement;
|
|
1586
|
-
if (event.shiftKey) {
|
|
1587
|
-
if (active === first || !panel.contains(active)) {
|
|
1588
|
-
event.preventDefault();
|
|
1589
|
-
last.focus();
|
|
1590
|
-
}
|
|
1591
|
-
return;
|
|
1592
|
-
}
|
|
1593
|
-
if (active === last || !panel.contains(active)) {
|
|
1594
|
-
event.preventDefault();
|
|
1595
|
-
first.focus();
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
1578
|
function AutomationGlyph({ size = 18 }) {
|
|
1600
1579
|
return h(
|
|
1601
1580
|
"svg",
|
|
@@ -1644,10 +1623,9 @@ window.__ModuleLoader__.load({
|
|
|
1644
1623
|
ref: triggerRef,
|
|
1645
1624
|
type: "button",
|
|
1646
1625
|
className: "dsh-auto-sidebar-trigger",
|
|
1647
|
-
title: wide ? undefined : "Automations",
|
|
1648
|
-
"aria-label": "Automations",
|
|
1649
|
-
"aria-
|
|
1650
|
-
"aria-expanded": open,
|
|
1626
|
+
title: wide ? undefined : open ? "Exit Automations" : "Automations",
|
|
1627
|
+
"aria-label": open ? "Exit Automations" : "Open Automations",
|
|
1628
|
+
"aria-pressed": open,
|
|
1651
1629
|
"data-active": open ? "true" : undefined,
|
|
1652
1630
|
"data-dsh-automations-trigger": "true",
|
|
1653
1631
|
onClick: disclosure.toggle,
|
|
@@ -1658,67 +1636,55 @@ window.__ModuleLoader__.load({
|
|
|
1658
1636
|
);
|
|
1659
1637
|
}
|
|
1660
1638
|
|
|
1661
|
-
function
|
|
1662
|
-
const
|
|
1663
|
-
disclosure.subscribe,
|
|
1664
|
-
disclosure.getSnapshot,
|
|
1665
|
-
disclosure.getSnapshot,
|
|
1666
|
-
);
|
|
1667
|
-
const closeRef = useRef(null);
|
|
1668
|
-
const panelRef = useRef(null);
|
|
1639
|
+
function AutomationsWorkspace({ disclosure }) {
|
|
1640
|
+
const workspaceRef = useRef(null);
|
|
1669
1641
|
const titleId = useId();
|
|
1670
1642
|
|
|
1671
1643
|
useEffect(() => {
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1644
|
+
const frame = window.requestAnimationFrame(() =>
|
|
1645
|
+
workspaceRef.current?.querySelector('[data-dsh-automations-exit="true"]')?.focus(),
|
|
1646
|
+
);
|
|
1647
|
+
const onKeyDown = (event) => {
|
|
1648
|
+
if (event.key !== "Escape" || event.defaultPrevented || event.__dshAutomationsNested) return;
|
|
1649
|
+
if (event.target?.closest?.('[role="dialog"],[role="menu"]')) return;
|
|
1650
|
+
if (document.querySelector('.dsh-auto-picker-trigger[aria-expanded="true"]')) return;
|
|
1651
|
+
event.preventDefault();
|
|
1652
|
+
disclosure.close();
|
|
1653
|
+
};
|
|
1654
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1655
|
+
return () => {
|
|
1656
|
+
window.cancelAnimationFrame(frame);
|
|
1657
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
1658
|
+
};
|
|
1659
|
+
}, [disclosure]);
|
|
1676
1660
|
|
|
1677
|
-
if (!open) return null;
|
|
1678
1661
|
return h(
|
|
1679
|
-
"
|
|
1680
|
-
{
|
|
1681
|
-
|
|
1662
|
+
"section",
|
|
1663
|
+
{
|
|
1664
|
+
ref: workspaceRef,
|
|
1665
|
+
className: "dsh-auto-workspace",
|
|
1666
|
+
"data-dsh-automations-workspace": "true",
|
|
1667
|
+
"aria-labelledby": titleId,
|
|
1668
|
+
},
|
|
1682
1669
|
h(
|
|
1683
|
-
"
|
|
1684
|
-
{
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
role: "dialog",
|
|
1688
|
-
tabIndex: -1,
|
|
1689
|
-
"aria-modal": "true",
|
|
1690
|
-
"aria-labelledby": titleId,
|
|
1691
|
-
onKeyDownCapture: (event) => {
|
|
1692
|
-
const panel = panelRef.current;
|
|
1693
|
-
if (panel && event.target && !panel.contains(event.target)) return;
|
|
1694
|
-
if (event.key === "Escape") {
|
|
1695
|
-
if (panelRef.current?.querySelector('.dsh-auto-picker-trigger[aria-expanded="true"]')) return;
|
|
1696
|
-
event.preventDefault();
|
|
1697
|
-
disclosure.close();
|
|
1698
|
-
return;
|
|
1699
|
-
}
|
|
1700
|
-
trapModalTab(event, panelRef.current);
|
|
1701
|
-
},
|
|
1702
|
-
},
|
|
1670
|
+
"header",
|
|
1671
|
+
{ className: "dsh-auto-workspace-toolbar" },
|
|
1672
|
+
h("span", { className: "dsh-auto-workspace-icon", "aria-hidden": "true" }, h(AutomationGlyph, { size: 16 })),
|
|
1673
|
+
h("strong", { id: titleId, className: "dsh-auto-workspace-title" }, "Automations"),
|
|
1703
1674
|
h(
|
|
1704
|
-
|
|
1705
|
-
{
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
"
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
title: "Close",
|
|
1715
|
-
onClick: disclosure.close,
|
|
1716
|
-
},
|
|
1717
|
-
h(IconCloseOutline16),
|
|
1718
|
-
),
|
|
1675
|
+
Button,
|
|
1676
|
+
{
|
|
1677
|
+
type: "button",
|
|
1678
|
+
variant: "toolbar",
|
|
1679
|
+
size: "sm",
|
|
1680
|
+
icon: h(IconChevronLeftOutline14),
|
|
1681
|
+
onClick: disclosure.close,
|
|
1682
|
+
"data-dsh-automations-exit": "true",
|
|
1683
|
+
},
|
|
1684
|
+
"Exit Automations",
|
|
1719
1685
|
),
|
|
1720
|
-
h("div", { className: "dsh-auto-overlay-body" }, h(AutomationsSection)),
|
|
1721
1686
|
),
|
|
1687
|
+
h("div", { className: "dsh-auto-workspace-scroll" }, h(AutomationsSection, { centerMode: true })),
|
|
1722
1688
|
);
|
|
1723
1689
|
}
|
|
1724
1690
|
|
|
@@ -1731,17 +1697,15 @@ window.__ModuleLoader__.load({
|
|
|
1731
1697
|
".dsh-auto-sidebar-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
1732
1698
|
".dsh-auto-sidebar-action-rail{width:36px;height:36px;margin:0;}",
|
|
1733
1699
|
".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%;}",
|
|
1734
|
-
".dsh-auto-
|
|
1735
|
-
".dsh-auto-
|
|
1736
|
-
".dsh-auto-
|
|
1737
|
-
".dsh-auto-
|
|
1738
|
-
".dsh-auto-
|
|
1739
|
-
".dsh-auto-
|
|
1740
|
-
".dsh-auto-overlay-close:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px;}",
|
|
1741
|
-
".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);}",
|
|
1742
|
-
".dsh-auto-overlay-body>.dsh-auto-root{width:100%;margin:0 auto;padding-top:0;}",
|
|
1700
|
+
".dsh-auto-workspace{box-sizing:border-box;width:100%;height:100%;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;color:var(--dsw-alias-label-primary,#0f1115);background:var(--dsw-alias-bg-base,#fff);font-family:inherit;}",
|
|
1701
|
+
".dsh-auto-workspace-toolbar{box-sizing:border-box;width:100%;height:44px;flex:none;display:flex;align-items:center;gap:8px;padding:6px 10px 6px 12px;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(15,17,21,.14));background:var(--dsw-alias-bg-base,#fff);}",
|
|
1702
|
+
".dsh-auto-workspace-icon{width:28px;height:28px;flex:none;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;color:var(--dsw-alias-state-business-primary,#4176e6);background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4176e6) 10%,transparent);}",
|
|
1703
|
+
".dsh-auto-workspace-title{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;line-height:20px;}",
|
|
1704
|
+
".dsh-auto-workspace-scroll{container:dsh-auto-workspace / inline-size;box-sizing:border-box;min-height:0;flex:1;padding:24px clamp(20px,4vw,48px) 40px;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);}",
|
|
1705
|
+
".dsh-auto-workspace-scroll>.dsh-auto-root{width:100%;margin:0 auto;padding-top:0;}",
|
|
1743
1706
|
".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;}",
|
|
1744
1707
|
".dsh-auto-root{--dsh-auto-border:var(--dsw-alias-border-l2,rgba(15,17,21,.14));--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-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);}",
|
|
1708
|
+
".dsh-auto-root-workspace{max-width:960px;}",
|
|
1745
1709
|
"body:not([data-ds-dark-theme]) .dsh-auto-root{color-scheme:light;}",
|
|
1746
1710
|
"body[data-ds-dark-theme] .dsh-auto-root{color-scheme:dark;}",
|
|
1747
1711
|
".dsh-auto-root *,.dsh-auto-root *::before,.dsh-auto-root *::after{box-sizing:border-box;}",
|
|
@@ -1837,13 +1801,34 @@ window.__ModuleLoader__.load({
|
|
|
1837
1801
|
"@keyframes dsh-auto-pulse{0%,100%{opacity:1}50%{opacity:.35}}",
|
|
1838
1802
|
".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);}",
|
|
1839
1803
|
".dsh-auto-error{color:var(--dsh-auto-danger);display:flex;flex-direction:column;gap:10px;align-items:center;}",
|
|
1840
|
-
"@
|
|
1804
|
+
"@container dsh-auto-workspace (max-width:680px){.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;}}",
|
|
1805
|
+
"@media (max-width:640px){.dsh-auto-workspace-toolbar{padding-inline:8px;}.dsh-auto-workspace-scroll{padding:16px 14px 28px;}.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;}}",
|
|
1841
1806
|
].join("\n");
|
|
1842
1807
|
|
|
1843
1808
|
function apply(ctx) {
|
|
1844
1809
|
const disclosure = createDisclosureStore();
|
|
1845
|
-
|
|
1846
|
-
|
|
1810
|
+
let centerDeclared = false;
|
|
1811
|
+
let disposeCenter = null;
|
|
1812
|
+
const unmountCenter = () => {
|
|
1813
|
+
if (!disposeCenter) return;
|
|
1814
|
+
const dispose = disposeCenter;
|
|
1815
|
+
disposeCenter = null;
|
|
1816
|
+
dispose();
|
|
1817
|
+
};
|
|
1818
|
+
const mountCenter = () => {
|
|
1819
|
+
if (!centerDeclared || !disclosure.getSnapshot() || disposeCenter) return;
|
|
1820
|
+
try {
|
|
1821
|
+
disposeCenter = ctx.slots.register({
|
|
1822
|
+
name: "conversation",
|
|
1823
|
+
priority: -200,
|
|
1824
|
+
inject: () => ({ disclosure }),
|
|
1825
|
+
}, AutomationsWorkspace);
|
|
1826
|
+
} catch (error) {
|
|
1827
|
+
console.error("dsh automations: could not mount center workspace", error);
|
|
1828
|
+
disclosure.close();
|
|
1829
|
+
}
|
|
1830
|
+
};
|
|
1831
|
+
|
|
1847
1832
|
ctx.effect(() => {
|
|
1848
1833
|
const tag = document.createElement("style");
|
|
1849
1834
|
tag.setAttribute("data-plugin", "@syncended/dsh-automations");
|
|
@@ -1853,7 +1838,28 @@ window.__ModuleLoader__.load({
|
|
|
1853
1838
|
tag.remove();
|
|
1854
1839
|
};
|
|
1855
1840
|
}, "@syncended/dsh-automations: client styles");
|
|
1856
|
-
ctx.effect(
|
|
1841
|
+
ctx.effect(
|
|
1842
|
+
() => ctx.slots.inject("conversation", () => {
|
|
1843
|
+
centerDeclared = true;
|
|
1844
|
+
mountCenter();
|
|
1845
|
+
return () => {
|
|
1846
|
+
centerDeclared = false;
|
|
1847
|
+
unmountCenter();
|
|
1848
|
+
};
|
|
1849
|
+
}),
|
|
1850
|
+
"@syncended/dsh-automations: center workspace",
|
|
1851
|
+
);
|
|
1852
|
+
ctx.effect(() => {
|
|
1853
|
+
const unsubscribe = disclosure.subscribe(() => {
|
|
1854
|
+
if (disclosure.getSnapshot()) mountCenter();
|
|
1855
|
+
else unmountCenter();
|
|
1856
|
+
});
|
|
1857
|
+
return () => {
|
|
1858
|
+
unsubscribe();
|
|
1859
|
+
unmountCenter();
|
|
1860
|
+
disclosure.dispose();
|
|
1861
|
+
};
|
|
1862
|
+
}, "@syncended/dsh-automations: workspace state");
|
|
1857
1863
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
1858
1864
|
name: "settings.section",
|
|
1859
1865
|
id: "automations",
|
|
@@ -1867,13 +1873,6 @@ window.__ModuleLoader__.load({
|
|
|
1867
1873
|
label: "Automations",
|
|
1868
1874
|
inject: () => ({ disclosure }),
|
|
1869
1875
|
}, AutomationsSidebarAction));
|
|
1870
|
-
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
1871
|
-
name: "shell.overlay",
|
|
1872
|
-
id: "automations",
|
|
1873
|
-
order: 50,
|
|
1874
|
-
label: "Automations",
|
|
1875
|
-
inject: () => ({ disclosure }),
|
|
1876
|
-
}, AutomationsOverlay));
|
|
1877
1876
|
}
|
|
1878
1877
|
|
|
1879
1878
|
exports.agentPresetDisplayLabel = agentPresetDisplayLabel;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncended/dsh-automations",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Durable cron automations for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"inject": [
|
|
31
31
|
"@deepseek-ai/dsh-client-runtime",
|
|
32
32
|
"@deepseek-ai/dsh-client-ui-layout",
|
|
33
|
+
"@deepseek-ai/dsh-client-ui-conversation",
|
|
33
34
|
"@deepseek-ai/dsh-client-ui-sidebar",
|
|
34
35
|
"@deepseek-ai/dsh-client-ui-settings"
|
|
35
36
|
],
|
|
@@ -82,6 +83,7 @@
|
|
|
82
83
|
"@deepseek-ai/dsh-agent-default-model": "^0.1.1-rc.2",
|
|
83
84
|
"@deepseek-ai/dsh-agent-presets": "^0.1.1-rc.2",
|
|
84
85
|
"@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
|
|
86
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.1-rc.2",
|
|
85
87
|
"@deepseek-ai/dsh-client-ui-layout": "^0.1.1-rc.2",
|
|
86
88
|
"@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
|
|
87
89
|
"@deepseek-ai/dsh-client-ui-sidebar": "^0.1.1-rc.2",
|
|
@@ -97,6 +99,7 @@
|
|
|
97
99
|
"@deepseek-ai/dsh-agent-default-model": "0.1.1-rc.2",
|
|
98
100
|
"@deepseek-ai/dsh-agent-presets": "0.1.1-rc.2",
|
|
99
101
|
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
102
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.1-rc.2",
|
|
100
103
|
"@deepseek-ai/dsh-client-ui-layout": "0.1.1-rc.2",
|
|
101
104
|
"@deepseek-ai/dsh-client-ui-primitives": "0.1.1-rc.2",
|
|
102
105
|
"@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
|