orcheo-studio 0.24.4 → 0.24.6
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/.bumpversion.cfg +1 -1
- package/dist/assets/{arc-99TH-Koz.js → arc-CJePtrV4.js} +1 -1
- package/dist/assets/{architectureDiagram-VXUJARFQ-DugaTSY2.js → architectureDiagram-VXUJARFQ-BavAz0jp.js} +1 -1
- package/dist/assets/{blockDiagram-VD42YOAC-BH68wVtD.js → blockDiagram-VD42YOAC-Bx1XAydH.js} +1 -1
- package/dist/assets/{c4Diagram-YG6GDRKO-V6Vqtp7B.js → c4Diagram-YG6GDRKO-B2LhByin.js} +1 -1
- package/dist/assets/channel-BuDj-lWJ.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-CvbCAMNv.js → chunk-4BX2VUAB-UqiH5dLp.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-h_T3kQh7.js → chunk-55IACEB6-ChxTr_6v.js} +1 -1
- package/dist/assets/{chunk-B4BG7PRW-Dm6dgbGh.js → chunk-B4BG7PRW-2ETw-eA1.js} +1 -1
- package/dist/assets/{chunk-DI55MBZ5-DSXFA4Fi.js → chunk-DI55MBZ5-BdxVSKej.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DJDlfjt1.js → chunk-FMBD7UC4-BJF2M5iQ.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-BnjUGeBL.js → chunk-QN33PNHL-DI9t3nKL.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-BRudOghZ.js → chunk-QZHKN3VN-DsbUIBgB.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-CpxSpvqK.js → chunk-TZMSLE5B-DzMhWfBV.js} +1 -1
- package/dist/assets/classDiagram-2ON5EDUG-Bc5AzWzU.js +1 -0
- package/dist/assets/classDiagram-v2-WZHVMYZB-Bc5AzWzU.js +1 -0
- package/dist/assets/clone-CtxIENQC.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-Dl80WZ_a.js → cose-bilkent-S5V4N54A-BcKKbLWz.js} +1 -1
- package/dist/assets/{dagre-6UL2VRFP-vw-vkw78.js → dagre-6UL2VRFP-CERJ9KSL.js} +1 -1
- package/dist/assets/{diagram-PSM6KHXK-B4MT5Nvf.js → diagram-PSM6KHXK-DGl--Cyq.js} +1 -1
- package/dist/assets/{diagram-QEK2KX5R-CMioZnRI.js → diagram-QEK2KX5R-DbfdELCd.js} +1 -1
- package/dist/assets/{diagram-S2PKOQOG-PJAE8YS0.js → diagram-S2PKOQOG-CsR4YAm5.js} +1 -1
- package/dist/assets/{erDiagram-Q2GNP2WA-DCd-WouG.js → erDiagram-Q2GNP2WA-BlOr_gpI.js} +1 -1
- package/dist/assets/{flowDiagram-NV44I4VS-DS__-WT4.js → flowDiagram-NV44I4VS-BAyDXjxF.js} +1 -1
- package/dist/assets/{ganttDiagram-JELNMOA3-Btifh-31.js → ganttDiagram-JELNMOA3-b2ntam6s.js} +1 -1
- package/dist/assets/{gitGraphDiagram-V2S2FVAM-BCyjopey.js → gitGraphDiagram-V2S2FVAM-BvdeZrga.js} +1 -1
- package/dist/assets/{graph-6YBx8iQ0.js → graph-DMrtDwYQ.js} +1 -1
- package/dist/assets/{index-lkycEDHM.js → index-CaWVBOSf.js} +204 -189
- package/dist/assets/index-CbLxL6va.css +1 -0
- package/dist/assets/{infoDiagram-HS3SLOUP-CAsJ2eU1.js → infoDiagram-HS3SLOUP-CFO6LsEb.js} +1 -1
- package/dist/assets/{isUndefined-CcAlyXn3.js → isUndefined-DE2VOYrW.js} +1 -1
- package/dist/assets/{journeyDiagram-XKPGCS4Q-Bi8XsX15.js → journeyDiagram-XKPGCS4Q-Svi8cltR.js} +1 -1
- package/dist/assets/{kanban-definition-3W4ZIXB7-PTAFVsDn.js → kanban-definition-3W4ZIXB7-C7uds03_.js} +1 -1
- package/dist/assets/{layout-Do-GOFdW.js → layout-D5N_DnHw.js} +1 -1
- package/dist/assets/{linear-CZlgolw0.js → linear-h9-K1RBq.js} +1 -1
- package/dist/assets/{min-N15IYW1Y.js → min-CjtZYucR.js} +1 -1
- package/dist/assets/{mindmap-definition-VGOIOE7T-Dlgxv6Jo.js → mindmap-definition-VGOIOE7T-Bw80_6TW.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-Dr2AfIw5.js → pieDiagram-ADFJNKIX-DGukFJSP.js} +1 -1
- package/dist/assets/{quadrantDiagram-AYHSOK5B-B8TPuvW6.js → quadrantDiagram-AYHSOK5B-CU7GPi0P.js} +1 -1
- package/dist/assets/{requirementDiagram-UZGBJVZJ-CdD2oP1N.js → requirementDiagram-UZGBJVZJ-D_aCZrji.js} +1 -1
- package/dist/assets/{sankeyDiagram-TZEHDZUN-XEMX6l5k.js → sankeyDiagram-TZEHDZUN-Wgtprjih.js} +1 -1
- package/dist/assets/{sequenceDiagram-WL72ISMW-BlIKpBev.js → sequenceDiagram-WL72ISMW-BCOCCVxS.js} +1 -1
- package/dist/assets/{stateDiagram-FKZM4ZOC-D3KGQY6v.js → stateDiagram-FKZM4ZOC-DHVe22f9.js} +1 -1
- package/dist/assets/stateDiagram-v2-4FDKWEC3-Bq9eQr8D.js +1 -0
- package/dist/assets/{timeline-definition-IT6M3QCI-TkL4mz_f.js → timeline-definition-IT6M3QCI-Cm4CAEQk.js} +1 -1
- package/dist/assets/{treemap-GDKQZRPO-BDp_c1Vc.js → treemap-GDKQZRPO-DvLhDp9r.js} +1 -1
- package/dist/assets/{xychartDiagram-PRI3JC2R-D0dNQImL.js → xychartDiagram-PRI3JC2R-BtcJYIPe.js} +1 -1
- package/dist/index.html +8 -2
- package/index.html +6 -0
- package/package.json +1 -1
- package/src/App.tsx +48 -44
- package/src/design-system/ui/button.tsx +1 -1
- package/src/features/account/components/settings/appearance-settings-tab.tsx +1 -1
- package/src/features/account/pages/profile/components/profile-general-tab.tsx +1 -1
- package/src/features/account/pages/workspace-members.tsx +58 -62
- package/src/features/auth/pages/login.tsx +4 -2
- package/src/features/auth/pages/verify.tsx +1 -1
- package/src/features/chatkit/components/public-chat-error-boundary.tsx +1 -1
- package/src/features/chatkit/components/public-chat-widget.tsx +2 -3
- package/src/features/chatkit/lib/chatkit-theme.ts +3 -2
- package/src/features/chatkit/lib/public-chat-access.ts +13 -0
- package/src/features/chatkit/pages/public-chat.tsx +18 -27
- package/src/features/shared/components/chat-interface.types.ts +1 -5
- package/src/features/shared/components/top-navigation/studio-brand.tsx +1 -1
- package/src/features/shared/components/top-navigation/version-status.tsx +27 -31
- package/src/features/shared/components/workspace-bootstrap-gate.tsx +4 -4
- package/src/features/workflow/components/dialogs/credential-access-badge.tsx +2 -2
- package/src/features/workflow/components/dialogs/credential-status-badge.tsx +2 -2
- package/src/features/workflow/components/dialogs/credentials-table.tsx +1 -1
- package/src/features/workflow/components/dialogs/update-workflow-dialog.tsx +34 -78
- package/src/features/workflow/components/dialogs/upload-workflow-dialog.tsx +40 -136
- package/src/features/workflow/components/dialogs/workflow-folder-picker.tsx +178 -0
- package/src/features/workflow/components/panels/rjsf-cron-widget.tsx +35 -10
- package/src/features/workflow/components/panels/workflow-diff-dialog.tsx +5 -5
- package/src/features/workflow/components/panels/workflow-history-table.tsx +3 -4
- package/src/features/workflow/components/trace/agent-prism/SpanCard/SpanCardConnector.tsx +1 -5
- package/src/features/workflow/components/trace/agent-prism/shared.ts +1 -10
- package/src/features/workflow/components/trace/agent-prism/theme/theme.css +74 -74
- package/src/features/workflow/lib/workflow-execution-builders.ts +4 -4
- package/src/features/workflow/lib/workflow-execution.types.ts +2 -9
- package/src/features/workflow/lib/workflow-folder-selection.ts +239 -0
- package/src/features/workflow/lib/workflow-frontmatter.ts +3 -1
- package/src/features/workflow/lib/workflow-storage-api.ts +5 -9
- package/src/features/workflow/lib/workflow-storage-helpers.ts +2 -4
- package/src/features/workflow/lib/workflow-storage.ts +6 -2
- package/src/features/workflow/lib/workflow-storage.types.ts +1 -6
- package/src/features/workflow/lib/workflow-upload-errors.ts +6 -2
- package/src/features/workflow/pages/workflow/components/settings-tab-content.tsx +24 -9
- package/src/features/workflow/pages/workflow/components/workflow-tab-content.tsx +6 -4
- package/src/features/workflow/pages/workflow/hooks/controller/use-workflow-execution-controller.ts +4 -1
- package/src/features/workflow/pages/workflow/hooks/use-execution-updates.ts +4 -2
- package/src/features/workflow/pages/workflow-gallery/create-team-dialog.tsx +2 -6
- package/src/features/workflow/pages/workflow-gallery/workflow-card.tsx +16 -16
- package/src/index.css +101 -59
- package/src/lib/api.ts +7 -2
- package/src/lib/workspace-routing.ts +1 -3
- package/tailwind.config.js +47 -2
- package/dist/assets/channel-D562bZxL.js +0 -1
- package/dist/assets/classDiagram-2ON5EDUG-Dix_KnuM.js +0 -1
- package/dist/assets/classDiagram-v2-WZHVMYZB-Dix_KnuM.js +0 -1
- package/dist/assets/clone-0c2Tu-SH.js +0 -1
- package/dist/assets/index-Df4jFRhd.css +0 -1
- package/dist/assets/stateDiagram-v2-4FDKWEC3-Di3Nkv2n.js +0 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { FileJson, FileText, FolderUp, Loader2 } from "lucide-react";
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
import {
|
|
5
|
+
collectDroppedFolderFiles,
|
|
6
|
+
collectFolderInputFiles,
|
|
7
|
+
loadWorkflowFolderSelection,
|
|
8
|
+
WorkflowFolderSelectionError,
|
|
9
|
+
type WorkflowFolderSelection,
|
|
10
|
+
} from "@features/workflow/lib/workflow-folder-selection";
|
|
11
|
+
|
|
12
|
+
interface WorkflowFolderPickerProps {
|
|
13
|
+
/** Unique prefix for the input id so labels stay associated per dialog. */
|
|
14
|
+
idPrefix: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/** Name of the currently selected script, or "" when none is selected. */
|
|
17
|
+
scriptName: string;
|
|
18
|
+
/** Name of the currently selected config, or null when none is selected. */
|
|
19
|
+
configName: string | null;
|
|
20
|
+
onSelect: (selection: WorkflowFolderSelection) => void;
|
|
21
|
+
onError: (message: string) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const READ_FOLDER_FALLBACK_ERROR =
|
|
25
|
+
"Could not read the selected folder. Please try again.";
|
|
26
|
+
const EMPTY_FOLDER_ERROR =
|
|
27
|
+
"No files were found in the selected folder. Add a folder containing a .py workflow script and try again.";
|
|
28
|
+
|
|
29
|
+
export function WorkflowFolderPicker({
|
|
30
|
+
idPrefix,
|
|
31
|
+
disabled = false,
|
|
32
|
+
scriptName,
|
|
33
|
+
configName,
|
|
34
|
+
onSelect,
|
|
35
|
+
onError,
|
|
36
|
+
}: WorkflowFolderPickerProps) {
|
|
37
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
38
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
39
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
40
|
+
const inputId = `${idPrefix}-folder`;
|
|
41
|
+
|
|
42
|
+
// `webkitdirectory` is not part of the standard input typings, so set it
|
|
43
|
+
// imperatively to opt the file picker into folder selection.
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const input = inputRef.current;
|
|
46
|
+
if (input) {
|
|
47
|
+
input.setAttribute("webkitdirectory", "");
|
|
48
|
+
input.setAttribute("directory", "");
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const processFiles = useCallback(
|
|
53
|
+
async (files: File[]) => {
|
|
54
|
+
if (files.length === 0) {
|
|
55
|
+
onError(EMPTY_FOLDER_ERROR);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
setIsProcessing(true);
|
|
59
|
+
try {
|
|
60
|
+
const selection = await loadWorkflowFolderSelection(files);
|
|
61
|
+
onSelect(selection);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
const message =
|
|
64
|
+
err instanceof WorkflowFolderSelectionError
|
|
65
|
+
? err.message
|
|
66
|
+
: READ_FOLDER_FALLBACK_ERROR;
|
|
67
|
+
onError(message);
|
|
68
|
+
} finally {
|
|
69
|
+
setIsProcessing(false);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
[onSelect, onError],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const handleInputChange = useCallback(
|
|
76
|
+
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
77
|
+
const files = collectFolderInputFiles(event.target.files);
|
|
78
|
+
// Allow re-selecting the same folder later.
|
|
79
|
+
event.target.value = "";
|
|
80
|
+
void processFiles(files);
|
|
81
|
+
},
|
|
82
|
+
[processFiles],
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const handleDrop = useCallback(
|
|
86
|
+
(event: React.DragEvent<HTMLLabelElement>) => {
|
|
87
|
+
event.preventDefault();
|
|
88
|
+
setIsDragging(false);
|
|
89
|
+
if (disabled) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
void (async () => {
|
|
93
|
+
try {
|
|
94
|
+
const files = await collectDroppedFolderFiles(event.dataTransfer);
|
|
95
|
+
await processFiles(files);
|
|
96
|
+
} catch {
|
|
97
|
+
onError(READ_FOLDER_FALLBACK_ERROR);
|
|
98
|
+
}
|
|
99
|
+
})();
|
|
100
|
+
},
|
|
101
|
+
[disabled, processFiles, onError],
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const handleDragOver = useCallback(
|
|
105
|
+
(event: React.DragEvent<HTMLLabelElement>) => {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
if (!disabled) {
|
|
108
|
+
setIsDragging(true);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
[disabled],
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const handleDragLeave = useCallback(
|
|
115
|
+
(event: React.DragEvent<HTMLLabelElement>) => {
|
|
116
|
+
// Ignore drag-leave events bubbling up from child elements.
|
|
117
|
+
if (event.currentTarget.contains(event.relatedTarget as Node | null)) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
setIsDragging(false);
|
|
121
|
+
},
|
|
122
|
+
[],
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const hasSelection = scriptName.length > 0;
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<div className="space-y-1.5">
|
|
129
|
+
<label
|
|
130
|
+
htmlFor={inputId}
|
|
131
|
+
onDrop={handleDrop}
|
|
132
|
+
onDragOver={handleDragOver}
|
|
133
|
+
onDragEnter={handleDragOver}
|
|
134
|
+
onDragLeave={handleDragLeave}
|
|
135
|
+
className={cn(
|
|
136
|
+
"flex w-full cursor-pointer flex-col items-center justify-center gap-2 rounded-md border border-dashed border-input bg-transparent px-4 py-6 text-center transition-colors",
|
|
137
|
+
"hover:border-ring focus-within:outline-none focus-within:ring-1 focus-within:ring-ring",
|
|
138
|
+
disabled && "pointer-events-none opacity-50",
|
|
139
|
+
isDragging && "border-ring bg-accent",
|
|
140
|
+
)}
|
|
141
|
+
>
|
|
142
|
+
{isProcessing ? (
|
|
143
|
+
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
|
|
144
|
+
) : (
|
|
145
|
+
<FolderUp className="h-6 w-6 text-muted-foreground" />
|
|
146
|
+
)}
|
|
147
|
+
<span className="text-sm font-medium">
|
|
148
|
+
{isDragging ? "Drop folder to load" : "Drag a folder here or browse"}
|
|
149
|
+
</span>
|
|
150
|
+
<span className="text-xs text-muted-foreground">
|
|
151
|
+
The folder should contain one <code>.py</code> script and an optional{" "}
|
|
152
|
+
<code>.json</code> config.
|
|
153
|
+
</span>
|
|
154
|
+
</label>
|
|
155
|
+
<input
|
|
156
|
+
ref={inputRef}
|
|
157
|
+
id={inputId}
|
|
158
|
+
type="file"
|
|
159
|
+
multiple
|
|
160
|
+
className="sr-only"
|
|
161
|
+
onChange={handleInputChange}
|
|
162
|
+
disabled={disabled}
|
|
163
|
+
/>
|
|
164
|
+
{hasSelection && (
|
|
165
|
+
<div className="space-y-1 rounded-md bg-muted/50 px-3 py-2 text-xs">
|
|
166
|
+
<p className="flex items-center gap-1.5 text-foreground">
|
|
167
|
+
<FileText className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
168
|
+
<span className="truncate">{scriptName}</span>
|
|
169
|
+
</p>
|
|
170
|
+
<p className="flex items-center gap-1.5 text-muted-foreground">
|
|
171
|
+
<FileJson className="h-3.5 w-3.5 shrink-0" />
|
|
172
|
+
<span className="truncate">{configName ?? "No config file"}</span>
|
|
173
|
+
</p>
|
|
174
|
+
</div>
|
|
175
|
+
)}
|
|
176
|
+
</div>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
@@ -72,11 +72,20 @@ const clampInt = (value: string, max: number, fallback: number) => {
|
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
/** Parse a single cron field's first numeric token, falling back to `fallback`. */
|
|
75
|
-
const parseField = (
|
|
76
|
-
field
|
|
75
|
+
const parseField = (
|
|
76
|
+
field: string | undefined,
|
|
77
|
+
max: number,
|
|
78
|
+
fallback: number,
|
|
79
|
+
) =>
|
|
80
|
+
field && field !== "*"
|
|
81
|
+
? clampInt(field.split(/[,/-]/)[0], max, fallback)
|
|
82
|
+
: fallback;
|
|
77
83
|
|
|
78
84
|
/** Extract the step N from a `*\/N` field (clamped to `max`), or undefined if it isn't a step. */
|
|
79
|
-
const parseStep = (
|
|
85
|
+
const parseStep = (
|
|
86
|
+
field: string | undefined,
|
|
87
|
+
max: number,
|
|
88
|
+
): number | undefined => {
|
|
80
89
|
const match = /^\*\/(\d+)$/.exec(field ?? "");
|
|
81
90
|
return match ? clampInt(match[1], max, 1) || 1 : undefined;
|
|
82
91
|
};
|
|
@@ -98,7 +107,9 @@ const parseDaysOfWeek = (field: string | undefined): number[] => {
|
|
|
98
107
|
return Array.from(new Set(days));
|
|
99
108
|
};
|
|
100
109
|
|
|
101
|
-
const parseCron = (
|
|
110
|
+
const parseCron = (
|
|
111
|
+
value: string | undefined,
|
|
112
|
+
): { freq: Frequency; parts: CronParts } => {
|
|
102
113
|
const [minute, hour, dom, , dow] = (value ?? "").trim().split(/\s+/);
|
|
103
114
|
const minuteStep = parseStep(minute, 59);
|
|
104
115
|
const hourStep = parseStep(hour, 23);
|
|
@@ -117,13 +128,15 @@ const parseCron = (value: string | undefined): { freq: Frequency; parts: CronPar
|
|
|
117
128
|
// `*/30 * * * *` (step) or `* * * * *` (every minute) → minute interval.
|
|
118
129
|
else if (minuteStep !== undefined || minute === "*") freq = "minute";
|
|
119
130
|
// `M */2 * * *` (step) or `M * * * *` (every hour) → hour interval.
|
|
120
|
-
else if (hourStep !== undefined || hour === "*" || hour === undefined)
|
|
131
|
+
else if (hourStep !== undefined || hour === "*" || hour === undefined)
|
|
132
|
+
freq = "hour";
|
|
121
133
|
|
|
122
134
|
return { freq, parts };
|
|
123
135
|
};
|
|
124
136
|
|
|
125
137
|
const buildCron = (freq: Frequency, parts: CronParts): string => {
|
|
126
|
-
const { interval, hourInterval, minute, hour, dayOfMonth, daysOfWeek } =
|
|
138
|
+
const { interval, hourInterval, minute, hour, dayOfMonth, daysOfWeek } =
|
|
139
|
+
parts;
|
|
127
140
|
switch (freq) {
|
|
128
141
|
case "minute":
|
|
129
142
|
// `*/1` is just "every minute"; emit the canonical wildcard form.
|
|
@@ -136,7 +149,9 @@ const buildCron = (freq: Frequency, parts: CronParts): string => {
|
|
|
136
149
|
case "day":
|
|
137
150
|
return `${minute} ${hour} * * *`;
|
|
138
151
|
case "week": {
|
|
139
|
-
const dow = daysOfWeek.length
|
|
152
|
+
const dow = daysOfWeek.length
|
|
153
|
+
? [...daysOfWeek].sort((a, b) => a - b).join(",")
|
|
154
|
+
: "*";
|
|
140
155
|
return `${minute} ${hour} * * ${dow}`;
|
|
141
156
|
}
|
|
142
157
|
case "month":
|
|
@@ -165,7 +180,11 @@ const canonicalCron = (value: string | undefined): string | null => {
|
|
|
165
180
|
if (/[a-z]/i.test(fields.join(""))) return null;
|
|
166
181
|
const days = parseDaysOfWeek(dow);
|
|
167
182
|
const dowField =
|
|
168
|
-
dow === "*"
|
|
183
|
+
dow === "*"
|
|
184
|
+
? "*"
|
|
185
|
+
: days.length
|
|
186
|
+
? [...days].sort((a, b) => a - b).join(",")
|
|
187
|
+
: dow;
|
|
169
188
|
return [minute, hour, dom, month, dowField].join(" ");
|
|
170
189
|
};
|
|
171
190
|
|
|
@@ -292,7 +311,9 @@ function CronWidget(props: WidgetProps) {
|
|
|
292
311
|
|
|
293
312
|
{(freq === "minute" || freq === "hour") && (
|
|
294
313
|
<Select
|
|
295
|
-
value={String(
|
|
314
|
+
value={String(
|
|
315
|
+
freq === "minute" ? parts.interval : parts.hourInterval,
|
|
316
|
+
)}
|
|
296
317
|
onValueChange={(v) =>
|
|
297
318
|
freq === "minute"
|
|
298
319
|
? update("minute", { ...parts, interval: Number(v) })
|
|
@@ -343,7 +364,11 @@ function CronWidget(props: WidgetProps) {
|
|
|
343
364
|
"flex h-9 min-w-[6rem] items-center justify-between gap-2 whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
|
344
365
|
)}
|
|
345
366
|
>
|
|
346
|
-
<span
|
|
367
|
+
<span
|
|
368
|
+
className={cn(
|
|
369
|
+
parts.daysOfWeek.length === 0 && "text-muted-foreground",
|
|
370
|
+
)}
|
|
371
|
+
>
|
|
347
372
|
{selectedDaysLabel}
|
|
348
373
|
</span>
|
|
349
374
|
<ChevronDown className="h-4 w-4 opacity-50" />
|
|
@@ -28,9 +28,9 @@ interface WorkflowDiffDialogProps {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const summaryBadgeClass = {
|
|
31
|
-
added: "bg-
|
|
32
|
-
removed: "bg-
|
|
33
|
-
modified: "bg-
|
|
31
|
+
added: "bg-success-muted text-success-muted-foreground",
|
|
32
|
+
removed: "bg-destructive-muted text-destructive-muted-foreground",
|
|
33
|
+
modified: "bg-info-muted text-info-muted-foreground",
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
const formatValue = (value: unknown) =>
|
|
@@ -103,12 +103,12 @@ const Differences = ({
|
|
|
103
103
|
<p className="text-muted-foreground">{entry.detail}</p>
|
|
104
104
|
)}
|
|
105
105
|
{entry.type !== "added" && entry.before !== undefined && (
|
|
106
|
-
<pre className="bg-
|
|
106
|
+
<pre className="bg-destructive-muted/60 rounded-md p-2 font-mono text-xs whitespace-pre-wrap">
|
|
107
107
|
- {formatValue(entry.before)}
|
|
108
108
|
</pre>
|
|
109
109
|
)}
|
|
110
110
|
{entry.type !== "removed" && entry.after !== undefined && (
|
|
111
|
-
<pre className="bg-
|
|
111
|
+
<pre className="bg-success-muted/60 rounded-md p-2 font-mono text-xs whitespace-pre-wrap">
|
|
112
112
|
+ {formatValue(entry.after)}
|
|
113
113
|
</pre>
|
|
114
114
|
)}
|
|
@@ -22,13 +22,12 @@ interface WorkflowHistoryTableProps {
|
|
|
22
22
|
onSelectVersion: (versionId: string) => void;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const statusBadgeClass =
|
|
26
|
-
"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400";
|
|
25
|
+
const statusBadgeClass = "bg-success-muted text-success-muted-foreground";
|
|
27
26
|
|
|
28
27
|
const summaryBadgeClasses: Record<"added" | "removed" | "modified", string> = {
|
|
29
28
|
added: statusBadgeClass,
|
|
30
|
-
removed: "bg-
|
|
31
|
-
modified: "bg-
|
|
29
|
+
removed: "bg-destructive-muted text-destructive-muted-foreground",
|
|
30
|
+
modified: "bg-info-muted text-info-muted-foreground",
|
|
32
31
|
};
|
|
33
32
|
|
|
34
33
|
const SummaryBadge = ({
|
|
@@ -31,16 +31,7 @@ export type ColorVariant =
|
|
|
31
31
|
| "gray";
|
|
32
32
|
|
|
33
33
|
export type ComponentSize =
|
|
34
|
-
| "
|
|
35
|
-
| "5"
|
|
36
|
-
| "6"
|
|
37
|
-
| "7"
|
|
38
|
-
| "8"
|
|
39
|
-
| "9"
|
|
40
|
-
| "10"
|
|
41
|
-
| "11"
|
|
42
|
-
| "12"
|
|
43
|
-
| "16";
|
|
34
|
+
"4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "16";
|
|
44
35
|
|
|
45
36
|
// CONSTANTS
|
|
46
37
|
|
|
@@ -1,59 +1,61 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
/*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
--agentprism-
|
|
8
|
-
--agentprism-
|
|
9
|
-
--agentprism-
|
|
10
|
-
--agentprism-
|
|
11
|
-
--agentprism-
|
|
12
|
-
--agentprism-
|
|
13
|
-
--agentprism-
|
|
14
|
-
--agentprism-
|
|
2
|
+
/*
|
|
3
|
+
* General-purpose colors aligned with the Orcheo design system
|
|
4
|
+
* (orcheo-design-system/tokens/colors.css): warm ink neutrals,
|
|
5
|
+
* Orcheo orange brand, warm-harmonized status hues.
|
|
6
|
+
*/
|
|
7
|
+
--agentprism-background: 97% 0.008 91.483; /* ink-50 */
|
|
8
|
+
--agentprism-foreground: 21.3% 0.006 91.63; /* ink-900 */
|
|
9
|
+
--agentprism-primary: 21.3% 0.006 91.63; /* ink-900 */
|
|
10
|
+
--agentprism-primary-foreground: 97% 0.008 91.483; /* ink-50 */
|
|
11
|
+
--agentprism-secondary: 93.4% 0.014 88.686; /* ink-100 */
|
|
12
|
+
--agentprism-secondary-foreground: 54.4% 0.02 84.589; /* ink-500 */
|
|
13
|
+
--agentprism-muted: 93.4% 0.014 88.686; /* ink-100 */
|
|
14
|
+
--agentprism-muted-foreground: 44.3% 0.015 86.885; /* ink-600 */
|
|
15
|
+
--agentprism-accent: 93.4% 0.014 88.686; /* ink-100 */
|
|
16
|
+
--agentprism-accent-foreground: 27.3% 0.009 88.77; /* ink-800 */
|
|
15
17
|
|
|
16
18
|
/* Brand colors */
|
|
17
|
-
--agentprism-brand:
|
|
19
|
+
--agentprism-brand: 71.1% 0.179 48.062; /* orange-500 */
|
|
18
20
|
--agentprism-brand-foreground: 1 0 0; /* white */
|
|
19
|
-
--agentprism-brand-secondary:
|
|
21
|
+
--agentprism-brand-secondary: 69.5% 0.092 72.981; /* tan-500 */
|
|
20
22
|
--agentprism-brand-secondary-foreground: 1 0 0; /* white */
|
|
21
23
|
|
|
22
24
|
/* Borders */
|
|
23
|
-
--agentprism-border:
|
|
24
|
-
--agentprism-border-subtle:
|
|
25
|
-
--agentprism-border-strong:
|
|
26
|
-
--agentprism-border-inverse: 21% 0.
|
|
25
|
+
--agentprism-border: 87.7% 0.02 87.522; /* ink-200 */
|
|
26
|
+
--agentprism-border-subtle: 93.4% 0.014 88.686; /* ink-100 */
|
|
27
|
+
--agentprism-border-strong: 78.7% 0.025 88.258; /* ink-300 */
|
|
28
|
+
--agentprism-border-inverse: 21.3% 0.006 91.63; /* ink-900 */
|
|
27
29
|
|
|
28
30
|
/* Success status color */
|
|
29
|
-
--agentprism-success:
|
|
30
|
-
--agentprism-success-muted:
|
|
31
|
-
--agentprism-success-muted-foreground:
|
|
31
|
+
--agentprism-success: 52.9% 0.103 156.217; /* green-500 */
|
|
32
|
+
--agentprism-success-muted: 94.2% 0.018 161.108; /* green-100 */
|
|
33
|
+
--agentprism-success-muted-foreground: 45.8% 0.089 156.156; /* green-600 */
|
|
32
34
|
|
|
33
35
|
/* Error status color */
|
|
34
|
-
--agentprism-error:
|
|
35
|
-
--agentprism-error-muted:
|
|
36
|
-
--agentprism-error-muted-foreground:
|
|
36
|
+
--agentprism-error: 57.3% 0.184 32.327; /* red-500 */
|
|
37
|
+
--agentprism-error-muted: 93.1% 0.029 36.154; /* red-100 */
|
|
38
|
+
--agentprism-error-muted-foreground: 50% 0.164 32.898; /* red-600 */
|
|
37
39
|
|
|
38
40
|
/* Warning status color */
|
|
39
|
-
--agentprism-warning:
|
|
40
|
-
--agentprism-warning-muted:
|
|
41
|
-
--agentprism-warning-muted-foreground:
|
|
41
|
+
--agentprism-warning: 72.9% 0.147 78.341; /* amber-500 */
|
|
42
|
+
--agentprism-warning-muted: 95.1% 0.041 88.794; /* amber-100 */
|
|
43
|
+
--agentprism-warning-muted-foreground: 63.6% 0.129 77.25; /* amber-600 */
|
|
42
44
|
|
|
43
45
|
/* Pending status color */
|
|
44
|
-
--agentprism-pending:
|
|
45
|
-
--agentprism-pending-muted:
|
|
46
|
-
--agentprism-pending-muted-foreground:
|
|
46
|
+
--agentprism-pending: 52.2% 0.082 245.431; /* blue-500 */
|
|
47
|
+
--agentprism-pending-muted: 93.8% 0.014 238.015; /* blue-100 */
|
|
48
|
+
--agentprism-pending-muted-foreground: 44.6% 0.07 244.417; /* blue-600 */
|
|
47
49
|
|
|
48
50
|
/* Code syntax highlighting */
|
|
49
|
-
--agentprism-code-string:
|
|
50
|
-
--agentprism-code-number:
|
|
51
|
-
--agentprism-code-key:
|
|
52
|
-
--agentprism-code-base:
|
|
51
|
+
--agentprism-code-string: 50% 0.164 32.898; /* red-600 */
|
|
52
|
+
--agentprism-code-number: 50% 0.164 32.898; /* red-600 */
|
|
53
|
+
--agentprism-code-key: 44.6% 0.07 244.417; /* blue-600 */
|
|
54
|
+
--agentprism-code-base: 54.4% 0.02 84.589; /* ink-500 */
|
|
53
55
|
|
|
54
56
|
/* Generic badge colors */
|
|
55
|
-
--agentprism-badge-default:
|
|
56
|
-
--agentprism-badge-default-foreground: 44.
|
|
57
|
+
--agentprism-badge-default: 93.4% 0.014 88.686; /* ink-100 */
|
|
58
|
+
--agentprism-badge-default-foreground: 44.3% 0.015 86.885; /* ink-600 */
|
|
57
59
|
|
|
58
60
|
/* Trace colors (llm) */
|
|
59
61
|
--agentprism-avatar-llm: 62.7% 0.265 303.9; /* purple.500 */
|
|
@@ -123,61 +125,59 @@
|
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
.dark {
|
|
126
|
-
/* General purpose colors */
|
|
127
|
-
--agentprism-background:
|
|
128
|
-
--agentprism-foreground:
|
|
129
|
-
--agentprism-primary:
|
|
130
|
-
--agentprism-primary-foreground:
|
|
131
|
-
--agentprism-
|
|
132
|
-
--agentprism-
|
|
133
|
-
--agentprism-
|
|
134
|
-
--agentprism-
|
|
135
|
-
--agentprism-
|
|
136
|
-
--agentprism-
|
|
137
|
-
--agentprism-accent: 96.7% 0.003 264.542; /* gray.100 */
|
|
138
|
-
--agentprism-accent-foreground: 21% 0.034 264.665; /* gray.900 */
|
|
128
|
+
/* General purpose colors — warm ink dark ramp (orcheo-design-system) */
|
|
129
|
+
--agentprism-background: 16.3% 0.004 106.847; /* ink-950 */
|
|
130
|
+
--agentprism-foreground: 93.4% 0.014 88.686; /* ink-100 */
|
|
131
|
+
--agentprism-primary: 93.4% 0.014 88.686; /* ink-100 */
|
|
132
|
+
--agentprism-primary-foreground: 16.3% 0.004 106.847; /* ink-950 */
|
|
133
|
+
--agentprism-secondary: 27.3% 0.009 88.77; /* ink-800 */
|
|
134
|
+
--agentprism-secondary-foreground: 66.5% 0.023 85.959; /* ink-400 */
|
|
135
|
+
--agentprism-muted: 21.3% 0.006 91.63; /* ink-900 */
|
|
136
|
+
--agentprism-muted-foreground: 66.5% 0.023 85.959; /* ink-400 */
|
|
137
|
+
--agentprism-accent: 27.3% 0.009 88.77; /* ink-800 */
|
|
138
|
+
--agentprism-accent-foreground: 93.4% 0.014 88.686; /* ink-100 */
|
|
139
139
|
|
|
140
140
|
/* Brand colors */
|
|
141
|
-
--agentprism-brand:
|
|
141
|
+
--agentprism-brand: 71.1% 0.179 48.062; /* orange-500 */
|
|
142
142
|
--agentprism-brand-foreground: 1 0 0; /* white */
|
|
143
|
-
--agentprism-brand-secondary:
|
|
143
|
+
--agentprism-brand-secondary: 69.5% 0.092 72.981; /* tan-500 */
|
|
144
144
|
--agentprism-brand-secondary-foreground: 1 0 0; /* white */
|
|
145
145
|
|
|
146
146
|
/* Borders */
|
|
147
|
-
--agentprism-border:
|
|
148
|
-
--agentprism-border-subtle:
|
|
149
|
-
--agentprism-border-strong:
|
|
150
|
-
--agentprism-border-inverse:
|
|
147
|
+
--agentprism-border: 34.9% 0.013 87.556; /* ink-700 */
|
|
148
|
+
--agentprism-border-subtle: 27.3% 0.009 88.77; /* ink-800 */
|
|
149
|
+
--agentprism-border-strong: 44.3% 0.015 86.885; /* ink-600 */
|
|
150
|
+
--agentprism-border-inverse: 87.7% 0.02 87.522; /* ink-200 */
|
|
151
151
|
|
|
152
152
|
/* Success status color */
|
|
153
|
-
--agentprism-success:
|
|
154
|
-
--agentprism-success-muted:
|
|
155
|
-
--agentprism-success-muted-foreground:
|
|
153
|
+
--agentprism-success: 52.9% 0.103 156.217; /* green-500 */
|
|
154
|
+
--agentprism-success-muted: 29.7% 0.053 156.812; /* dark forest tint */
|
|
155
|
+
--agentprism-success-muted-foreground: 77.1% 0.081 159.669;
|
|
156
156
|
|
|
157
157
|
/* Error status color */
|
|
158
|
-
--agentprism-error:
|
|
159
|
-
--agentprism-error-muted:
|
|
160
|
-
--agentprism-error-muted-foreground:
|
|
158
|
+
--agentprism-error: 57.3% 0.184 32.327; /* red-500 */
|
|
159
|
+
--agentprism-error-muted: 26.5% 0.076 33.199; /* dark warm-red tint */
|
|
160
|
+
--agentprism-error-muted-foreground: 74.1% 0.111 33.398;
|
|
161
161
|
|
|
162
162
|
/* Warning status color */
|
|
163
|
-
--agentprism-warning:
|
|
164
|
-
--agentprism-warning-muted:
|
|
165
|
-
--agentprism-warning-muted-foreground:
|
|
163
|
+
--agentprism-warning: 72.9% 0.147 78.341; /* amber-500 */
|
|
164
|
+
--agentprism-warning-muted: 31.6% 0.06 79.88; /* dark ochre tint */
|
|
165
|
+
--agentprism-warning-muted-foreground: 81.5% 0.114 84.939;
|
|
166
166
|
|
|
167
167
|
/* Pending status color */
|
|
168
|
-
--agentprism-pending:
|
|
169
|
-
--agentprism-pending-muted:
|
|
170
|
-
--agentprism-pending-muted-foreground:
|
|
168
|
+
--agentprism-pending: 52.2% 0.082 245.431; /* blue-500 */
|
|
169
|
+
--agentprism-pending-muted: 27.9% 0.039 244.504; /* dark slate-blue tint */
|
|
170
|
+
--agentprism-pending-muted-foreground: 75.9% 0.061 243.329;
|
|
171
171
|
|
|
172
172
|
/* Code syntax highlighting */
|
|
173
|
-
--agentprism-code-string:
|
|
174
|
-
--agentprism-code-number:
|
|
175
|
-
--agentprism-code-key:
|
|
176
|
-
--agentprism-code-base:
|
|
173
|
+
--agentprism-code-string: 74.1% 0.111 33.398; /* warm red, lightened */
|
|
174
|
+
--agentprism-code-number: 74.1% 0.111 33.398;
|
|
175
|
+
--agentprism-code-key: 75.9% 0.061 243.329; /* slate blue, lightened */
|
|
176
|
+
--agentprism-code-base: 66.5% 0.023 85.959; /* ink-400 */
|
|
177
177
|
|
|
178
178
|
/* Generic badge colors */
|
|
179
|
-
--agentprism-badge-default: 21% 0.
|
|
180
|
-
--agentprism-badge-default-foreground:
|
|
179
|
+
--agentprism-badge-default: 21.3% 0.006 91.63; /* ink-900 */
|
|
180
|
+
--agentprism-badge-default-foreground: 66.5% 0.023 85.959; /* ink-400 */
|
|
181
181
|
|
|
182
182
|
/* Trace colors (llm) */
|
|
183
183
|
--agentprism-avatar-llm: 82.7% 0.119 306.383; /* purple.300 */
|
|
@@ -50,10 +50,10 @@ const extractVersionRecord = (
|
|
|
50
50
|
lookup: WorkflowLookup,
|
|
51
51
|
) => {
|
|
52
52
|
const inputs = history.inputs ?? {};
|
|
53
|
-
const metadata = (inputs.metadata ??
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const metadata = (inputs.metadata ??
|
|
54
|
+
inputs.workflow ??
|
|
55
|
+
inputs.canvas ??
|
|
56
|
+
{}) as Record<string, unknown>;
|
|
57
57
|
const versionIdRaw = metadata?.workflow_version_id;
|
|
58
58
|
if (typeof versionIdRaw === "string" && versionIdRaw) {
|
|
59
59
|
return lookup.versions.get(versionIdRaw);
|
|
@@ -31,17 +31,10 @@ export type WorkflowLookup = {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export type WorkflowExecutionStatus =
|
|
34
|
-
| "
|
|
35
|
-
| "success"
|
|
36
|
-
| "failed"
|
|
37
|
-
| "partial";
|
|
34
|
+
"running" | "success" | "failed" | "partial";
|
|
38
35
|
|
|
39
36
|
export type WorkflowExecutionNodeStatus =
|
|
40
|
-
| "
|
|
41
|
-
| "running"
|
|
42
|
-
| "success"
|
|
43
|
-
| "error"
|
|
44
|
-
| "warning";
|
|
37
|
+
"idle" | "running" | "success" | "error" | "warning";
|
|
45
38
|
|
|
46
39
|
export interface WorkflowExecutionNode {
|
|
47
40
|
id: string;
|