@oomol-lab/open-flow 0.1.0-beta.77 → 0.1.0-beta.78

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 (58) hide show
  1. package/README.md +2 -0
  2. package/dist/browser/{ContentIcon-VZQO8VZU.js → ContentIcon-CMn0c-kl.js} +93 -3
  3. package/dist/browser/{FlowCanvas-BNGDMaWr.js → FlowCanvas-BQGBcfoL.js} +1675 -591
  4. package/dist/browser/{createResourceDialog-BmtakfVg.js → createResourceDialog-DCGxfKFM.js} +3 -3
  5. package/dist/browser/{dialog-BcFBfRB1.js → dialog-WzR4CRFH.js} +11 -81
  6. package/dist/browser/{exportSvg-CG8hEUNk.js → exportSvg-CYwyYiuH.js} +2 -2
  7. package/dist/browser/{flowChanges-BGo_4Ypo.js → flowChanges-Bz4dbDN_.js} +1204 -387
  8. package/dist/browser/{flowWorkspace-BFHGev7s.js → flowWorkspace-BI6L6a4r.js} +557 -597
  9. package/dist/browser/licenses.md +1 -1
  10. package/dist/browser/preview.css +512 -462
  11. package/dist/browser/preview.js +8457 -6732
  12. package/dist/browser/{tooltip-BAWSUexx.js → tooltip-BDcVTNpu.js} +65 -2
  13. package/dist/browser/ui.css +5 -24
  14. package/dist/browser/workbench.css +512 -462
  15. package/dist/browser/workbench.d.ts +2 -3
  16. package/dist/browser/workbench.js +65 -690
  17. package/dist/browser/{workbenchSelect-CjK-xdm3.js → workbenchSelect-DtAd0zc4.js} +2 -2
  18. package/dist/command/index.js +25 -25
  19. package/dist/common/authoring.d.ts +3 -3
  20. package/dist/common/authoringExamples.d.ts +3 -3
  21. package/dist/common/authoringSchema.d.ts +14 -22
  22. package/dist/common/control-api-conformance.js +11 -18
  23. package/dist/common/control-api.d.ts +5 -1
  24. package/dist/common/control-api.js +11 -18
  25. package/dist/common/control-requests.d.ts +4 -3
  26. package/dist/common/control-requests.js +26 -37
  27. package/dist/common/flow-authoring.js +6 -14
  28. package/dist/common/flow-change.d.ts +1 -1
  29. package/dist/common/flow-change.js +6 -14
  30. package/dist/common/flow-encoding.js +5 -13
  31. package/dist/common/flow-semantics.js +15 -21
  32. package/dist/common/flow-state.d.ts +16 -39
  33. package/dist/common/flow-state.js +47 -105
  34. package/dist/common/mcp.d.ts +3 -3
  35. package/dist/common/mcp.js +11 -18
  36. package/dist/common/run-events.js +19 -9
  37. package/dist/common/runtime-contract.js +6 -12
  38. package/dist/common/runtime-nodejs-compat.js +11 -12
  39. package/dist/common/scheduler.d.ts +2 -1
  40. package/dist/common/scheduler.js +56 -50
  41. package/dist/common/state-conformance.d.ts +3 -3
  42. package/package.json +1 -1
  43. package/src/control/common/api.ts +20 -3
  44. package/src/control/common/authoring.ts +6 -5
  45. package/src/control/common/authoringExamples.ts +6 -5
  46. package/src/control/common/authoringSchema.ts +7 -7
  47. package/src/control/common/requests.ts +7 -1
  48. package/src/execution/common/events.ts +22 -10
  49. package/src/execution/common/node-execution.ts +1 -1
  50. package/src/execution/common/scheduler.ts +28 -14
  51. package/src/flow/common/change.ts +1 -1
  52. package/src/flow/common/changeSchema.ts +4 -4
  53. package/src/flow/common/errorHandling.ts +1 -1
  54. package/src/flow/common/semantics.ts +12 -6
  55. package/src/runtime/common/nodejsGuest.generated.json +11 -12
  56. package/src/runtime/common/runtime.ts +6 -7
  57. package/src/state/common/conformance.ts +16 -21
  58. package/src/state/common/state.ts +44 -72
@@ -1,15 +1,15 @@
1
1
  import { i as __require, o as __toESM, r as __exportAll, t as __commonJSMin } from "./rolldown-runtime-CEgmsyvS.js";
2
- import { A as DropdownMenuSub, C as DropdownMenuContent, D as DropdownMenuRadioGroup, E as DropdownMenuLabel, I as useCompositeItem, J as waitBranchDescription, M as DropdownMenuSubTrigger, N as DropdownMenuTrigger, O as DropdownMenuRadioItem, P as isElementDisabled, S as DropdownMenuCheckboxItem, T as DropdownMenuItem, _ as NativeScrollArea, at as Checkbox, b as Z$1, c as useIconifyData, d as PopoverContent, f as PopoverDescription, g as PopoverTrigger, h as PopoverTitle, j as DropdownMenuSubContent, k as DropdownMenuSeparator, m as PopoverPanelContent, o as IconifyProvider, ot as useAriaLabelledBy, p as PopoverHeader, s as useIconifyCollectionLoader, t as ContentIcon, u as Popover, v as ScrollArea, w as DropdownMenuGroup, x as DropdownMenu, y as VirtualScrollArea } from "./ContentIcon-VZQO8VZU.js";
2
+ import { A as DropdownMenuSeparator, C as DropdownMenuCheckboxItem, D as DropdownMenuLabel, E as DropdownMenuItem, M as DropdownMenuSubContent, N as DropdownMenuSubTrigger, O as DropdownMenuRadioGroup, P as DropdownMenuTrigger, R as useCompositeItem, S as DropdownMenu, T as DropdownMenuGroup, X as waitBranchDescription, _ as PopoverTrigger, b as VirtualScrollArea, c as useIconifyData, ct as useAriaLabelledBy, d as Popover, f as PopoverContent, g as PopoverTitle, h as PopoverPanelContent, j as DropdownMenuSub, k as DropdownMenuRadioItem, m as PopoverHeader, o as IconifyProvider, p as PopoverDescription, s as useIconifyCollectionLoader, st as Checkbox, t as ContentIcon, v as NativeScrollArea, w as DropdownMenuContent, x as Z$1, y as ScrollArea } from "./ContentIcon-CMn0c-kl.js";
3
3
  import { i as compute, l as val } from "./dist-bO8nvHFH.js";
4
4
  import { c as useLang, l as useTranslate, o as I18nProvider, r as isPlainObject, s as useI18n, u as useVal } from "./dist-BFmpkX4P.js";
