@oomol-lab/open-flow 0.1.0-beta.89 → 0.1.0-beta.90

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 (33) hide show
  1. package/README.md +29 -0
  2. package/dist/browser/{FlowCanvas-SqPUBqze.js → FlowCanvas-C4iuvVKB.js} +2 -2
  3. package/dist/browser/{exportPng-CLZKdNzR.js → exportPng-DMsB9ku_.js} +4 -4
  4. package/dist/browser/{flowChanges-CnOOPJJR.js → flowChanges-SKYJBr6X.js} +12 -11
  5. package/dist/browser/{flowWorkspace-d9Ef-aRK.js → flowWorkspace-4UHRaHcz.js} +10 -7
  6. package/dist/browser/{markdownContent-D0BBrFcF.js → markdownContent-B75ojl0E.js} +1 -1
  7. package/dist/browser/preview.css +14 -5
  8. package/dist/browser/preview.d.ts +4 -1
  9. package/dist/browser/preview.js +397 -95
  10. package/dist/browser/workbench-contract.d.ts +3 -0
  11. package/dist/browser/workbench.css +14 -5
  12. package/dist/browser/workbench.js +12 -9
  13. package/dist/browser/{wrapLayout-BB_qwy3k.js → wrapLayout-DU5HG1qH.js} +371 -71
  14. package/dist/command/index.js +13 -13
  15. package/dist/common/cache.d.ts +7 -0
  16. package/dist/common/catalogCache.d.ts +3 -7
  17. package/dist/common/control-api-conformance.js +10 -9
  18. package/dist/common/control-api.d.ts +3 -1
  19. package/dist/common/control-api.js +10 -9
  20. package/dist/common/mcp.js +10 -9
  21. package/dist/common/provider-icons.d.ts +35 -0
  22. package/dist/common/provider-icons.js +134 -0
  23. package/dist/render/browser/runtime.css +14 -5
  24. package/dist/render/browser/runtime.js +667 -365
  25. package/dist/render/common/png.d.ts +7 -0
  26. package/dist/render/node/index.d.ts +10 -2
  27. package/dist/render/node/index.js +1284 -37
  28. package/dist/render/node/licenses.md +24 -0
  29. package/package.json +5 -1
  30. package/src/base/common/cache.ts +8 -0
  31. package/src/connector/common/providerIconCache.ts +191 -0
  32. package/src/control/common/api.ts +10 -3
  33. package/src/control/common/catalogCache.ts +19 -11
package/README.md CHANGED
@@ -48,6 +48,34 @@ renderer's Context. Bundled rendering resources remain available. The exporter s
48
48
  node icons may instead use a component fallback or be omitted without setting this
49
49
  flag. A `false` value does not guarantee that every remote image loaded.
50
50
 
51
+ For Provider artwork, pass the same `ControlClient` used by offline authoring as
52
+ `client`. The renderer reuses its Provider JSON cache; without a client it keeps
53
+ bundled fallback icons and does not request a public catalog.
54
+
55
+ ```ts
56
+ import { ProviderIconCache } from '@oomol-lab/open-flow/provider-icons'
57
+
58
+ const iconCache = new ProviderIconCache({ scope, delegate, mode: 'default' })
59
+ const result = await flowToPng(browser, workflow, { client, iconCache })
60
+ ```
61
+
62
+ The storage delegate implements `get(key)`, `set(key, json)` and `delete(key)`,
63
+ matching `ControlCacheDelegate`. Reuse the icon cache across exports. It uses a
64
+ separate namespace for complete image responses with base64 bodies. Each scope has
65
+ two fixed sprite slots, light and dark, and one original-image slot per Provider.
66
+ URL and sprite version must match before reuse. Successfully loaded versions replace
67
+ their slot; failed loads never combine old artwork with new crop coordinates.
68
+ Original images use HTTP caching and ETag, with a 24-hour default; `no-store` is
69
+ respected. Options include `mode: 'refresh' | 'offline' | 'default'` and `fetch`.
70
+ Without a delegate, the cache uses memory. Storage failures retain successful loads
71
+ in memory. `allowNetwork: false` reads both Provider JSON and artwork caches only,
72
+ and blocks remote requests in the temporary browser Context. Missing artwork falls
73
+ back without failing the export.
74
+
75
+ Browser Workbench and Preview cache Provider artwork in IndexedDB by default. Supply
76
+ `host.iconCache` or the Preview's `iconCache` prop to replace it. Workbench PNG
77
+ export uses the same cache. Iconify and Markdown images keep their existing behavior.
78
+
51
79
  Install the Task contracts as a development dependency:
52
80
 
