@oomol-lab/open-flow 0.1.0-beta.66 → 0.1.0-beta.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/browser/{createResourceDialog-C-Si_cYs.js → createResourceDialog-BQVD8Rqb.js} +2 -2
  2. package/dist/browser/{icons-BD3m0RQq.js → dialog-CS2Vt2if.js} +1225 -1224
  3. package/dist/browser/event-sources.d.ts +4 -1
  4. package/dist/browser/flow-authoring-node.d.ts +2 -0
  5. package/dist/browser/flow-authoring.js +6 -5
  6. package/dist/browser/flow-change.js +6 -5
  7. package/dist/browser/{flowChanges-T4_R5p1f.js → flowChanges-VB9Y4iy7.js} +2186 -1939
  8. package/dist/browser/{flowWorkspace-C0J5C0oM.js → flowWorkspace-C1hlTnZq.js} +801 -666
  9. package/dist/browser/preview.css +121 -55
  10. package/dist/browser/preview.js +34156 -33896
  11. package/dist/browser/theme.css +1 -0
  12. package/dist/browser/ui.css +34 -4
  13. package/dist/browser/workbench-contract.d.ts +1 -1
  14. package/dist/browser/workbench.css +130 -98
  15. package/dist/browser/workbench.d.ts +0 -1
  16. package/dist/browser/workbench.js +361 -120
  17. package/dist/browser/{workbenchSelect-B-PFpF_Q.js → workbenchSelect-CpXhjUou.js} +1 -1
  18. package/dist/command/index.js +25 -25
  19. package/dist/common/authoringExamples.d.ts +2 -2
  20. package/dist/common/control-api-conformance.js +31 -9
  21. package/dist/common/control-api.d.ts +4 -1
  22. package/dist/common/control-api.js +15 -5
  23. package/dist/common/control-requests.js +7 -6
  24. package/dist/common/decision.js +5 -4
  25. package/dist/common/flow-encoding.js +7 -4
  26. package/dist/common/flow-semantics.js +11 -8
  27. package/dist/common/integration-trigger.js +5 -4
  28. package/dist/common/mcp.js +16 -6
  29. package/dist/common/openapi.js +5 -4
  30. package/dist/common/poll-trigger.js +5 -4
  31. package/dist/common/scheduler.js +5 -4
  32. package/dist/common/webhook-trigger.js +5 -4
  33. package/dist/common/workflow.js +5 -4
  34. package/package.json +1 -1
  35. package/skills/open-flow/SKILL.md +9 -0
  36. package/skills/open-flow/references/flow-authoring.md +2 -0
@@ -1,7 +1,7 @@
1
- import { $n as normalizeTriggerOutputs, $t as EmptyHeader, At as updateStartInputDefs, B as scopedValue, Cr as inputValue, Ct as setNodePositions, Dr as string, Dt as setConnectorConnection, Er as record, Et as setCodeActions, Ft as followWorkbenchLink, G as connectorActionPorts, Gn as errorNotice, I as feishuResourceKind, It as Popover, Jn as allConnectorConnectionsQuery, Jt as InputGroupAddon, K as designerGraph, Kn as WorkbenchClient, L as supportsFeishuChatFilter, Lt as PopoverContent, Mn as createI18n, Mr as IconThemeContext, Mt as updateTriggerSchedule, N as addNodeIntent, Nt as WorkflowExportMenuItem, On as Badge, Or as ApiError, Ot as setInputSources, P as deriveAddNodeOptions, Pt as IdTooltip, Qt as EmptyDescription, R as combineSources, St as setNodeContentHidden, Tr as jsonValue, Tt as resetInputValues, U as resourceData, V as CacheResource, Vt as PopoverTitle, W as resourceValue, X as providerIcon, Xn as decodeTriggerCatalog, Xt as Empty, Yt as InputGroupInput, Zt as EmptyContent, _ as updateTaskPorts, _t as flowPresentation, a as nameCreatedNodes, ar as encodeWorkflowFile, at as revisionView, br as workflowCandidate, bt as setComment, c as updateCondition, cr as workflowNameFromFile, ct as deriveInspectorDiagnostics, d as updateNodeName, dr as providerIconAppearance, en as EmptyMedia, er as sampleErrorOutputs, f as updateNodeSettings, g as updateTaskAdditionalInputs, gt as commentIds, h as updateTask, ht as canvasPresentationChange, i as deleteSelection, in as DropdownMenuContent, ir as connectorActionMetadata, jt as updateTriggerConfig, kn as EventSourcesPage, kr as controlErrorCode, kt as setTriggerConnection, l as updateNodeDescription, lt as diagnosticItems, m as updateResolution, mn as DropdownMenuTrigger, mt as connectionCatalog, nn as DropdownMenu, nr as isJsonObject, nt as RunStore, o as setInputValue, on as DropdownMenuItem, or as parseWorkflowFile, ot as flowResourceReferences, p as updateOutputPorts, pt as actionWithConnections, qn as randomId, qt as InputGroup, r as applyFlowChanges, rr as connection, s as setInputVariable, sr as workflowFileName, st as Latest, t as addNode, tn as EmptyTitle, tr as triggerOutputDefinitions, u as updateNodeIcon, un as DropdownMenuSeparator, v as updateValue, vt as removeComments, wr as invalidResponse, wt as repairNodeNames, xt as setFlowViewport, y as updateWebhook, yt as restoreCanvasPresentation } from "./flowChanges-T4_R5p1f.js";
1
+ import { $t as EmptyDescription, An as EventSourcesPage, Ar as controlErrorCode, At as setTriggerConnection, B as scopedValue, Ct as setNodePositions, Dr as record, Dt as setConnectorConnection, Er as jsonValue, Et as setCodeActions, Ft as IdTooltip, G as connectorActionPorts, Ht as PopoverTitle, I as feishuResourceKind, It as followWorkbenchLink, Jn as randomId, Jt as InputGroup, K as designerGraph, Kn as errorNotice, L as supportsFeishuChatFilter, Lt as Popover, Mt as updateTriggerConfig, N as addNodeIntent, Nn as createI18n, Nr as IconThemeContext, Nt as updateTriggerSchedule, Or as string, Ot as setInputSources, P as deriveAddNodeOptions, Pt as WorkflowExportMenuItem, Qt as EmptyContent, R as combineSources, Rt as PopoverContent, St as setNodeContentHidden, Tr as invalidResponse, Tt as resetInputValues, U as resourceData, Ut as PopoverTrigger, V as CacheResource, W as resourceValue, X as providerIcon, Xt as InputGroupInput, Yn as allConnectorConnectionsQuery, Yt as InputGroupAddon, Zn as decodeTriggerCatalog, Zt as Empty, _ as updateTaskPorts, _t as flowPresentation, a as nameCreatedNodes, an as DropdownMenuContent, ar as connectorActionMetadata, at as revisionView, bt as setComment, c as updateCondition, cr as workflowFileName, ct as deriveInspectorDiagnostics, d as updateNodeName, dn as DropdownMenuSeparator, en as EmptyHeader, er as normalizeTriggerOutputs, f as updateNodeSettings, fr as providerIconAppearance, g as updateTaskAdditionalInputs, gt as commentIds, h as updateTask, hn as DropdownMenuTrigger, ht as canvasPresentationChange, i as deleteSelection, ir as connection, jt as updateStartInputDefs, kn as Badge, kr as ApiError, kt as setServiceConnections, l as updateNodeDescription, lr as workflowNameFromFile, lt as diagnosticItems, m as updateResolution, mt as connectionCatalog, nn as EmptyTitle, nr as triggerOutputDefinitions, nt as RunStore, o as setInputValue, or as encodeWorkflowFile, ot as flowResourceReferences, p as updateOutputPorts, pt as actionWithConnections, qn as WorkbenchClient, r as applyFlowChanges, rn as DropdownMenu, rr as isJsonObject, s as setInputVariable, sn as DropdownMenuItem, sr as parseWorkflowFile, st as Latest, t as addNode, tn as EmptyMedia, tr as sampleErrorOutputs, u as updateNodeIcon, v as updateValue, vt as removeComments, wr as inputValue, wt as repairNodeNames, xr as workflowCandidate, xt as setFlowViewport, y as updateWebhook, yt as restoreCanvasPresentation } from "./flowChanges-VB9Y4iy7.js";
2
2
  import { a as derive, i as compute, l as val } from "./dist-bO8nvHFH.js";