5
- import { Ar as useButton, B as ARROW_KEYS, Cr as clsx, En as getTarget, Er as EMPTY_OBJECT, Fn as useOpenChangeComplete, Fr as useIsoLayoutEffect, Gn as clearPress, H as ARROW_RIGHT, Hn as createChangeEventDetails, J as MODIFIER_KEYS, K as HORIZONTAL_KEYS, L as useCompositeListItem, Ln as TransitionStatusDataAttributes, Lr as useStableCallback, Nr as formatErrorMessage, Pn as useTransitionStatus, Pr as mergeProps, Q as scrollIntoViewIfNeeded, R as ALL_KEYS, Rn as transitionStatusMapping, Sr as cva, Tn as contains, Tr as EMPTY_ARRAY$1, U as ARROW_UP, V as ARROW_LEFT, Vn as useValueChanged, X as VERTICAL_KEYS_WITH_EXTRA_KEYS, Y as VERTICAL_KEYS, Z as isNativeInput, Zt as useStore, _n as getMinListIndex, _r as visuallyHiddenInput, a as createTooltipHandle, br as buttonVariants, c as TooltipPositioner, cr as useLabelableContext, ct as CompositeList, d as TooltipRoot, dn as createGridCellMap, dr as useFieldRootContext, fn as findNonDisabledListIndex, fr as useBaseUiId, gn as getMaxListIndex, gr as visuallyHidden, hn as getGridNavigatedIndex, hr as fieldValidityMapping, i as TooltipTrigger, j as string, jn as ownerDocument, jr as CompositeRootContext, kr as useMergedRefs, l as TooltipPortal, lr as useFormContext, lt as inertValue, mn as getGridCellIndices, mt as triggerOpenStateMapping, n as TooltipContent, o as TooltipArrow, p as timeZoneOffsetMinutes, pn as getGridCellIndexOfCorner, q as HORIZONTAL_KEYS_WITH_EXTRA_KEYS, r as TooltipProvider, s as TooltipPopup, st as useDirection, t as Tooltip, tn as require_builtin_esm_external_require_react, tr as none, u as TooltipTrigger$1, ur as useRegisterFieldControl, vn as isIndexOutOfListBounds, vr as useControlled, wn as activeElement, wr as useRenderElement, xr as cn, yn as isListIndexDisabled, yr as Button$1, z as ARROW_DOWN } from "./tooltip-BAWSUexx.js";
6
- import { $ as waitAutoContinueSchema, A as comparisonIssue, At as variableInputCompatible, Bt as SelectGroup, Ct as limitDecisionQuestions, D as nodeSystemOutputPorts, Dt as matchesSchema, E as nodeErrorSchema, F as operatorsForType, Ht as SelectSeparator, It as dequal, J as webhookResponseAllowsBody, K as webhookHeaderValuePort, L as unaryOperator, Lt as Select$1, O as supportsNodeErrorHandling, Ot as portsAssignable, P as operandHandle, Q as workflowOutputsPort, R as valueType, Rt as SelectChevron, St as defaultDecisionQuestion, T as workflowToolNameIssue, Tt as webhookSupportsBody, U as decodeRevisionContent, Ut as SelectTrigger, Vt as SelectItem, Wt as SelectValue, X as webhookResponseTimeout, Y as webhookResponseInputs, Z as webhookStatusCodePort, _t as isHttpHost, a as DialogFooter, at as httpHeaderSchema, b as nodeNameIssue, bt as decisionQuestionIssues, c as DialogTrigger, d as Field, et as defaultNodeRetry, f as FieldDescription, h as FieldLabel, i as DialogDescription, in as ChevronDown, kt as schemaObject, l as Icon, lt as httpRequestIssues, m as FieldGroup, nn as Input, nt as retryConfigurationSchema, o as DialogHeader, ot as httpQuerySchema, p as FieldError, pt as httpHeaderNameIssue, q as webhookHeadersPort, r as DialogContent, rn as useLabelableId, rt as supportsNodeRetry, s as DialogTitle, t as Dialog, tn as Label, tt as nodeRetryLimits, u as Spinner, ut as httpRequestTask, vt as decisionLimits, wt as webhookMethods, xt as decisionTask, zt as SelectContent } from "./dialog-BcFBfRB1.js";
7
- import { C as isMac, S as toManifestNodeId, _ as E$1, a as JSONViewer, b as toViewEdge, c as CanvasNodeIcon, d as IconStack, f as selectableTimeZones, g as cronDescription, h as timeZoneOffset, i as Textarea, l as defaultTriggerIcon, m as timeZoneLongLabel, n as setAddItemId, o as collapseAllNested, p as timeZoneLabel, r as NodeHistoryContext, s as formatDuration, t as FlowCanvas, u as useDebouncedValue, v as CanvasTooltip, w as isSameViewport, x as toManifestHandleName, y as CanvasStore } from "./FlowCanvas-BNGDMaWr.js";
8
- import { $n as openApiFieldIssues, $t as GroupCollectionProvider, A as schemaForEditor, An as decodeResultList, B as datePickerValue, Bn as triggerOutputDefinitions, Cn as FeishuEventPicker, D as defaultValueEditorSchema, E as supportsFeishuChatFilter, F as calendarChange, Fn as webhookResponseDiagnostics, Ft as dequal$1, G as indexAddNodeOptions, Gt as ValueEditorFeedback, H as isDateFormat, Ht as selectionMenuContentClass, I as calendarDate, In as sourceOutputLabel, It as WorkflowExportMenuItem, Jn as triggerConfigValue, Jt as ComboboxItem, Kt as valueEditor_module_default, L as dateFromTimeZone, Ln as sourcePort, Lt as IdTooltip, M as getDefaultValue, Mn as executionReachableNodes, N as isUnconstrainedSchema, Nn as inputSourceCandidates, O as editorComponent, P as typeOfSchema, Pn as resolutionOutputPorts, Q as resourceValue, Qn as object$1, Qt as ComboboxList, R as dateInTimeZone, Rt as FlowSettingsButton, Sn as createI18n, T as feishuResourceKind, Tn as errorNotice, Ut as selectionMenuItemClass, V as dateTimeWall, Vn as isJsonObject, Wt as ValueControl, X as observeResource, Xn as inputValue, Xt as ComboboxPositioner, Yn as triggerConfigValues, Yt as ComboboxPopup, Z as resourceData, Zn as listOperations, Zt as ComboboxPortal, _n as EmptyTitle, _r as eventSourceKind, _t as connectionCatalog, an as useComboboxInputValueContext, ar as sameWorkflowInterface, bn as SourceForm, cn as followWorkbenchLink, cr as workflowCandidateGroup, ct as revisionView, dn as InputGroupInput, en as ComboboxTrigger, er as openApiTask, et as designerGraph, fn as Empty, gn as EmptyMedia, gr as controlErrorCode, hn as EmptyHeader, ht as schemaMismatchMessage, in as selectors, ir as servers, it as providerIcon, j as valueForEditor, k as editorGroups, ln as InputGroup, lr as workflowCapability, mn as EmptyDescription, mt as diagnosticNodeId, n as agentTool, nn as ComboboxInput, nr as selectOperation, nt as triggerNodeIcon, on as useComboboxRootContext, or as workflowAgentTool, ot as canCancelRun, pn as EmptyContent, pt as diagnosticMessage, q as mapSource, qt as ComboboxItemIndicator, rn as ComboboxRoot, rr as serverAddress, rt as actionSummary, st as hasRunFilter, tn as ComboboxInputGroup, tr as securityOptions, tt as semanticNodeIcon, un as InputGroupAddon, ur as workflowSelectionTask, vn as Badge, wn as EventSourceSetup, xn as SourceSelect, z as datePickerChange } from "./flowChanges-BGo_4Ypo.js";
5
+ import { A as string, Bn as transitionStatusMapping, Cr as cn, Dr as EMPTY_ARRAY, En as contains, Er as useRenderElement, Fr as formatErrorMessage, I as useCompositeListItem, In as useTransitionStatus, Ir as mergeProps, Ln as useOpenChangeComplete, Lr as useIsoLayoutEffect, Mn as ownerDocument, Mr as useButton, Nn as useLabelableId, Or as EMPTY_OBJECT, Qt as useStore, Sr as buttonVariants, Tn as activeElement, Tr as clsx, Un as useValueChanged, Wn as createChangeEventDetails, _r as fieldValidityMapping, a as createTooltipHandle, br as useControlled, c as TooltipPositioner, ct as CompositeList, d as TooltipRoot, dr as useFormContext, fr as useRegisterFieldControl, i as TooltipTrigger, jr as useMergedRefs, l as TooltipPortal, lt as inertValue, mr as useBaseUiId, mt as triggerOpenStateMapping, n as TooltipContent, nn as require_builtin_esm_external_require_react, o as TooltipArrow, p as timeZoneOffsetMinutes, pr as useFieldRootContext, qn as clearPress, r as TooltipProvider, rr as none, s as TooltipPopup, t as Tooltip, u as TooltipTrigger$1, ur as useLabelableContext, vr as visuallyHidden, wr as cva, xr as Button$1, yr as visuallyHiddenInput, zn as TransitionStatusDataAttributes, zr as useStableCallback } from "./tooltip-BDcVTNpu.js";
6
+ import { $ as waitAutoContinueSchema, A as comparisonIssue, At as variableInputCompatible, Bt as SelectGroup, Ct as limitDecisionQuestions, D as nodeSystemOutputPorts, Dt as matchesSchema, E as nodeErrorSchema, F as operatorsForType, Ht as SelectSeparator, It as dequal, J as webhookResponseAllowsBody, K as webhookHeaderValuePort, L as unaryOperator, Lt as Select$1, O as supportsNodeErrorHandling, Ot as portsAssignable, P as operandHandle, Pt as skipDuplicatesConfigSchema, Q as workflowOutputsPort, R as valueType, Rt as SelectChevron, St as defaultDecisionQuestion, T as workflowToolNameIssue, Tt as webhookSupportsBody, U as decodeRevisionContent, Ut as SelectTrigger, Vt as SelectItem, Wt as SelectValue, X as webhookResponseTimeout, Y as webhookResponseInputs, Z as webhookStatusCodePort, _t as isHttpHost, a as DialogFooter, at as httpHeaderSchema, b as nodeNameIssue, bt as decisionQuestionIssues, c as DialogTrigger, d as Field, et as defaultNodeRetry, f as FieldDescription, h as FieldLabel, i as DialogDescription, kt as schemaObject, l as Icon, lt as httpRequestIssues, m as FieldGroup, nn as Input, nt as retryConfigurationSchema, o as DialogHeader, ot as httpQuerySchema, p as FieldError, pt as httpHeaderNameIssue, q as webhookHeadersPort, r as DialogContent, rn as ChevronDown, rt as supportsNodeRetry, s as DialogTitle, t as Dialog, tn as Label, tt as nodeRetryLimits, u as Spinner, ut as httpRequestTask, vt as decisionLimits, wt as webhookMethods, xt as decisionTask, zt as SelectContent } from "./dialog-WzR4CRFH.js";
7
+ import { C as toManifestHandleName, E as isSameViewport, S as toViewEdge, T as isMac, _ as timeZoneOffset, a as NodeHistoryContext, b as CanvasTooltip, c as defaultTriggerIcon, d as formatDuration, f as useDebouncedValue, g as timeZoneLongLabel, h as timeZoneLabel, i as setAddItemId, l as JSONViewer, m as selectableTimeZones, n as CompositeRoot, o as Textarea, p as IconStack, r as ACTIVE_COMPOSITE_ITEM, s as CanvasNodeIcon, t as FlowCanvas, u as collapseAllNested, v as cronDescription, w as toManifestNodeId, x as CanvasStore, y as E$1 } from "./FlowCanvas-BQGBcfoL.js";
8
+ import { $n as triggerOutputDefinitions, A as schemaForEditor, An as EmptyTitle, B as datePickerValue, Cn as InputGroupAddon, Cr as workflowSelectionTask, D as defaultValueEditorSchema, Dn as EmptyDescription, Dr as controlErrorCode, E as supportsFeishuChatFilter, En as EmptyContent, Et as schemaMismatchMessage, F as calendarChange, Fn as createI18n, G as indexAddNodeOptions, Gn as executionReachableNodes, H as isDateFormat, I as calendarDate, In as FeishuEventPicker, Jn as webhookResponseDiagnostics, Jt as dequal$1, Kn as inputSourceCandidates, L as dateFromTimeZone, Ln as EventSourceSetup, M as getDefaultValue, N as isUnconstrainedSchema, Nn as SourceForm, O as editorComponent, On as EmptyHeader, Or as eventSourceKind, Ot as connectionCatalog, P as typeOfSchema, Pn as SourceSelect, Q as resourceValue, R as dateInTimeZone, Rn as errorNotice, Sn as InputGroup, Sr as workflowCapability, T as feishuResourceKind, Tn as Empty, Tt as diagnosticNodeId, Un as decodeResultList, V as dateTimeWall, X as observeResource, Xn as sourcePort, Xt as IdTooltip, Yn as sourceOutputLabel, Yt as WorkflowExportMenuItem, Z as resourceData, Zt as FlowSettingsButton, _n as selectors, _r as servers, _t as canCancelRun, an as valueEditor_module_default, at as getAppCatalogCache, cn as ComboboxPopup, cr as triggerConfigValues, dn as ComboboxList, dr as object$1, dt as designerGraph, er as isJsonObject, et as provider, fn as GroupCollectionProvider, fr as openApiFieldIssues, ft as semanticNodeIcon, gn as ComboboxRoot, gr as serverAddress, hn as ComboboxInput, hr as selectOperation, ht as providerIcon, in as ValueEditorFeedback, j as valueForEditor, jn as Badge, k as editorGroups, kn as EmptyMedia, ln as ComboboxPositioner, lr as inputValue, mn as ComboboxInputGroup, mr as securityOptions, mt as actionSummary, n as agentTool, nn as selectionMenuItemClass, on as ComboboxItemIndicator, pn as ComboboxTrigger, pr as openApiTask, pt as triggerNodeIcon, q as mapSource, qn as resolutionOutputPorts, rn as ValueControl, rt as decodeAppCatalogResponse, sn as ComboboxItem, sr as triggerConfigValue, tn as selectionMenuContentClass, un as ComboboxPortal, ur as listOperations, ut as loadJson, vn as useComboboxInputValueContext, vr as sameWorkflowInterface, vt as hasRunFilter, wn as InputGroupInput, wt as diagnosticMessage, xn as followWorkbenchLink, xr as workflowCandidateGroup, yn as useComboboxRootContext, yr as workflowAgentTool, yt as revisionView, z as datePickerChange } from "./flowChanges-Bz4dbDN_.js";
9
9
  import { r as resolveUiLanguage } from "./languages-gYzoQqCi.js";
10
10
  import { a as renameObjectField, i as objectValue, n as isJsonValue, o as setObjectField, r as jsonDataTypes, s as valueType$1, t as initialValue } from "./value-BbFQZZ_V.js";
11
11
  import { n as compile, r as validate } from "./flowRunInputEditorStore-ys1-w9GW.js";
12
- import { t as WorkbenchSelect } from "./workbenchSelect-CjK-xdm3.js";
12
+ import { t as WorkbenchSelect } from "./workbenchSelect-DtAd0zc4.js";
13
13
  import * as React from "react";