53
81
  ```bash
@@ -90,6 +118,7 @@ Source paths are not public import APIs. Source maps and declaration maps are no
90
118
  | Public entry | Source |
91
119
  | --- | --- |
92
120
  | `@oomol-lab/open-flow` (types) | [src/types/index.ts](src/types/index.ts) |
121
+ | `@oomol-lab/open-flow/provider-icons` | [src/connector/common/providerIconCache.ts](src/connector/common/providerIconCache.ts) |
93
122
  | `@oomol-lab/open-flow/connector-action` | [src/connector/common/actionSchema.ts](src/connector/common/actionSchema.ts) |
94
123
  | `@oomol-lab/open-flow/connector-proxy` | [src/connector/common/proxy.ts](src/connector/common/proxy.ts) |
95
124
  | `@oomol-lab/open-flow/control-api` | [src/control/common/api.ts](src/control/common/api.ts) |
@@ -1,5 +1,5 @@
1
1
  import { o as __toESM, t as __commonJSMin } from "./rolldown-runtime-CEgmsyvS.js";
2
- import { $ as waitBranchDescription, A as DropdownMenuItem, B as CompositeItem, D as DropdownMenuCheckboxItem, E as DropdownMenu, G as MenuPopup, H as MenuRoot, J as ContextMenuRootContext, K as MenuItem, M as DropdownMenuRadioGroup, N as DropdownMenuRadioItem, O as DropdownMenuContent, P as DropdownMenuSeparator, Q as uiLocales, R as DropdownMenuTrigger, U as MenuPositioner, W as MenuPortal, X as MenuRootContext, Y as useContextMenuRootContext, Z as useMenuRootContext, a as CompositeRoot, at as ja_default, c as PopoverContent, ct as I18n, dt as useAriaLabelledBy, f as PopoverTitle, ft as useFieldItemContext, h as ScrollArea, i as Textarea, it as ko_default, j as DropdownMenuLabel, k as DropdownMenuGroup, m as NativeScrollArea, n as wrapLayout, nt as zh_CN_default, o as ACTIVE_COMPOSITE_ITEM, ot as fr_default, p as PopoverTrigger, pt as IconThemeContext, q as MenuGroup, r as canvasDirection, rt as ru_default, s as Popover, st as en_default, t as layoutAxes, tt as zh_TW_default, ut as Checkbox, v as ContentIcon, z as findRootOwnerId } from "./wrapLayout-BB_qwy3k.js";
2
+ import { $ as waitBranchDescription, A as DropdownMenuItem, B as CompositeItem, D as DropdownMenuCheckboxItem, E as DropdownMenu, G as MenuPopup, H as MenuRoot, J as ContextMenuRootContext, K as MenuItem, M as DropdownMenuRadioGroup, N as DropdownMenuRadioItem, O as DropdownMenuContent, P as DropdownMenuSeparator, Q as uiLocales, R as DropdownMenuTrigger, U as MenuPositioner, W as MenuPortal, X as MenuRootContext, Y as useContextMenuRootContext, Z as useMenuRootContext, a as CompositeRoot, at as ja_default, c as PopoverContent, ct as I18n, dt as useAriaLabelledBy, f as PopoverTitle, ft as useFieldItemContext, h as ScrollArea, ht as IconThemeContext, i as Textarea, it as ko_default, j as DropdownMenuLabel, k as DropdownMenuGroup, m as NativeScrollArea, n as wrapLayout, nt as zh_CN_default, o as ACTIVE_COMPOSITE_ITEM, ot as fr_default, p as PopoverTrigger, q as MenuGroup, r as canvasDirection, rt as ru_default, s as Popover, st as en_default, t as layoutAxes, tt as zh_TW_default, ut as Checkbox, v as ContentIcon, z as findRootOwnerId } from "./wrapLayout-DU5HG1qH.js";
3
3
  import { a as derive, c as strictEqual, i as compute, l as val, n as attachSetter, r as combine, s as readonlyVal } from "./dist-bO8nvHFH.js";
4
4
  import { c as useLang, i as isString, l as useTranslate, n as isBoolean, o as I18nProvider, r as isPlainObject, t as isArray$1, u as useVal } from "./dist-BFmpkX4P.js";
5
5
  import { A as string, Bn as transitionStatusMapping, Br as useStableCallback, C as literal, Cr as cn$1, Dn as getTarget, En as contains, Er as useRenderElement, Fn as createLucideIcon, Fr as formatErrorMessage, J as SHIFT, Kn as cancelOpen, Lr as useIsoLayoutEffect, Mn as ownerDocument, Mr as useButton, Nn as useLabelableId, Or as EMPTY_OBJECT, Sn as stopEvent$1, T as number, Tr as clsx, Un as useValueChanged, Wn as createChangeEventDetails, Yt as addEventListener, _r as fieldValidityMapping, br as useControlled, cr as triggerPress, dr as useFormContext, fr as useRegisterFieldControl, gt as serializeValue, hr as useId$1, i as TooltipTrigger, jr as useMergedRefs, k as strictObject, kr as NOOP, mr as useBaseUiId, n as TooltipContent, p as timeZoneOffsetMinutes, pr as useFieldRootContext, pt as pressableTriggerOpenStateMapping, r as TooltipProvider, rr as none$1, sn as useTimeout, t as Tooltip, tn as require_with_selector, ur as useLabelableContext, vr as visuallyHidden, xr as Button, y as discriminatedUnion, yr as visuallyHiddenInput } from "./tooltip-BZ6tpqnr.js";
@@ -20935,7 +20935,7 @@ var markdownPreview_module_default = {
20935
20935
  };
20936
20936
  //#endregion
20937
20937
  //#region src/canvas/browser/preview/markdownPreview.tsx
20938
- var MarkdownContent = lazy(() => import("./markdownContent-D0BBrFcF.js"));
20938
+ var MarkdownContent = lazy(() => import("./markdownContent-B75ojl0E.js"));
20939
20939
  var MarkdownPreview = /* @__PURE__ */ memo(({ dark, unstyled, components, contentClassName, content, draggable, onDoubleClick }) => {
20940
20940
  const [focus, setFocus] = useState(false);
20941
20941
  return /* @__PURE__ */ jsx("div", {
@@ -1,5 +1,5 @@
1
- import { C as IconifyProvider, y as IconImageCrossOriginContext } from "./wrapLayout-BB_qwy3k.js";
2
- import { E as getFlowPngAspectRatio, t as FlowCanvas, y as CanvasStore } from "./FlowCanvas-SqPUBqze.js";
1
+ import { C as IconifyProvider, pt as ProviderIconCacheContext, y as IconImageCrossOriginContext } from "./wrapLayout-DU5HG1qH.js";
2
+ import { E as getFlowPngAspectRatio, t as FlowCanvas, y as CanvasStore } from "./FlowCanvas-C4iuvVKB.js";
3
3
  import { createElement } from "react";
4
4
  import "react/jsx-runtime";
5
5
  import { createRoot } from "react-dom/client";
@@ -837,7 +837,7 @@ async function captureFlowImage(model, language, options, aspectRatio) {
837
837
  });
838
838
  store.reconcile(snapshot, false, language, [], options.ignoredNodeIds ?? []);
839
839
  try {
840
- root.render(createElement(IconifyProvider, null, createElement(IconImageCrossOriginContext.Provider, { value: "anonymous" }, createElement(FlowCanvas, {
840
+ root.render(createElement(ProviderIconCacheContext.Provider, { value: options.iconCache }, createElement(IconifyProvider, null, createElement(IconImageCrossOriginContext.Provider, { value: "anonymous" }, createElement(FlowCanvas, {
841
841
  flowCanvasStore: store,
842
842
  dark: options.dark ?? false,
843
843
  fitView: false,
@@ -846,7 +846,7 @@ async function captureFlowImage(model, language, options, aspectRatio) {
846
846
  onInit: (value) => {
847
847
  instance = value;
848
848
  }
849
- }))));
849
+ })))));
850
850
  const deadline = performance.now() + 15e3;
851
851
  await waitFor(() => store.$.initialized.value && store.$.rfNodes.value.every((node) => !!node.measured?.width && !!node.measured.height), deadline);
852
852
  let hasImagePlaceholders = await prepareImages(host, deadline);
@@ -1,5 +1,5 @@
1
1
  import { i as __require, o as __toESM, t as __commonJSMin } from "./rolldown-runtime-CEgmsyvS.js";
2
- import { A as DropdownMenuItem, E as DropdownMenu, O as DropdownMenuContent, P as DropdownMenuSeparator, Q as uiLocales, R as DropdownMenuTrigger, S as spriteIcon, T as useIconifyData, V as useCompositeItem, _ as Z, a as CompositeRoot, at as ja_default$3, b as imageIcon, c as PopoverContent, ct as I18n, et as waitBranchLocales, f as PopoverTitle, h as ScrollArea, i as Textarea, it as ko_default$3, lt as providerIconAppearance, n as wrapLayout, nt as zh_CN_default$3, o as ACTIVE_COMPOSITE_ITEM, ot as fr_default$3, p as PopoverTrigger, r as canvasDirection, rt as ru_default$3, s as Popover, st as en_default$3, tt as zh_TW_default$3, ut as Checkbox, v as ContentIcon, w as useIconifyCollectionLoader, x as placeholderIcon } from "./wrapLayout-BB_qwy3k.js";
2
+ import { A as DropdownMenuItem, E as DropdownMenu, O as DropdownMenuContent, P as DropdownMenuSeparator, Q as uiLocales, R as DropdownMenuTrigger, S as spriteIcon, T as useIconifyData, V as useCompositeItem, _ as Z, a as CompositeRoot, at as ja_default$3, b as imageIcon, c as PopoverContent, ct as I18n, et as waitBranchLocales, f as PopoverTitle, h as ScrollArea, i as Textarea, it as ko_default$3, lt as providerIconAppearance, n as wrapLayout, nt as zh_CN_default$3, o as ACTIVE_COMPOSITE_ITEM, ot as fr_default$3, p as PopoverTrigger, r as canvasDirection, rt as ru_default$3, s as Popover, st as en_default$3, tt as zh_TW_default$3, ut as Checkbox, v as ContentIcon, w as useIconifyCollectionLoader, x as placeholderIcon } from "./wrapLayout-DU5HG1qH.js";
3
3
  import { a as derive, i as compute, l as val, t as arrayShallowEqual } from "./dist-bO8nvHFH.js";
4
4
  import { a as toPlainObject, l as useTranslate, o as I18nProvider, s as useI18n, u as useVal } from "./dist-BFmpkX4P.js";
5
5
  import { $n as inputClear, A as string$1, Bn as transitionStatusMapping, Br as useStableCallback, C as literal, Cr as cn, Dn as getTarget, Dr as EMPTY_ARRAY, E as object$2, En as contains, Er as useRenderElement, Et as useFloatingRootContext, F as IndexGuessBehavior, Fr as formatErrorMessage, Ft as useDismiss, Gn as createGenericEventDetails, I as useCompositeListItem, In as useTransitionStatus, Ir as mergeProps, It as useClick, Jn as closePress, Kt as DROPDOWN_COLLISION_AVOIDANCE, Ln as useOpenChangeComplete, Lr as useIsoLayoutEffect, Lt as FloatingFocusManager, M as unknown, Mn as ownerDocument, Mr as useButton, Nn as useLabelableId, O as record$3, On as isAndroid, Or as EMPTY_OBJECT, Qn as inputChange, Qt as useStore, S as lazy$1, Sn as stopEvent, Sr as buttonVariants, T as number, Tn as activeElement, Tr as clsx, Un as useValueChanged, Vr as useRefWithInit, Wn as createChangeEventDetails, Wr as isElement, Wt as FloatingPortal, Yn as escapeKey, Zt as Store, _ as array, _r as fieldValidityMapping, an as useOnFirstRender, at as useAnchorPositioning, b as int, br as useControlled, bt as useListNavigation, ct as CompositeList, dr as useFormContext, er as inputPress, et as useAnchoredPopupScrollLock, fr as useRegisterFieldControl, ft as popupStateMapping, g as _enum, gr as DEFAULT_FIELD_STATE_ATTRIBUTES, ht as useOpenInteractionType, i as TooltipTrigger, in as useValueAsRef, it as InternalBackdrop, j as union, jr as useMergedRefs, k as strictObject, kn as isFirefox, kr as NOOP, lt as inertValue, mr as useBaseUiId, n as TooltipContent, nr as listNavigation, nt as usePositioner, p as timeZoneOffsetMinutes, pr as useFieldRootContext, pt as pressableTriggerOpenStateMapping, rn as createSelector, rr as none, rt as getDisabledMountTransitionStyles, sn as useTimeout, st as useDirection, t as Tooltip, tr as itemPress, ur as useLabelableContext, ut as getPseudoElementBounds, v as boolean, vr as visuallyHidden, vt as useTypeahead, wn as isInteractiveElement, wr as cva, x as json$3, xr as Button, xt as useInteractions, y as discriminatedUnion, yr as visuallyHiddenInput, zn as TransitionStatusDataAttributes } from "./tooltip-BZ6tpqnr.js";
@@ -3254,7 +3254,7 @@ var ControlCatalogCache = class {
3254
3254
  if (!options.scope.trim()) throw new TypeError("Control cache scope must be nonempty.");
3255
3255
  if (options.maxAgeMs != null && (!Number.isFinite(options.maxAgeMs) || options.maxAgeMs < 0)) throw new TypeError("Control cache maxAgeMs must be finite and nonnegative.");
3256
3256
  }
3257
- async read(query, load, maxAgeMs, signal, fresh = false) {
3257
+ async read(query, load, maxAgeMs, signal, fresh = false, cacheOnly = false) {
3258
3258
  signal?.throwIfAborted();
3259
3259
  const key = JSON.stringify([
3260
3260
  "open-flow:catalog",
@@ -3262,7 +3262,7 @@ var ControlCatalogCache = class {
3262
3262
  this.options.scope,
3263
3263
  query.path
3264
3264
  ]);
3265
- const result = await wait$1(this.#request(key, query, load, this.options.maxAgeMs ?? maxAgeMs, fresh || this.options.mode == "refresh"), signal);
3265
+ const result = await wait$1(cacheOnly ? this.#load(key, query, load, this.options.maxAgeMs ?? maxAgeMs, false, true) : this.#request(key, query, load, this.options.maxAgeMs ?? maxAgeMs, fresh || this.options.mode == "refresh"), signal);
3266
3266
  const data = query.decode(structuredClone(result.body));
3267
3267
  try {
3268
3268
  this.options.onRead?.({
@@ -3290,7 +3290,7 @@ var ControlCatalogCache = class {
3290
3290
  });
3291
3291
  return promise;
3292
3292
  }
3293
- async #load(key, query, load, maxAgeMs, fresh) {
3293
+ async #load(key, query, load, maxAgeMs, fresh, cacheOnly = false) {
3294
3294
  let cached;
3295
3295
  try {
3296
3296
  const stored = await this.options.delegate.get(key);
@@ -3305,13 +3305,13 @@ var ControlCatalogCache = class {
3305
3305
  }
3306
3306
  const now = Date.now();
3307
3307
  const stale = cached == null || cached.validatedAt > now || now - cached.validatedAt >= maxAgeMs;
3308
- if (cached != null && (this.options.mode == "offline" || !fresh && !stale)) return {
3308
+ if (cached != null && (cacheOnly || this.options.mode == "offline" || !fresh && !stale)) return {
3309
3309
  ...cached,
3310
3310
  path: query.path,
3311
3311
  source: "cache",
3312
3312
  stale
3313
3313
  };
3314
- if (this.options.mode == "offline") throw new ApiError(503, "catalog.cache-miss", `No compatible cached response for ${query.path}.`);
3314
+ if (cacheOnly || this.options.mode == "offline") throw new ApiError(503, "catalog.cache-miss", `No compatible cached response for ${query.path}.`);
3315
3315
  const result = await load(cached?.etag ?? null);
3316
3316
  if (!result.modified && cached == null) throw new ApiError(502, "response.invalid", "A catalog returned 304 without a cached response.");
3317
3317
  const entry = {
@@ -4698,9 +4698,10 @@ var ControlClient = class {
4698
4698
  version: 1
4699
4699
  };
4700
4700
  }
4701
- async listConnectorProviders(signal, flowId, locale) {
4701
+ async listConnectorProviders(signal, flowId, locale, options = {}) {
4702
4702
  const query = connectorProvidersQuery(flowId, locale);
4703
- if (this.catalogCache != null) return (await this.catalogResponse(query, 3e5, signal)).data;
4703
+ if (this.catalogCache != null) return (await this.catalogResponse(query, 3e5, signal, false, options.cacheOnly)).data;
4704
+ if (options.cacheOnly) throw new ApiError(503, "catalog.cache-miss", "No Provider catalog cache is configured.");
4704
4705
  return this.connectorRequest(query.path, "providers", signal, query.decode);
4705
4706
  }
4706
4707
  async listLeinaBots(flowId, signal) {
@@ -5029,11 +5030,11 @@ var ControlClient = class {
5029
5030
  method: "POST"
5030
5031
  }));
5031
5032
  }
5032
- async catalogResponse(query, maxAgeMs, signal, fresh = false) {
5033
+ async catalogResponse(query, maxAgeMs, signal, fresh = false, cacheOnly = false) {
5033
5034
  if (this.catalogCache != null) return this.catalogCache.read(query, (etag) => this.readCatalog({
5034
5035
  path: query.path,
5035
5036
  decode: jsonValue
5036
- }, etag), maxAgeMs, signal, fresh);
5037
+ }, etag), maxAgeMs, signal, fresh, cacheOnly);
5037
5038
  const response = await this.readCatalog(query, null, signal);
5038
5039
  if (!response.modified) return invalidResponse();
5039
5040
  return {
@@ -24711,7 +24712,7 @@ var RunStore = class {
24711
24712
  //#region src/workbench/browser/runtime/providerIcon.ts
24712
24713
  function providerIcon(provider) {
24713
24714
  const source = provider.icon?.trim();
24714
- const original = source ? imageIcon(source, placeholderIcon) : placeholderIcon;
24715
+ const original = source ? imageIcon(source, placeholderIcon, provider.serviceId) : placeholderIcon;
24715
24716
  const appearance = providerIconAppearance(provider.iconSprite, provider.iconSpritePosition);
24716
24717
  return appearance?.iconSprite && appearance.iconSpritePosition ? spriteIcon({
24717
24718
  iconSprite: appearance.iconSprite,
@@ -1,11 +1,11 @@
1
1
  import { o as __toESM, r as __exportAll, t as __commonJSMin } from "./rolldown-runtime-CEgmsyvS.js";
2
- import { $ as waitBranchDescription, A as DropdownMenuItem, B as CompositeItem, C as IconifyProvider, D as DropdownMenuCheckboxItem, E as DropdownMenu, F as DropdownMenuSub, I as DropdownMenuSubContent, L as DropdownMenuSubTrigger, M as DropdownMenuRadioGroup, N as DropdownMenuRadioItem, O as DropdownMenuContent, P as DropdownMenuSeparator, R as DropdownMenuTrigger, _ as Z$1, a as CompositeRoot, c as PopoverContent, d as PopoverPanelContent, dt as useAriaLabelledBy, f as PopoverTitle, g as VirtualScrollArea, h as ScrollArea, i as Textarea, j as DropdownMenuLabel, k as DropdownMenuGroup, l as PopoverDescription, m as NativeScrollArea, p as PopoverTrigger, s as Popover, u as PopoverHeader, ut as Checkbox, v as ContentIcon } from "./wrapLayout-BB_qwy3k.js";
2
+ import { $ as waitBranchDescription, A as DropdownMenuItem, B as CompositeItem, C as IconifyProvider, D as DropdownMenuCheckboxItem, E as DropdownMenu, F as DropdownMenuSub, I as DropdownMenuSubContent, L as DropdownMenuSubTrigger, M as DropdownMenuRadioGroup, N as DropdownMenuRadioItem, O as DropdownMenuContent, P as DropdownMenuSeparator, R as DropdownMenuTrigger, _ as Z$1, a as CompositeRoot, c as PopoverContent, d as PopoverPanelContent, dt as useAriaLabelledBy, f as PopoverTitle, g as VirtualScrollArea, h as ScrollArea, i as Textarea, j as DropdownMenuLabel, k as DropdownMenuGroup, l as PopoverDescription, m as NativeScrollArea, mt as useProviderIconCache, p as PopoverTrigger, s as Popover, u as PopoverHeader, ut as Checkbox, v as ContentIcon } from "./wrapLayout-DU5HG1qH.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
5
  import { $ as useToolbarRootContext, A as string, Bn as transitionStatusMapping, Br as useStableCallback, Cr as cn, Er as useRenderElement, Fr as formatErrorMessage, In as useTransitionStatus, Ir as mergeProps, Ln as useOpenChangeComplete, Lr as useIsoLayoutEffect, Mr as useButton, Nn as useLabelableId, Or as EMPTY_OBJECT, Qt as useStore, Sr as buttonVariants, Un as useValueChanged, Wn as createChangeEventDetails, _r as fieldValidityMapping, a as createTooltipHandle, br as useControlled, c as TooltipPositioner, d as TooltipRoot, dr as useFormContext, fr as useRegisterFieldControl, i as TooltipTrigger, jr as useMergedRefs, l as TooltipPortal, 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, zr as error$1 } from "./tooltip-BZ6tpqnr.js";
6
6
  import { $ as waitAutoContinueSchema, $t as SelectGroup, A as comparisonIssue, Bt as schemaObject, D as nodeSystemOutputPorts, Dt as connectorProxyTask, E as nodeErrorSchema, Et as connectorProxySupportsBody, F as operatorsForType, Ft as webhookMethods, It as webhookSupportsBody, J as webhookResponseAllowsBody, K as webhookHeaderValuePort, L as unaryOperator, O as supportsNodeErrorHandling, P as operandHandle, Pt as httpHeaderNameIssue, Q as workflowOutputsPort, Qt as SelectContent, R as valueType, Rt as matchesSchema, St as connectorProxyHeaderSchema, T as workflowToolNameIssue, Tt as connectorProxyQuerySchema, U as decodeRevisionContent, Vt as variableInputCompatible, X as webhookResponseTimeout, Xt as Select$1, Y as webhookResponseInputs, Yt as dequal, Z as webhookStatusCodePort, Zt as SelectChevron, _t as defaultDecisionQuestion, a as DialogFooter, at as httpHeaderSchema, b as nodeNameIssue, c as DialogTrigger, ct as httpRequestIssues, d as Field, en as SelectItem, et as defaultNodeRetry, f as FieldDescription, ft as isHttpHost, gn as ChevronDown, gt as decisionTask, h as FieldLabel, hn as Input, ht as decisionQuestionIssues, i as DialogDescription, l as Icon, lt as httpRequestTask, m as FieldGroup, mn as Label, n as DialogClose, nn as SelectTrigger, nt as retryConfigurationSchema, o as DialogHeader, ot as httpQuerySchema, p as FieldError, pt as decisionLimits, q as webhookHeadersPort, qt as skipDuplicatesConfigSchema, r as DialogContent, rn as SelectValue, rt as supportsNodeRetry, s as DialogTitle, t as Dialog, tn as SelectSeparator, tt as nodeRetryLimits, u as Spinner, vt as limitDecisionQuestions, wt as connectorProxyIssues, xt as connectorProxyHasBody, yt as connectorProxyBodyInput, zt as portsAssignable } from "./dialog-Bi-MVTGj.js";
7
- import { C as isMac, S as toManifestNodeId, T as flowPngAspectRatios, _ as E$1, a as CanvasNodeIcon, b as toViewEdge, c as collapseAllNested, d as IconStack, f as selectableTimeZones, g as cronDescription, h as timeZoneOffset, i as pasteVideoLink, l as formatDuration, m as timeZoneLongLabel, n as setAddItemId, o as defaultTriggerIcon, p as timeZoneLabel, s as JSONViewer, t as FlowCanvas, u as useDebouncedValue, v as CanvasTooltip, w as isSameViewport, x as toManifestHandleName, y as CanvasStore } from "./FlowCanvas-SqPUBqze.js";
8
- import { $ as resourceValue, $t as WorkflowExportDialog, A as schemaForEditor, An as TabsTrigger, Ar as serverAddress, B as datePickerValue, Bn as EmptyMedia, Br as ApiError, Cn as selectors, Cr as inputValue, D as defaultValueEditorSchema, Dn as Tabs, Dr as openApiTask, Dt as diagnosticMessage, E as supportsFeishuChatFilter, En as IconPickerButton, Er as openApiFieldIssues, F as calendarChange, Fn as InputGroupInput, Fr as workflowCandidateGroup, G as indexAddNodeOptions, Gn as SourceSelect, H as isDateFormat, Hn as Badge, Hr as eventSourceKind, I as calendarDate, In as Empty, Ir as workflowCapability, Jn as EventSourceSetup, Kn as createI18n, L as dateFromTimeZone, Ln as EmptyContent, Lr as workflowSelectionTask, M as getDefaultValue, Mn as followWorkbenchLink, Mr as sameWorkflowInterface, N as isUnconstrainedSchema, Nn as InputGroup, Nr as workflowAgentTool, O as editorComponent, On as TabsContent, Or as securityOptions, Ot as diagnosticNodeId, P as typeOfSchema, Pn as InputGroupAddon, Q as resourceData, R as dateInTimeZone, Rn as EmptyDescription, Sn as ComboboxRoot, Sr as triggerConfigValues, St as revisionView, T as feishuResourceKind, Tn as useComboboxRootContext, Tr as object$1, V as dateTimeWall, Vn as EmptyTitle, Vr as controlErrorCode, Wn as SourceForm, Y as connectorActionPresentation, Yn as errorNotice, Z as observeResource, Zt as dequal$1, _n as ComboboxList, _t as actionSummary, ar as webhookResponseDiagnostics, bn as ComboboxInputGroup, bt as canCancelRun, cn as selectionMenuItemClass, dn as valueEditor_module_default, dr as isJsonObject, dt as loadJson, en as WorkflowExportMenuItem, er as decodeResultList, fn as ComboboxItemIndicator, ft as designerGraph, gn as ComboboxPortal, gt as triggerNodeIcon, hn as ComboboxPositioner, ht as semanticNodeIcon, ir as resolutionOutputPorts, it as decodeAppCatalogResponse, j as valueForEditor, jr as servers, jt as connectionCatalog, k as editorGroups, kn as TabsList, kr as selectOperation, kt as schemaMismatchMessage, ln as ValueControl, mn as ComboboxPopup, mt as nodeTitle, n as agentTool, nn as IdTooltip, nr as executionReachableNodes, or as sourceOutputLabel, ot as getAppCatalogCache, pn as ComboboxItem, pt as nodeIcon, q as mapSource, qn as FeishuEventPicker, rn as FlowSettingsButton, rr as inputSourceCandidates, sn as selectionMenuContentClass, sr as sourcePort, tn as useWorkflowExportAction, tt as provider, un as ValueEditorFeedback, ur as triggerOutputDefinitions, vn as GroupCollectionProvider, vt as providerIcon, wn as useComboboxInputValueContext, wr as listOperations, xn as ComboboxInput, xr as triggerConfigValue, xt as hasRunFilter, yn as ComboboxTrigger, z as datePickerChange, zn as EmptyHeader } from "./flowChanges-CnOOPJJR.js";
7
+ import { C as isMac, S as toManifestNodeId, T as flowPngAspectRatios, _ as E$1, a as CanvasNodeIcon, b as toViewEdge, c as collapseAllNested, d as IconStack, f as selectableTimeZones, g as cronDescription, h as timeZoneOffset, i as pasteVideoLink, l as formatDuration, m as timeZoneLongLabel, n as setAddItemId, o as defaultTriggerIcon, p as timeZoneLabel, s as JSONViewer, t as FlowCanvas, u as useDebouncedValue, v as CanvasTooltip, w as isSameViewport, x as toManifestHandleName, y as CanvasStore } from "./FlowCanvas-C4iuvVKB.js";
8
+ import { $ as resourceValue, $t as WorkflowExportDialog, A as schemaForEditor, An as TabsTrigger, Ar as serverAddress, B as datePickerValue, Bn as EmptyMedia, Br as ApiError, Cn as selectors, Cr as inputValue, D as defaultValueEditorSchema, Dn as Tabs, Dr as openApiTask, Dt as diagnosticMessage, E as supportsFeishuChatFilter, En as IconPickerButton, Er as openApiFieldIssues, F as calendarChange, Fn as InputGroupInput, Fr as workflowCandidateGroup, G as indexAddNodeOptions, Gn as SourceSelect, H as isDateFormat, Hn as Badge, Hr as eventSourceKind, I as calendarDate, In as Empty, Ir as workflowCapability, Jn as EventSourceSetup, Kn as createI18n, L as dateFromTimeZone, Ln as EmptyContent, Lr as workflowSelectionTask, M as getDefaultValue, Mn as followWorkbenchLink, Mr as sameWorkflowInterface, N as isUnconstrainedSchema, Nn as InputGroup, Nr as workflowAgentTool, O as editorComponent, On as TabsContent, Or as securityOptions, Ot as diagnosticNodeId, P as typeOfSchema, Pn as InputGroupAddon, Q as resourceData, R as dateInTimeZone, Rn as EmptyDescription, Sn as ComboboxRoot, Sr as triggerConfigValues, St as revisionView, T as feishuResourceKind, Tn as useComboboxRootContext, Tr as object$1, V as dateTimeWall, Vn as EmptyTitle, Vr as controlErrorCode, Wn as SourceForm, Y as connectorActionPresentation, Yn as errorNotice, Z as observeResource, Zt as dequal$1, _n as ComboboxList, _t as actionSummary, ar as webhookResponseDiagnostics, bn as ComboboxInputGroup, bt as canCancelRun, cn as selectionMenuItemClass, dn as valueEditor_module_default, dr as isJsonObject, dt as loadJson, en as WorkflowExportMenuItem, er as decodeResultList, fn as ComboboxItemIndicator, ft as designerGraph, gn as ComboboxPortal, gt as triggerNodeIcon, hn as ComboboxPositioner, ht as semanticNodeIcon, ir as resolutionOutputPorts, it as decodeAppCatalogResponse, j as valueForEditor, jr as servers, jt as connectionCatalog, k as editorGroups, kn as TabsList, kr as selectOperation, kt as schemaMismatchMessage, ln as ValueControl, mn as ComboboxPopup, mt as nodeTitle, n as agentTool, nn as IdTooltip, nr as executionReachableNodes, or as sourceOutputLabel, ot as getAppCatalogCache, pn as ComboboxItem, pt as nodeIcon, q as mapSource, qn as FeishuEventPicker, rn as FlowSettingsButton, rr as inputSourceCandidates, sn as selectionMenuContentClass, sr as sourcePort, tn as useWorkflowExportAction, tt as provider, un as ValueEditorFeedback, ur as triggerOutputDefinitions, vn as GroupCollectionProvider, vt as providerIcon, wn as useComboboxInputValueContext, wr as listOperations, xn as ComboboxInput, xr as triggerConfigValue, xt as hasRunFilter, yn as ComboboxTrigger, z as datePickerChange, zn as EmptyHeader } from "./flowChanges-SKYJBr6X.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";
@@ -232,7 +232,7 @@ function CanvasHistoryScope({ history, disabled, ...props }) {
232
232
  }
233
233
  //#endregion
234
234
  //#region src/workbench/browser/runtime/editor/commentInspector.tsx
235
- var MarkdownContent = lazy(() => import("./markdownContent-D0BBrFcF.js"));
235
+ var MarkdownContent = lazy(() => import("./markdownContent-B75ojl0E.js"));
236
236
  /** A comment is presentation data; editing it does not require the canvas store. */
237
237
  function CommentInspector({ title, content, disabled = false, readOnly, dark, onSave }) {
238
238
  const t = useTranslate();
@@ -36141,17 +36141,20 @@ function FlowEditor({ portalRoot, navigationIsland, onRun, onRunStarted, onClose
36141
36141
  const moduleEditor = useVal(store.workspace.$.moduleEditor);
36142
36142
  const initialAddNodeTab = triggers.length == 0 ? "triggers" : "nodes";
36143
36143
  const { ignoredNodeIds, onIgnoreNodes } = useIgnoredNodes(flowId ?? "");
36144
+ const iconCache = useProviderIconCache();
36144
36145
  const renderPng = useCallback(async (options) => {
36145
36146
  const model = store.$.designer.value;
36146
- const { flowToPng } = await import("./exportPng-CLZKdNzR.js");
36147
+ const { flowToPng } = await import("./exportPng-DMsB9ku_.js");
36147
36148
  return flowToPng(model, language, {
36148
36149
  ...options,
36149
- ignoredNodeIds
36150
+ ignoredNodeIds,
36151
+ iconCache
36150
36152
  });
36151
36153
  }, [
36152
36154
  store,
36153
36155
  language,
36154
- ignoredNodeIds
36156
+ ignoredNodeIds,
36157
+ iconCache
36155
36158
  ]);
36156
36159
  const panel = useInspectorPanel({
36157
36160
  identity: flowId ?? "",
@@ -1,6 +1,6 @@
1
1
  import { o as __toESM, r as __exportAll, t as __commonJSMin } from "./rolldown-runtime-CEgmsyvS.js";
2
2
  import { i as isString, l as useTranslate } from "./dist-BFmpkX4P.js";
3
- import { r as getVideoLink } from "./FlowCanvas-SqPUBqze.js";
3
+ import { r as getVideoLink } from "./FlowCanvas-C4iuvVKB.js";
4
4
  import { memo, useEffect, useMemo, useRef } from "react";
5
5
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region ../../node_modules/.bun/deepmerge@4.3.1/node_modules/deepmerge/dist/cjs.js
@@ -9234,7 +9234,7 @@ svg.react-flow__connectionline {
9234
9234
 
9235
9235
  .NodeLayout_vertical_d0397.NodeLayout_compactContent_d0397 .NodeLayout_branchRow_d0397 {
9236
9236
  background: transparent;
9237
- }.ContentIcon_img_4e5d2 {
9237
+ }.ContentIcon_img_e2c99 {
9238
9238
  width: 1em;
9239
9239
  height: 1em;
9240
9240
  vertical-align: middle;
@@ -9242,7 +9242,16 @@ svg.react-flow__connectionline {
9242
9242
  object-fit: contain;
9243
9243
  }
9244
9244
 
9245
- .ContentIcon_initials_4e5d2 {
9245
+ .ContentIcon_pending_e2c99 {
9246
+ display: inline-flex;
9247
+ width: 1em;
9248
+ height: 1em;
9249
+ align-items: center;
9250
+ justify-content: center;
9251
+ vertical-align: middle;
9252
+ }
9253
+
9254
+ .ContentIcon_initials_e2c99 {
9246
9255
  display: inline-flex;
9247
9256
  width: 1em;
9248
9257
  height: 1em;
@@ -9255,13 +9264,13 @@ svg.react-flow__connectionline {
9255
9264
  vertical-align: middle;
9256
9265
  pointer-events: none;
9257
9266
  }
9258
- .ContentIcon_initials_4e5d2 > span {
9267
+ .ContentIcon_initials_e2c99 > span {
9259
9268
  font-size: 0.42em;
9260
9269
  font-weight: 400;
9261
9270
  line-height: 1;
9262
9271
  }
9263
9272
 
9264
- .ContentIcon_sprite_4e5d2 {
9273
+ .ContentIcon_sprite_e2c99 {
9265
9274
  display: inline-block;
9266
9275
  position: relative;
9267
9276
  overflow: hidden;
@@ -9271,7 +9280,7 @@ svg.react-flow__connectionline {
9271
9280
  vertical-align: middle;
9272
9281
  pointer-events: none;
9273
9282
  }
9274
- .ContentIcon_sprite_4e5d2 > span {
9283
+ .ContentIcon_sprite_e2c99 > span {
9275
9284
  position: absolute;
9276
9285
  background-size: 100% 100%;
9277
9286
  background-repeat: no-repeat;
@@ -1,6 +1,7 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import type { CanvasDirection } from '../common/canvas-direction.js';
3
3
  import type { InteractiveMode } from '../common/canvas-interactive-mode.js';
4
+ import type { ProviderIconLoader } from '../common/provider-icons.js';
4
5
  import type { Draft, Presentation } from '../common/control-api.js';
5
6
  import type { UiLanguage } from '../common/localization.js';
6
7
  export type { Draft, Presentation } from '../common/control-api.js';
@@ -8,6 +9,8 @@ export type { UiLanguage } from '../common/localization.js';
8
9
  export type { InteractiveMode } from '../common/canvas-interactive-mode.js';
9
10
  export type { CanvasDirection } from '../common/canvas-direction.js';
10
11
  export interface OpenFlowPreviewProps {
12
+ /** Optional shared Provider artwork cache; defaults to browser IndexedDB. */
13
+ readonly iconCache?: ProviderIconLoader;
11
14
  readonly draft: Draft;
12
15
  readonly presentation: Presentation | null;
13
16
  readonly language: UiLanguage;
@@ -32,4 +35,4 @@ export interface OpenFlowPreviewProps {
32
35
  readonly className?: string;
33
36
  }
34
37
  /** Offline workflow preview. Use a React key to start a new layout/selection session. */
35
- export declare function OpenFlowPreview({ draft, presentation, language, theme, defaultInteractiveMode, defaultDirection, defaultMiniMapExpanded, defaultInspectorOpen, defaultSelectedNodeIds, nodesDraggable, dottedBackground, layoutMotion, label, className, }: OpenFlowPreviewProps): ReactElement;
38
+ export declare function OpenFlowPreview({ iconCache, draft, presentation, language, theme, defaultInteractiveMode, defaultDirection, defaultMiniMapExpanded, defaultInspectorOpen, defaultSelectedNodeIds, nodesDraggable, dottedBackground, layoutMotion, label, className, }: OpenFlowPreviewProps): ReactElement;