3
3
  import { c as useLang, l as useTranslate, o as I18nProvider, u as useVal } from "./dist-BFmpkX4P.js";
4
- import { B as upgradeManualTrigger, E as FieldLabel, Ei as cn, G as mapConditionSources, K as nodeInputMappings, M as applyFlowChanges$1, P as isTriggerNode, S as Field, T as FieldGroup, Tt as dequal$1, V as upgradeRevisionContent, a as DialogDescription, c as DialogTitle, d as TooltipContent, fr as Input, i as DialogContent, j as FlowChangeError, n as Dialog, o as DialogFooter, p as TooltipTrigger, r as DialogClose, s as DialogHeader, t as Icon, u as Tooltip, w as FieldError, wi as Button, x as Spinner, z as resourceNameIssue } from "./icons-BD3m0RQq.js";
4
+ import { B as upgradeManualTrigger, E as FieldLabel, Ei as cn, G as mapConditionSources, K as nodeInputMappings, M as applyFlowChanges$1, P as isTriggerNode, S as Field, T as FieldGroup, Tt as dequal$1, V as upgradeRevisionContent, a as DialogFooter, d as TooltipContent, fr as Input, i as DialogDescription, j as FlowChangeError, l as Icon, o as DialogHeader, p as TooltipTrigger, r as DialogContent, s as DialogTitle, t as Dialog, u as Tooltip, w as FieldError, wi as Button, x as Spinner, z as resourceNameIssue } from "./dialog-CS2Vt2if.js";
5
5
  import { c as importedWorkflowName, d as uiLanguageNames, f as uiLanguages, l as isUiLanguage, u as resolveUiLanguage } from "./value-BADHeZ9I.js";
6
6
  import { Suspense, forwardRef, lazy, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -189,24 +189,199 @@ function Skeleton({ className, ...props }) {
189
189
  });
190
190
  }
191
191
  //#endregion