14
14
  import reactExports, { Children, Fragment, Suspense, createContext, forwardRef, isValidElement, lazy, memo, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
15
15
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -761,9 +761,6 @@ function computeActivationDirection(oldValue, newValue, orientation, tabMap) {
761
761
  return "none";
762
762
  }
763
763
  //#endregion
764
- //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/constants.js
765
- var ACTIVE_COMPOSITE_ITEM = "data-composite-item-active";
766
- //#endregion
767
764
  //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/tabs/list/TabsListContext.js
768
765
  var TabsListContext = /*#__PURE__*/ React.createContext(void 0);
769
766
  if (process.env.NODE_ENV !== "production") TabsListContext.displayName = "TabsListContext";
@@ -994,238 +991,6 @@ var TabsPanel = /*#__PURE__*/ React.forwardRef(function TabPanel(componentProps,
994
991
  });
995
992
  if (process.env.NODE_ENV !== "production") TabsPanel.displayName = "TabsPanel";
996
993
  //#endregion
997
- //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/root/useCompositeRoot.js
998
- var EMPTY_ARRAY = [];
999
- function useCompositeRoot(params) {
1000
- const { itemSizes, cols = 1, loopFocus = true, onLoop, dense = false, orientation = "both", direction, highlightedIndex: externalHighlightedIndex, onHighlightedIndexChange: externalSetHighlightedIndex, rootRef: externalRef, enableHomeAndEndKeys = false, stopEventPropagation = false, disabledIndices, modifierKeys = EMPTY_ARRAY } = params;
1001
- const [internalHighlightedIndex, internalSetHighlightedIndex] = React.useState(0);
1002
- const isGrid = cols > 1;
1003
- const rootRef = React.useRef(null);
1004
- const mergedRef = useMergedRefs(rootRef, externalRef);
1005
- const elementsRef = React.useRef([]);
1006
- const hasSetDefaultIndexRef = React.useRef(false);
1007
- const highlightedIndex = externalHighlightedIndex ?? internalHighlightedIndex;
1008
- const onHighlightedIndexChange = useStableCallback((index, shouldScrollIntoView = false) => {
1009
- (externalSetHighlightedIndex ?? internalSetHighlightedIndex)(index);
1010
- if (shouldScrollIntoView) {
1011
- const newActiveItem = elementsRef.current[index];
1012
- scrollIntoViewIfNeeded(rootRef.current, newActiveItem, direction, orientation);
1013
- }
1014
- });
1015
- const onMapChange = useStableCallback((map) => {
1016
- if (map.size === 0 || hasSetDefaultIndexRef.current) return;
1017
- hasSetDefaultIndexRef.current = true;
1018
- const sortedElements = Array.from(map.keys());
1019
- const activeItem = sortedElements.find((compositeElement) => compositeElement?.hasAttribute("data-composite-item-active")) ?? null;
1020
- const activeIndex = activeItem ? sortedElements.indexOf(activeItem) : -1;
1021
- if (activeIndex !== -1) onHighlightedIndexChange(activeIndex);
1022
- scrollIntoViewIfNeeded(rootRef.current, activeItem, direction, orientation);
1023
- });
1024
- const wrappedOnLoop = useStableCallback((event, prevIndex, nextIndex) => {
1025
- if (!onLoop) return nextIndex;
1026
- return onLoop?.(event, prevIndex, nextIndex, elementsRef);
1027
- });
1028
- const props = React.useMemo(() => ({
1029
- "aria-orientation": orientation === "both" ? void 0 : orientation,
1030
- ref: mergedRef,
1031
- onFocus(event) {
1032
- const element = rootRef.current;
1033
- const target = getTarget(event.nativeEvent);
1034
- if (!element || target == null || !isNativeInput(target)) return;
1035
- target.setSelectionRange(0, target.value.length ?? 0);
1036
- },
1037
- onKeyDown(event) {
1038
- const RELEVANT_KEYS = enableHomeAndEndKeys ? ALL_KEYS : ARROW_KEYS;
1039
- if (!RELEVANT_KEYS.has(event.key)) return;
1040
- if (isModifierKeySet(event, modifierKeys)) return;
1041
- if (!rootRef.current) return;
1042
- const isRtl = direction === "rtl";
1043
- const horizontalForwardKey = isRtl ? ARROW_LEFT : ARROW_RIGHT;
1044
- const forwardKey = {
1045
- horizontal: horizontalForwardKey,
1046
- vertical: ARROW_DOWN,
1047
- both: horizontalForwardKey
1048
- }[orientation];
1049
- const horizontalBackwardKey = isRtl ? ARROW_RIGHT : ARROW_LEFT;
1050
- const backwardKey = {
1051
- horizontal: horizontalBackwardKey,
1052
- vertical: ARROW_UP,
1053
- both: horizontalBackwardKey
1054
- }[orientation];
1055
- const target = getTarget(event.nativeEvent);
1056
- if (target != null && isNativeInput(target) && !isElementDisabled(target)) {
1057
- const selectionStart = target.selectionStart;
1058
- const selectionEnd = target.selectionEnd;
1059
- const textContent = target.value ?? "";
1060
- if (selectionStart == null || event.shiftKey || selectionStart !== selectionEnd) return;
1061
- if (event.key !== backwardKey && selectionStart < textContent.length) return;
1062
- if (event.key !== forwardKey && selectionStart > 0) return;
1063
- }
1064
- let nextIndex = highlightedIndex;
1065
- const minIndex = getMinListIndex(elementsRef, disabledIndices);
1066
- const maxIndex = getMaxListIndex(elementsRef, disabledIndices);
1067
- if (isGrid) {
1068
- const sizes = itemSizes || Array.from({ length: elementsRef.current.length }, () => ({
1069
- width: 1,
1070
- height: 1
1071
- }));
1072
- const cellMap = createGridCellMap(sizes, cols, dense);
1073
- const minGridIndex = cellMap.findIndex((index) => index != null && !isListIndexDisabled(elementsRef.current, index, disabledIndices));
1074
- const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !isListIndexDisabled(elementsRef.current, index, disabledIndices) ? cellIndex : foundIndex, -1);
1075
- nextIndex = cellMap[getGridNavigatedIndex(cellMap.map((itemIndex) => itemIndex != null ? elementsRef.current[itemIndex] : null), {
1076
- event,
1077
- orientation,
1078
- loopFocus,
1079
- onLoop: wrappedOnLoop,
1080
- cols,
1081
- disabledIndices: getGridCellIndices([...disabledIndices || elementsRef.current.map((_, index) => isListIndexDisabled(elementsRef.current, index) ? index : void 0), void 0], cellMap),
1082
- minIndex: minGridIndex,
1083
- maxIndex: maxGridIndex,
1084
- prevIndex: getGridCellIndexOfCorner(highlightedIndex > maxIndex ? minIndex : highlightedIndex, sizes, cellMap, cols, event.key === "ArrowDown" ? "bl" : event.key === "ArrowRight" ? "tr" : "tl"),
1085
- rtl: isRtl
1086
- })];
1087
- }
1088
- const forwardKeys = {
1089
- horizontal: [horizontalForwardKey],
1090
- vertical: [ARROW_DOWN],
1091
- both: [horizontalForwardKey, ARROW_DOWN]
1092
- }[orientation];
1093
- const backwardKeys = {
1094
- horizontal: [horizontalBackwardKey],
1095
- vertical: [ARROW_UP],
1096
- both: [horizontalBackwardKey, ARROW_UP]
1097
- }[orientation];
1098
- const preventedKeys = isGrid ? RELEVANT_KEYS : {
1099
- horizontal: enableHomeAndEndKeys ? HORIZONTAL_KEYS_WITH_EXTRA_KEYS : HORIZONTAL_KEYS,
1100
- vertical: enableHomeAndEndKeys ? VERTICAL_KEYS_WITH_EXTRA_KEYS : VERTICAL_KEYS,
1101
- both: RELEVANT_KEYS
1102
- }[orientation];
1103
- if (enableHomeAndEndKeys) {
1104
- if (event.key === "Home") nextIndex = minIndex;
1105
- else if (event.key === "End") nextIndex = maxIndex;
1106
- }
1107
- if (nextIndex === highlightedIndex && (forwardKeys.includes(event.key) || backwardKeys.includes(event.key))) {
1108
- if (loopFocus && nextIndex === maxIndex && forwardKeys.includes(event.key)) {
1109
- nextIndex = minIndex;
1110
- if (onLoop) nextIndex = onLoop(event, highlightedIndex, nextIndex, elementsRef);
1111
- } else if (loopFocus && nextIndex === minIndex && backwardKeys.includes(event.key)) {
1112
- nextIndex = maxIndex;
1113
- if (onLoop) nextIndex = onLoop(event, highlightedIndex, nextIndex, elementsRef);
1114
- } else nextIndex = findNonDisabledListIndex(elementsRef.current, {
1115
- startingIndex: nextIndex,
1116
- decrement: backwardKeys.includes(event.key),
1117
- disabledIndices
1118
- });
1119
- }
1120
- if (nextIndex !== highlightedIndex && !isIndexOutOfListBounds(elementsRef.current, nextIndex)) {
1121
- if (stopEventPropagation) event.stopPropagation();
1122
- if (preventedKeys.has(event.key)) event.preventDefault();
1123
- onHighlightedIndexChange(nextIndex, true);
1124
- queueMicrotask(() => {
1125
- elementsRef.current[nextIndex]?.focus();
1126
- });
1127
- }
1128
- }
1129
- }), [
1130
- cols,
1131
- dense,
1132
- direction,
1133
- disabledIndices,
1134
- elementsRef,
1135
- enableHomeAndEndKeys,
1136
- highlightedIndex,
1137
- isGrid,
1138
- itemSizes,
1139
- loopFocus,
1140
- onLoop,
1141
- wrappedOnLoop,
1142
- mergedRef,
1143
- modifierKeys,
1144
- onHighlightedIndexChange,
1145
- orientation,
1146
- stopEventPropagation
1147
- ]);
1148
- return React.useMemo(() => ({
1149
- props,
1150
- highlightedIndex,
1151
- onHighlightedIndexChange,
1152
- elementsRef,
1153
- disabledIndices,
1154
- onMapChange,
1155
- relayKeyboardEvent: props.onKeyDown
1156
- }), [
1157
- props,
1158
- highlightedIndex,
1159
- onHighlightedIndexChange,
1160
- elementsRef,
1161
- disabledIndices,
1162
- onMapChange
1163
- ]);
1164
- }
1165
- function isModifierKeySet(event, ignoredModifierKeys) {
1166
- for (const key of MODIFIER_KEYS.values()) {
1167
- if (ignoredModifierKeys.includes(key)) continue;
1168
- if (event.getModifierState(key)) return true;
1169
- }
1170
- return false;
1171
- }
1172
- //#endregion
1173
- //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/root/CompositeRoot.js
1174
- /**
1175
- * @internal
1176
- */
1177
- function CompositeRoot(componentProps) {
1178
- const { render, className, style, refs = EMPTY_ARRAY$1, props = EMPTY_ARRAY$1, state = EMPTY_OBJECT, stateAttributesMapping, highlightedIndex: highlightedIndexProp, onHighlightedIndexChange: onHighlightedIndexChangeProp, orientation, dense, itemSizes, loopFocus, onLoop, cols, enableHomeAndEndKeys, onMapChange: onMapChangeProp, stopEventPropagation = true, rootRef, disabledIndices, modifierKeys, highlightItemOnHover = false, tag = "div", ...elementProps } = componentProps;
1179
- const { props: defaultProps, highlightedIndex, onHighlightedIndexChange, elementsRef, onMapChange: onMapChangeUnwrapped, relayKeyboardEvent } = useCompositeRoot({
1180
- itemSizes,
1181
- cols,
1182
- loopFocus,
1183
- onLoop,
1184
- dense,
1185
- orientation,
1186
- highlightedIndex: highlightedIndexProp,
1187
- onHighlightedIndexChange: onHighlightedIndexChangeProp,
1188
- rootRef,
1189
- stopEventPropagation,
1190
- enableHomeAndEndKeys,
1191
- direction: useDirection(),
1192
- disabledIndices,
1193
- modifierKeys
1194
- });
1195
- const element = useRenderElement(tag, componentProps, {
1196
- state,
1197
- ref: refs,
1198
- props: [
1199
- defaultProps,
1200
- ...props,
1201
- elementProps
1202
- ],
1203
- stateAttributesMapping
1204
- });
1205
- const contextValue = React.useMemo(() => ({
1206
- highlightedIndex,
1207
- onHighlightedIndexChange,
1208
- highlightItemOnHover,
1209
- relayKeyboardEvent
1210
- }), [
1211
- highlightedIndex,
1212
- onHighlightedIndexChange,
1213
- highlightItemOnHover,
1214
- relayKeyboardEvent
1215
- ]);
1216
- return /*#__PURE__*/ jsx(CompositeRootContext.Provider, {
1217
- value: contextValue,
1218
- children: /*#__PURE__*/ jsx(CompositeList, {
1219
- elementsRef,
1220
- onMapChange: (newMap) => {
1221
- onMapChangeProp?.(newMap);
1222
- onMapChangeUnwrapped(newMap);
1223
- },
1224
- children: element
1225
- })
1226
- });
1227
- }
1228
- //#endregion
1229
994
  //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/tabs/list/TabsList.js
1230
995
  /**
1231
996
  * Groups the individual tab buttons.
@@ -1320,7 +1085,7 @@ var TabsList$1 = /*#__PURE__*/ React.forwardRef(function TabsList(componentProps
1320
1085
  orientation,
1321
1086
  onHighlightedIndexChange: setHighlightedTabIndex,
1322
1087
  onMapChange: setTabMap,
1323
- disabledIndices: EMPTY_ARRAY$1
1088
+ disabledIndices: EMPTY_ARRAY
1324
1089
  })
1325
1090
  });
1326
1091
  });
@@ -2682,7 +2447,7 @@ function fallbackIcon$1(item) {
2682
2447
  case "agent": return "llm";
2683
2448
  case "condition": return "condition";
2684
2449
  case "decision": return "decision";
2685
- case "dedupe":
2450
+ case "skip-duplicates":
2686
2451
  case "http-request":
2687
2452
  case "openapi":
2688
2453
  case "connector":
@@ -3376,7 +3141,7 @@ function ConnectorAccessSettings({ connectionHref, onManage, onSelectReference,
3376
3141
  const referenceIcon = (reference) => {
3377
3142
  const node = displayed?.node(reference.nodeId);
3378
3143
  if (node == null) return;
3379
- return node.kind == "trigger" ? triggerNodeIcon(node.trigger, providerMetadata) : semanticNodeIcon(node, actions);
3144
+ return node.kind == "trigger" ? triggerNodeIcon(node.trigger, providerMetadata) : semanticNodeIcon(node, actions, providerMetadata);
3380
3145
  };
3381
3146
  const affected = removing == null ? void 0 : accounts.get(removing);
3382
3147
  return /* @__PURE__ */ jsxs("section", {
@@ -5761,8 +5526,8 @@ function NativeSelectOption({ className, ...props }) {
5761
5526
  //#region src/workbench/browser/runtime/editor/flowStatePanel.tsx
5762
5527
  function FlowStatePanel({ value, nodeIds, busy, onClearValues, onClearSpace, space }) {
5763
5528
  const t = useTranslate();
5764
- const count = value.spaces.reduce((total, item) => total + item.count, 0);
5765
- const spaces = space == null ? value.spaces : value.spaces.filter((item) => typeof space === "string" ? item.space === space : space.includes(item.space));
5529
+ const count = value.spaces.reduce((total, item) => total + item.reservedCount, 0);
5530
+ const spaces = space == null ? value.spaces : value.spaces.filter((item) => item.space === space);
5766
5531
  return /* @__PURE__ */ jsxs("div", {
5767
5532
  className: "flex flex-col gap-4",
5768
5533
  children: [space == null && /* @__PURE__ */ jsxs("section", {
@@ -5786,7 +5551,7 @@ function FlowStatePanel({ value, nodeIds, busy, onClearValues, onClearSpace, spa
5786
5551
  variant: "outline",
5787
5552
  size: "sm",
5788
5553
  disabled: busy,
5789
- onClick: () => onClearValues(),
5554
+ onClick: (event) => onClearValues(void 0, event.currentTarget),
5790
5555
  children: t("flowState.clearAll")
5791
5556
  })
5792
5557
  ]
@@ -5810,7 +5575,7 @@ function FlowStatePanel({ value, nodeIds, busy, onClearValues, onClearSpace, spa
5810
5575
  variant: "outline",
5811
5576
  size: "sm",
5812
5577
  disabled: busy,
5813
- onClick: () => onClearValues(item.key),
5578
+ onClick: (event) => onClearValues(item.key, event.currentTarget),
5814
5579
  children: t("flowState.delete")
5815
5580
  })]
5816
5581
  }, item.key))
@@ -5858,15 +5623,15 @@ function FlowStatePanel({ value, nodeIds, busy, onClearValues, onClearSpace, spa
5858
5623
  ]
5859
5624
  })
5860
5625
  ]
5861
- }), /* @__PURE__ */ jsx("p", {
5626
+ }), /* @__PURE__ */ jsxs("p", {
5862
5627
  className: "m-0 text-xs",
5863
- children: item.mode === "new" ? t("flowState.records", { count: item.count.toLocaleString() }) : `${t("flowState.watermark")}: ${item.watermark ?? "-"}`
5628
+ children: [t("flowState.records", { count: item.count.toLocaleString() }), item.pendingCount > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [" · ", t("flowState.pendingRecords", { count: item.pendingCount.toLocaleString() })] })]
5864
5629
  })]
5865
5630
  }), /* @__PURE__ */ jsx(Button$1, {
5866
5631
  variant: "outline",
5867
5632
  size: "sm",
5868
- disabled: busy,
5869
- onClick: () => onClearSpace(item.space),
5633
+ disabled: busy || item.pendingCount > 0,
5634
+ onClick: (event) => onClearSpace(item.space, event.currentTarget),
5870
5635
  children: t("flowState.clear")
5871
5636
  })]
5872
5637
  }, item.space))
@@ -5882,15 +5647,24 @@ function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
5882
5647
  }, []);
5883
5648
  const [open, setOpen] = useState(onClose != null);
5884
5649
  const [scope, setScope] = useState("draft");
