dsh-workflow-map 0.0.0-stage → 0.3.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.
- package/CHANGELOG.md +98 -0
- package/LICENSE +21 -0
- package/README.en.md +447 -0
- package/README.md +423 -2
- package/client.js +9673 -0
- package/cordis.patch.yml +11 -0
- package/docs/OPEN-SOURCE-GUIDE.md +256 -0
- package/docs/screenshot-detail.png +0 -0
- package/docs/screenshot.png +0 -0
- package/icon.svg +6 -0
- package/index.js +12 -0
- package/lib/index.js +974 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +65 -4
- package/src/client/Branches.js +241 -0
- package/src/client/FlowColumn.js +572 -0
- package/src/client/FlowEffects.js +677 -0
- package/src/client/HotInject.js +628 -0
- package/src/client/MainFlow.js +359 -0
- package/src/client/NodeCard.js +545 -0
- package/src/client/NodeDetail.js +569 -0
- package/src/client/ProgressUnder.js +216 -0
- package/src/client/RightPage.js +285 -0
- package/src/client/Settings.js +212 -0
- package/src/client/StepColumn.js +479 -0
- package/src/client/StepDetail.js +250 -0
- package/src/client/export.js +280 -0
- package/src/client/panel.js +1911 -0
- package/src/client/pulse.js +126 -0
- package/src/client/store.js +1090 -0
- package/src/client/theme.js +1164 -0
- package/src/fold.mjs +2633 -0
- package/src/orchestrator.mjs +426 -0
- package/src/route.js +621 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pulse.js - the breathing / blinking layer for "what is happening right now".
|
|
3
|
+
*
|
|
4
|
+
* Three things, all testable without a browser:
|
|
5
|
+
* wfMotionMode - a matchMedia wrapper -> "css" | "static" ("static" when the OS requests reduced motion)
|
|
6
|
+
* wfSessionRunning - is the session actually working: prefer the host boolean when present; otherwise infer it with two fallbacks (an active node, or a recent event)
|
|
7
|
+
* wfRenderLive - the "● working ..." widget: a 6 px breathing dot plus a three-dot ellipsis (pure markup, `h`/`say` injected)
|
|
8
|
+
*
|
|
9
|
+
* Why the idle decision needs three legs: the host view now carries `view.running` (folded from `turn/start` /
|
|
10
|
+
* `turn/end`), which is the most accurate signal; but old checkpoints and views that have not reached a turn event do not carry it,
|
|
11
|
+
* so two fallbacks remain - "a node is being called" (active.nodeId) and "there was an event recently" (asOf within <
|
|
12
|
+
* WF_IDLE_AFTER_MS). The boolean wins; the other two apply only when it is absent. A step's running status is
|
|
13
|
+
* not rewritten by PAE right after a turn ends, so it never participates in this decision.
|
|
14
|
+
*
|
|
15
|
+
* Pure, no import/export: inlined into client.js by tools/build-client.mjs (single-file browser half).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** The rhythm of the thinking indicator: one breathing cycle every 1.2 s (deliberately different
|
|
19
|
+
* from the 1.6 s status dot: 1.2 s is for "what is happening now", 1.6 s for "the running row",
|
|
20
|
+
* so on the same screen they do not pulse in sync). */
|
|
21
|
+
var WF_PULSE_PERIOD = "1.2s";
|
|
22
|
+
var WF_PULSE_MS = 1200;
|
|
23
|
+
|
|
24
|
+
/** The last event older than this, with no active node => the session is idle. 15 s covers a normal tool-call gap
|
|
25
|
+
* while still stopping the animation soon after the user replies (no continuous GPU use). */
|
|
26
|
+
var WF_IDLE_AFTER_MS = 15000;
|
|
27
|
+
|
|
28
|
+
/** Number of dots in the ellipsis (three, lit one after another). */
|
|
29
|
+
var WF_LIVE_DOTS = 3;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The OS "reduced motion" switch. `matchMediaFn` is injected rather than read off window, so the Node self-test can
|
|
33
|
+
* cover three environments: matchMedia present / absent / throwing.
|
|
34
|
+
*/
|
|
35
|
+
function wfMotionMode(matchMediaFn) {
|
|
36
|
+
if (typeof matchMediaFn !== "function") return "css";
|
|
37
|
+
try {
|
|
38
|
+
var query = matchMediaFn("(prefers-reduced-motion: reduce)");
|
|
39
|
+
return query && query.matches === true ? "static" : "css";
|
|
40
|
+
} catch (error) {
|
|
41
|
+
// A throwing matchMedia is not a request for reduced motion - the environment simply cannot answer -> animate as usual.
|
|
42
|
+
return "css";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Is the session working.
|
|
48
|
+
* 1. The host's `view.running` (the turn flag) -> use it as-is; the other three no longer participate.
|
|
49
|
+
* 2. An active node (active.nodeId) -> it is calling right now, regardless of how old the last event is.
|
|
50
|
+
* 3. The last event is within WF_IDLE_AFTER_MS -> still working.
|
|
51
|
+
* 4. Anything else -> idle.
|
|
52
|
+
* When `nowMs` is unavailable (offline self-test, no clock) return "working": better to animate one extra frame than to treat a
|
|
53
|
+
* working session as idle (which would make the curve and the frame look broken).
|
|
54
|
+
*/
|
|
55
|
+
function wfSessionRunning(view, activeNodeId, nowMs) {
|
|
56
|
+
if (view && typeof view.running === "boolean") return view.running;
|
|
57
|
+
if (typeof activeNodeId === "string" && activeNodeId !== "") return true;
|
|
58
|
+
var asOf = wfFinite(view && view.asOf);
|
|
59
|
+
if (asOf === null || asOf <= 0) return false;
|
|
60
|
+
var now = wfFinite(nowMs);
|
|
61
|
+
if (now === null) return true;
|
|
62
|
+
return now - asOf < WF_IDLE_AFTER_MS;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The component's motion mode: follows the OS preference, listener removed on unmount. */
|
|
66
|
+
function wfUseMotion() {
|
|
67
|
+
var pair = React.useState(function () {
|
|
68
|
+
return wfMotionMode(typeof window !== "undefined" && window ? window.matchMedia : null);
|
|
69
|
+
});
|
|
70
|
+
var mode = pair[0];
|
|
71
|
+
var setMode = pair[1];
|
|
72
|
+
|
|
73
|
+
React.useEffect(function () {
|
|
74
|
+
if (typeof window === "undefined" || !window || typeof window.matchMedia !== "function") return undefined;
|
|
75
|
+
var query = null;
|
|
76
|
+
try {
|
|
77
|
+
query = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
if (!query) return undefined;
|
|
82
|
+
setMode(query.matches === true ? "static" : "css");
|
|
83
|
+
function onChange() {
|
|
84
|
+
setMode(wfMotionMode(window.matchMedia));
|
|
85
|
+
}
|
|
86
|
+
// Old Safari only has addListener; try both and remove whichever was used.
|
|
87
|
+
if (typeof query.addEventListener === "function") {
|
|
88
|
+
query.addEventListener("change", onChange);
|
|
89
|
+
return function () {
|
|
90
|
+
query.removeEventListener("change", onChange);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (typeof query.addListener === "function") {
|
|
94
|
+
query.addListener(onChange);
|
|
95
|
+
return function () {
|
|
96
|
+
query.removeListener(onChange);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
}, []);
|
|
101
|
+
|
|
102
|
+
return mode === "static" ? "static" : "css";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* "● working ..." - the marker for current activity. `scope` is just a tag for tests and styling (step / node);
|
|
107
|
+
* the three dots are separate elements rather than keyframe `content`, which jumps discretely
|
|
108
|
+
* and whose intermediate state cannot be read in a headless browser.
|
|
109
|
+
*/
|
|
110
|
+
function wfRenderLive(h, say, scope) {
|
|
111
|
+
var word = typeof say === "function" ? say("panel.live") : "";
|
|
112
|
+
var dots = [];
|
|
113
|
+
for (var i = 0; i < WF_LIVE_DOTS; i += 1) dots.push(h("i", { key: "d" + i }));
|
|
114
|
+
return h(
|
|
115
|
+
"span",
|
|
116
|
+
{
|
|
117
|
+
className: "wf-live",
|
|
118
|
+
key: "live",
|
|
119
|
+
"data-dsh-workflow-map": "live",
|
|
120
|
+
"data-live": typeof scope === "string" && scope !== "" ? scope : "node",
|
|
121
|
+
},
|
|
122
|
+
h("i", { className: "wf-live-dot", key: "dot", "aria-hidden": "true" }),
|
|
123
|
+
h("span", { className: "wf-live-word", key: "word" }, word),
|
|
124
|
+
h("span", { className: "wf-live-dots", key: "dots", "aria-hidden": "true" }, dots)
|
|
125
|
+
);
|
|
126
|
+
}
|