192
- //#region src/workbench/browser/runtime/shell/resourceBrowser.tsx
193
- var CreateResourceDialog = lazy(() => import("./createResourceDialog-C-Si_cYs.js"));
194
- var flowIdTooltipAlignOffset = 44;
195
- var renamePopoverAlignOffset = -12;
196
- function compactFlowId(flowId) {
197
- return flowId.length <= 20 ? flowId : `${flowId.slice(0, 10)}…${flowId.slice(-6)}`;
192
+ //#region src/workbench/browser/runtime/shell/flowReferences.tsx
193
+ function useFlowReferences(flowId, workspace) {
194
+ const [result, setResult] = useState();
195
+ const [status, setStatus] = useState("loading");
196
+ const [offset, setOffset] = useState(0);
197
+ const [attempt, setAttempt] = useState(0);
198
+ useEffect(() => {
199
+ const controller = new AbortController();
200
+ setStatus("loading");
201
+ workspace.getFlowReferences(flowId, {
202
+ offset,
203
+ signal: controller.signal
204
+ }).then((page) => {
205
+ if (controller.signal.aborted) return;
206
+ setResult((previous) => {
207
+ const references = new Map((offset == 0 ? [] : previous?.references ?? []).map((item) => [item.flowId, item]));
208
+ for (const item of page.references) references.set(item.flowId, item);
209
+ return {
210
+ ...page,
211
+ references: [...references.values()]
212
+ };
213
+ });
214
+ setStatus("ready");
215
+ }, () => {
216
+ if (controller.signal.aborted) return;
217
+ setStatus("failed");
218
+ });
219
+ return () => controller.abort();
220
+ }, [
221
+ workspace,
222
+ flowId,
223
+ offset,
224
+ attempt
225
+ ]);
226
+ return {
227
+ result,
228
+ status,
229
+ retry: () => {
230
+ setStatus("loading");
231
+ setAttempt((value) => value + 1);
232
+ },
233
+ loadMore: () => {
234
+ if (status != "ready" || result?.nextOffset == null) return;
235
+ setStatus("loading");
236
+ setOffset(result.nextOffset);
237
+ }
238
+ };
198
239
  }
199
- function formatUpdatedAt(updatedAt, locale) {
200
- const date = new Date(updatedAt);
201
- const current = /* @__PURE__ */ new Date();
202
- return date.toLocaleString(locale, {
203
- day: "numeric",
204
- hour: "2-digit",
205
- minute: "2-digit",
206
- month: "short",
207
- year: date.getFullYear() == current.getFullYear() ? void 0 : "numeric"
240
+ function FlowReferenceQuery({ flowId, workspace, ...navigation }) {
241
+ return /* @__PURE__ */ jsx(FlowReferenceResults, {
242
+ state: useFlowReferences(flowId, workspace),
243
+ ...navigation
244
+ });
245
+ }
246
+ function FlowReferenceResults({ state, hrefForFlow, onSelectFlow, showEmpty = true, summary, disabled = false }) {
247
+ const t = useTranslate();
248
+ const { result, status } = state;
249
+ const list = result != null && result.references.length > 0 && /* @__PURE__ */ jsxs("div", {
250
+ className: "space-y-3",
251
+ children: [/* @__PURE__ */ jsx("ul", {
252
+ className: "m-0 max-h-64 list-none space-y-3 overflow-y-auto p-0",
253
+ children: result.references.map((item) => {
254
+ const defaultView = item.draft ? "design" : "publications";
255
+ return /* @__PURE__ */ jsxs("li", {
256
+ className: "flex items-start justify-between gap-3",
257
+ children: [/* @__PURE__ */ jsxs("a", {
258
+ className: "flex min-w-0 items-start gap-2 text-foreground no-underline hover:underline",
259
+ href: hrefForFlow(item, defaultView),
260
+ onClick: (event) => followWorkbenchLink(event, () => onSelectFlow(item, defaultView)),
261
+ children: [/* @__PURE__ */ jsx("i", {
262
+ "aria-hidden": "true",
263
+ className: "i-lucide-light:workflow mt-0.5 size-4 shrink-0 text-muted-foreground"
264
+ }), /* @__PURE__ */ jsx("span", {
265
+ className: "min-w-0 break-words",
266
+ children: item.name ?? item.flowId
267
+ })]
268
+ }), /* @__PURE__ */ jsxs("div", {
269
+ className: "flex shrink-0 flex-wrap justify-end gap-1",
270
+ children: [item.draft && /* @__PURE__ */ jsx("a", {
271
+ className: "rounded-md bg-muted px-2 py-0.5 text-muted-foreground no-underline hover:underline",
272
+ href: hrefForFlow(item, "design"),
273
+ onClick: (event) => followWorkbenchLink(event, () => onSelectFlow(item, "design")),
274
+ children: t("flowReferences.draft")
275
+ }), item.live != null && /* @__PURE__ */ jsxs("a", {
276
+ className: "rounded-md bg-muted px-2 py-0.5 text-muted-foreground no-underline hover:underline",
277
+ href: hrefForFlow(item, "publications"),
278
+ onClick: (event) => followWorkbenchLink(event, () => onSelectFlow(item, "publications")),
279
+ children: [t("flowReferences.live"), !item.live.enabled && ` · ${t("flowReferences.disabled")}`]
280
+ })]
281
+ })]
282
+ }, item.flowId);
283
+ })
284
+ }), status != "failed" && result?.nextOffset != null && /* @__PURE__ */ jsx(Button, {
285
+ variant: "outline",
286
+ size: "sm",
287
+ disabled: disabled || status == "loading",
288
+ onClick: state.loadMore,
289
+ children: t("flowReferences.loadMore")
290
+ })]
291
+ });
292
+ return /* @__PURE__ */ jsxs("div", {
293
+ className: "space-y-3 text-sm",
294
+ children: [
295
+ summary != null && list ? /* @__PURE__ */ jsxs("details", {
296
+ className: "group rounded-lg border border-border",
297
+ children: [/* @__PURE__ */ jsxs("summary", {
298
+ className: "flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 text-sm font-medium [&::-webkit-details-marker]:hidden",
299
+ children: [/* @__PURE__ */ jsx("i", {
300
+ "aria-hidden": "true",
301
+ className: "i-lucide-light:chevron-right shrink-0 text-muted-foreground group-open:rotate-90"
302
+ }), /* @__PURE__ */ jsx("span", { children: summary })]
303
+ }), /* @__PURE__ */ jsx("div", {
304
+ className: "border-t border-border py-3 pr-3 pl-[calc(1.25rem+1em)]",
305
+ children: list
306
+ })]
307
+ }) : list,
308
+ status == "loading" && /* @__PURE__ */ jsx("p", {
309
+ className: "m-0 text-muted-foreground",
310
+ role: "status",
311
+ children: t("flowReferences.loading")
312
+ }),
313
+ status == "failed" && /* @__PURE__ */ jsxs("div", {
314
+ className: "space-y-2",
315
+ role: "alert",
316
+ children: [/* @__PURE__ */ jsx("p", {
317
+ className: "m-0 text-muted-foreground",
318
+ children: t("flowReferences.failed")
319
+ }), /* @__PURE__ */ jsx(Button, {
320
+ variant: "outline",
321
+ size: "sm",
322
+ disabled,
323
+ onClick: state.retry,
324
+ children: t("flowReferences.retry")
325
+ })]
326
+ }),
327
+ showEmpty && status == "ready" && result?.references.length == 0 && /* @__PURE__ */ jsx("p", {
328
+ className: "m-0 text-muted-foreground",
329
+ children: t("flowReferences.empty")
330
+ })
331
+ ]
208
332
  });
209
333
  }
334
+ function FlowReferencesButton(props) {
335
+ const referenceCount = props.flow.referenceCount;
336
+ if (referenceCount == null || referenceCount == 0) return null;
337
+ return /* @__PURE__ */ jsx(FlowReferencesPopover, {
338
+ ...props,
339
+ referenceCount
340
+ }, props.flow.flowId);
341
+ }
342
+ function FlowReferencesPopover({ flow, referenceCount, workspace, container, hrefForFlow, onSelectFlow }) {
343
+ const t = useTranslate();
344
+ const [open, setOpen] = useState(false);
345
+ const label = t("flowReferences.count", { count: referenceCount });
346
+ return /* @__PURE__ */ jsxs(Popover, {
347
+ open,
348
+ onOpenChange: setOpen,
349
+ children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsxs(TooltipTrigger, {
350
+ render: /* @__PURE__ */ jsx(PopoverTrigger, { render: /* @__PURE__ */ jsx(Button, {
351
+ "aria-label": label,
352
+ variant: "ghost",
353
+ size: "sm",
354
+ className: "text-muted-foreground"
355
+ }) }),
356
+ children: [/* @__PURE__ */ jsx("i", {
357
+ "aria-hidden": "true",
358
+ className: "i-lucide-light:link"
359
+ }), /* @__PURE__ */ jsx("span", { children: referenceCount })]
360
+ }), /* @__PURE__ */ jsx(TooltipContent, {
361
+ container,
362
+ collisionBoundary: [],
363
+ positionMethod: "fixed",
364
+ children: label
365
+ })] }), /* @__PURE__ */ jsxs(PopoverContent, {
366
+ container,
367
+ collisionBoundary: [],
368
+ positionMethod: "fixed",
369
+ align: "end",
370
+ className: "w-96 max-w-[calc(100vw-2rem)] max-h-(--available-height) overflow-y-auto gap-4 p-4",
371
+ children: [/* @__PURE__ */ jsx(PopoverTitle, {
372
+ className: "break-words text-base font-semibold",
373
+ children: t("flowReferences.title", { name: flow.name })
374
+ }), open && /* @__PURE__ */ jsx(FlowReferenceQuery, {
375
+ flowId: flow.flowId,
376
+ workspace,
377
+ hrefForFlow,
378
+ onSelectFlow
379
+ })]
380
+ })]
381
+ });
382
+ }
383
+ //#endregion
384
+ //#region src/workbench/browser/runtime/shell/flowDeletionDialog.tsx
210
385
  function FlowDeletionImpact({ listeners, failed, onRetry }) {
211
386
  const t = useTranslate();
212
387
  if (failed) return /* @__PURE__ */ jsxs("div", {
@@ -228,11 +403,17 @@ function FlowDeletionImpact({ listeners, failed, onRetry }) {
228
403
  children: t("sidebar.listenersLoading")
229
404
  });
230
405
  if (listeners.length == 0) return null;
231
- return /* @__PURE__ */ jsxs("div", {
232
- className: "min-w-0 space-y-3 text-sm",
233
- children: [
234
- /* @__PURE__ */ jsx("p", { children: t("sidebar.listenersTitle") }),
235
- /* @__PURE__ */ jsx("ul", {
406
+ return /* @__PURE__ */ jsxs("details", {
407
+ className: "group rounded-lg border border-border text-sm",
408
+ children: [/* @__PURE__ */ jsxs("summary", {
409
+ className: "flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 font-medium [&::-webkit-details-marker]:hidden",
410
+ children: [/* @__PURE__ */ jsx("i", {
411
+ "aria-hidden": "true",
412
+ className: "i-lucide-light:chevron-right shrink-0 text-muted-foreground group-open:rotate-90"
413
+ }), /* @__PURE__ */ jsx("span", { children: t("flowReferences.deleteListeners", { count: listeners.length }) })]
414
+ }), /* @__PURE__ */ jsxs("div", {
415
+ className: "space-y-3 border-t border-border py-3 pr-3 pl-[calc(1.25rem+1em)]",
416
+ children: [/* @__PURE__ */ jsx("ul", {
236
417
  className: "m-0 max-h-48 list-none space-y-2 overflow-y-auto p-0",
237
418
  children: listeners.map((listener) => /* @__PURE__ */ jsxs("li", {
238
419
  className: "break-words",
@@ -249,46 +430,117 @@ function FlowDeletionImpact({ listeners, failed, onRetry }) {
249
430
  })
250
431
  ]
251
432
  }, `${listener.flowId}/${listener.nodeId}`))
252
- }),
253
- /* @__PURE__ */ jsx("p", {
254
- className: "text-muted-foreground",
433
+ }), /* @__PURE__ */ jsx("p", {
434
+ className: "m-0 text-muted-foreground",
255
435
  children: t("sidebar.listenersImpact")
256
- })
257
- ]
436
+ })]
437
+ })]
258
438
  });
259
439
  }
260
- function FlowItem({ showTeam, badge, busy, flow, href, onSelect, store }) {
261
- const [root, setRoot] = useState(null);
262
- const renameAnchor = useRef(null);
263
- const actionsButton = useRef(null);
264
- const nameInput = useRef(null);
265
- const cancelDelete = useRef(null);
266
- const locale = useLang();
440
+ function FlowDeletionDialog({ flow, workspace, container, busy, finalFocus, onClose, onDelete, ...navigation }) {
267
441
  const t = useTranslate();
268
- const [mode, setMode] = useState("idle");
269
- const [name, setName] = useState(flow.name);
442
+ const cancel = useRef(null);
443
+ const references = useFlowReferences(flow.flowId, workspace);
270
444
  const [listeners, setListeners] = useState();
271
- const [listenersFailed, setListenersFailed] = useState(false);
272
- const [listenersRetry, setListenersRetry] = useState(0);
445
+ const [listenerStatus, setListenerStatus] = useState("loading");
446
+ const [attempt, setAttempt] = useState(0);
273
447
  useEffect(() => {
274
- if (mode != "delete") return;
275
448
  const controller = new AbortController();
276
449
  setListeners(void 0);
277
- setListenersFailed(false);
278
- store.workspace.getErrorListeners(flow.flowId, controller.signal).then((value) => {
279
- if (!controller.signal.aborted) setListeners(value);
450
+ setListenerStatus("loading");
451
+ workspace.getErrorListeners(flow.flowId, controller.signal).then((value) => {
452
+ if (controller.signal.aborted) return;
453
+ setListeners(value);
454
+ setListenerStatus("ready");
280
455
  }, () => {
281
- if (!controller.signal.aborted) setListenersFailed(true);
456
+ if (!controller.signal.aborted) setListenerStatus("failed");
282
457
  });
283
458
  return () => controller.abort();
284
459
  }, [
285
- mode,
286
460
  flow.flowId,
287
- store,
288
- listenersRetry
461
+ workspace,
462
+ attempt
289
463
  ]);
464
+ const hasReferences = references.result != null && references.result.total > 0;
465
+ const canDelete = busy == null && references.status == "ready" && listenerStatus == "ready";
466
+ return /* @__PURE__ */ jsx(Dialog, {
467
+ open: true,
468
+ onOpenChange: (open) => {
469
+ if (!open && busy == null) onClose();
470
+ },
471
+ children: /* @__PURE__ */ jsxs(DialogContent, {
472
+ container,
473
+ initialFocus: cancel,
474
+ finalFocus,
475
+ showCloseButton: false,
476
+ className: "max-h-[calc(100dvh-2rem)] grid-rows-[auto_minmax(0,1fr)_auto]",
477
+ children: [
478
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, {
479
+ className: "break-words leading-snug",
480
+ children: t("sidebar.deleteFlowConfirm", { name: flow.name })
481
+ }), /* @__PURE__ */ jsx(DialogDescription, { children: t("resource.deleteDescription") })] }),
482
+ /* @__PURE__ */ jsxs("div", {
483
+ className: "min-h-0 space-y-2 overflow-y-auto",
484
+ children: [/* @__PURE__ */ jsx(FlowReferenceResults, {
485
+ state: references,
486
+ disabled: busy != null,
487
+ showEmpty: false,
488
+ summary: hasReferences ? t("flowReferences.deleteImpact", { count: references.result.total }) : void 0,
489
+ ...navigation
490
+ }), /* @__PURE__ */ jsx(FlowDeletionImpact, {
491
+ listeners,
492
+ failed: listenerStatus == "failed",
493
+ onRetry: () => {
494
+ setListenerStatus("loading");
495
+ setAttempt((value) => value + 1);
496
+ }
497
+ })]
498
+ }),
499
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button, {
500
+ ref: cancel,
501
+ variant: "outline",
502
+ disabled: busy != null,
503
+ onClick: onClose,
504
+ children: t("common.cancel")
505
+ }), /* @__PURE__ */ jsx(Button, {
506
+ disabled: !canDelete,
507
+ onClick: onDelete,
508
+ variant: "destructive",
509
+ children: t(busy == "flow" ? "common.deleting" : hasReferences ? "flowReferences.deleteAnyway" : "common.delete")
510
+ })] })
511
+ ]
512
+ })
513
+ });
514
+ }
515
+ //#endregion
516
+ //#region src/workbench/browser/runtime/shell/resourceBrowser.tsx
517
+ var CreateResourceDialog = lazy(() => import("./createResourceDialog-BQVD8Rqb.js"));
518
+ var flowIdTooltipAlignOffset = 44;
519
+ var renamePopoverAlignOffset = -12;
520
+ function compactFlowId(flowId) {
521
+ return flowId.length <= 20 ? flowId : `${flowId.slice(0, 10)}…${flowId.slice(-6)}`;
522
+ }
523
+ function formatUpdatedAt(updatedAt, locale) {
524
+ const date = new Date(updatedAt);
525
+ const current = /* @__PURE__ */ new Date();
526
+ return date.toLocaleString(locale, {
527
+ day: "numeric",
528
+ hour: "2-digit",
529
+ minute: "2-digit",
530
+ month: "short",
531
+ year: date.getFullYear() == current.getFullYear() ? void 0 : "numeric"
532
+ });
533
+ }
534
+ function FlowItem({ busy, flow, href, hrefForFlow, onSelect, store }) {
535
+ const [root, setRoot] = useState(null);
536
+ const renameAnchor = useRef(null);
537
+ const actionsButton = useRef(null);
538
+ const nameInput = useRef(null);
539
+ const locale = useLang();
540
+ const t = useTranslate();
541
+ const [mode, setMode] = useState("idle");
542
+ const [name, setName] = useState(flow.name);
290
543
  const [pending, setPending] = useState();
291
- const hasTeam = showTeam && Boolean(badge?.trim());
292
544
  const changed = flow.live != null && flow.live.revisionId != flow.draftRevisionId;
293
545
  const publicationStatus = flow.status == "retiring" ? "resource.retiring" : flow.live == null ? "resource.notPublished" : changed ? "resource.unpublishedChanges" : "resource.isPublished";
294
546
  const publicationTone = flow.status == "retiring" ? "danger" : flow.live == null ? "neutral" : changed ? "running" : "success";
@@ -316,7 +568,6 @@ function FlowItem({ showTeam, badge, busy, flow, href, onSelect, store }) {
316
568
  children: [
317
569
  /* @__PURE__ */ jsxs("div", {
318
570
  className: "resource-list-row flow-columns",
319
- "data-has-team": hasTeam,
320
571
  children: [
321
572
  /* @__PURE__ */ jsxs("span", {
322
573
  className: "resource-primary-cell",
@@ -439,11 +690,6 @@ function FlowItem({ showTeam, badge, busy, flow, href, onSelect, store }) {
439
690
  alignOffset: flowIdTooltipAlignOffset
440
691
  })
441
692
  }),
442
- showTeam && /* @__PURE__ */ jsx("span", {
443
- className: "resource-team-cell",
444
- title: badge,
445
- children: hasTeam ? badge : "—"
446
- }),
447
693
  /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
448
694
  render: /* @__PURE__ */ jsx("time", {
449
695
  className: "resource-updated-at",
@@ -475,10 +721,16 @@ function FlowItem({ showTeam, badge, busy, flow, href, onSelect, store }) {
475
721
  })
476
722
  ]
477
723
  }),
478
- /* @__PURE__ */ jsx("div", {
724
+ /* @__PURE__ */ jsxs("div", {
479
725
  className: "resource-live-controls",
480
726
  "aria-busy": pending != null,
481
- children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
727
+ children: [/* @__PURE__ */ jsx(FlowReferencesButton, {
728
+ flow,
729
+ workspace: store.workspace,
730
+ container: root,
731
+ hrefForFlow,
732
+ onSelectFlow: onSelect
733
+ }), /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
482
734
  render: /* @__PURE__ */ jsx(DropdownMenuTrigger, { render: /* @__PURE__ */ jsx(Button, {
483
735
  ref: actionsButton,
484
736
  "aria-label": t("resource.actions"),
@@ -569,50 +821,28 @@ function FlowItem({ showTeam, badge, busy, flow, href, onSelect, store }) {
569
821
  }), t("common.delete")]
570
822
  })
571
823
  ]
572
- })] })
824
+ })] })]
573
825
  }),