5885
- const space = history?.space;
5650
+ const space = history == null ? void 0 : `node:${history.nodeId}`;
5886
5651
  const [values, setValues] = useState(false);
5887
5652
  const [data, setData] = useState();
5888
5653
  const [error, setError] = useState();
5889
5654
  const [busy, setBusy] = useState(false);
5890
5655
  const [refresh, setRefresh] = useState(0);
5891
5656
  const [confirm, setConfirm] = useState();
5657
+ const cancelButton = useRef(null);
5658
+ const confirmTrigger = useRef();
5892
5659
  useEffect(() => {
5893
- if (!open && space == null) return;
5660
+ if (confirm != null) cancelButton.current?.focus();
5661
+ }, [confirm]);
5662
+ const cancelConfirm = () => {
5663
+ setConfirm(void 0);
5664
+ confirmTrigger.current?.focus();
5665
+ };
5666
+ useEffect(() => {
5667
+ if (!open) return;
5894
5668
  let active = true;
5895
5669
  setData(void 0);
5896
5670
  setError(void 0);
@@ -5925,7 +5699,11 @@ function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
5925
5699
  setBusy(false);
5926
5700
  }
5927
5701
  };
5928
- const request = (target) => scope === "live" ? setConfirm(target) : void clear(target);
5702
+ const request = (target, trigger) => {
5703
+ confirmTrigger.current = trigger;
5704
+ if (scope === "live") setConfirm(target);
5705
+ else clear(target);
5706
+ };
5929
5707
  return /* @__PURE__ */ jsx("span", {
5930
5708
  className: "contents",
5931
5709
  ref: portal,
@@ -5934,13 +5712,17 @@ function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
5934
5712
  onOpenChange: (next) => {
5935
5713
  if (!busy) {
5936
5714
  setOpen(next);
5715
+ if (next) {
5716
+ setScope("draft");
5717
+ setValues(false);
5718
+ }
5937
5719
  if (!next) onClose?.();
5938
5720
  setConfirm(void 0);
5939
5721
  }
5940
5722
  },
5941
5723
  children: [onClose == null && /* @__PURE__ */ jsxs(DialogTrigger, {
5942
5724
  render: /* @__PURE__ */ jsx(Button$1, {
5943
- variant: space != null && data != null && data.spaces.reduce((total, item) => total + item.count, 0) >= data.limits.maxIdentities * .8 ? "destructive" : "ghost",
5725
+ variant: "ghost",
5944
5726
  size: "sm"
5945
5727
  }),
5946
5728
  children: [/* @__PURE__ */ jsx("i", {
@@ -5952,7 +5734,7 @@ function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
5952
5734
  className: "max-h-[80vh] overflow-auto",
5953
5735
  closeLabel: t("common.close"),
5954
5736
  children: [
5955
- /* @__PURE__ */ jsx(DialogTitle, { children: t("flowState.title") }),
5737
+ /* @__PURE__ */ jsx(DialogTitle, { children: t(space == null ? "flowState.title" : "flowState.history") }),
5956
5738
  /* @__PURE__ */ jsxs("div", {
5957
5739
  className: "flex flex-wrap items-center gap-3",
5958
5740
  children: [
@@ -6044,9 +5826,10 @@ function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
6044
5826
  onClick: () => void clear(confirm),
6045
5827
  children: t("flowState.clear")
6046
5828
  }), /* @__PURE__ */ jsx(Button$1, {
5829
+ ref: cancelButton,
6047
5830
  disabled: busy,
6048
5831
  variant: "outline",
6049
- onClick: () => setConfirm(void 0),
5832
+ onClick: cancelConfirm,
6050
5833
  children: t("flowState.cancel")
6051
5834
  })]
6052
5835
  })
@@ -6057,11 +5840,11 @@ function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
6057
5840
  children: error == null ? t("flowState.loading") : ""
6058
5841
  }) : /* @__PURE__ */ jsx(FlowStatePanel, {
6059
5842
  value: data,
6060
- space: scope === "live" && history != null ? ["flow", `node:${history.nodeId}`] : space,
5843
+ space,
6061
5844
  nodeIds,
6062
5845
  busy,
6063
- onClearValues: (key) => request({ key }),
6064
- onClearSpace: (targetSpace) => request({ space: targetSpace })
5846
+ onClearValues: (key, trigger) => request({ key }, trigger),
5847
+ onClearSpace: (targetSpace, trigger) => request({ space: targetSpace }, trigger)
6065
5848
  })
6066
5849
  ]
6067
5850
  })]
@@ -6737,7 +6520,7 @@ function SelectedToolRow({ icon, title, subtitle, actions, children }) {
6737
6520
  })]
6738
6521
  }),
6739
6522
  actions,
6740
- /* @__PURE__ */ jsx("div", {
6523
+ children != null && /* @__PURE__ */ jsx("div", {
6741
6524
  className: "col-start-2 min-w-0",
6742
6525
  children
6743
6526
  })
@@ -7128,6 +6911,27 @@ function WorkflowToolPicker({ catalog, selected, disabled, onToggle }) {
7128
6911
  onChoose: onToggle
7129
6912
  });
7130
6913
  }
6914
+ function SelectedWorkflowToolRow({ entry, workflowName = entry.flowId, title = entry.name, actions, children }) {
6915
+ const t = useTranslate();
6916
+ return /* @__PURE__ */ jsx(SelectedToolRow, {
6917
+ icon: /* @__PURE__ */ jsx(ProviderAppIcon, { children: /* @__PURE__ */ jsx("i", {
6918
+ "aria-hidden": "true",
6919
+ className: "i-lucide-light:workflow size-4 text-muted-foreground"
6920
+ }) }),
6921
+ title,
6922
+ subtitle: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
6923
+ className: "truncate",
6924
+ title: workflowName,
6925
+ children: [
6926
+ t("toolPicker.workflow"),
6927
+ " · ",
6928
+ workflowName
6929
+ ]
6930
+ }), /* @__PURE__ */ jsx(OpenWorkflowLink, { flowId: entry.flowId })] }),
6931
+ actions,
6932
+ children
6933
+ });
6934
+ }
7131
6935
  function SelectedWorkflowTool({ entry, workflowName, disabled, load, onRefresh, onChange, otherNames, onValidChange, onRemove, children, portalRoot }) {
7132
6936
  const t = useTranslate();
7133
6937
  const [issue, setIssue] = useState();
@@ -7167,11 +6971,9 @@ function SelectedWorkflowTool({ entry, workflowName, disabled, load, onRefresh,
7167
6971
  ]);
7168
6972
  const targetName = target?.name ?? workflowName ?? entry.flowId;
7169
6973
  const removeLabel = t("actionPicker.remove", { action: targetName });
7170
- return /* @__PURE__ */ jsx(SelectedToolRow, {
7171
- icon: /* @__PURE__ */ jsx(ProviderAppIcon, { children: /* @__PURE__ */ jsx("i", {
7172
- "aria-hidden": "true",
7173
- className: "i-lucide-light:workflow size-4 text-muted-foreground"
7174
- }) }),
6974
+ return /* @__PURE__ */ jsx(SelectedWorkflowToolRow, {
6975
+ entry,
6976
+ workflowName: targetName,
7175
6977
  title: children == null ? /* @__PURE__ */ jsx(WorkflowToolTitle, {
7176
6978
  name: entry.name,
7177
6979
  disabled,
@@ -7179,15 +6981,6 @@ function SelectedWorkflowTool({ entry, workflowName, disabled, load, onRefresh,
7179
6981
  otherNames,
7180
6982
  onValidChange
7181
6983
  }) : entry.name,
7182
- subtitle: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
7183
- className: "truncate",
7184
- title: targetName,
7185
- children: [
7186
- t("toolPicker.workflow"),
7187
- " · ",
7188
- targetName
7189
- ]
7190
- }), /* @__PURE__ */ jsx(OpenWorkflowLink, { flowId: entry.flowId })] }),
7191
6984
  actions: children ?? /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsx(Button$1, {
7192
6985
  type: "button",
7193
6986
  size: "icon-sm",
@@ -7334,7 +7127,9 @@ function WorkflowToolTitle({ name, disabled, onChange, otherNames, onValidChange
7334
7127
  function entryKey(entry) {
7335
7128
  return entry.kind == "workflow" ? `workflow:${entry.flowId}` : entry.action;
7336
7129
  }
7337
- function ActionSelectionDialog({ title, entries, connectors, prepareAction, workflows, disabled, createEntry, onSave, notify, settings, trigger, triggerHint }) {
7130
+ function ActionSelectionDialog(props) {
7131
+ const { title, entries, settings, trigger, triggerHint } = props;
7132
+ const editor = props.readOnly === true ? void 0 : props;
7338
7133
  const t = useTranslate();
7339
7134
  const [open, setOpen] = useState(false);
7340
7135
  const [root, setRoot] = useState(null);
@@ -7379,7 +7174,7 @@ function ActionSelectionDialog({ title, entries, connectors, prepareAction, work
7379
7174
  variant: "outline",
7380
7175
  size: "xs"
7381
7176
  }),
7382
- disabled,
7177
+ disabled: editor?.disabled ?? false,
7383
7178
  "aria-label": `${title} · ${entries.length}`,
7384
7179
  children: trigger?.props.children ?? `${title} · ${entries.length}`
7385
7180
  }) }), /* @__PURE__ */ jsx(TooltipContent, {
@@ -7388,7 +7183,7 @@ function ActionSelectionDialog({ title, entries, connectors, prepareAction, work
7388
7183
  })] }), /* @__PURE__ */ jsxs(DialogContent, {
7389
7184
  container: root,
7390
7185
  closeLabel: t("common.close"),
7391
- className: "flex h-[min(640px,85dvh)] flex-col gap-0 p-0 text-[13px] leading-5 font-normal sm:max-w-[min(46rem,calc(100%-2rem))]",
7186
+ className: cn("flex flex-col gap-0 p-0 text-[13px] leading-5 font-normal", editor == null ? "max-h-[85dvh] sm:max-w-sm" : "h-[min(640px,85dvh)] sm:max-w-[min(46rem,calc(100%-2rem))]"),
7392
7187
  showCloseButton: !pending,
7393
7188
  children: [
7394
7189
  /* @__PURE__ */ jsx(DialogTitle, {
@@ -7396,32 +7191,35 @@ function ActionSelectionDialog({ title, entries, connectors, prepareAction, work
7396
7191
  children: title
7397
7192
  }),
7398
7193
  /* @__PURE__ */ jsx("div", { className: "mx-4 h-px shrink-0 bg-border/50" }),
7399
- /* @__PURE__ */ jsx(DialogDescription, {
7194
+ props.readOnly === true ? /* @__PURE__ */ jsx(ReadonlyToolSelection, {
7195
+ entries,
7196
+ providers: props.providers,
7197
+ settings
7198
+ }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DialogDescription, {
7400
7199
  className: "m-0 shrink-0 px-4 pt-3 text-[13px] leading-5",
7401
7200
  children: t("actionPicker.description")
7402
- }),
7403
- /* @__PURE__ */ jsx(ActionSelectionEditor, {
7404
- notify,
7201
+ }), /* @__PURE__ */ jsx(ActionSelectionEditor, {
7202
+ notify: props.notify,
7405
7203
  entries,
7406
- connectors,
7407
- prepareAction,
7408
- workflows,
7409
- disabled: disabled || pending,
7410
- createEntry,
7204
+ connectors: props.connectors,
7205
+ prepareAction: props.prepareAction,
7206
+ workflows: props.workflows,
7207
+ disabled: props.disabled || pending,
7208
+ createEntry: props.createEntry,
7411
7209
  settings,
7412
7210
  onDirtyChange: setDirty,
7413
7211
  onCancel: requestClose,
7414
7212
  onSave: async (next) => {
7415
7213
  setPending(true);
7416
7214
  try {
7417
- const saved = await onSave(next);
7215
+ const saved = await props.onSave(next);
7418
7216
  if (saved) setOpen(false);
7419
7217
  return saved;
7420
7218
  } finally {
7421
7219
  setPending(false);
7422
7220
  }
7423
7221
  }
7424
- }),
7222
+ })] }),
7425
7223
  /* @__PURE__ */ jsx(Dialog, {
7426
7224
  open: confirmDiscard,
7427
7225
  onOpenChange: setConfirmDiscard,
@@ -7460,6 +7258,121 @@ function ActionSelectionDialog({ title, entries, connectors, prepareAction, work
7460
7258
  })
7461
7259
  });
7462
7260
  }
7261
+ function SelectedToolsList({ count, actions, children, containerRef, headingRef, className }) {
7262
+ const t = useTranslate();
7263
+ return /* @__PURE__ */ jsxs("div", {
7264
+ ref: containerRef,
7265
+ className: cn("flex min-h-0 min-w-0 flex-1 flex-col gap-2", className),
7266
+ children: [/* @__PURE__ */ jsxs("div", {
7267
+ className: "flex h-8 shrink-0 items-center justify-between gap-2 px-4",
7268
+ children: [/* @__PURE__ */ jsx("h3", {
7269
+ ref: headingRef,
7270
+ tabIndex: -1,
7271
+ className: "m-0 text-[13px] font-normal text-muted-foreground outline-none",
7272
+ children: t("actionPicker.selected", { count })
7273
+ }), actions]
7274
+ }), count === 0 ? /* @__PURE__ */ jsx(Empty, { children: /* @__PURE__ */ jsxs(EmptyHeader, { children: [/* @__PURE__ */ jsx(EmptyMedia, {
7275
+ variant: "icon",
7276
+ children: /* @__PURE__ */ jsx("i", {
7277
+ "aria-hidden": "true",
7278
+ className: "i-lucide-light:list-checks size-4"
7279
+ })
7280
+ }), /* @__PURE__ */ jsx(EmptyDescription, {
7281
+ className: "text-[13px]",
7282
+ children: t("actionPicker.empty")
7283
+ })] }) }) : /* @__PURE__ */ jsx(ScrollArea, {
7284
+ className: "min-h-0 flex-1",
7285
+ children: /* @__PURE__ */ jsx("div", {
7286
+ className: "flex flex-col divide-y divide-border/50 px-4",
7287
+ children
7288
+ })
7289
+ })]
7290
+ });
7291
+ }
7292
+ function SelectedToolSettings({ title, name, container, disabled = false, footer, children }) {
7293
+ const t = useTranslate();
7294
+ return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
7295
+ render: /* @__PURE__ */ jsx(PopoverTrigger, { render: /* @__PURE__ */ jsx(Button$1, {
7296
+ type: "button",
7297
+ size: "icon-sm",
7298
+ variant: "ghost",
7299
+ disabled,
7300
+ "aria-label": `${title} · ${name}`
7301
+ }) }),
7302
+ children: /* @__PURE__ */ jsx("i", {
7303
+ "aria-hidden": "true",
7304
+ className: "i-lucide-light:settings size-4 text-muted-foreground"
7305
+ })
7306
+ }), /* @__PURE__ */ jsx(TooltipContent, {
7307
+ container,
7308
+ children: title
7309
+ })] }), /* @__PURE__ */ jsx(PopoverPanelContent, {
7310
+ keepMounted: true,
7311
+ container,
7312
+ title,
7313
+ closeLabel: t("common.close"),
7314
+ className: "open-flow-property-panel w-96",
7315
+ footer,
7316
+ children
7317
+ })] });
7318
+ }
7319
+ function ReadonlyToolSelection({ entries, providers, settings }) {
7320
+ const t = useTranslate();
7321
+ const [root, setRoot] = useState(null);
7322
+ return /* @__PURE__ */ jsx("div", {
7323
+ className: "flex min-h-0 flex-1 py-4",
7324
+ children: /* @__PURE__ */ jsx(SelectedToolsList, {
7325
+ count: entries.length,
7326
+ containerRef: setRoot,
7327
+ children: entries.map((entry) => {
7328
+ const name = entry.kind === "workflow" ? entry.name : entry.action;
7329
+ const controls = settings && /* @__PURE__ */ jsx(SelectedToolSettings, {
7330
+ title: settings.title,
7331
+ name,
7332
+ container: root,
7333
+ children: settings.render({
7334
+ entry,
7335
+ disabled: true
7336
+ })
7337
+ });
7338
+ if (entry.kind === "workflow") return /* @__PURE__ */ jsx(SelectedWorkflowToolRow, {
7339
+ entry,
7340
+ actions: controls
7341
+ }, entry.id ?? entryKey(entry));
7342
+ const service = entry.action.split(".")[0];
7343
+ const provider = providers?.[service];
7344
+ return /* @__PURE__ */ jsx(SelectedToolRow, {
7345
+ icon: /* @__PURE__ */ jsx(ProviderAppIcon, { src: providerIcon(provider ?? {
7346
+ serviceId: service,
7347
+ serviceName: service
7348
+ }) }),
7349
+ title: name,
7350
+ subtitle: /* @__PURE__ */ jsxs("span", {
7351
+ className: "truncate",
7352
+ children: [
7353
+ t("toolPicker.connector"),
7354
+ " · ",
7355
+ provider?.serviceName ?? service
7356
+ ]
7357
+ }),
7358
+ actions: controls,
7359
+ children: provider?.noSetup ? /* @__PURE__ */ jsx("div", {
7360
+ className: "text-muted-foreground",
7361
+ children: t("actionPicker.noAccount")
7362
+ }) : entry.connectionId == null ? null : /* @__PURE__ */ jsx("div", {
7363
+ className: "open-flow-property-panel flex min-h-[30px] min-w-0 items-center [&>*]:w-full",
7364
+ children: /* @__PURE__ */ jsx(Input, {
7365
+ controlSize: "field",
7366
+ readOnly: true,
7367
+ "aria-label": t("actionPicker.accountFor", { action: name }),
7368
+ value: entry.connectionId === "" ? t("inspector.account.deferred") : entry.connectionId
7369
+ })
7370
+ })
7371
+ }, entry.id ?? entry.action);
7372
+ })
7373
+ })
7374
+ });
7375
+ }
7463
7376
  function ActionSelectionEditor({ entries, connectors, prepareAction, workflows, disabled, createEntry, onSave, notify, onCancel, onDirtyChange, settings }) {
7464
7377
  const t = useTranslate();
7465
7378
  const [draft, setDraft] = useState(entries);
@@ -7624,27 +7537,11 @@ function ActionSelectionEditor({ entries, connectors, prepareAction, workflows,
7624
7537
  controller.abort();
7625
7538
  }
7626
7539
  };
7627
- const renderSettings = (entry, index, name, ready = true) => settings == null ? void 0 : /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
7628
- render: /* @__PURE__ */ jsx(PopoverTrigger, { render: /* @__PURE__ */ jsx(Button$1, {
7629
- type: "button",
7630
- size: "icon-sm",
7631
- variant: "ghost",
7632
- disabled,
7633
- "aria-label": `${settings.title} · ${name}`
7634
- }) }),
7635
- children: /* @__PURE__ */ jsx("i", {
7636
- "aria-hidden": "true",
7637
- className: "i-lucide-light:settings size-4 text-muted-foreground"
7638
- })
7639
- }), /* @__PURE__ */ jsx(TooltipContent, {
7640
- container: portalRoot,
7641
- children: settings.title
7642
- })] }), /* @__PURE__ */ jsx(PopoverPanelContent, {
7643
- keepMounted: true,
7644
- container: portalRoot,
7540
+ const renderSettings = (entry, index, name, ready = true) => settings == null ? void 0 : /* @__PURE__ */ jsx(SelectedToolSettings, {
7645
7541
  title: settings.title,
7646
- closeLabel: t("common.close"),
7647
- className: "open-flow-property-panel w-96",
7542
+ name,
7543
+ container: portalRoot,
7544
+ disabled,
7648
7545
  footer: /* @__PURE__ */ jsx(Button$1, {
7649
7546
  type: "button",
7650
7547
  size: "field",
@@ -7660,7 +7557,7 @@ function ActionSelectionEditor({ entries, connectors, prepareAction, workflows,
7660
7557
  disabled: disabled || !ready,
7661
7558
  onValidChange: (key, value) => setValidity(`${entry.id ?? entryKey(entry)}:${key}`, value)
7662
7559
  })
7663
- })] });
7560
+ });
7664
7561
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
7665
7562
  /* @__PURE__ */ jsxs("div", {
7666
7563
  className: "grid min-h-0 flex-1 grid-cols-1 gap-y-4 py-4 sm:grid-cols-2",
@@ -7721,128 +7618,108 @@ function ActionSelectionEditor({ entries, connectors, prepareAction, workflows,
7721
7618
  }));
7722
7619
  }