574
- /* @__PURE__ */ jsx(Dialog, {
575
- open: mode == "delete",
576
- onOpenChange: (open) => {
577
- if (!open) setMode("idle");
578
- },
579
- children: /* @__PURE__ */ jsxs(DialogContent, {
580
- container: root,
581
- initialFocus: cancelDelete,
582
- finalFocus: actionsButton,
583
- showCloseButton: false,
584
- children: [
585
- /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: t("sidebar.deleteFlowConfirm", { name: flow.name }) }), /* @__PURE__ */ jsx(DialogDescription, { children: t("resource.deleteDescription") })] }),
586
- /* @__PURE__ */ jsx(FlowDeletionImpact, {
587
- listeners,
588
- failed: listenersFailed,
589
- onRetry: () => setListenersRetry((value) => value + 1)
590
- }),
591
- /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(DialogClose, {
592
- render: /* @__PURE__ */ jsx(Button, {
593
- ref: cancelDelete,
594
- variant: "outline"
595
- }),
596
- children: t("common.cancel")
597
- }), /* @__PURE__ */ jsx(Button, {
598
- disabled: busy != null || listeners == null && !listenersFailed,
599
- onClick: () => void remove(),
600
- variant: "destructive",
601
- children: t(busy == "flow" ? "common.deleting" : "common.delete")
602
- })] })
603
- ]
604
- })
826
+ mode == "delete" && /* @__PURE__ */ jsx(FlowDeletionDialog, {
827
+ flow,
828
+ workspace: store.workspace,
829
+ container: root,
830
+ busy,
831
+ finalFocus: () => actionsButton.current,
832
+ onClose: () => setMode("idle"),
833
+ onDelete: () => void remove(),
834
+ hrefForFlow,
835
+ onSelectFlow: onSelect
605
836
  })
606
837
  ]
607
838
  });
608
839
  }
609
- function FlowSkeleton({ showTeam }) {
840
+ function FlowSkeleton() {
610
841
  return /* @__PURE__ */ jsxs("div", {
611
842
  "aria-hidden": "true",
612
843
  className: "resource-item-row",
613
844
  children: [/* @__PURE__ */ jsxs("div", {
614
845
  className: "resource-list-row flow-columns",
615
- "data-has-team": showTeam,
616
846
  children: [
617
847
  /* @__PURE__ */ jsxs("span", {
618
848
  className: "resource-primary-cell",
@@ -622,7 +852,6 @@ function FlowSkeleton({ showTeam }) {
622
852
  })]
623
853
  }),
624
854
  /* @__PURE__ */ jsx(Skeleton, { className: "resource-flow-id-cell h-3 w-36 max-w-full" }),
625
- showTeam && /* @__PURE__ */ jsx(Skeleton, { className: "resource-team-cell h-3 w-24 max-w-full" }),
626
855
  /* @__PURE__ */ jsx(Skeleton, { className: "resource-updated-at h-3 w-28 max-w-full" }),
627
856
  /* @__PURE__ */ jsx(Skeleton, { className: "resource-publication-status h-3 w-16" }),
628
857
  /* @__PURE__ */ jsx(Skeleton, { className: "resource-status h-3 w-16" })
@@ -633,7 +862,7 @@ function FlowSkeleton({ showTeam }) {
633
862
  })]
634
863
  });
635
864
  }
636
- var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBadges, hrefForFlow, initializing = false, onCreateFlow, onImportFlow, onSelectFlow, store, language }, ref) {
865
+ var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, hrefForFlow, initializing = false, onCreateFlow, onImportFlow, onSelectFlow, store, language }, ref) {
637
866
  const t = useTranslate();
638
867
  const busy = useVal(store.workspace.$.busy);
639
868
  const loadFailed = useVal(store.workspace.$.flowLoadFailed);
@@ -647,11 +876,9 @@ var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisa
647
876
  const total = useVal(store.workspace.$.flowTotal);
648
877
  const [creation$] = useState(() => val(void 0));
649
878
  const creation = useVal(creation$);
650
- const [importError, setImportError] = useState(false);
651
879
  const fileInput = useRef(null);
652
880
  const [filter, setFilter] = useState("");
653
881
  const [name, setName] = useState("");
654
- const showTeam = flows.some((flow) => (flowBadges?.[flow.flowId]?.trim().length ?? 0) > 0);
655
882
  const normalized = filter.trim().toLocaleLowerCase();
656
883
  const visible = flows.filter((flow) => flow.name.toLocaleLowerCase().includes(normalized));
657
884
  const command = useRef();
@@ -664,12 +891,14 @@ var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisa
664
891
  });