7723
7620
  })]
7724
- }), /* @__PURE__ */ jsxs("div", {
7725
- ref: setPortalRoot,
7726
- className: "flex min-h-0 min-w-0 flex-col gap-2 sm:border-l sm:border-border/50",
7727
- children: [/* @__PURE__ */ jsxs("div", {
7728
- className: "flex h-8 shrink-0 items-center justify-between gap-2 px-4",
7729
- children: [/* @__PURE__ */ jsx("h3", {
7730
- ref: selectedHeading,
7731
- tabIndex: -1,
7732
- className: "m-0 text-[13px] font-normal text-muted-foreground outline-none",
7733
- children: t("actionPicker.selected", { count: draft.length })
7734
- }), /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsx(Button$1, {
7735
- type: "button",
7736
- size: "icon-sm",
7737
- variant: "ghost",
7738
- disabled: disabled || refreshing || !draft.some((entry) => entry.kind != "workflow" && prepared[entry.action]?.action.authenticated),
7739
- "aria-label": t("actionPicker.refresh"),
7740
- onClick: () => void refresh(),
7741
- children: refreshing ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx("i", {
7742
- "aria-hidden": "true",
7743
- className: "i-lucide-light:rotate-cw size-4 text-muted-foreground"
7744
- })
7745
- }) }), /* @__PURE__ */ jsx(TooltipContent, {
7746
- container: portalRoot,
7747
- children: t("actionPicker.refresh")
7748
- })] })]
7749
- }), draft.length == 0 ? /* @__PURE__ */ jsx(Empty, { children: /* @__PURE__ */ jsxs(EmptyHeader, { children: [/* @__PURE__ */ jsx(EmptyMedia, {
7750
- variant: "icon",
7751
- children: /* @__PURE__ */ jsx("i", {
7621
+ }), /* @__PURE__ */ jsx(SelectedToolsList, {
7622
+ count: draft.length,
7623
+ containerRef: setPortalRoot,
7624
+ headingRef: selectedHeading,
7625
+ className: "sm:border-l sm:border-border/50",
7626
+ actions: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsx(Button$1, {
7627
+ type: "button",
7628
+ size: "icon-sm",
7629
+ variant: "ghost",
7630
+ disabled: disabled || refreshing || !draft.some((entry) => entry.kind != "workflow" && prepared[entry.action]?.action.authenticated),
7631
+ "aria-label": t("actionPicker.refresh"),
7632
+ onClick: () => void refresh(),
7633
+ children: refreshing ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx("i", {
7752
7634
  "aria-hidden": "true",
7753
- className: "i-lucide-light:list-checks size-4"
7635
+ className: "i-lucide-light:rotate-cw size-4 text-muted-foreground"
7754
7636
  })
7755
- }), /* @__PURE__ */ jsx(EmptyDescription, {
7756
- className: "text-[13px]",
7757
- children: t("actionPicker.empty")
7758
- })] }) }) : /* @__PURE__ */ jsx(ScrollArea, {
7759
- className: "min-h-0 flex-1",
7760
- children: /* @__PURE__ */ jsx("div", {
7761
- className: "flex flex-col divide-y divide-border/50 px-4",
7762
- children: sortedEntries.map(({ entry, index }) => {
7763
- if (entry.kind == "workflow") return /* @__PURE__ */ jsx(SelectedWorkflowTool, {
7764
- entry,
7765
- workflowName: workflowCatalog.choices.find((item) => item.flowId == entry.flowId)?.name,
7637
+ }) }), /* @__PURE__ */ jsx(TooltipContent, {
7638
+ container: portalRoot,
7639
+ children: t("actionPicker.refresh")
7640
+ })] }),
7641
+ children: sortedEntries.map(({ entry, index }) => {
7642
+ if (entry.kind == "workflow") return /* @__PURE__ */ jsx(SelectedWorkflowTool, {
7643
+ entry,
7644
+ workflowName: workflowCatalog.choices.find((item) => item.flowId == entry.flowId)?.name,
7645
+ disabled,
7646
+ load: workflows?.load,
7647
+ onChange: (name) => replace(index, {
7648
+ ...entry,
7649
+ name
7650
+ }),
7651
+ otherNames: workflowEntries.filter((other) => other.flowId != entry.flowId).map((other) => other.name),
7652
+ onValidChange: (value) => setValidity(`${entry.id ?? entryKey(entry)}:alias`, value),
7653
+ portalRoot,
7654
+ onRemove: () => remove(index),
7655
+ onRefresh: (contract) => {
7656
+ if (workflows) setDraft((current) => current.map((item) => item.kind == "workflow" && item.flowId == entry.flowId ? workflows.refresh(item, contract) : item));
7657
+ },
7658
+ children: renderSettings(entry, index, entry.name)
7659
+ }, entry.id ?? entryKey(entry));
7660
+ const resolved = prepared[entry.action];
7661
+ const action = resolved?.action ?? discovered.current.get(entry.action) ?? actions[entry.action];
7662
+ const accounts = resolved?.connections ?? [];
7663
+ const selected = connections.find((account) => account.connectionId == entry.connectionId);
7664
+ const accountInvalid = resolved != null && action?.authenticated && entry.connectionId != null && entry.connectionId !== "" && !accounts.some((account) => account.connectionId == entry.connectionId && account.status == "active");
7665
+ return /* @__PURE__ */ jsx(SelectedToolRow, {
7666
+ icon: /* @__PURE__ */ jsx(ProviderAppIcon, { src: action == null ? void 0 : providerIcon(action) }),
7667
+ title: action?.name ?? entry.action,
7668
+ subtitle: /* @__PURE__ */ jsxs("span", {
7669
+ className: "truncate",
7670
+ children: [t("toolPicker.connector"), action == null ? "" : ` · ${action.serviceName}`]
7671
+ }),
7672
+ actions: settings ? renderSettings(entry, index, action?.name ?? entry.action, resolved != null) : /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsx(Button$1, {
7673
+ type: "button",
7674
+ size: "icon-sm",
7675
+ variant: "ghost",
7676
+ disabled,
7677
+ "aria-label": t("actionPicker.remove", { action: action?.name ?? entry.action }),
7678
+ onClick: () => remove(index),
7679
+ children: /* @__PURE__ */ jsx("i", {
7680
+ "aria-hidden": "true",
7681
+ className: "i-lucide-light:trash-2 size-4 text-muted-foreground"
7682
+ })
7683
+ }) }), /* @__PURE__ */ jsx(TooltipContent, {
7684
+ container: portalRoot,
7685
+ children: t("actionPicker.remove", { action: action?.name ?? entry.action })
7686
+ })] }),
7687
+ children: /* @__PURE__ */ jsx("div", {
7688
+ className: "open-flow-property-panel flex min-h-[30px] min-w-0 items-center [&>*]:w-full",
7689
+ children: resolved == null && preparationErrors[entry.action] != null ? /* @__PURE__ */ jsx(AccountControlButton, {
7690
+ status: "danger",
7766
7691
  disabled,
7767
- load: workflows?.load,
7768
- onChange: (name) => replace(index, {
7769
- ...entry,
7770
- name
7771
- }),
7772
- otherNames: workflowEntries.filter((other) => other.flowId != entry.flowId).map((other) => other.name),
7773
- onValidChange: (value) => setValidity(`${entry.id ?? entryKey(entry)}:alias`, value),
7774
- portalRoot,
7775
- onRemove: () => remove(index),
7776
- onRefresh: (contract) => {
7777
- if (workflows) setDraft((current) => current.map((item) => item.kind == "workflow" && item.flowId == entry.flowId ? workflows.refresh(item, contract) : item));
7692
+ label: t("inspector.account.retry"),
7693
+ hint: preparationErrors[entry.action],
7694
+ onClick: () => {
7695
+ connectors.retryAction(entry.action);
7696
+ setAttempt((value) => value + 1);
7697
+ }
7698
+ }) : action?.authenticated === false ? /* @__PURE__ */ jsx("div", {
7699
+ className: "text-muted-foreground",
7700
+ children: t("actionPicker.noAccount")
7701
+ }) : /* @__PURE__ */ jsx(AccountSelect, {
7702
+ loading: resolved == null,
7703
+ connections: accounts.filter((account) => account.status == "active"),
7704
+ selectedConnection: selected,
7705
+ selectedId: entry.connectionId,
7706
+ invalid: accountInvalid === true,
7707
+ warning: entry.connectionId == null,
7708
+ allowDeferred: true,
7709
+ label: t("actionPicker.accountFor", { action: action?.name ?? entry.action }),
7710
+ disabled,
7711
+ onChange: (connectionId) => {
7712
+ const { connectionId: _previous, ...rest } = entry;
7713
+ replace(index, connectionId == null ? rest : {
7714
+ ...rest,
7715
+ connectionId
7716
+ });
7778
7717
  },
7779
- children: renderSettings(entry, index, entry.name)
7780
- }, entry.id ?? entryKey(entry));
7781
- const resolved = prepared[entry.action];
7782
- const action = resolved?.action ?? discovered.current.get(entry.action) ?? actions[entry.action];
7783
- const accounts = resolved?.connections ?? [];
7784
- const selected = connections.find((account) => account.connectionId == entry.connectionId);
7785
- const accountInvalid = resolved != null && action?.authenticated && entry.connectionId != null && entry.connectionId !== "" && !accounts.some((account) => account.connectionId == entry.connectionId && account.status == "active");
7786
- return /* @__PURE__ */ jsx(SelectedToolRow, {
7787
- icon: /* @__PURE__ */ jsx(ProviderAppIcon, { src: action == null ? void 0 : providerIcon(action) }),
7788
- title: action?.name ?? entry.action,
7789
- subtitle: /* @__PURE__ */ jsxs("span", {
7790
- className: "truncate",
7791
- children: [t("toolPicker.connector"), action == null ? "" : ` · ${action.serviceName}`]
7792
- }),
7793
- actions: settings ? renderSettings(entry, index, action?.name ?? entry.action, resolved != null) : /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsx(Button$1, {
7794
- type: "button",
7795
- size: "icon-sm",
7796
- variant: "ghost",
7797
- disabled,
7798
- "aria-label": t("actionPicker.remove", { action: action?.name ?? entry.action }),
7799
- onClick: () => remove(index),
7800
- children: /* @__PURE__ */ jsx("i", {
7801
- "aria-hidden": "true",
7802
- className: "i-lucide-light:trash-2 size-4 text-muted-foreground"
7803
- })
7804
- }) }), /* @__PURE__ */ jsx(TooltipContent, {
7805
- container: portalRoot,
7806
- children: t("actionPicker.remove", { action: action?.name ?? entry.action })
7807
- })] }),
7808
- children: /* @__PURE__ */ jsx("div", {
7809
- className: "open-flow-property-panel flex min-h-[30px] min-w-0 items-center [&>*]:w-full",
7810
- children: resolved == null && preparationErrors[entry.action] != null ? /* @__PURE__ */ jsx(AccountControlButton, {
7811
- status: "danger",
7812
- disabled,
7813
- label: t("inspector.account.retry"),
7814
- hint: preparationErrors[entry.action],
7815
- onClick: () => {
7816
- connectors.retryAction(entry.action);
7817
- setAttempt((value) => value + 1);
7818
- }
7819
- }) : action?.authenticated === false ? /* @__PURE__ */ jsx("div", {
7820
- className: "text-muted-foreground",
7821
- children: t("actionPicker.noAccount")
7822
- }) : /* @__PURE__ */ jsx(AccountSelect, {
7823
- loading: resolved == null,
7824
- connections: accounts.filter((account) => account.status == "active"),
7825
- selectedConnection: selected,
7826
- selectedId: entry.connectionId,
7827
- invalid: accountInvalid === true,
7828
- warning: entry.connectionId == null,
7829
- allowDeferred: true,
7830
- label: t("actionPicker.accountFor", { action: action?.name ?? entry.action }),
7831
- disabled,
7832
- onChange: (connectionId) => {
7833
- const { connectionId: _previous, ...rest } = entry;
7834
- replace(index, connectionId == null ? rest : {
7835
- ...rest,
7836
- connectionId
7837
- });
7838
- },
7839
- onManage: resolved == null ? void 0 : () => void connectors.connect(resolved.action.serviceId)
7840
- })
7841
- })
7842
- }, entry.id ?? entry.action);
7718
+ onManage: resolved == null ? void 0 : () => void connectors.connect(resolved.action.serviceId)
7719
+ })
7843
7720
  })