665
892
  function openImport(input) {
666
893
  if (initializing || store.workspace.$.busy.value != null || creation$.value != null || onImportFlow == null) return "unavailable";
667
- setImportError(false);
668
894
  let file;
669
895
  try {
670
896
  file = parseWorkflowFile(input.text);
671
897
  } catch {
672
- setImportError(true);
898
+ store.workspace.notify({
899
+ kind: "error",
900
+ message: t("resource.importInvalid")
901
+ });
673
902
  return "invalid-file";
674
903
  }
675
904
  setName(file.name ?? (input.fileName == null ? importedWorkflowName(language) : workflowNameFromFile(input.fileName)));
@@ -748,13 +977,15 @@ var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisa
748
977
  const file = event.target.files?.[0];
749
978
  event.target.value = "";
750
979
  if (file == null) return;
751
- setImportError(false);
752
980
  file.text().then((text) => {
753
981
  command.current?.({
754
982
  text,
755
983
  fileName: file.name
756
984
  });
757
- }).catch(() => setImportError(true));
985
+ }).catch(() => store.workspace.notify({
986
+ kind: "error",
987
+ message: t("resource.importInvalid")
988
+ }));
758
989
  }
759
990
  }), /* @__PURE__ */ jsx(Button, {
760
991
  variant: "outline",
@@ -774,14 +1005,10 @@ var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisa
774
1005
  ]
775
1006
  })]