7844
- })
7845
- })]
7721
+ }, entry.id ?? entry.action);
7722
+ })
7846
7723
  })]
7847
7724
  }),
7848
7725
  attempted && !valid && /* @__PURE__ */ jsx("div", {
@@ -22015,7 +21892,7 @@ function AgentToolSettings({ entry: tool, onChange, disabled, onValidChange, inp
22015
21892
  return /* @__PURE__ */ jsxs("fieldset", {
22016
21893
  className: "m-0 flex min-w-0 flex-col gap-4 border-0 p-0",
22017
21894
  children: [
22018
- /* @__PURE__ */ jsx(PopoverDescription, {
21895
+ onChange != null && /* @__PURE__ */ jsx(PopoverDescription, {
22019
21896
  className: "m-0 text-xs leading-5",
22020
21897
  children: t("agent.toolSettingsHint")
22021
21898
  }),
@@ -22084,28 +21961,25 @@ function AgentTools(props) {
22084
21961
  ...props.editor
22085
21962
  });
22086
21963
  if (props.config.tools.length === 0) return null;
22087
- return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
22088
- render: /* @__PURE__ */ jsx(Button$1, {
21964
+ return /* @__PURE__ */ jsx(ActionSelectionDialog, {
21965
+ readOnly: true,
21966
+ title: t("agent.tools"),
21967
+ entries: props.config.tools,
21968
+ providers: props.providers,
21969
+ trigger: /* @__PURE__ */ jsx(Button$1, {
22089
21970
  type: "button",
22090
21971
  variant: "ghost",
22091
- size: "sm"
21972
+ size: "sm",
21973
+ children: t("agent.tools")
22092
21974
  }),
22093
- children: t("agent.tools")
22094
- }), /* @__PURE__ */ jsx(PopoverContent, { children: /* @__PURE__ */ jsx("div", {
22095
- className: "grid max-h-96 gap-4 overflow-auto",
22096
- children: props.config.tools.map((tool) => /* @__PURE__ */ jsxs("details", { children: [
22097
- /* @__PURE__ */ jsx("summary", { children: tool.name || (tool.kind == "workflow" ? tool.flowId : tool.action) }),
22098
- /* @__PURE__ */ jsxs("p", {
22099
- className: "reference-value",
22100
- children: [tool.kind == "workflow" ? tool.flowId : tool.action, tool.connectionId == null ? "" : ` · ${tool.connectionId === "" ? t("inspector.account.deferred") : tool.connectionId}`]
22101
- }),
22102
- /* @__PURE__ */ jsx(AgentToolSettings, {
22103
- entry: tool,
22104
- disabled: true,
21975
+ settings: {
21976
+ title: t("agent.toolSettings"),
21977
+ render: (settings) => /* @__PURE__ */ jsx(AgentToolSettings, {
21978
+ ...settings,
22105
21979
  inputs: props.inputs
22106
21980
  })
22107
- ] }, tool.id))
22108
- }) })] });
21981
+ }
21982
+ });
22109
21983
  }
22110
21984
  //#endregion
22111
21985
  //#region src/workbench/browser/runtime/editor/codeEditorPlaceholder.tsx
@@ -22422,7 +22296,7 @@ function EditableAgentSettingsProvider({ children, task, nodeId, store, connecto
22422
22296
  saveFailed
22423
22297
  });
22424
22298
  }
22425
- function AgentSettingsContent({ children, task, config, nodeId, toolsEditor, disabled, theme, validationError, setConfig, save, saveFailed = false }) {
22299
+ function AgentSettingsContent({ children, task, config, nodeId, toolsEditor, providers, disabled, theme, validationError, setConfig, save, saveFailed = false }) {
22426
22300
  const t = useTranslate();
22427
22301
  const inputs = task.inputs.filter((port) => "handle" in port);
22428
22302
  const promptSection = /* @__PURE__ */ jsxs("section", {
@@ -22437,7 +22311,8 @@ function AgentSettingsContent({ children, task, config, nodeId, toolsEditor, dis
22437
22311
  config,
22438
22312
  disabled,
22439
22313
  inputs,
22440
- editor: toolsEditor
22314
+ editor: toolsEditor,
22315
+ providers
22441
22316
  })]
22442
22317
  }), /* @__PURE__ */ jsxs("div", {
22443
22318
  className: "inspector-section-content",
@@ -22565,6 +22440,7 @@ function AgentSettingsProvider(props) {
22565
22440
  nodeId: props.nodeId,
22566
22441
  disabled: true,
22567
22442
  theme: props.theme,
22443
+ providers: props.providers,
22568
22444
  children: props.children
22569
22445
  });
22570
22446
  }
@@ -25967,122 +25843,6 @@ function DecisionItemActions({ addLabel, removeLabel, canAdd = true, onAdd, onRe
25967
25843
  }), /* @__PURE__ */ jsx(TooltipContent, { children: removeLabel })] })] });
25968
25844
  }
25969
25845
  //#endregion
25970
- //#region src/workbench/browser/runtime/editor/dedupeSection.tsx
25971
- function DedupeSection({ task, disabled, onSave, history }) {
25972
- const t = useTranslate();
25973
- const id = useId();
25974
- const taskRef = useRef(task);
25975
- taskRef.current = task;
25976
- const saveRef = useRef(onSave);
25977
- saveRef.current = onSave;
25978
- const [changes] = useState(() => new TaskExecutorChanges(task.executor, (before, next) => {
25979
- const current = taskRef.current;
25980
- if (before.kind !== "dedupe" || next.kind !== "dedupe" || current.executor.kind !== "dedupe") return Promise.resolve(false);
25981
- const executor = { ...current.executor };
25982
- for (const key of [
25983
- "field",
25984
- "mode",
25985
- "space"
25986
- ]) if (before[key] !== next[key]) Object.assign(executor, { [key]: next[key] });
25987
- return saveRef.current(current, {
25988
- ...current,
25989
- executor
25990
- });
25991
- }));
25992
- const [config, setConfig] = useState(changes.value);
25993
- const [failed, setFailed] = useState(false);
25994
- useEffect(() => {
25995
- changes.sync(task.executor);
25996
- setConfig(changes.value);
25997
- }, [changes, task.executor]);
25998
- async function save() {
25999
- try {
26000
- setFailed(!await changes.save());
26001
- } catch {
26002
- setFailed(true);
26003
- }
26004
- }
26005
- function update(patch) {
26006
- if (disabled || changes.value.kind !== "dedupe") return;
26007
- changes.value = {
26008
- ...changes.value,
26009
- ...patch
26010
- };
26011
- setConfig(changes.value);
26012
- save();
26013
- }
26014
- if (config.kind !== "dedupe") return null;
26015
- return /* @__PURE__ */ jsx(InspectorSection, {
26016
- title: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
26017
- className: "min-w-0 flex-1",
26018
- children: t("flowState.nodeTitle")
26019
- }), history] }),
26020
- children: /* @__PURE__ */ jsxs("div", {
26021
- className: "node-settings flex flex-col gap-3",
26022
- children: [
26023
- /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, {
26024
- htmlFor: `${id}-field`,
26025
- children: t("flowState.field")
26026
- }), /* @__PURE__ */ jsx(Input, {
26027
- id: `${id}-field`,
26028
- disabled,
26029
- defaultValue: config.field,
26030
- placeholder: t("flowState.fieldPlaceholder"),
26031
- onBlur: (event) => {
26032
- if (event.target.value !== config.field) update({ field: event.target.value });
26033
- }
26034
- }, config.field)] }),
26035
- /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, {
26036
- htmlFor: `${id}-mode`,
26037
- children: t("flowState.mode")
26038
- }), /* @__PURE__ */ jsxs(NativeSelect, {
26039
- id: `${id}-mode`,
26040
- disabled,
26041
- value: config.mode,
26042
- onChange: (event) => update({ mode: event.target.value }),
26043
- children: [/* @__PURE__ */ jsx(NativeSelectOption, {
26044
- value: "new",
26045
- children: t("flowState.new")
26046
- }), /* @__PURE__ */ jsx(NativeSelectOption, {
26047
- value: "increasing",
26048
- children: t("flowState.increasing")
26049
- })]
26050
- })] }),
26051
- /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, {
26052
- htmlFor: `${id}-space`,
26053
- children: t("flowState.space")
26054
- }), /* @__PURE__ */ jsxs(NativeSelect, {
26055
- id: `${id}-space`,
26056
- disabled,
26057
- value: config.space,
26058
- onChange: (event) => update({ space: event.target.value }),
26059
- children: [/* @__PURE__ */ jsx(NativeSelectOption, {
26060
- value: "node",
26061
- children: t("flowState.nodeSpace")
26062
- }), /* @__PURE__ */ jsx(NativeSelectOption, {
26063
- value: "flow",
26064
- children: t("flowState.flowSpace")
26065
- })]
26066
- })] }),
26067
- failed && /* @__PURE__ */ jsxs("div", {
26068
- role: "alert",
26069
- children: [/* @__PURE__ */ jsx("p", { children: t("httpRequest.saveFailed") }), /* @__PURE__ */ jsx(Button$1, {
26070
- disabled,
26071
- onClick: () => void save(),
26072
- variant: "outline",
26073
- size: "sm",
26074
- children: t("httpRequest.retry")
26075
- })]
26076
- }),
26077
- /* @__PURE__ */ jsx("p", {
26078
- className: "m-0 text-muted-foreground text-xs",
26079
- children: t("flowState.warning")
26080
- })
26081
- ]
26082
- })
26083
- });
26084
- }
26085
- //#endregion
26086
25846
  //#region src/workbench/browser/runtime/editor/errorTriggerSources.tsx
26087
25847
  function ErrorTriggerSources({ flows, flowId, value, disabled = false, complete = true, footer, onChange }) {
26088
25848
  const t = useTranslate();
@@ -29563,6 +29323,169 @@ function ResolutionDefinition({ disabled, selection, store }) {
29563
29323
  });
29564
29324
  }
29565
29325
  //#endregion
29326
+ //#region src/workbench/browser/runtime/editor/skipDuplicatesSection.tsx
29327
+ function SkipDuplicatesSection({ task, disabled, onSave, history }) {
29328
+ const t = useTranslate();
29329
+ const id = useId();
29330
+ const taskRef = useRef(task);
29331
+ const saveRef = useRef(onSave);
29332
+ useLayoutEffect(() => {
29333
+ taskRef.current = task;
29334
+ saveRef.current = onSave;
29335
+ }, [task, onSave]);
29336
+ const request = useRef();
29337
+ const [changes] = useState(() => new TaskExecutorChanges(task.executor, (_before, next) => {
29338
+ const current = taskRef.current;
29339
+ if (next.kind !== "skip-duplicates" || current.executor.kind !== "skip-duplicates") return Promise.resolve(false);
29340
+ return saveRef.current(current, {
29341
+ ...current,
29342
+ executor: {
29343
+ ...current.executor,
29344
+ fields: next.fields
29345
+ }
29346
+ });
29347
+ }));
29348
+ const initial = task.executor.kind === "skip-duplicates" ? task.executor.fields : [];
29349
+ const [fields, setFields] = useState(initial.length ? initial : [""]);
29350
+ const inputs = useRef([]);
29351
+ const focusField = useRef();
29352
+ useEffect(() => {
29353
+ if (focusField.current == null) return;
29354
+ inputs.current[focusField.current]?.focus();
29355
+ focusField.current = void 0;
29356
+ }, [fields]);
29357
+ const [error, setError] = useState();
29358
+ useEffect(() => {
29359
+ const previous = changes.value;
29360
+ changes.sync(task.executor);
29361
+ if (previous.kind === "skip-duplicates" && changes.value.kind === "skip-duplicates" && !dequal(previous.fields, changes.value.fields)) {
29362
+ request.current?.abort();
29363
+ setFields(changes.value.fields.length ? changes.value.fields : [""]);
29364
+ setError(void 0);
29365
+ }
29366
+ }, [changes, task.executor]);
29367
+ useEffect(() => () => request.current?.abort(), [disabled]);
29368
+ function change(next) {
29369
+ request.current?.abort();
29370
+ setFields(next);
29371
+ setError(void 0);
29372
+ }
29373
+ async function commit(next = fields) {
29374
+ if (disabled || changes.value.kind !== "skip-duplicates") return;
29375
+ request.current?.abort();
29376
+ const controller = new AbortController();
29377
+ request.current = controller;
29378
+ const rows = next.length ? next : [""];
29379
+ setFields(rows);
29380
+ await Promise.resolve();
29381
+ if (controller.signal.aborted || request.current !== controller) return;
29382
+ const normalized = rows.map((field) => field.trim());
29383
+ const parsed = skipDuplicatesConfigSchema.safeParse({ fields: normalized.filter(Boolean) });
29384
+ if (!parsed.success) {
29385
+ setError("invalid");
29386
+ return;
29387
+ }
29388
+ setFields(normalized);
29389
+ setError(void 0);
29390
+ changes.value = {
29391
+ ...changes.value,
29392
+ fields: parsed.data.fields
29393
+ };
29394
+ try {
29395
+ const saved = await changes.save();
29396
+ if (!controller.signal.aborted && request.current === controller) setError(saved ? void 0 : "save");
29397
+ } catch {
29398
+ if (!controller.signal.aborted && request.current === controller) setError("save");
29399
+ }
29400
+ }
29401
+ if (task.executor.kind !== "skip-duplicates") return null;
29402
+ return /* @__PURE__ */ jsx(InspectorSection, {
29403
+ title: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
29404
+ className: "min-w-0 flex-1",
29405
+ children: t("flowState.nodeTitle")
29406
+ }), history] }),
29407
+ children: /* @__PURE__ */ jsxs("div", {
29408
+ className: "node-settings flex flex-col gap-3",
29409
+ children: [
29410
+ /* @__PURE__ */ jsxs(Field, { children: [
29411
+ /* @__PURE__ */ jsx(FieldLabel, {
29412
+ htmlFor: `${id}-field-0`,
29413
+ children: t("flowState.field")
29414
+ }),
29415
+ fields.map((field, index) => /* @__PURE__ */ jsxs("div", {
29416
+ className: "flex items-center gap-2",
29417
+ children: [/* @__PURE__ */ jsx(Input, {
29418
+ ref: (element) => {
29419
+ inputs.current[index] = element;
29420
+ },
29421
+ id: `${id}-field-${index}`,
29422
+ "aria-label": t("flowState.fieldIndex", { index: index + 1 }),
29423
+ "aria-invalid": error === "invalid" || void 0,
29424
+ "aria-describedby": error === "invalid" ? `${id}-error` : void 0,
29425
+ disabled,
29426
+ value: field,
29427
+ placeholder: t(fields.length === 1 ? "flowState.fieldPlaceholder" : "flowState.pathPlaceholder"),
29428
+ onChange: (event) => change(fields.map((value, at) => at === index ? event.target.value : value)),
29429
+ onBlur: () => {
29430
+ commit();
29431
+ },
29432
+ onKeyDown: (event) => {
29433
+ if (event.key === "Enter") {
29434
+ event.preventDefault();
29435
+ event.currentTarget.blur();
29436
+ }
29437
+ }
29438
+ }), !disabled && (fields.length > 1 || field !== "") && /* @__PURE__ */ jsx(Button$1, {
29439
+ variant: "ghost",
29440
+ size: "xs",
29441
+ "aria-label": t("flowState.removeField", { index: index + 1 }),
29442
+ onMouseDown: (event) => event.preventDefault(),
29443
+ onClick: () => {
29444
+ focusField.current = Math.max(0, index - 1);
29445
+ commit(fields.filter((_, at) => at !== index));
29446
+ },
29447
+ children: t("flowState.delete")
29448
+ })]
29449
+ }, index)),
29450
+ !disabled && /* @__PURE__ */ jsx("div", {
29451
+ className: "flex",
29452
+ children: /* @__PURE__ */ jsx(Button$1, {
29453
+ variant: "ghost",
29454
+ size: "sm",
29455
+ onMouseDown: (event) => event.preventDefault(),
29456
+ onClick: () => {
29457
+ const empty = fields.findIndex((field) => field.trim() === "");
29458
+ if (empty >= 0) {
29459
+ inputs.current[empty]?.focus();
29460
+ return;
29461
+ }
29462
+ focusField.current = fields.length;
29463
+ change([...fields, ""]);
29464
+ },
29465
+ children: t("flowState.addField")
29466
+ })
29467
+ })
29468
+ ] }),
29469
+ error != null && /* @__PURE__ */ jsxs("div", {
29470
+ role: "alert",
29471
+ id: `${id}-error`,
29472
+ children: [/* @__PURE__ */ jsx("p", { children: t(error === "invalid" ? "flowState.invalidFields" : "flowState.saveFailed") }), error === "save" && /* @__PURE__ */ jsx(Button$1, {
29473
+ disabled,
29474
+ onClick: () => void commit(),
29475
+ variant: "outline",
29476
+ size: "sm",
29477
+ children: t("flowState.retry")
29478
+ })]
29479
+ }),
29480
+ /* @__PURE__ */ jsx("p", {
29481
+ className: "m-0 text-muted-foreground text-xs",
29482
+ children: t("flowState.warning")
29483
+ })
29484
+ ]
29485
+ })
29486
+ });
29487
+ }
29488
+ //#endregion
29566
29489
  //#region src/workbench/browser/runtime/editor/tallyTriggerConfig.tsx