776
1007
  }),
777
- importError && /* @__PURE__ */ jsx("p", {
778
- role: "alert",
779
- children: t("resource.importInvalid")
780
- }),
781
1008
  /* @__PURE__ */ jsx("div", {
782
1009
  className: "resource-table-scroll",
783
1010
  children: /* @__PURE__ */ jsxs("div", {
784
- className: cn("resource-table", showTeam && "resource-table-with-teams"),
1011
+ className: "resource-table",
785
1012
  children: [/* @__PURE__ */ jsxs("div", {
786
1013
  "aria-hidden": "true",
787
1014
  className: "resource-list-columns-shell",
@@ -793,10 +1020,6 @@ var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisa
793
1020
  className: "resource-flow-id-heading",
794
1021
  children: t("resource.flowId")
795
1022
  }),
796
- showTeam && /* @__PURE__ */ jsx("span", {
797
- className: "resource-team-heading",
798
- children: t("resource.team")
799
- }),
800
1023
  /* @__PURE__ */ jsx("span", {
801
1024
  className: "resource-updated-heading",
802
1025
  children: t("resource.updated")
@@ -810,7 +1033,7 @@ var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisa
810
1033
  })]
811
1034
  }), /* @__PURE__ */ jsx("div", {
812
1035
  className: "resource-list",
813
- children: loading ? Array.from({ length: 5 }, (_, index) => /* @__PURE__ */ jsx(FlowSkeleton, { showTeam }, index)) : loadFailed ? /* @__PURE__ */ jsxs(Empty, {
1036
+ children: loading ? Array.from({ length: 5 }, (_, index) => /* @__PURE__ */ jsx(FlowSkeleton, {}, index)) : loadFailed ? /* @__PURE__ */ jsxs(Empty, {
814
1037
  className: "min-h-64",
815
1038
  role: "alert",
816
1039
  children: [/* @__PURE__ */ jsxs(EmptyHeader, { children: [
@@ -849,11 +1072,10 @@ var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisa
849
1072
  }), t("resource.newFlow")]
850
1073
  }) })]
851
1074
  }) : visible.map((flow) => /* @__PURE__ */ jsx(FlowItem, {
852
- showTeam,
853
- badge: flowBadges?.[flow.flowId],
854
1075
  busy,
855
1076
  flow,
856
1077
  href: hrefForFlow(flow),
1078
+ hrefForFlow,
857
1079
  onSelect: onSelectFlow,
858
1080
  store
859
1081
  }, flow.flowId))
@@ -3496,7 +3718,7 @@ function connectionDiagnostics(revision, actions, catalogs) {
3496
3718
  const diagnostics = [];
3497
3719
  for (const { nodeId, actionId, connectionId } of revision.connectorNodes()) {
3498
3720
  const action = actions[actionId];
3499
- if (action?.authenticated != true) continue;
3721
+ if (action?.authenticated != true || connectionId === "") continue;
3500
3722
  const connection = connectionId == null ? void 0 : catalogs[action.serviceId]?.byId.get(connectionId);
3501
3723
  if (connectionId != null && (catalogs[action.serviceId] == null || connection?.status == "active")) continue;
3502
3724
  diagnostics.push({
@@ -4893,11 +5115,12 @@ var FlowCatalog = class {
4893
5115
  limit: pageLimit
4894
5116
  });
4895
5117
  if (!current()) return;
4896
- const seen = new Set(this.#state.value.flows.map((flow) => flow.flowId));
5118
+ const flows = new Map(this.#state.value.flows.map((flow) => [flow.flowId, flow]));
5119
+ for (const flow of page.flows) flows.set(flow.flowId, flow);
4897
5120
  this.#set({
4898
5121
  loadingMore: false,
4899
5122
  nextCursor: page.nextCursor,
4900
- flows: [...this.#state.value.flows, ...page.flows.filter((flow) => !seen.has(flow.flowId))]
5123
+ flows: [...flows.values()]
4901
5124
  });
4902
5125
  } catch (error) {
4903
5126
  if (!current()) return;
@@ -4959,7 +5182,11 @@ var FlowCatalog = class {
4959
5182
  this.#set({ flows: [...this.#state.value.flows, flow] });
4960
5183
  return;
4961
5184
  }
4962
- this.#set({ flows: this.#state.value.flows.with(index, flow) });
5185
+ const referenceCount = this.#state.value.flows[index].referenceCount;
5186
+ this.#set({ flows: this.#state.value.flows.with(index, {
5187
+ ...flow,
5188
+ ...referenceCount == null ? {} : { referenceCount }
5189
+ }) });
4963
5190
  }
4964
5191
  insert(flow) {
4965
5192
  if (this.#state.value.flows.some((candidate) => candidate.flowId == flow.flowId)) return;
@@ -5393,6 +5620,9 @@ var WorkspaceStore = class {
5393
5620
  this.filterTriggerConnections = filterTriggerConnections;
5394
5621
  this.#canvasCommandListeners = /* @__PURE__ */ new Set();
5395
5622
  this.#draftSession = new Latest();
5623
+ this.notify = (notice) => {
5624
+ if (!this.#disposed) this.#setNotice(notice);
5625
+ };
5396
5626
  this.#history = new CanvasHistory();
5397
5627
  this.history$ = this.#history.state$;
5398
5628
  this.#diagnosticFocusId = 0;
@@ -5682,6 +5912,13 @@ var WorkspaceStore = class {
5682
5912
  this.#set({ busy: void 0 });
5683
5913
  }
5684
5914
  }
5915
+ getFlowReferences(flowId, options = {}) {
5916
+ return this.#client.getFlowReferences(flowId, {
5917
+ ...options,
5918
+ direction: "incoming",
5919
+ limit: 50
5920
+ });
5921
+ }
5685
5922
  getErrorListeners(flowId, signal) {
5686
5923
  return this.#client.getErrorListeners(flowId, signal);
5687
5924
  }
@@ -6024,6 +6261,12 @@ var WorkspaceStore = class {
6024
6261
  const changes = setConnectorConnection(revision.revision.content, nodeId, connectionId);
6025
6262
  return changes != null && await this.#editDraft(changes) != null;
6026
6263
  }
6264
+ async setServiceConnections(providerId, connectionId, previousConnectionId) {
6265
+ const revision = this.$.revision.value;
6266
+ if (revision == null) return false;
6267
+ const changes = setServiceConnections(revision.revision.content, providerId, connectionId, previousConnectionId);
6268
+ return changes.length == 0 || await this.#editDraft(changes) != null;
6269
+ }
6027
6270
  async setCodeActions(nodeId, capabilities) {
6028
6271
  const revision = this.$.revision.value;
6029
6272
  if (revision == null) return false;
@@ -6941,7 +7184,7 @@ var WorkbenchStore = class {
6941
7184
  };
6942
7185
  //#endregion
6943
7186
  //#region src/workbench/browser/runtime/openFlowWorkbench.tsx
6944
- var FlowWorkspace = lazy(() => import("./flowWorkspace-C0J5C0oM.js"));
7187
+ var FlowWorkspace = lazy(() => import("./flowWorkspace-C1hlTnZq.js"));
6945
7188
  function OpenFlowSessionGate({ action, description, error, onSubmit, onTokenChange, pending = false, title, token, tokenLabel }) {
6946
7189
  const hasToken = token != null && tokenLabel != null && onTokenChange != null;
6947
7190
  const tokenValue = token ?? "";
@@ -7047,7 +7290,7 @@ function FlowNameBridge({ store, onChange }) {
7047
7290
  useEffect(() => () => onChange(void 0), [onChange]);
7048
7291
  return null;
7049
7292
  }
7050
- function Workbench({ importRef, catalogWidth, createFlow, importFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, hrefFor, initializing, language, navigation, onConfigureConnector, onManageConnectorAccess, onLanguageChange, store, theme }) {
7293
+ function Workbench({ importRef, catalogWidth, createFlow, importFlow, createFlowDisabled, createFlowField, connectionHref, hrefFor, initializing, language, navigation, onConfigureConnector, onManageConnectorAccess, onLanguageChange, store, theme }) {
7051
7294
  const flowId = useVal(store.workspace.$.flowId);
7052
7295
  return /* @__PURE__ */ jsx("div", {
7053
7296
  className: "app-shell",
@@ -7056,10 +7299,9 @@ function Workbench({ importRef, catalogWidth, createFlow, importFlow, createFlow
7056
7299
  catalogWidth,
7057
7300
  createFlowDisabled,
7058
7301
  createFlowField,
7059
- flowBadges,
7060
- hrefForFlow: (flow) => hrefFor({
7302
+ hrefForFlow: (flow, view = "design") => hrefFor({
7061
7303
  flowId: flow.flowId,
7062
- view: "design"
7304
+ view
7063
7305
  }),
7064
7306
  initializing,
7065
7307
  language,
@@ -7085,7 +7327,7 @@ function Workbench({ importRef, catalogWidth, createFlow, importFlow, createFlow
7085
7327
  })
7086
7328
  });
7087
7329
  }
7088
- var Session = forwardRef(function Session({ catalogWidth, createFlow, importFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, host, hrefFor, language, location, onConfigureConnector, onManageConnectorAccess, onLanguageChange, onNavigate, onFlowNameChange, preferences, sessionKey, theme, variables = true }, ref) {
7330
+ var Session = forwardRef(function Session({ catalogWidth, createFlow, importFlow, createFlowDisabled, createFlowField, connectionHref, host, hrefFor, language, location, onConfigureConnector, onManageConnectorAccess, onLanguageChange, onNavigate, onFlowNameChange, preferences, sessionKey, theme, variables = true }, ref) {
7089
7331
  const importRef = useRef(null);
7090
7332
  useImperativeHandle(ref, () => ({ openImport: (input) => importRef.current?.openImport(input) ?? "unavailable" }), []);
7091
7333
  const navigate = useRef(onNavigate);
@@ -7157,7 +7399,6 @@ var Session = forwardRef(function Session({ catalogWidth, createFlow, importFlow
7157
7399
  importFlow,
7158
7400
  createFlowDisabled,
7159
7401
  createFlowField,
7160
- flowBadges,
7161
7402
  connectionHref,
7162
7403
  hrefFor,
7163
7404
  initializing: !started,