29567
29490
  function TallyTriggerConfig({ inputs, fieldLabels, config, nodeId, connectionId, disabled, store }) {
29568
29491
  const t = useTranslate();
@@ -30834,7 +30757,7 @@ function inspectorIcon(node) {
30834
30757
  if (node?.kind == "task" && node.definition != null && "executor" in node.definition) {
30835
30758
  if (node.definition.executor.kind == "decision") return "decision";
30836
30759
  if (node.definition.executor.kind == "workflow") return "flow";
30837
- if (node.definition.executor.kind == "openapi" || node.definition.executor.kind == "http-request" || node.definition.executor.kind == "dedupe") return "task";
30760
+ if (node.definition.executor.kind == "openapi" || node.definition.executor.kind == "http-request" || node.definition.executor.kind == "skip-duplicates") return "task";
30838
30761
  return node.definition.executor.kind == "connector" ? "connection" : "llm";
30839
30762
  }
30840
30763
  return "task";
@@ -30867,7 +30790,7 @@ function nodePurposePlaceholder(selection, t, action, displays) {
30867
30790
  case "agent": return t("addNode.agentDescription");
30868
30791
  case "decision": return t("decision.description");
30869
30792
  case "workflow": return t("workflow.description");
30870
- case "dedupe": return;
30793
+ case "skip-duplicates": return;
30871
30794
  case "http-request": return t("httpRequest.description");
30872
30795
  case "openapi": return t("openapi.description");
30873
30796
  case "connector": return action?.description;
@@ -30920,7 +30843,7 @@ function NodeInspector({ onAddWorkflowOutputs, onAddResponseNode, webhookDeploym
30920
30843
  loading: false,
30921
30844
  names: [],
30922
30845
  onOpen: void 0
30923
- }, readOnly = false, connectorAction, connectorActionError, connectorAccessError, connectorAuthorizationPending = false, connectorConnection, connectorConnectionError, activeConnectorConnections, connectors: liveConnectors, connectorAccess, connectorCandidates, onConfigureConnectorAccess, prepareConnectorAction, connectorLoading = false, disabled: temporarilyDisabled = false, diagnostics, focus, revision, selection, sourceNodeIcons, store: writableStore, theme, triggerActiveConnections, triggerAuthorizationPending = false, triggerConnection, triggerConnectionError, triggerConnectionLoading = false, triggerDisplays, triggers: liveTriggers }) {
30846
+ }, readOnly = false, connectorAction, connectorActionError, connectorAccessError, connectorAuthorizationPending = false, connectorConnection, connectorConnectionError, activeConnectorConnections, connectorProviders, connectors: liveConnectors, connectorAccess, connectorCandidates, onConfigureConnectorAccess, prepareConnectorAction, connectorLoading = false, disabled: temporarilyDisabled = false, diagnostics, focus, revision, selection, sourceNodeIcons, store: writableStore, theme, triggerActiveConnections, triggerAuthorizationPending = false, triggerConnection, triggerConnectionError, triggerConnectionLoading = false, triggerDisplays, triggers: liveTriggers }) {
30924
30847
  const store = readOnly ? void 0 : writableStore;
30925
30848
  const connectors = readOnly ? void 0 : liveConnectors;
30926
30849
  const triggers = readOnly ? void 0 : liveTriggers;
@@ -31215,25 +31138,6 @@ function NodeInspector({ onAddWorkflowOutputs, onAddResponseNode, webhookDeploym
31215
31138
  actions: workflowActions,
31216
31139
  list: (signal) => store.listWorkflowTargets(signal)
31217
31140
  }, `workflow:${selection?.id}`),
31218
- task != null && "executor" in task && task.executor.kind === "dedupe" && /* @__PURE__ */ jsx(DedupeSection, {
31219
- task,
31220
- disabled,
31221
- history: store != null && store.$.flowId.value != null ? /* @__PURE__ */ jsx(FlowStateButton, {
31222
- client: store.state,
31223
- flowId: store.$.flowId.value,
31224
- nodeIds: Object.keys(revision.graph()?.nodes ?? {}),
31225
- history: {
31226
- nodeId: selection.id,
31227
- space: task.executor.space === "flow" ? "flow" : `node:${selection.id}`
31228
- }
31229
- }, selection.id) : void 0,
31230
- onSave: (before, value) => store?.nodes.saveTaskSettings(selection.id, {
31231
- kind: "dedupe",
31232
- name: task.name,
31233
- before,
31234
- task: value
31235
- }) ?? Promise.resolve(false)
31236
- }, `${revision.revision.flowId}:${selection.id}`),
31237
31141
  isHttpRequest && task != null && "executor" in task && /* @__PURE__ */ jsx(HttpRequestSection, {
31238
31142
  task,
31239
31143
  disabled,
@@ -31559,6 +31463,22 @@ function NodeInspector({ onAddWorkflowOutputs, onAddResponseNode, webhookDeploym
31559
31463
  onChange: () => {}
31560
31464
  })
31561
31465
  }),
31466
+ task != null && "executor" in task && task.executor.kind === "skip-duplicates" && /* @__PURE__ */ jsx(SkipDuplicatesSection, {
31467
+ task,
31468
+ disabled,
31469
+ history: store != null && store.$.flowId.value != null ? /* @__PURE__ */ jsx(FlowStateButton, {
31470
+ client: store.state,
31471
+ flowId: store.$.flowId.value,
31472
+ nodeIds: Object.keys(revision.graph()?.nodes ?? {}),
31473
+ history: { nodeId: selection.id }
31474
+ }, selection.id) : void 0,
31475
+ onSave: (before, value) => store?.nodes.saveTaskSettings(selection.id, {
31476
+ kind: "skip-duplicates",
31477
+ name: task.name,
31478
+ before,
31479
+ task: value
31480
+ }) ?? Promise.resolve(false)
31481
+ }, `${revision.revision.flowId}:${selection.id}`),
31562
31482
  selection == null ? /* @__PURE__ */ jsx("div", {
31563
31483
  className: "inspector-empty",
31564
31484
  children: t("inspector.selectNode")
@@ -31604,6 +31524,7 @@ function NodeInspector({ onAddWorkflowOutputs, onAddResponseNode, webhookDeploym
31604
31524
  nodeId: selection.id,
31605
31525
  store,
31606
31526
  connectors,
31527
+ providers: connectorProviders,
31607
31528
  prepareAction: prepareConnectorAction,
31608
31529
  disabled,
31609
31530
  theme,
@@ -31724,7 +31645,8 @@ function CanvasNodePicker({ request, centered, ...props }) {
31724
31645
  ...props,
31725
31646
  anchor: request.screenPosition,
31726
31647
  centered,
31727
- isOptionDisabled: (option) => request.connectionSide != null && (option.kind == "trigger" || option.kind == "comment" || request.connectionSide == "left" && (option.kind == "approval" || option.kind == "condition" || option.kind == "wait"))
31648
+ initialTab: request.connectionDirection != null ? "nodes" : props.initialTab,
31649
+ isOptionDisabled: (option) => request.connectionDirection != null && (option.kind == "trigger" || option.kind == "comment" || request.connectionDirection == "downstream" && option.kind == "value" || request.connectionDirection == "upstream" && (option.kind == "approval" || option.kind == "condition" || option.kind == "wait" || option.kind == "outputs"))
31728
31650
  });
31729
31651
  }
31730
31652
  //#endregion
@@ -31806,9 +31728,11 @@ function useInspectorPanel({ identity, preferences, selectedNodeIds, onSelectNod
31806
31728
  function callbacksFromProps(props) {
31807
31729
  return {
31808
31730
  onIgnoreNodes: props.onIgnoreNodes,
31731
+ onChangeDirection: props.onChangeDirection,
31809
31732
  onAddNode: props.onAddNode,
31810
31733
  onMoveNodes: props.onMoveNodes,
31811
31734
  onChangeNodeContentHidden: props.onChangeNodeContentHidden,
31735
+ onChangeNodeWidth: props.onChangeNodeWidth,
31812
31736
  onChangeComment: props.onChangeComment,
31813
31737
  onConnect: props.onConnect,
31814
31738
  onDeleteNodes: props.onDeleteNodes,
@@ -32025,7 +31949,7 @@ function focusPanel(event) {
32025
31949
  if (element instanceof Element && element.closest("a, button, input, label, select, textarea, [contenteditable=\"true\"]")) return;
32026
31950
  event.currentTarget.focus({ preventScroll: true });
32027
31951
  }
32028
- var WorkbenchCanvas = forwardRef(function WorkbenchCanvas({ nodePicker, annotationContext, addNodeControl, addNodeOptions, history, disabled, interactiveMode$, focusNodeRequest, inspectorOpen, model, onAddNode, onConnect, onChangeNodeContentHidden, onChangeComment, onCopy, onDeleteEdge, onDeleteNodes, onDuplicate, onMoveNodes, onMoveViewport, subscribeCanvasCommands, onPaste, provideAddNodeOptions, onSelectNodes, onActivateSelection, onSelectionStart, onSelectionEnd, onToggleInspector, ignoredNodeIds, onIgnoreNodes, runControl, cornerLeading, connectionControl, topLeftTools, bottomRightTools, selectedNodeIds, theme }, ref) {
31952
+ var WorkbenchCanvas = forwardRef(function WorkbenchCanvas({ nodePicker, annotationContext, addNodeControl, addNodeOptions, history, disabled, interactiveMode$, focusNodeRequest, inspectorOpen, model, onAddNode, onConnect, onChangeNodeContentHidden, onChangeNodeWidth, onChangeComment, onCopy, onDeleteEdge, onDeleteNodes, onDuplicate, onMoveNodes, onChangeDirection, onMoveViewport, subscribeCanvasCommands, onPaste, provideAddNodeOptions, onSelectNodes, onActivateSelection, onSelectionStart, onSelectionEnd, onToggleInspector, ignoredNodeIds, onIgnoreNodes, runControl, cornerLeading, connectionControl, topLeftTools, bottomRightTools, selectedNodeIds, theme }, ref) {
32029
31953
  const [pickerRequest, setPickerRequest] = useState();
32030
31954
  const [pickerCentered, setPickerCentered] = useState(false);
32031
31955
  useEffect(() => {
@@ -32220,6 +32144,7 @@ var WorkbenchCanvas = forwardRef(function WorkbenchCanvas({ nodePicker, annotati
32220
32144
  },
32221
32145
  onConnect,
32222
32146
  onChangeNodeContentHidden,
32147
+ onChangeNodeWidth,
32223
32148
  onChangeComment,
32224
32149
  onDeleteNodes: (nodeIds) => {
32225
32150
  canvas.current?.focus({ preventScroll: true });
@@ -32233,6 +32158,7 @@ var WorkbenchCanvas = forwardRef(function WorkbenchCanvas({ nodePicker, annotati
32233
32158
  onDuplicate(positions, offset);
32234
32159
  },
32235
32160
  onMoveNodes,
32161
+ onChangeDirection,
32236
32162
  onMoveViewport,
32237
32163
  subscribeCanvasCommands,
32238
32164
  onCopy: (nodeIds) => {
@@ -32632,10 +32558,45 @@ function RevisionCanvas({ draft, presentation, theme, interactiveMode$, label, b
32632
32558
  const [selected, setSelected] = useState([]);
32633
32559
  const [inspectorOpen, setInspectorOpen] = useState(false);
32634
32560
  const [focus, setFocus] = useState();
32635
- const baseline = useMemo(() => designerGraph(draft, presentation?.value, [], {}, {}, t), [
32561
+ const [catalog, setCatalog] = useState();
32562
+ const needsProviders = revision.connectorProviderIds.size > 0;
32563
+ useEffect(() => {
32564
+ if (!needsProviders) return;
32565
+ const controller = new AbortController();
32566
+ const cache = getAppCatalogCache({
32567
+ locale: language.toLowerCase(),
32568
+ schemaVersion: 1,
32569
+ maxAge: 3e5,
32570
+ decode: decodeAppCatalogResponse,
32571
+ load: ({ locale }, validation) => loadJson(`https://connector.oomol.com/public/v1/apps?locale=${encodeURIComponent(locale)}`, validation, decodeAppCatalogResponse, {
32572
+ credentials: "omit",
32573
+ signal: AbortSignal.timeout(15e3)
32574
+ })
32575
+ });
32576
+ const publish = (response) => {
32577
+ if (controller.signal.aborted) return;
32578
+ setCatalog({
32579
+ language,
32580
+ providers: Object.fromEntries(response.data.map((app) => [app.service, provider(app, response.meta.iconSprite)]))
32581
+ });
32582
+ };
32583
+ (async () => {
32584
+ try {
32585
+ const cached = await cache.peek(void 0);
32586
+ if (cached) publish(cached.data);
32587
+ publish(await cache.get(void 0, { signal: controller.signal }));
32588
+ } catch (error) {
32589
+ if (!controller.signal.aborted) console.warn("Could not load Preview Provider metadata.", error);
32590
+ }
32591
+ })();
32592
+ return () => controller.abort();
32593
+ }, [language, needsProviders]);
32594
+ const providerMetadata = catalog?.language === language ? catalog.providers : void 0;
32595
+ const baseline = useMemo(() => designerGraph(draft, presentation?.value, [], {}, {}, t, void 0, [], providerMetadata), [
32636
32596
  draft,
32637
32597
  presentation,
32638
- t
32598
+ t,
32599
+ providerMetadata
32639
32600
  ]);
32640
32601
  const session = sessions[graphId];
32641
32602
  const model = useMemo(() => ({
@@ -32730,7 +32691,8 @@ function RevisionCanvas({ draft, presentation, theme, interactiveMode$, label, b
32730
32691
  readOnly: true,
32731
32692
  revision,
32732
32693
  selection,
32733
- theme
32694
+ theme,
32695
+ connectorProviders: providerMetadata
32734
32696
  }, `${graphId}:${selection.id}`) : comment?.kind === "comment" ? /* @__PURE__ */ jsx(CommentInspector, {
32735
32697
  title: comment.title,
32736
32698
  content: comment.content ?? "",
@@ -36652,14 +36614,10 @@ function FlowEditor({ navigationIsland, onRun, onRunStarted, onCloseRuns, onConf
36652
36614
  return /* @__PURE__ */ jsx(NodeHistoryContext.Provider, {
36653
36615
  value: (nodeId) => {
36654
36616
  const node = revision?.graph().nodes[nodeId];
36655
- if (flowId == null || node?.kind !== "task" || !("executor" in node.task) || node.task.executor.kind !== "dedupe") return void 0;
36656
- const space = node.task.executor.space === "flow" ? "flow" : `node:${nodeId}`;
36617
+ if (flowId == null || node?.kind !== "task" || !("executor" in node.task) || node.task.executor.kind !== "skip-duplicates") return void 0;
36657
36618
  return {
36658
36619
  label: t("flowState.history"),
36659
- onClick: () => setStateTarget({ history: {
36660
- nodeId,
36661
- space
36662
- } })
36620
+ onClick: () => setStateTarget({ history: { nodeId } })
36663
36621
  };
36664
36622
  },
36665
36623
  children: /* @__PURE__ */ jsxs(CanvasHistoryScope, {
@@ -36801,12 +36759,14 @@ function FlowEditor({ navigationIsland, onRun, onRunStarted, onCloseRuns, onConf
36801
36759
  },
36802
36760
  onConnect: (edge) => void store.workspace.connect(edge),
36803
36761
  onChangeNodeContentHidden: (nodeId, hidden) => void store.workspace.saveNodeContentHidden(nodeId, hidden),
36762
+ onChangeNodeWidth: (nodeId, width, position) => store.workspace.saveNodeWidth(nodeId, width, position),
36804
36763
  onChangeComment: (nodeId, value) => void store.workspace.saveComment(nodeId, value),
36805
36764
  onCopy: () => store.workspace.copySelectedNodes(),
36806
36765
  onDeleteEdge: (edge) => void store.workspace.disconnect(edge),
36807
36766
  onDeleteNodes: () => void store.workspace.deleteSelectedNodes(),
36808
36767
  onDuplicate: (positions, offset) => void store.workspace.duplicateSelectedNodes(positions, offset),
36809
36768
  onMoveNodes: (positions) => void store.workspace.moveNodes(positions),
36769
+ onChangeDirection: (direction, positions) => store.changeDirection(direction, positions),
36810
36770
  onMoveViewport: (viewport) => void store.workspace.moveViewport(viewport),
36811
36771
  onPaste: () => void store.workspace.pasteNodes(),
36812
36772
  provideAddNodeOptions: store.provideAddNodeOptions,