@oomol-lab/open-flow 0.1.0-beta.79 → 0.1.0-beta.80

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 (32) hide show
  1. package/dist/browser/{FlowCanvas-BQGBcfoL.js → FlowCanvas-CrsiDHK8.js} +50 -51
  2. package/dist/browser/{createResourceDialog-DkovGogv.js → createResourceDialog-CS3u9ga9.js} +2 -2
  3. package/dist/browser/{dialog-CFFuRM8s.js → dialog-CFlvkliO.js} +7 -2
  4. package/dist/browser/{exportSvg-CYwyYiuH.js → exportPng-BOPfjeEi.js} +236 -38
  5. package/dist/browser/{flowChanges-CN2R-m1M.js → flowChanges-pFjPHU5k.js} +326 -203
  6. package/dist/browser/{flowWorkspace-CXVL1FNv.js → flowWorkspace-CRlqc403.js} +698 -480
  7. package/dist/browser/preview.css +153 -132
  8. package/dist/browser/preview.js +921 -643
  9. package/dist/browser/ui-logo.d.ts +1 -0
  10. package/dist/browser/ui.css +29 -4
  11. package/dist/browser/ui.js +4 -1
  12. package/dist/browser/workbench.css +153 -132
  13. package/dist/browser/workbench.js +9 -9
  14. package/dist/browser/{workbenchSelect-CkOS95gX.js → workbenchSelect-Ci0KCYv9.js} +1 -1
  15. package/dist/command/index.js +41 -41
  16. package/dist/common/control-api-conformance.js +49 -19
  17. package/dist/common/control-api.d.ts +26 -6
  18. package/dist/common/control-api.js +49 -19
  19. package/dist/common/control-requests.js +6 -2
  20. package/dist/common/flow-authoring.js +6 -2
  21. package/dist/common/flow-change.js +6 -2
  22. package/dist/common/flow-encoding.js +6 -2
  23. package/dist/common/flow-semantics.js +6 -2
  24. package/dist/common/flow-state.d.ts +47 -0
  25. package/dist/common/flow-state.js +7 -1
  26. package/dist/common/mcp.js +49 -18
  27. package/dist/common/scheduler.js +6 -2
  28. package/package.json +1 -1
  29. package/src/control/common/api.ts +24 -8
  30. package/src/control/common/connectorDecoders.ts +11 -30
  31. package/src/control/common/revisionDecoders.ts +14 -0
  32. package/src/state/common/state.ts +14 -0
@@ -12410,7 +12410,7 @@ var CanvasStore = class {
12410
12410
  if (this.$.editable.value) this.#callbacks.onIgnoreNodes?.(nodeIds, ignored);
12411
12411
  };
12412
12412
  this.changeDirection = (direction) => {
12413
- if (!this.$.editable.value || !this.canChangeDirection || this.$.changingDirection.value || this.$.direction.value === direction) return;
12413
+ if (!this.canChangeDirection || this.$.changingDirection.value || this.$.direction.value === direction) return;
12414
12414
  this.layoutComplete = false;
12415
12415
  this.layoutMeasurementAttempts = 0;
12416
12416
  this.$$.changingDirection.set(true);
@@ -37407,31 +37407,31 @@ function IconStack({ icons, count, limit = 3, size = "default", countClassName }
37407
37407
  });
37408
37408
  }
37409
37409
  var CanvasCard_module_default = {
37410
- card: "CanvasCard_card_5d8a7",
37411
- value: "CanvasCard_value_5d8a7",
37412
- preview: "CanvasCard_preview_5d8a7",
37413
- comment: "CanvasCard_comment_5d8a7",
37414
- selected: "CanvasCard_selected_5d8a7",
37415
- problem: "CanvasCard_problem_5d8a7",
37416
- runningBeam: "CanvasCard_runningBeam_5d8a7",
37417
- "running-beam": "CanvasCard_running-beam_5d8a7",
37418
- header: "CanvasCard_header_5d8a7",
37419
- icon: "CanvasCard_icon_5d8a7",
37420
- identity: "CanvasCard_identity_5d8a7",
37421
- indicator: "CanvasCard_indicator_5d8a7",
37422
- warning: "CanvasCard_warning_5d8a7",
37423
- danger: "CanvasCard_danger_5d8a7",
37424
- content: "CanvasCard_content_5d8a7",
37425
- branches: "CanvasCard_branches_5d8a7",
37426
- collapse: "CanvasCard_collapse_5d8a7",
37427
- collapseInner: "CanvasCard_collapseInner_5d8a7",
37428
- compactIdentity: "CanvasCard_compactIdentity_5d8a7",
37429
- compact: "CanvasCard_compact_5d8a7",
37430
- withBody: "CanvasCard_withBody_5d8a7",
37431
- compactContent: "CanvasCard_compactContent_5d8a7",
37432
- singleContent: "CanvasCard_singleContent_5d8a7",
37433
- subtitle: "CanvasCard_subtitle_5d8a7",
37434
- fill: "CanvasCard_fill_5d8a7"
37410
+ card: "CanvasCard_card_e92f9",
37411
+ value: "CanvasCard_value_e92f9",
37412
+ preview: "CanvasCard_preview_e92f9",
37413
+ comment: "CanvasCard_comment_e92f9",
37414
+ selected: "CanvasCard_selected_e92f9",
37415
+ problem: "CanvasCard_problem_e92f9",
37416
+ runningBeam: "CanvasCard_runningBeam_e92f9",
37417
+ "running-beam": "CanvasCard_running-beam_e92f9",
37418
+ header: "CanvasCard_header_e92f9",
37419
+ icon: "CanvasCard_icon_e92f9",
37420
+ identity: "CanvasCard_identity_e92f9",
37421
+ indicator: "CanvasCard_indicator_e92f9",
37422
+ warning: "CanvasCard_warning_e92f9",
37423
+ danger: "CanvasCard_danger_e92f9",
37424
+ content: "CanvasCard_content_e92f9",
37425
+ branches: "CanvasCard_branches_e92f9",
37426
+ collapse: "CanvasCard_collapse_e92f9",
37427
+ collapseInner: "CanvasCard_collapseInner_e92f9",
37428
+ compactIdentity: "CanvasCard_compactIdentity_e92f9",
37429
+ compact: "CanvasCard_compact_e92f9",
37430
+ withBody: "CanvasCard_withBody_e92f9",
37431
+ compactContent: "CanvasCard_compactContent_e92f9",
37432
+ singleContent: "CanvasCard_singleContent_e92f9",
37433
+ subtitle: "CanvasCard_subtitle_e92f9",
37434
+ fill: "CanvasCard_fill_e92f9"
37435
37435
  };
37436
37436
  //#endregion
37437
37437
  //#region src/ui/browser/hooks.ts
@@ -47299,6 +47299,7 @@ var NodeLayout = /* @__PURE__ */ memo(({ canvasStore, nodeStore, visible }) => {
47299
47299
  modelNode?.kind === "trigger" && /* @__PURE__ */ jsx(Zap, {
47300
47300
  "aria-hidden": "true",
47301
47301
  className: NodeLayout_module_default.triggerIcon,
47302
+ "data-canvas-bounds": true,
47302
47303
  strokeWidth: 1.5
47303
47304
  }),
47304
47305
  /* @__PURE__ */ jsxs("div", {
@@ -47518,27 +47519,27 @@ var fitViewOptions = {
47518
47519
  maxZoom: 1
47519
47520
  };
47520
47521
  var ReactFlowContainer_module_default = {
47521
- container: "ReactFlowContainer_container_40f4d",
47522
- flow: "ReactFlowContainer_flow_40f4d",
47523
- contextMenu: "ReactFlowContainer_contextMenu_40f4d",
47524
- movingLayout: "ReactFlowContainer_movingLayout_40f4d",
47525
- layoutPending: "ReactFlowContainer_layoutPending_40f4d",
47526
- dock: "ReactFlowContainer_dock_40f4d",
47527
- viewDock: "ReactFlowContainer_viewDock_40f4d",
47528
- expandedViewControls: "ReactFlowContainer_expandedViewControls_40f4d",
47529
- viewOptionButtons: "ReactFlowContainer_viewOptionButtons_40f4d",
47530
- compactViewControls: "ReactFlowContainer_compactViewControls_40f4d",
47531
- createDock: "ReactFlowContainer_createDock_40f4d",
47532
- zoomValue: "ReactFlowContainer_zoomValue_40f4d",
47533
- viewChoiceTrigger: "ReactFlowContainer_viewChoiceTrigger_40f4d",
47534
- viewChoicePanel: "ReactFlowContainer_viewChoicePanel_40f4d",
47535
- viewChoices: "ReactFlowContainer_viewChoices_40f4d",
47536
- viewChoice: "ReactFlowContainer_viewChoice_40f4d",
47537
- dockActions: "ReactFlowContainer_dockActions_40f4d",
47538
- miniMap: "ReactFlowContainer_miniMap_40f4d",
47539
- viewOptions: "ReactFlowContainer_viewOptions_40f4d",
47540
- viewOptionsClip: "ReactFlowContainer_viewOptionsClip_40f4d",
47541
- viewSeparator: "ReactFlowContainer_viewSeparator_40f4d"
47522
+ container: "ReactFlowContainer_container_18f86",
47523
+ flow: "ReactFlowContainer_flow_18f86",
47524
+ contextMenu: "ReactFlowContainer_contextMenu_18f86",
47525
+ movingLayout: "ReactFlowContainer_movingLayout_18f86",
47526
+ layoutPending: "ReactFlowContainer_layoutPending_18f86",
47527
+ dock: "ReactFlowContainer_dock_18f86",
47528
+ viewDock: "ReactFlowContainer_viewDock_18f86",
47529
+ expandedViewControls: "ReactFlowContainer_expandedViewControls_18f86",
47530
+ viewOptionButtons: "ReactFlowContainer_viewOptionButtons_18f86",
47531
+ compactViewControls: "ReactFlowContainer_compactViewControls_18f86",
47532
+ createDock: "ReactFlowContainer_createDock_18f86",
47533
+ zoomValue: "ReactFlowContainer_zoomValue_18f86",
47534
+ viewChoiceTrigger: "ReactFlowContainer_viewChoiceTrigger_18f86",
47535
+ viewChoicePanel: "ReactFlowContainer_viewChoicePanel_18f86",
47536
+ viewChoices: "ReactFlowContainer_viewChoices_18f86",
47537
+ viewChoice: "ReactFlowContainer_viewChoice_18f86",
47538
+ dockActions: "ReactFlowContainer_dockActions_18f86",
47539
+ miniMap: "ReactFlowContainer_miniMap_18f86",
47540
+ viewOptions: "ReactFlowContainer_viewOptions_18f86",
47541
+ viewOptionsClip: "ReactFlowContainer_viewOptionsClip_18f86",
47542
+ viewSeparator: "ReactFlowContainer_viewSeparator_18f86"
47542
47543
  };
47543
47544
  //#endregion
47544
47545
  //#region src/canvas/browser/addItemDrag.ts
@@ -54159,14 +54160,13 @@ function CanvasOptionsMenu({ onRelayout, miniMapExpanded$, interactiveMode$, dir
54159
54160
  interactiveMode$ != null && /* @__PURE__ */ jsx(CanvasInteractiveModeMenu, { interactiveMode$ })
54160
54161
  ] });
54161
54162
  }
54162
- function CanvasViewControls({ readOnly = false, direction, changingDirection, onChangeDirection, interactiveMode$, miniMapExpanded$, maxZoomReached, minZoomReached, onFitView, onRelayout, onZoomIn, onZoomOut, onZoomReset, zoom }) {
54163
+ function CanvasViewControls({ direction, changingDirection, onChangeDirection, interactiveMode$, miniMapExpanded$, maxZoomReached, minZoomReached, onFitView, onRelayout, onZoomIn, onZoomOut, onZoomReset, zoom }) {
54163
54164
  const t = useTranslate();
54164
54165
  const [optionsExpanded, setOptionsExpanded] = useState(false);
54165
54166
  const [popupContainer, setPopupContainer] = useState(null);
54166
54167
  return /* @__PURE__ */ jsxs(Panel, {
54167
54168
  position: "bottom-left",
54168
54169
  className: cn$1("open-flow-control-island open-flow-control-island-compact", ReactFlowContainer_module_default.dock, ReactFlowContainer_module_default.viewDock),
54169
- "data-readonly": readOnly,
54170
54170
  "data-canvas-control-scope": true,
54171
54171
  "data-tooltip-toolbar": true,
54172
54172
  ref: setPopupContainer,
@@ -54702,7 +54702,6 @@ var FlowControls = /*#__PURE__*/ memo((props) => {
54702
54702
  variant: BackgroundVariant.Dots
54703
54703
  }),
54704
54704
  /* @__PURE__ */ jsx(CanvasViewControls, {
54705
- readOnly: !props.editable,
54706
54705
  interactiveMode$: props.interactiveMode$,
54707
54706
  direction: props.direction,
54708
54707
  changingDirection: props.changingDirection,
@@ -55418,7 +55417,7 @@ var FlowCanvas = ({ flowCanvasStore, annotationContext, onActivateSelection, onS
55418
55417
  editable,
55419
55418
  direction,
55420
55419
  changingDirection,
55421
- onChangeDirection: editable && flowCanvasStore.canChangeDirection ? flowCanvasStore.changeDirection : void 0,
55420
+ onChangeDirection: flowCanvasStore.canChangeDirection ? flowCanvasStore.changeDirection : void 0,
55422
55421
  nodesDraggable: nodesDraggable ?? editable,
55423
55422
  className,
55424
55423
  i18n: flowCanvasStore.i18n,
@@ -59921,7 +59920,7 @@ var keySchema = string$1().min(1).refine((value) => new TextEncoder().encode(val
59921
59920
  strictObject({
59922
59921
  scope: _enum(["draft", "live"]),
59923
59922
  values: literal(false).optional()
59924
- });
59923
+ }).omit({ values: true });
59925
59924
  strictObject({
59926
59925
  scope: _enum(["draft", "live"]),
59927
59926
  keys: array(keySchema).min(1).max(stateReadLimits.maxKeys).refine((keys) => new Set(keys).size === keys.length, "State keys must be distinct.")
@@ -59934,6 +59933,7 @@ strictObject({
59934
59933
  scope: _enum(["draft", "live"]),
59935
59934
  space: string$1().regex(/^(flow|node:.+)$/)
59936
59935
  });
59936
+ strictObject({ scope: _enum(["draft", "live"]) });
59937
59937
  var skipDuplicatesConfigSchema = strictObject({ fields: array(string$1().refine((field) => field.length > 0 && field.split(".").every((part) => part.length > 0), "Use a nonempty dot-separated field path.")).refine((fields) => new Set(fields).size === fields.length, "Identity fields must be distinct.").default([]) });
59938
59938
  var skipDuplicatesExecutorSchema = skipDuplicatesConfigSchema.extend({ kind: literal("skip-duplicates") });
59939
59939
  object$2({
@@ -59958,7 +59958,10 @@ object$2({
59958
59958
  reservedCount: number().nonnegative(),
59959
59959
  updatedAt: number()
59960
59960
  }))
59961
- });
59961
+ }).extend({ values: strictObject({
59962
+ count: number().int().nonnegative(),
59963
+ updatedAt: number().nullable()
59964
+ }) });
59962
59965
  object$2({
59963
59966
  version: literal(1),
59964
59967
  scope: _enum(["draft", "live"]),
@@ -82868,47 +82871,54 @@ function ArrayValueFields(props) {
82868
82871
  label,
82869
82872
  children: (item, index, handle) => {
82870
82873
  const itemSchema = Array.isArray(source.items) ? source.items[index] ?? source.additionalItems ?? {} : source.items ?? {};
82874
+ const addLabel = `${t("valueEditor.addItem")} ${label}.${index}`;
82875
+ const removeLabel = `${t("valueEditor.remove")} ${label}.${index}`;
82871
82876
  return /* @__PURE__ */ jsx("div", {
82872
82877
  "data-array-field-content": true,
82873
82878
  children: child(index, itemSchema, item, (next, deletion) => onChange(setArrayItem(array, index, next), deletion), {
82874
82879
  arrayChild: true,
82875
82880
  header: /* @__PURE__ */ jsx(Fragment$1, {}),
82876
- disclosureContent: /* @__PURE__ */ jsxs("span", {
82881
+ disclosureContent: props.showIndices !== false ? /* @__PURE__ */ jsxs("span", {
82877
82882
  className: valueEditor_module_default.arrayIndex,
82878
82883
  children: [index, "."]
82879
- }),
82884
+ }) : void 0,
82885
+ ...props.showIndices === false ? { depth: props.depth ?? 0 } : {},
82880
82886
  leadingControl: handle || void 0,
82881
82887
  onDefinitionChange: props.onDefinitionChange && !Array.isArray(source.items) ? (items, nextValue, deletion) => props.onDefinitionChange({
82882
82888
  ...source,
82883
82889
  items
82884
82890
  }, array.map((entry, at) => at === index ? nextValue : entry), deletion) : void 0,
82885
82891
  hideOptions: true,
82886
- actions: !props.readOnly && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button$1, {
82887
- type: "button",
82888
- variant: "ghost",
82889
- size: "icon-xs",
82890
- "aria-label": `${t("valueEditor.addItem")} ${label}.${index}`,
82891
- disabled: disabled || typeof source.maxItems === "number" && array.length >= source.maxItems,
82892
- onClick: () => onChange(array.toSpliced(index + 1, 0, initialValue(Array.isArray(source.items) ? source.items[index + 1] ?? source.additionalItems ?? {} : source.items ?? {}))),
82892
+ actions: !props.readOnly && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
82893
+ render: /* @__PURE__ */ jsx(Button$1, {
82894
+ type: "button",
82895
+ variant: "ghost",
82896
+ size: "icon-xs",
82897
+ "aria-label": addLabel,
82898
+ disabled: disabled || typeof source.maxItems === "number" && array.length >= source.maxItems,
82899
+ onClick: () => onChange(array.toSpliced(index + 1, 0, initialValue(Array.isArray(source.items) ? source.items[index + 1] ?? source.additionalItems ?? {} : source.items ?? {})))
82900
+ }),
82893
82901
  children: /* @__PURE__ */ jsx("i", {
82894
82902
  "aria-hidden": "true",
82895
82903
  className: "i-tabler-light:square-rounded-plus text-lg"
82896
82904
  })
82897
- }), /* @__PURE__ */ jsx(Button$1, {
82898
- type: "button",
82899
- variant: "ghost",
82900
- size: "icon-xs",
82901
- "aria-label": `${t("valueEditor.remove")} ${label}.${index}`,
82902
- disabled: disabled || typeof source.minItems === "number" && array.length <= source.minItems,
82903
- onClick: () => onChange(array.toSpliced(index, 1), {
82904
- target: "arrayItem",
82905
- name: `${label}.${index}`
82905
+ }), /* @__PURE__ */ jsx(TooltipContent, { children: addLabel })] }), /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
82906
+ render: /* @__PURE__ */ jsx(Button$1, {
82907
+ type: "button",
82908
+ variant: "ghost",
82909
+ size: "icon-xs",
82910
+ "aria-label": removeLabel,
82911
+ disabled: disabled || typeof source.minItems === "number" && array.length <= source.minItems,
82912
+ onClick: () => onChange(array.toSpliced(index, 1), {
82913
+ target: "arrayItem",
82914
+ name: `${label}.${index}`
82915
+ })
82906
82916
  }),
82907
82917
  children: /* @__PURE__ */ jsx("i", {
82908
82918
  "aria-hidden": "true",
82909
82919
  className: "i-tabler-light:square-rounded-minus text-lg"
82910
82920
  })
82911
- })] })
82921
+ }), /* @__PURE__ */ jsx(TooltipContent, { children: removeLabel })] })] })
82912
82922
  })
82913
82923
  });
82914
82924
  }
@@ -99770,7 +99780,7 @@ function FieldNullable({ name, checked, onChange }) {
99770
99780
  //#endregion
99771
99781
  //#region src/ui/browser/helpButton.tsx
99772
99782
  /** Supplementary, non-interactive help that can also be opened by click. */
99773
- function HelpButton({ label, children, size = 24 }) {
99783
+ function HelpButton({ label, children, container, size = 24 }) {
99774
99784
  const id = useId();
99775
99785
  const [tooltip] = useState(() => createTooltipHandle());
99776
99786
  return /* @__PURE__ */ jsxs(Tooltip, {
@@ -99795,7 +99805,10 @@ function HelpButton({ label, children, size = 24 }) {
99795
99805
  className: "i-lucide-light:info text-muted-foreground",
99796
99806
  style: { fontSize: size * 5 / 8 }
99797
99807
  })
99798
- }), /* @__PURE__ */ jsx(TooltipContent, { children })]
99808
+ }), /* @__PURE__ */ jsx(TooltipContent, {
99809
+ container,
99810
+ children
99811
+ })]
99799
99812
  });
99800
99813
  }
99801
99814
  //#endregion
@@ -102080,11 +102093,15 @@ var resources = {
102080
102093
  "deleteDescription": "Permanently delete this workflow and its run history, and stop its live triggers.",
102081
102094
  "importFlow": "Import workflow",
102082
102095
  "exportFlow": "Export workflow",
102083
- "exportSvg": "Export SVG image",
102084
- "exportSvgPending": "Exporting SVG…",
102085
- "exportSvgPendingDescription": "Preparing the workflow and image resources. Large images may take a little longer.",
102086
- "exportSvgComplete": "SVG image exported.",
102087
- "exportSvgFailed": "Could not export the SVG image. Please try again.",
102096
+ "exportPng": "Export PNG image",
102097
+ "exportPngFrame": "Show frame",
102098
+ "exportPngLight": "Light",
102099
+ "exportPngDark": "Dark",
102100
+ "exportPngPending": "Exporting PNG…",
102101
+ "exportPngPendingDescription": "Preparing the workflow and image resources. Large images may take a little longer.",
102102
+ "exportPngComplete": "PNG image exported.",
102103
+ "exportPngPartial": "PNG image exported. Some images were replaced with placeholders.",
102104
+ "exportPngFailed": "Could not export the PNG image. Please try again.",
102088
102105
  "importInvalid": "Invalid or unsupported workflow file."
102089
102106
  },
102090
102107
  inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"Node outline\",\"backToOutline\":\"Back to node outline\",\"emptyOutline\":\"No nodes yet\",\"triggers\":\"Triggers\",\"nodes\":\"Nodes\",\"multipleSelected\":\"{{count}} nodes selected\",\"account\":{\"contactAdmin\":\"You do not have permission to perform this operation. Contact an administrator.\",\"accessTitle\":\"Access permissions\",\"manageFlowAccess\":\"Connections available to Code\",\"configureAccess\":\"Choose an account\",\"manageAccount\":\"Manage accounts\",\"required\":\"Account connection required\",\"addAccount\":\"Add account\",\"manage\":\"Manage\",\"authorizationPending\":\"Finish authorization in the Connection page, then return here to refresh this account.\",\"chooseAccount\":\"Choose an account\",\"deferred\":\"Not configured for now\",\"clearDeferred\":\"Clear selection\",\"noAccounts\":\"No accounts available\",\"connectBeforeRun\":\"Connect {{service}} before this block can run or be published.\",\"connectService\":\"Connect {{service}}\",\"connection\":\"Connection\",\"loading\":\"Loading connections…\",\"oomolBuiltIn\":\"OOMOL Built-in\",\"missing\":\"The account selected for this node is unavailable. Choose another account or manage connections.\",\"refreshFailed\":\"Connections could not be refreshed.\",\"retry\":\"Retry\",\"status\":{\"disconnected\":\"This Connection is disconnected. Reconnect it or choose another account.\",\"error\":\"This Connection has an error. Repair it or choose another account.\",\"reauth_required\":\"This Connection needs authorization again. Reconnect it or choose another account.\"},\"statusUnavailable\":\"Connection status is unavailable for {{action}}.\",\"teamDefault\":\"Team default\",\"title\":\"Account\",\"unavailable\":\"unavailable\"},\"close\":\"Close inspector\",\"configurationRequired\":\"Configuration required\",\"diagnostics\":\"Diagnostics\",\"errors\":{\"jsonObject\":\"{{label}} must be a JSON object.\",\"portDefinitions\":\"Enter valid port definitions.\"},\"node\":{\"nameDuplicate\":\"A node with this name already exists in this graph.\",\"nameEmpty\":\"Node name cannot be empty.\",\"timeout\":\"Timeout (ms)\",\"maxExecutions\":\"Node execution limit\",\"maxExecutionsError\":\"Node execution limit must be a positive integer.\",\"timeoutError\":\"Timeout must be a positive integer in milliseconds.\",\"title\":\"Node settings\",\"description\":\"Purpose\",\"describe\":\"Describe what this step does.\",\"icon\":\"Icon\",\"name\":\"Title\",\"retry\":\"Retry on error\",\"retryCount\":\"Up to {{count}} retries\",\"retryInterval\":\"Retry interval\",\"retryError\":\"Use an interval of 1–60 whole seconds.\",\"retryHint\":\"The retry count is the number of additional attempts after the first execution. Retries repeat the entire node and may repeat external operations. The timeout includes all attempts and intervals.\",\"retryNone\":\"No retries\",\"retrySeconds\":\"seconds\",\"retryHelp\":\"About retries\",\"retryOnce\":\"Retry once\",\"onError\":\"On failure\",\"onErrorStop\":\"Stop workflow\",\"onErrorOutput\":\"Output to error port\",\"onErrorHelp\":\"About failure handling\",\"onErrorHint\":\"After retries fail, write the error to the system error output and continue along existing connections. On success, error is null. Cancellation, timeouts, resource limits and indeterminate outcomes still stop execution.\",\"systemOutputs\":\"System outputs\",\"systemError\":\"Error information (system)\",\"errorFields\":{\"error\":\"Error information when the node fails; null on success.\",\"code\":\"A code identifying the type of error.\",\"message\":\"A description of the error, with sensitive content redacted.\",\"nodeId\":\"The ID of the node that failed.\",\"nodeName\":\"The node name at the time of failure.\",\"runId\":\"The ID of this workflow run.\",\"executionId\":\"The ID of this node execution, shared across its retry attempts.\"}},\"selectNode\":\"Select one Draft node to inspect and edit it.\",\"locateNode\":\"Locate this node on the canvas\",\"task\":{\"sharedPermissions\":\"Use Flow shared permission group\",\"sharedPermissionsHint\":\"Use all Actions authorized by the Flow permission group. No need to add them to this node.\",\"httpHosts\":\"HTTP hosts\",\"httpHostsHint\":\"One host per line. *.example.com includes subdomains.\",\"httpHostsInvalid\":\"\\\"{{host}}\\\" is not a valid host. Use a host name such as api.example.com.\",\"httpHostsLimit\":\"Declare at most {{count}} hosts.\",\"addAction\":\"Add Action\",\"removeAction\":\"Remove Action\",\"actionAccount\":\"Account\",\"chooseAccount\":\"Choose an account\",\"permissionSaveFailed\":\"Could not save Code permissions. Retry the change.\",\"chatText\":\"Chat text\",\"connectorAction\":\"Connector action\",\"definition\":\"Task definition\",\"discardCode\":\"Discard changes\",\"editorLoading\":\"Loading editor…\",\"editorUnavailable\":\"The code editor couldn’t be loaded.\",\"inputPorts\":\"Input ports\",\"javascriptModule\":\"Code\",\"missing\":\"The referenced Task does not exist.\",\"outputPorts\":\"Output ports\",\"responseMode\":\"Response mode\",\"source\":\"Source\",\"structuredJson\":\"Structured JSON\",\"retrySave\":\"Retry save\",\"additionalInputs\":\"Additional inputs\",\"httpHostsUpdated\":\"Hosts changed elsewhere. The latest configuration is loaded; review it before saving.\"},\"wait\":{\"approval\":\"Approve or reject\",\"changeNotification\":\"Change\",\"continue\":\"Continue\",\"mode\":\"Resolution\",\"inputsLoading\":\"Loading notification parameters…\",\"pendingDescription\":\"The pending output fires once when waiting begins and provides confirmation links and related data. Connect it to send a message or run other steps.\",\"prompt\":\"Prompt\",\"promptError\":\"Prompt must contain 1 to 1,000 characters.\",\"autoContinue\":\"Automatic continuation\",\"autoOff\":\"Off\",\"autoAfter\":\"After a duration\",\"autoAt\":\"At a specific time\",\"autoSeconds\":\"Duration (seconds)\",\"autoDate\":\"Date and time\",\"autoInvalid\":\"Enter a positive duration or a valid date and time.\",\"autoDescription\":\"You can continue manually before the scheduled time.\"},\"title\":\"Inspector\",\"sources\":{\"loading\":\"Loading input sources…\",\"loadFailed\":\"Could not load input sources. Reopen the menu to retry.\",\"checkFailed\":\"Could not check this source.\",\"select\":\"Select input source\",\"title\":\"Input source\",\"sourceMissing\":\"The original input source no longer exists. Choose again.\",\"outputMissing\":\"“{{output}}” could not be found in “{{source}}”. Choose again.\",\"wholeObject\":\"Whole object\",\"fieldMissing\":\"Field {{field}} is no longer declared in “{{output}}”. Choose again.\",\"notReady\":\"“{{source}} {{handle}}” may not have a value when this step runs.\",\"sourceConflict\":\"These fields may have values at the same time: {{sources}}. Only one can be used here.\",\"incompatibleRight\":\"The right value type is incompatible with this comparison.\",\"incompatible\":\"Mismatch\",\"unverified\":\"Unverified\",\"schemaIncompatible\":\"The data format does not match.\",\"schemaPathIncompatible\":\"The data format of “{{path}}” does not match.\",\"schemaCompareFailed\":\"Could not check the data format. Check the JSON Schema.\",\"binaryIncompatible\":\"Binary data cannot be used here.\",\"artifactIncompatible\":\"File data cannot be used here.\",\"nullableIncompatible\":\"A value is required, but the selected field may be empty.\",\"typeIncompatible\":\"Expected {{target}}, but the selected field is {{source}}.\",\"propertyTypeIncompatible\":\"“{{path}}” must be {{target}}, but it is {{source}}.\",\"requiredIncompatible\":\"The required property “{{property}}” may be missing.\",\"enumIncompatible\":\"Some possible values are not accepted: {{values}}.\",\"constIncompatible\":\"Only {{target}} is accepted, but the selected field is always {{source}}.\",\"constraintSubject\":\"“{{path}}” \",\"minLength\":\"{{subject}}must contain at least {{value}} characters.\",\"maxLength\":\"{{subject}}must contain at most {{value}} characters.\",\"pattern\":\"{{subject}}must match {{value}}.\",\"minimum\":\"{{subject}}cannot be less than {{value}}.\",\"exclusiveMinimum\":\"{{subject}}must be greater than {{value}}.\",\"maximum\":\"{{subject}}cannot be greater than {{value}}.\",\"exclusiveMaximum\":\"{{subject}}must be less than {{value}}.\",\"multipleOf\":\"{{subject}}must be a multiple of {{value}}.\",\"minItems\":\"{{subject}}must contain at least {{value}} items.\",\"maxItems\":\"{{subject}}must contain at most {{value}} items.\",\"minProperties\":\"{{subject}}must contain at least {{value}} properties.\",\"maxProperties\":\"{{subject}}must contain at most {{value}} properties.\",\"integer\":\"Integer\",\"unknownType\":\"unknown type\",\"typeSeparator\":\" or \"},\"actions\":{\"flowAccess\":\"Available services\",\"flowAccessHint\":\"Manage connections shared by all Code nodes in this Flow\",\"chooseConnection\":\"Choose a {{provider}} connection\",\"connectionDescription\":\"The connection is inserted into this call. Flow provider access still controls whether it may be used.\",\"title\":\"Actions available to this code\",\"search\":\"Search actions\",\"description\":\"Choose the actions and accounts this code can use.\",\"empty\":\"No matching actions.\",\"remove\":\"Remove\",\"default\":\"Default account\",\"defaultHint\":\"Used when the call does not specify an account.\",\"removeAction\":\"Remove action\",\"explicit\":\"Choose explicitly in code\",\"connect\":\"Connect account\",\"refresh\":\"Refresh accounts\",\"aliases\":\"Update saved aliases\",\"add\":\"Add action\",\"cancel\":\"Cancel\",\"loading\":\"Searching…\",\"needsAccount\":\"Connect an account\",\"accounts\":\"{{count}} accounts\",\"public\":\"No account needed\",\"allowed\":\"Allowed accounts\",\"unavailable\":\"Unavailable\",\"details\":\"Connection details\",\"example\":\"Call example\",\"syntax\":\"Call syntax\",\"nested\":\"Provider method\",\"fullId\":\"Full ID\",\"copy\":\"Copy\",\"copied\":\"Copied\",\"copyError\":\"Copy failed. Select the code and copy it manually.\",\"introDescription\":\"Add actions as needed to call external apps through {{context}}.\",\"insertAction\":\"Insert code\",\"chooseAccounts\":\"Manage accounts\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"Preview\"},\"ports\":{\"reorder\":\"Reorder {{name}}\",\"reorderHint\":\"Drag to reorder within the group, or use Up / Down while focused.\",\"moved\":\"{{name}} moved to position {{position}}.\",\"groupSettings\":\"Group settings\",\"connected\":\"Connected\",\"sort\":\"Sort\",\"finishSorting\":\"Done sorting\",\"inputsTitle\":\"Inputs\",\"requiredInputs\":\"Required\",\"optionalInputs\":\"Optional\",\"noInputs\":\"This node does not require input data.\",\"noOutputs\":\"This node does not provide output data.\",\"outputsTitle\":\"Outputs\",\"valuesTitle\":\"Values\",\"columnHandle\":\"Handle\",\"columnName\":\"Name\",\"columnType\":\"Type\",\"columnValue\":\"Value\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"The scheduled time that triggered this run, in ISO 8601 format.\"},\"webhook\":{\"headers\":\"The headers received with this Webhook request.\",\"query\":\"The URL query parameters received with this Webhook request.\",\"body\":\"The body received with this Webhook request.\",\"webhookUrl\":\"The Webhook URL that received this request, without query parameters.\"}},\"startParametersTitle\":\"Start parameters\"}}"),
@@ -102935,7 +102952,6 @@ var resources = {
102935
102952
  snapshot: {
102936
102953
  "title": "Snapshot",
102937
102954
  "restore": "Restore layout",
102938
- "missingLayout": "This version has no saved layout. Nodes are arranged automatically.",
102939
102955
  "loading": "Loading version…",
102940
102956
  "failed": "This version could not be loaded. Its content may no longer be available.",
102941
102957
  "root": "Main flow"
@@ -103177,41 +103193,52 @@ var resources = {
103177
103193
  "nodeTitle": "Skip Duplicates",
103178
103194
  "warning": "History is saved after this Run succeeds. Failed or canceled Runs allow these items to be processed again.",
103179
103195
  "field": "Identity fields",
103196
+ "fieldDescription": "Field values identify duplicates; multiple fields are combined. With no fields, items are compared directly.",
103180
103197
  "values": "Saved data",
103181
- "spaces": "Deduplication records",
103182
- "clearAll": "Clear all",
103198
+ "spaces": "Deduplication history",
103183
103199
  "delete": "Delete",
103184
103200
  "clear": "Clear",
103185
- "orphaned": "Orphaned in this view",
103201
+ "orphaned": "Outside the current view",
103186
103202
  "nearLimit": "Flow history is at least 80% full. Clear unused history.",
103187
- "history": "History",
103203
+ "history": "Usage",
103188
103204
  "scope": "Scope",
103189
- "showValue": "View value",
103190
- "hideValue": "Hide value",
103191
103205
  "refresh": "Refresh",
103192
- "confirmLive": "This clears production state immediately. Future Live Runs may process these items again. Continue?",
103193
103206
  "cancel": "Cancel",
103194
- "loading": "Loading state...",
103195
- "draft": "Debug data",
103196
- "live": "Production data",
103197
- "isolation": "Debug and production data are independent.",
103198
- "rules": "Storage rules",
103199
- "retention": "Data survives publishing and rollback. Clear it explicitly when no longer needed. Do not store credentials.",
103200
- "emptyValues": "No saved data",
103201
- "emptySpaces": "No deduplication records",
103202
- "entries": "{{count}} / {{limit}} entries",
103207
+ "loading": "Loading…",
103208
+ "draft": "Draft",
103209
+ "live": "Published",
103210
+ "isolation": "Debug and Live data are stored separately. Publishing and rollback do not clear data.",
103211
+ "rules": "Storage notes",
103203
103212
  "records": "{{count}} records",
103204
- "valueLimit": "Each JSON value allows up to {{size}} UTF-8 bytes.",
103205
- "sharedLimit": "All spaces share the identity limit. Spaces: {{count}} / {{limit}}. Pending records reserve capacity.",
103206
103213
  "fieldPlaceholder": "Whole item (string or number)",
103207
103214
  "addField": "Add field",
103208
103215
  "removeField": "Remove field {{index}}",
103209
103216
  "fieldIndex": "Identity field {{index}}",
103210
103217
  "invalidFields": "Use distinct, nonempty field paths such as id or record.id.",
103211
- "pendingRecords": "{{count}} pending",
103212
103218
  "pathPlaceholder": "id or record.id",
103213
103219
  "saveFailed": "Unable to save identity fields.",
103214
- "retry": "Retry"
103220
+ "retry": "Retry",
103221
+ "limit": " / {{limit}}",
103222
+ "source": "Source",
103223
+ "count": "Records",
103224
+ "updated": "Updated",
103225
+ "shared": "Workflow shared",
103226
+ "globalUsage": "Total workflow deduplication records",
103227
+ "valuesNearLimit": "Saved data is at least 80% full. Clear entries you no longer need.",
103228
+ "pendingClear": "{{count}} pending; finish or cancel their Runs before clearing.",
103229
+ "clearBlocked": "This history has pending records. Finish or cancel their Runs, then refresh.",
103230
+ "clearSource": "Clear {{name}}",
103231
+ "sourceHistory": "{{name}} history",
103232
+ "confirmTitle": "Clear {{name}}?",
103233
+ "confirmValues": "This will clear {{count}} saved entries in {{scope}}. Subsequent Runs will no longer be able to read these values.",
103234
+ "confirmHistory": "This will clear {{count}} deduplication records in {{scope}}. These items may be processed again.",
103235
+ "confirmClear": "Clear",
103236
+ "retainedHistory": "All history from sources with pending records will be kept ({{count}} pending).",
103237
+ "emptyValues": "No saved data",
103238
+ "emptySpaces": "No history yet",
103239
+ "loadFailed": "Unable to load",
103240
+ "valuesHelp": "{{name}}: Content explicitly saved by the workflow, available to later runs.",
103241
+ "historyHelp": "{{name}}: Item identifiers used to avoid processing duplicates."
103215
103242
  }
103216
103243
  },
103217
103244
  "zh-CN": {
@@ -103435,11 +103462,15 @@ var resources = {
103435
103462
  "deleteDescription": "工作流及运行记录将永久删除,并停止线上触发。",
103436
103463
  "importFlow": "导入工作流",
103437
103464
  "exportFlow": "导出工作流",
103438
- "exportSvg": "导出 SVG 图片",
103439
- "exportSvgPending": "正在导出 SVG…",
103440
- "exportSvgPendingDescription": "正在处理工作流和图片资源,图片较大时可能需要一些时间。",
103441
- "exportSvgComplete": "SVG 图片已导出。",
103442
- "exportSvgFailed": "SVG 图片导出失败,请重试。",
103465
+ "exportPng": "导出 PNG 图片",
103466
+ "exportPngFrame": "显示外框",
103467
+ "exportPngLight": "浅色",
103468
+ "exportPngDark": "深色",
103469
+ "exportPngPending": "正在导出 PNG…",
103470
+ "exportPngPendingDescription": "正在处理工作流和图片资源,图片较大时可能需要一些时间。",
103471
+ "exportPngComplete": "PNG 图片已导出。",
103472
+ "exportPngPartial": "PNG 图片已导出,部分图片已用占位图替代。",
103473
+ "exportPngFailed": "PNG 图片导出失败,请重试。",
103443
103474
  "importInvalid": "文件损坏或工作流格式不受支持。"
103444
103475
  },
103445
103476
  inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"节点大纲\",\"backToOutline\":\"返回节点大纲\",\"emptyOutline\":\"暂无节点\",\"triggers\":\"触发器\",\"nodes\":\"节点\",\"multipleSelected\":\"已选择 {{count}} 个节点\",\"account\":{\"contactAdmin\":\"你没有执行此操作的权限,请联系管理员。\",\"accessTitle\":\"访问权限\",\"manageFlowAccess\":\"Code 允许使用的连接\",\"configureAccess\":\"选择可用账号\",\"manageAccount\":\"管理账号\",\"required\":\"待连接账号\",\"addAccount\":\"添加账号\",\"manage\":\"管理\",\"authorizationPending\":\"请在 Connection 页面完成授权,返回这里后会刷新当前账号。\",\"chooseAccount\":\"选择账号\",\"deferred\":\"暂不设置\",\"clearDeferred\":\"清除选择\",\"noAccounts\":\"暂无可用账号\",\"connectBeforeRun\":\"请先连接 {{service}},此节点才能运行或发布。\",\"connectService\":\"连接 {{service}}\",\"connection\":\"连接\",\"loading\":\"正在加载连接…\",\"oomolBuiltIn\":\"OOMOL 内置账号\",\"missing\":\"此节点选择的账号当前不可用,请选择其他账号或管理账号。\",\"refreshFailed\":\"无法刷新 Connection。\",\"retry\":\"重试\",\"status\":{\"disconnected\":\"此 Connection 已断开,请重新连接或选择其他账号。\",\"error\":\"此 Connection 状态异常,请修复后重试或选择其他账号。\",\"reauth_required\":\"此 Connection 需要重新授权,请重新连接或选择其他账号。\"},\"statusUnavailable\":\"暂时无法获取 {{action}} 的连接状态。\",\"teamDefault\":\"团队默认\",\"title\":\"账号\",\"unavailable\":\"不可用\"},\"close\":\"关闭检查器\",\"configurationRequired\":\"配置待完成\",\"diagnostics\":\"诊断\",\"errors\":{\"jsonObject\":\"{{label}} 必须是 JSON 对象。\",\"portDefinitions\":\"请输入有效的端口定义。\"},\"node\":{\"nameDuplicate\":\"当前图中已存在同名节点。\",\"nameEmpty\":\"节点名称不能为空。\",\"timeout\":\"超时时间(毫秒)\",\"maxExecutions\":\"节点执行上限\",\"maxExecutionsError\":\"节点执行上限必须是正整数。\",\"timeoutError\":\"超时时间必须是以毫秒为单位的正整数。\",\"title\":\"节点设置\",\"description\":\"用途说明\",\"describe\":\"描述这一步要完成什么。\",\"icon\":\"图标\",\"name\":\"标题\",\"retry\":\"失败重试\",\"retryCount\":\"最多重试 {{count}} 次\",\"retryInterval\":\"重试间隔\",\"retryError\":\"间隔须为 1~60 整数秒。\",\"retryHint\":\"重试次数是首次执行失败后的追加次数。重试会重新执行整个节点,可能重复外部操作。超时包含全部尝试和等待间隔。\",\"retryNone\":\"不重试\",\"retrySeconds\":\"秒\",\"retryHelp\":\"重试说明\",\"retryOnce\":\"最多重试 1 次\",\"onError\":\"失败处理\",\"onErrorStop\":\"终止工作流\",\"onErrorOutput\":\"输出到 error 端口\",\"onErrorHelp\":\"失败处理说明\",\"onErrorHint\":\"重试后仍失败时,将错误写入系统 error 并沿现有连线继续。成功时 error 为 null。取消、超时、资源限制和结果不确定仍终止工作流。\",\"systemOutputs\":\"系统输出\",\"systemError\":\"错误信息(系统)\",\"errorFields\":{\"error\":\"节点失败时的错误信息;成功时为 null。\",\"code\":\"用于识别错误类型的错误码。\",\"message\":\"错误的说明信息,敏感内容已脱敏。\",\"nodeId\":\"发生错误的节点 ID。\",\"nodeName\":\"发生错误时的节点名称。\",\"runId\":\"本次工作流运行的 ID。\",\"executionId\":\"本次节点执行的 ID,多次重试共用此 ID。\"}},\"selectNode\":\"选择一个草稿节点以查看和编辑。\",\"locateNode\":\"在画布上定位该节点\",\"task\":{\"sharedPermissions\":\"使用 Flow 共享权限组\",\"sharedPermissionsHint\":\"直接使用 Flow 共享权限组已授权的全部 Actions,无需逐个添加。\",\"httpHosts\":\"HTTP 主机\",\"httpHostsHint\":\"每行一个主机,支持 *.example.com 子域名匹配。\",\"httpHostsInvalid\":\"“{{host}}”不是有效的主机,请填写 api.example.com 这样的主机名。\",\"httpHostsLimit\":\"最多声明 {{count}} 个主机。\",\"addAction\":\"添加 Action\",\"removeAction\":\"移除 Action\",\"actionAccount\":\"账号\",\"chooseAccount\":\"选择账号\",\"permissionSaveFailed\":\"无法保存 Code 权限,请重试。\",\"chatText\":\"对话文本\",\"connectorAction\":\"连接器操作\",\"definition\":\"任务定义\",\"discardCode\":\"放弃修改\",\"editorLoading\":\"正在加载编辑器…\",\"editorUnavailable\":\"代码编辑器加载失败。\",\"inputPorts\":\"输入端口\",\"javascriptModule\":\"代码\",\"missing\":\"引用的任务不存在。\",\"outputPorts\":\"输出端口\",\"responseMode\":\"响应模式\",\"source\":\"源代码\",\"structuredJson\":\"结构化 JSON\",\"retrySave\":\"重试保存\",\"additionalInputs\":\"附加输入\",\"httpHostsUpdated\":\"主机配置已在别处更新。已加载最新配置,请检查后再保存。\"},\"wait\":{\"approval\":\"通过或拒绝\",\"changeNotification\":\"更换\",\"continue\":\"继续\",\"mode\":\"处理方式\",\"inputsLoading\":\"正在加载通知参数…\",\"pendingDescription\":\"待确认出口在开始等待时触发一次,提供确认链接及相关数据。连接此出口可发送消息或执行其他步骤。\",\"prompt\":\"提示\",\"promptError\":\"提示必须包含 1 到 1,000 个字符。\",\"autoContinue\":\"自动继续\",\"autoOff\":\"关闭\",\"autoAfter\":\"等待一段时间\",\"autoAt\":\"到指定时间\",\"autoSeconds\":\"等待时长(秒)\",\"autoDate\":\"日期和时间\",\"autoInvalid\":\"请输入正数时长或有效的日期和时间。\",\"autoDescription\":\"可提前手动继续。\"},\"title\":\"检查器\",\"sources\":{\"loading\":\"正在加载输入来源…\",\"loadFailed\":\"无法加载输入来源,请重新打开菜单重试。\",\"checkFailed\":\"无法检查此来源。\",\"select\":\"选择输入来源\",\"title\":\"输入来源\",\"sourceMissing\":\"原输入来源已不存在,请重新选择。\",\"outputMissing\":\"“{{source}}”中找不到“{{output}}”,请重新选择。\",\"wholeObject\":\"整个对象\",\"fieldMissing\":\"“{{output}}”中已不再声明字段 {{field}},请重新选择。\",\"notReady\":\"运行到这里时,“{{source}} {{handle}}”可能还没有值。\",\"sourceConflict\":\"这些字段可能同时有值:{{sources}}。这里只能取一个。\",\"incompatibleRight\":\"右值类型不符合此比较的要求。\",\"incompatible\":\"不兼容\",\"unverified\":\"无法验证\",\"schemaIncompatible\":\"数据格式不匹配。\",\"schemaPathIncompatible\":\"“{{path}}”的数据格式不匹配。\",\"schemaCompareFailed\":\"无法检查数据格式,请检查 JSON Schema。\",\"binaryIncompatible\":\"不能使用二进制数据。\",\"artifactIncompatible\":\"不能使用文件数据。\",\"nullableIncompatible\":\"不能为空,但所选字段可能为空。\",\"typeIncompatible\":\"需要{{target}},但所选字段是{{source}}。\",\"propertyTypeIncompatible\":\"“{{path}}”需要{{target}},实际是{{source}}。\",\"requiredIncompatible\":\"不一定包含必填属性“{{property}}”。\",\"enumIncompatible\":\"可能出现不接受的值:{{values}}。\",\"constIncompatible\":\"只接受 {{target}},所选字段固定为 {{source}}。\",\"constraintSubject\":\"“{{path}}”\",\"minLength\":\"{{subject}}至少需要 {{value}} 个字符。\",\"maxLength\":\"{{subject}}最多接受 {{value}} 个字符。\",\"pattern\":\"{{subject}}文本格式应符合 {{value}}。\",\"minimum\":\"{{subject}}不能小于 {{value}}。\",\"exclusiveMinimum\":\"{{subject}}必须大于 {{value}}。\",\"maximum\":\"{{subject}}不能大于 {{value}}。\",\"exclusiveMaximum\":\"{{subject}}必须小于 {{value}}。\",\"multipleOf\":\"{{subject}}必须是 {{value}} 的倍数。\",\"minItems\":\"{{subject}}至少需要 {{value}} 项。\",\"maxItems\":\"{{subject}}最多接受 {{value}} 项。\",\"minProperties\":\"{{subject}}至少需要 {{value}} 个属性。\",\"maxProperties\":\"{{subject}}最多接受 {{value}} 个属性。\",\"integer\":\"整数\",\"unknownType\":\"未知类型\",\"typeSeparator\":\"或\"},\"actions\":{\"flowAccess\":\"可用服务\",\"flowAccessHint\":\"管理整个工作流的 Code 共享使用的连接\",\"chooseConnection\":\"选择 {{provider}} Connection\",\"connectionDescription\":\"Connection 将写入本次调用;是否允许使用仍由工作流 Provider Access 决定。\",\"title\":\"代码可调用的动作\",\"search\":\"搜索应用或动作…\",\"description\":\"搜索并添加这段代码需要调用的动作。\",\"empty\":\"没有匹配的 Action。\",\"remove\":\"移除\",\"default\":\"默认账号\",\"defaultHint\":\"调用时未指定账号,将使用此账号。\",\"removeAction\":\"移除动作\",\"explicit\":\"每次调用时指定\",\"connect\":\"连接账号\",\"refresh\":\"刷新账号\",\"aliases\":\"同步账号别名\",\"add\":\"添加动作\",\"cancel\":\"取消\",\"loading\":\"搜索中…\",\"needsAccount\":\"待连接账号\",\"accounts\":\"{{count}} 个账号\",\"public\":\"无需账号\",\"allowed\":\"允许使用的账号\",\"unavailable\":\"不可用\",\"details\":\"账号详情\",\"example\":\"调用示例\",\"syntax\":\"调用写法\",\"nested\":\"分层写法\",\"fullId\":\"完整 ID\",\"copy\":\"复制\",\"copied\":\"已复制\",\"copyError\":\"复制失败,请选中示例代码手动复制。\",\"introDescription\":\"按需添加动作,通过 {{context}} 调用外部应用。\",\"insertAction\":\"插入代码\",\"chooseAccounts\":\"管理账号\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"预览\"},\"ports\":{\"reorder\":\"调整 {{name}} 的顺序\",\"reorderHint\":\"拖动调整组内顺序,或聚焦后使用上、下方向键。\",\"moved\":\"{{name}} 已移至第 {{position}} 位。\",\"groupSettings\":\"分组设置\",\"connected\":\"已连接\",\"sort\":\"排序\",\"finishSorting\":\"完成排序\",\"inputsTitle\":\"输入\",\"requiredInputs\":\"必填\",\"optionalInputs\":\"选填\",\"noInputs\":\"此节点不需要输入数据\",\"noOutputs\":\"此节点不提供输出数据\",\"outputsTitle\":\"输出\",\"valuesTitle\":\"数据\",\"columnHandle\":\"Handle\",\"columnName\":\"名称\",\"columnType\":\"类型\",\"columnValue\":\"值\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"本次运行的计划触发时间,采用 ISO 8601 格式。\"},\"webhook\":{\"headers\":\"此 Webhook 请求携带的请求头。\",\"query\":\"此 Webhook 请求携带的 URL 查询参数。\",\"body\":\"此 Webhook 请求携带的请求体。\",\"webhookUrl\":\"接收此次请求的 Webhook URL,不含查询参数。\"}},\"startParametersTitle\":\"启动参数\"}}"),
@@ -104290,7 +104321,6 @@ var resources = {
104290
104321
  snapshot: {
104291
104322
  "title": "快照",
104292
104323
  "restore": "恢复布局",
104293
- "missingLayout": "此版本未保存布局,已自动排列",
104294
104324
  "loading": "正在加载版本…",
104295
104325
  "failed": "无法加载此版本,其内容可能已不可用。",
104296
104326
  "root": "主流程"
@@ -104532,41 +104562,52 @@ var resources = {
104532
104562
  "nodeTitle": "跳过重复",
104533
104563
  "warning": "记录在本次 Run 成功后保存。失败或取消后,下次仍可处理这些条目。",
104534
104564
  "field": "标识字段",
104565
+ "fieldDescription": "根据字段值识别重复条目,多个字段组合判断。留空时比较条目本身。",
104535
104566
  "values": "保存的数据",
104536
- "spaces": "去重记录",
104537
- "clearAll": "清空",
104567
+ "spaces": "去重历史",
104538
104568
  "delete": "删除",
104539
104569
  "clear": "清空",
104540
- "orphaned": "当前视图中的遗留空间",
104541
- "nearLimit": "该流程的去重记录已使用至少 80%。请清理不再需要的记录。",
104542
- "history": "历史记录",
104570
+ "orphaned": "当前视图外",
104571
+ "nearLimit": "该工作流的去重记录已使用至少 80%。请清理不再需要的记录。",
104572
+ "history": "用量",
104543
104573
  "scope": "作用域",
104544
- "showValue": "查看值",
104545
- "hideValue": "收起值",
104546
104574
  "refresh": "刷新",
104547
- "confirmLive": "这将立即清空生产状态,后续 Live Run 可能再次处理这些条目。是否继续?",
104548
104575
  "cancel": "取消",
104549
- "loading": "正在加载状态…",
104550
- "draft": "调试数据",
104551
- "live": "正式运行数据",
104552
- "isolation": "调试与正式运行的数据相互独立。",
104553
- "rules": "存储规则",
104554
- "retention": "发布和回滚不会清空数据。不再需要时请手动清理。请勿存储凭据。",
104555
- "emptyValues": "暂无保存的数据",
104556
- "emptySpaces": "暂无去重记录",
104557
- "entries": "{{count}} / {{limit}} 条",
104576
+ "loading": "加载中…",
104577
+ "draft": "草稿",
104578
+ "live": "已发布",
104579
+ "isolation": "调试与正式运行分别保存。发布和回滚不会清空。",
104580
+ "rules": "存储说明",
104558
104581
  "records": "{{count}} 条记录",
104559
- "valueLimit": "每条 JSON 值最多 {{size}} 个 UTF-8 字节。",
104560
- "sharedLimit": "所有空间共享记录额度。空间:{{count}} / {{limit}} 个。待提交记录会预占额度。",
104561
104582
  "fieldPlaceholder": "整个条目(字符串或数字)",
104562
104583
  "addField": "添加字段",
104563
104584
  "removeField": "删除第 {{index}} 个字段",
104564
104585
  "fieldIndex": "第 {{index}} 个标识字段",
104565
104586
  "invalidFields": "请填写不重复的字段路径,例如 id 或 record.id。",
104566
- "pendingRecords": "{{count}} 条待提交",
104567
104587
  "pathPlaceholder": "id 或 record.id",
104568
104588
  "saveFailed": "无法保存标识字段。",
104569
- "retry": "重试"
104589
+ "retry": "重试",
104590
+ "limit": " / {{limit}}",
104591
+ "source": "来源",
104592
+ "count": "条数",
104593
+ "updated": "最近更新",
104594
+ "shared": "工作流共享",
104595
+ "globalUsage": "工作流去重记录总数",
104596
+ "valuesNearLimit": "保存的数据已使用至少 80% 的额度。请清理不再需要的数据。",
104597
+ "pendingClear": "{{count}} 条待提交,相关运行结束或取消后可清理。",
104598
+ "clearBlocked": "这些记录尚待提交。请等待相关运行结束或取消后再刷新。",
104599
+ "clearSource": "清空{{name}}",
104600
+ "sourceHistory": "{{name}}的历史记录",
104601
+ "confirmTitle": "清空「{{name}}」?",
104602
+ "confirmValues": "将清空{{scope}}环境保存的 {{count}} 条数据,后续运行将无法读取这些值。",
104603
+ "confirmHistory": "将清空{{scope}}环境的 {{count}} 条去重记录,这些条目之后可能再次被处理。",
104604
+ "confirmClear": "清空",
104605
+ "retainedHistory": "含 {{count}} 条待提交记录的来源将保留全部历史。",
104606
+ "emptyValues": "暂无数据",
104607
+ "emptySpaces": "暂无记录",
104608
+ "loadFailed": "加载失败",
104609
+ "valuesHelp": "{{name}}:工作流主动保存的内容,后续运行可以继续读取。",
104610
+ "historyHelp": "{{name}}:条目的识别标记,用来避免重复处理。"
104570
104611
  }
104571
104612
  },
104572
104613
  "zh-TW": {
@@ -104790,11 +104831,15 @@ var resources = {
104790
104831
  "deleteDescription": "工作流程及執行記錄將永久刪除,並停止線上觸發。",
104791
104832
  "importFlow": "匯入工作流",
104792
104833
  "exportFlow": "匯出工作流",
104793
- "exportSvg": "匯出 SVG 圖片",
104794
- "exportSvgPending": "正在匯出 SVG…",
104795
- "exportSvgPendingDescription": "正在處理工作流程和圖片資源,圖片較大時可能需要一些時間。",
104796
- "exportSvgComplete": "SVG 圖片已匯出。",
104797
- "exportSvgFailed": "SVG 圖片匯出失敗,請重試。",
104834
+ "exportPng": "匯出 PNG 圖片",
104835
+ "exportPngFrame": "顯示外框",
104836
+ "exportPngLight": "淺色",
104837
+ "exportPngDark": "深色",
104838
+ "exportPngPending": "正在匯出 PNG…",
104839
+ "exportPngPendingDescription": "正在處理工作流程和圖片資源,圖片較大時可能需要一些時間。",
104840
+ "exportPngComplete": "PNG 圖片已匯出。",
104841
+ "exportPngPartial": "PNG 圖片已匯出,部分圖片已用佔位圖替代。",
104842
+ "exportPngFailed": "PNG 圖片匯出失敗,請重試。",
104798
104843
  "importInvalid": "檔案損壞或工作流格式不受支援。"
104799
104844
  },
104800
104845
  inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"節點大綱\",\"backToOutline\":\"返回節點大綱\",\"emptyOutline\":\"暫無節點\",\"triggers\":\"觸發器\",\"nodes\":\"節點\",\"multipleSelected\":\"已選擇 {{count}} 個節點\",\"account\":{\"contactAdmin\":\"你沒有執行此操作的權限,請聯絡管理員。\",\"accessTitle\":\"存取權限\",\"manageFlowAccess\":\"Code 允許使用的連線\",\"configureAccess\":\"選擇可用帳號\",\"manageAccount\":\"管理帳號\",\"required\":\"待連線帳號\",\"addAccount\":\"新增帳號\",\"manage\":\"管理\",\"authorizationPending\":\"請在 Connection 頁面完成授權,再回到這裡重新整理這個帳號。\",\"chooseAccount\":\"選擇帳號\",\"deferred\":\"暫不設定\",\"clearDeferred\":\"清除選擇\",\"noAccounts\":\"暫無可用帳號\",\"connectBeforeRun\":\"請先連接 {{service}},這個節點才能執行或發布。\",\"connectService\":\"連接 {{service}}\",\"connection\":\"Connection\",\"loading\":\"正在載入 Connection…\",\"oomolBuiltIn\":\"OOMOL 內建帳號\",\"missing\":\"此節點選擇的帳號目前無法使用,請選擇其他帳號或管理帳號。\",\"refreshFailed\":\"無法重新整理 Connection。\",\"retry\":\"重試\",\"status\":{\"disconnected\":\"這個 Connection 已中斷。請重新連接或選擇其他帳號。\",\"error\":\"這個 Connection 發生錯誤。請修復它或選擇其他帳號。\",\"reauth_required\":\"這個 Connection 需要重新授權。請重新連接或選擇其他帳號。\"},\"statusUnavailable\":\"無法取得 {{action}} 的 Connection 狀態。\",\"teamDefault\":\"團隊預設\",\"title\":\"帳號\",\"unavailable\":\"無法使用\"},\"close\":\"關閉檢查器\",\"configurationRequired\":\"尚未完成設定\",\"diagnostics\":\"診斷\",\"errors\":{\"jsonObject\":\"{{label}} 必須是 JSON 物件。\",\"portDefinitions\":\"請輸入有效的埠定義。\"},\"node\":{\"nameDuplicate\":\"目前圖中已存在同名節點。\",\"nameEmpty\":\"節點名稱不能為空。\",\"timeout\":\"逾時時間(毫秒)\",\"maxExecutions\":\"節點執行上限\",\"maxExecutionsError\":\"節點執行上限必須是正整數。\",\"timeoutError\":\"逾時時間必須是以毫秒為單位的正整數。\",\"title\":\"節點設定\",\"description\":\"用途說明\",\"describe\":\"描述這個步驟要完成什麼。\",\"icon\":\"圖示\",\"name\":\"標題\",\"retry\":\"失敗重試\",\"retryCount\":\"最多重試 {{count}} 次\",\"retryInterval\":\"重試間隔\",\"retryError\":\"間隔須為 1~60 整數秒。\",\"retryHint\":\"重試次數是首次執行失敗後的追加次數。重試會重新執行整個節點,可能重複外部操作。逾時包含全部嘗試和等待間隔。\",\"retryNone\":\"不重試\",\"retrySeconds\":\"秒\",\"retryHelp\":\"重試說明\",\"retryOnce\":\"最多重試 1 次\",\"onError\":\"失敗處理\",\"onErrorStop\":\"終止工作流程\",\"onErrorOutput\":\"輸出至 error 連接埠\",\"onErrorHelp\":\"失敗處理說明\",\"onErrorHint\":\"重試後仍失敗時,將錯誤寫入系統 error 並沿現有連線繼續。成功時 error 為 null。取消、逾時、資源限制及結果不確定仍終止工作流程。\",\"systemOutputs\":\"系統輸出\",\"systemError\":\"錯誤資訊(系統)\",\"errorFields\":{\"error\":\"節點失敗時的錯誤資訊;成功時為 null。\",\"code\":\"用於識別錯誤類型的錯誤碼。\",\"message\":\"錯誤的說明資訊,敏感內容已遮蔽。\",\"nodeId\":\"發生錯誤的節點 ID。\",\"nodeName\":\"發生錯誤時的節點名稱。\",\"runId\":\"本次工作流程執行的 ID。\",\"executionId\":\"本次節點執行的 ID,多次重試共用此 ID。\"}},\"selectNode\":\"選取一個草稿節點即可檢視並編輯它。\",\"locateNode\":\"在畫布上定位此節點\",\"task\":{\"sharedPermissions\":\"使用 Flow 共用權限群組\",\"sharedPermissionsHint\":\"直接使用 Flow 共用權限群組已授權的所有 Actions,無需逐一新增。\",\"httpHosts\":\"HTTP 主機\",\"httpHostsHint\":\"每行一個主機,支援 *.example.com 子網域比對。\",\"httpHostsInvalid\":\"「{{host}}」不是有效的主機,請填寫 api.example.com 這類主機名稱。\",\"httpHostsLimit\":\"最多宣告 {{count}} 個主機。\",\"addAction\":\"新增 Action\",\"removeAction\":\"移除 Action\",\"actionAccount\":\"帳號\",\"chooseAccount\":\"選擇帳號\",\"permissionSaveFailed\":\"無法儲存 Code 權限,請重試。\",\"chatText\":\"對話文字\",\"connectorAction\":\"Connector 操作\",\"definition\":\"任務定義\",\"discardCode\":\"放棄變更\",\"editorLoading\":\"正在載入編輯器…\",\"editorUnavailable\":\"無法載入程式碼編輯器。\",\"inputPorts\":\"輸入埠\",\"javascriptModule\":\"程式碼\",\"missing\":\"引用的任務不存在。\",\"outputPorts\":\"輸出埠\",\"responseMode\":\"回應模式\",\"source\":\"原始碼\",\"structuredJson\":\"結構化 JSON\",\"retrySave\":\"重試儲存\",\"additionalInputs\":\"附加輸入\",\"httpHostsUpdated\":\"主機設定已在別處更新。已載入最新設定,請檢查後再儲存。\"},\"wait\":{\"approval\":\"通過或拒絕\",\"changeNotification\":\"更換\",\"continue\":\"繼續\",\"mode\":\"處理方式\",\"inputsLoading\":\"正在載入通知參數…\",\"pendingDescription\":\"待確認出口在開始等待時觸發一次,提供確認連結及相關資料。連接此出口可傳送訊息或執行其他步驟。\",\"prompt\":\"提示\",\"promptError\":\"提示必須包含 1 到 1,000 個字元。\",\"autoContinue\":\"自動繼續\",\"autoOff\":\"關閉\",\"autoAfter\":\"等待一段時間\",\"autoAt\":\"到指定時間\",\"autoSeconds\":\"等待時長(秒)\",\"autoDate\":\"日期和時間\",\"autoInvalid\":\"請輸入正數時長或有效的日期和時間。\",\"autoDescription\":\"可提前手動繼續。\"},\"title\":\"檢查器\",\"sources\":{\"loading\":\"正在載入輸入來源…\",\"loadFailed\":\"無法載入輸入來源,請重新開啟選單重試。\",\"checkFailed\":\"無法檢查此來源。\",\"select\":\"選擇輸入來源\",\"title\":\"輸入來源\",\"sourceMissing\":\"原輸入來源已不存在,請重新選擇。\",\"outputMissing\":\"「{{source}}」中找不到「{{output}}」,請重新選擇。\",\"wholeObject\":\"整個物件\",\"fieldMissing\":\"「{{output}}」中已不再宣告欄位 {{field}},請重新選擇。\",\"notReady\":\"執行到這裡時,「{{source}} {{handle}}」可能還沒有值。\",\"sourceConflict\":\"這些欄位可能同時有值:{{sources}}。這裡只能取一個。\",\"incompatibleRight\":\"右值類型不符合此比較的要求。\",\"incompatible\":\"不相容\",\"unverified\":\"無法驗證\",\"schemaIncompatible\":\"資料格式不符。\",\"schemaPathIncompatible\":\"「{{path}}」的資料格式不符。\",\"schemaCompareFailed\":\"無法檢查資料格式,請檢查 JSON Schema。\",\"binaryIncompatible\":\"不能使用二進位資料。\",\"artifactIncompatible\":\"不能使用檔案資料。\",\"nullableIncompatible\":\"不能為空,但所選欄位可能為空。\",\"typeIncompatible\":\"需要{{target}},但所選欄位是{{source}}。\",\"propertyTypeIncompatible\":\"「{{path}}」需要{{target}},實際是{{source}}。\",\"requiredIncompatible\":\"不一定包含必填屬性「{{property}}」。\",\"enumIncompatible\":\"可能出現不接受的值:{{values}}。\",\"constIncompatible\":\"只接受 {{target}},所選欄位固定為 {{source}}。\",\"constraintSubject\":\"「{{path}}」\",\"minLength\":\"{{subject}}至少需要 {{value}} 個字元。\",\"maxLength\":\"{{subject}}最多接受 {{value}} 個字元。\",\"pattern\":\"{{subject}}文字格式應符合 {{value}}。\",\"minimum\":\"{{subject}}不能小於 {{value}}。\",\"exclusiveMinimum\":\"{{subject}}必須大於 {{value}}。\",\"maximum\":\"{{subject}}不能大於 {{value}}。\",\"exclusiveMaximum\":\"{{subject}}必須小於 {{value}}。\",\"multipleOf\":\"{{subject}}必須是 {{value}} 的倍數。\",\"minItems\":\"{{subject}}至少需要 {{value}} 項。\",\"maxItems\":\"{{subject}}最多接受 {{value}} 項。\",\"minProperties\":\"{{subject}}至少需要 {{value}} 個屬性。\",\"maxProperties\":\"{{subject}}最多接受 {{value}} 個屬性。\",\"integer\":\"整數\",\"unknownType\":\"未知類型\",\"typeSeparator\":\"或\"},\"actions\":{\"flowAccess\":\"可用服務\",\"flowAccessHint\":\"管理此 Flow 中所有 Code 節點共用的連線\",\"chooseConnection\":\"選擇 {{provider}} Connection\",\"connectionDescription\":\"Connection 將寫入這次呼叫;是否允許使用仍由 Flow Provider Access 決定。\",\"title\":\"程式碼可呼叫的動作\",\"search\":\"搜尋應用程式或動作…\",\"description\":\"搜尋並新增這段程式碼需要呼叫的動作。\",\"empty\":\"沒有符合的 Action。\",\"remove\":\"移除\",\"default\":\"預設帳號\",\"defaultHint\":\"呼叫時未指定帳號,將使用此帳號。\",\"removeAction\":\"移除動作\",\"explicit\":\"在程式碼中明確選擇\",\"connect\":\"連接帳號\",\"refresh\":\"重新整理帳號\",\"aliases\":\"同步帳號別名\",\"add\":\"新增動作\",\"cancel\":\"取消\",\"loading\":\"搜尋中…\",\"needsAccount\":\"待連接帳號\",\"accounts\":\"{{count}} 個帳號\",\"public\":\"無需帳號\",\"allowed\":\"可用帳號\",\"unavailable\":\"無法使用\",\"details\":\"帳號詳情\",\"example\":\"呼叫範例\",\"syntax\":\"呼叫寫法\",\"nested\":\"分層寫法\",\"fullId\":\"完整 ID\",\"copy\":\"複製\",\"copied\":\"已複製\",\"copyError\":\"複製失敗,請選取範例程式碼手動複製。\",\"introDescription\":\"依需求新增動作,透過 {{context}} 呼叫外部應用程式。\",\"insertAction\":\"插入程式碼\",\"chooseAccounts\":\"管理帳號\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"預覽\"},\"ports\":{\"reorder\":\"調整 {{name}} 的順序\",\"reorderHint\":\"拖動調整組內順序,或聚焦後使用上、下方向鍵。\",\"moved\":\"{{name}} 已移至第 {{position}} 位。\",\"groupSettings\":\"群組設定\",\"connected\":\"已連接\",\"sort\":\"排序\",\"finishSorting\":\"完成排序\",\"inputsTitle\":\"輸入\",\"requiredInputs\":\"必填\",\"optionalInputs\":\"選填\",\"noInputs\":\"此節點不需要輸入資料\",\"noOutputs\":\"此節點不提供輸出資料\",\"outputsTitle\":\"輸出\",\"valuesTitle\":\"資料\",\"columnHandle\":\"Handle\",\"columnName\":\"名稱\",\"columnType\":\"類型\",\"columnValue\":\"值\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"本次執行的排程觸發時間,採用 ISO 8601 格式。\"},\"webhook\":{\"headers\":\"此 Webhook 請求攜帶的請求標頭。\",\"query\":\"此 Webhook 請求攜帶的 URL 查詢參數。\",\"body\":\"此 Webhook 請求攜帶的請求本文。\",\"webhookUrl\":\"接收此次請求的 Webhook URL,不含查詢參數。\"}},\"startParametersTitle\":\"啟動參數\"}}"),
@@ -105645,7 +105690,6 @@ var resources = {
105645
105690
  snapshot: {
105646
105691
  "title": "快照",
105647
105692
  "restore": "還原佈局",
105648
- "missingLayout": "此版本未儲存佈局,已自動排列",
105649
105693
  "loading": "正在載入版本…",
105650
105694
  "failed": "無法載入此版本,其內容可能已無法使用。",
105651
105695
  "root": "主流程"
@@ -105887,41 +105931,52 @@ var resources = {
105887
105931
  "nodeTitle": "跳過重複",
105888
105932
  "warning": "記錄在本次 Run 成功後儲存。失敗或取消後,下次仍可處理這些項目。",
105889
105933
  "field": "識別欄位",
105934
+ "fieldDescription": "依欄位值識別重複項目,多個欄位組合判斷。留空時比較項目本身。",
105890
105935
  "values": "儲存的資料",
105891
- "spaces": "去重記錄",
105892
- "clearAll": "清空",
105936
+ "spaces": "去重歷史",
105893
105937
  "delete": "刪除",
105894
105938
  "clear": "清空",
105895
- "orphaned": "目前檢視中的遺留空間",
105896
- "nearLimit": "此流程的去重記錄已使用至少 80%。請清理不再需要的記錄。",
105897
- "history": "歷史記錄",
105939
+ "orphaned": "目前檢視之外",
105940
+ "nearLimit": "此工作流的去重記錄已使用至少 80%。請清理不再需要的記錄。",
105941
+ "history": "用量",
105898
105942
  "scope": "範圍",
105899
- "showValue": "檢視值",
105900
- "hideValue": "收合值",
105901
105943
  "refresh": "重新整理",
105902
- "confirmLive": "這會立即清空正式環境狀態,後續 Live Run 可能再次處理這些項目。是否繼續?",
105903
105944
  "cancel": "取消",
105904
- "loading": "正在載入狀態…",
105905
- "draft": "偵錯資料",
105906
- "live": "正式執行資料",
105907
- "isolation": "偵錯與正式執行的資料相互獨立。",
105908
- "rules": "儲存規則",
105909
- "retention": "發布和回復版本不會清空資料。不再需要時請手動清理。請勿儲存憑證。",
105910
- "emptyValues": "尚無儲存的資料",
105911
- "emptySpaces": "尚無去重記錄",
105912
- "entries": "{{count}} / {{limit}} 筆",
105945
+ "loading": "載入中…",
105946
+ "draft": "草稿",
105947
+ "live": "已發佈",
105948
+ "isolation": "偵錯與正式執行分別儲存。發佈和回復版本不會清空資料。",
105949
+ "rules": "儲存說明",
105913
105950
  "records": "{{count}} 筆記錄",
105914
- "valueLimit": "每筆 JSON 值最多 {{size}} 個 UTF-8 位元組。",
105915
- "sharedLimit": "所有空間共用記錄額度。空間:{{count}} / {{limit}} 個。待提交記錄會預占額度。",
105916
105951
  "fieldPlaceholder": "整個項目(字串或數字)",
105917
105952
  "addField": "新增欄位",
105918
105953
  "removeField": "刪除第 {{index}} 個欄位",
105919
105954
  "fieldIndex": "第 {{index}} 個識別欄位",
105920
105955
  "invalidFields": "請填寫不重複的欄位路徑,例如 id 或 record.id。",
105921
- "pendingRecords": "{{count}} 筆待提交",
105922
105956
  "pathPlaceholder": "id 或 record.id",
105923
105957
  "saveFailed": "無法儲存識別欄位。",
105924
- "retry": "重試"
105958
+ "retry": "重試",
105959
+ "limit": " / {{limit}}",
105960
+ "source": "來源",
105961
+ "count": "筆數",
105962
+ "updated": "最近更新",
105963
+ "shared": "工作流共用",
105964
+ "globalUsage": "工作流去重記錄總數",
105965
+ "valuesNearLimit": "儲存資料已使用至少 80% 的額度。請清理不再需要的資料。",
105966
+ "pendingClear": "{{count}} 筆待提交,相關執行結束或取消後可清理。",
105967
+ "clearBlocked": "這些記錄尚待提交。請等待相關執行結束或取消後再重新整理。",
105968
+ "clearSource": "清空{{name}}",
105969
+ "sourceHistory": "{{name}}的歷史記錄",
105970
+ "confirmTitle": "清空「{{name}}」?",
105971
+ "confirmValues": "將清空{{scope}}環境儲存的 {{count}} 筆資料,後續執行將無法讀取這些值。",
105972
+ "confirmHistory": "將清空{{scope}}環境的 {{count}} 筆去重記錄,這些項目之後可能再次被處理。",
105973
+ "confirmClear": "清空",
105974
+ "retainedHistory": "含 {{count}} 筆待提交記錄的來源將保留全部歷史。",
105975
+ "emptyValues": "尚無資料",
105976
+ "emptySpaces": "尚無記錄",
105977
+ "loadFailed": "載入失敗",
105978
+ "valuesHelp": "{{name}}:工作流主動儲存的內容,後續執行可以繼續讀取。",
105979
+ "historyHelp": "{{name}}:項目的識別標記,用來避免重複處理。"
105925
105980
  }
105926
105981
  },
105927
105982
  "ja": {
@@ -106145,11 +106200,15 @@ var resources = {
106145
106200
  "deleteDescription": "ワークフローと実行履歴を完全に削除し、公開中のトリガーを停止します。",
106146
106201
  "importFlow": "ワークフローをインポート",
106147
106202
  "exportFlow": "ワークフローをエクスポート",
106148
- "exportSvg": "SVG 画像をエクスポート",
106149
- "exportSvgPending": "SVG をエクスポート中…",
106150
- "exportSvgPendingDescription": "ワークフローと画像を準備しています。画像が大きい場合は時間がかかることがあります。",
106151
- "exportSvgComplete": "SVG 画像をエクスポートしました。",
106152
- "exportSvgFailed": "SVG 画像をエクスポートできませんでした。もう一度お試しください。",
106203
+ "exportPng": "PNG 画像をエクスポート",
106204
+ "exportPngFrame": "フレームを表示",
106205
+ "exportPngLight": "ライト",
106206
+ "exportPngDark": "ダーク",
106207
+ "exportPngPending": "PNG をエクスポート中…",
106208
+ "exportPngPendingDescription": "ワークフローと画像を準備しています。画像が大きい場合は時間がかかることがあります。",
106209
+ "exportPngComplete": "PNG 画像をエクスポートしました。",
106210
+ "exportPngPartial": "PNG 画像をエクスポートしました。一部の画像はプレースホルダーに置き換えられました。",
106211
+ "exportPngFailed": "PNG 画像をエクスポートできませんでした。もう一度お試しください。",
106153
106212
  "importInvalid": "無効または未対応のワークフローファイルです。"
106154
106213
  },
106155
106214
  inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"ノード一覧\",\"backToOutline\":\"ノード一覧に戻る\",\"emptyOutline\":\"ノードはまだありません\",\"triggers\":\"トリガー\",\"nodes\":\"ノード\",\"multipleSelected\":\"{{count}} 個のノードを選択中\",\"account\":{\"contactAdmin\":\"この操作を実行する権限がありません。管理者にお問い合わせください。\",\"accessTitle\":\"アクセス権限\",\"manageFlowAccess\":\"Code で使用できる接続\",\"configureAccess\":\"アカウントを選択\",\"manageAccount\":\"アカウントを管理\",\"required\":\"アカウント接続が必要\",\"addAccount\":\"アカウントを追加\",\"manage\":\"管理\",\"authorizationPending\":\"Connection ページで認証を完了してください。ここに戻ると、このアカウントが更新されます。\",\"chooseAccount\":\"アカウントを選択\",\"deferred\":\"今は設定しない\",\"clearDeferred\":\"選択をクリア\",\"noAccounts\":\"利用可能なアカウントがありません\",\"connectBeforeRun\":\"このノードを実行または公開するには、先に {{service}} を接続してください。\",\"connectService\":\"{{service}} を接続\",\"connection\":\"Connection\",\"loading\":\"Connection を読み込み中…\",\"oomolBuiltIn\":\"OOMOL 組み込みアカウント\",\"missing\":\"このノードで選択されたアカウントは現在利用できません。別のアカウントを選択するか、アカウントを管理してください。\",\"refreshFailed\":\"Connection を更新できませんでした。\",\"retry\":\"再試行\",\"status\":{\"disconnected\":\"この Connection は切断されています。再接続するか、別のアカウントを選択してください。\",\"error\":\"この Connection にエラーがあります。修復するか、別のアカウントを選択してください。\",\"reauth_required\":\"この Connection は再認証が必要です。再接続するか、別のアカウントを選択してください。\"},\"statusUnavailable\":\"{{action}} の Connection 状態を取得できません。\",\"teamDefault\":\"チームのデフォルト\",\"title\":\"アカウント\",\"unavailable\":\"利用不可\"},\"close\":\"インスペクターを閉じる\",\"configurationRequired\":\"設定が必要\",\"diagnostics\":\"診断\",\"errors\":{\"jsonObject\":\"{{label}} は JSON オブジェクトである必要があります。\",\"portDefinitions\":\"有効なポート定義を入力してください。\"},\"node\":{\"nameDuplicate\":\"このグラフには同じ名前のノードが既に存在します。\",\"nameEmpty\":\"ノード名を空にすることはできません。\",\"timeout\":\"タイムアウト(ミリ秒)\",\"maxExecutions\":\"ノード実行上限\",\"maxExecutionsError\":\"ノード実行上限は正の整数で指定してください。\",\"timeoutError\":\"タイムアウトはミリ秒単位の正の整数で指定してください。\",\"title\":\"ノード設定\",\"description\":\"目的\",\"describe\":\"このステップの目的を記述します。\",\"icon\":\"アイコン\",\"name\":\"タイトル\",\"retry\":\"失敗時の再試行\",\"retryCount\":\"最大 {{count}} 回再試行\",\"retryInterval\":\"再試行の間隔\",\"retryError\":\"間隔は 1~60 の整数秒で指定してください。\",\"retryHint\":\"再試行回数は、初回の実行に失敗した後に追加する試行の回数です。再試行はノード全体を再実行するため、外部操作が重複する場合があります。タイムアウトには全試行と待機時間を含みます。\",\"retryNone\":\"再試行しない\",\"retrySeconds\":\"秒\",\"retryHelp\":\"再試行について\",\"retryOnce\":\"最大 1 回再試行\",\"onError\":\"失敗時の処理\",\"onErrorStop\":\"ワークフローを停止\",\"onErrorOutput\":\"error ポートに出力\",\"onErrorHelp\":\"失敗時の処理について\",\"onErrorHint\":\"再試行後も失敗した場合、システム error にエラーを出力して既存の接続で続行します。成功時は null です。キャンセル、タイムアウト、リソース制限、結果不明の場合は停止します。\",\"systemOutputs\":\"システム出力\",\"systemError\":\"エラー情報(システム)\",\"errorFields\":{\"error\":\"ノードが失敗した場合のエラー情報。成功時は null です。\",\"code\":\"エラーの種類を識別するコード。\",\"message\":\"機密情報をマスクしたエラーの説明。\",\"nodeId\":\"エラーが発生したノードの ID。\",\"nodeName\":\"エラー発生時のノード名。\",\"runId\":\"今回のワークフロー実行の ID。\",\"executionId\":\"今回のノード実行の ID。再試行でも同じ ID を使用します。\"}},\"selectNode\":\"ドラフトのノードを 1 つ選択すると、内容を確認して編集できます。\",\"locateNode\":\"キャンバス上でこのノードを表示\",\"task\":{\"sharedPermissions\":\"Flow の共有権限グループを使用\",\"sharedPermissionsHint\":\"Flow の共有権限グループで許可されたすべての Action を使用します。個別の追加は不要です。\",\"httpHosts\":\"HTTP ホスト\",\"httpHostsHint\":\"1 行に 1 ホスト。*.example.com はサブドメインに一致します。\",\"httpHostsInvalid\":\"「{{host}}」は有効なホストではありません。api.example.com のようなホスト名を入力してください。\",\"httpHostsLimit\":\"宣言できるホストは最大 {{count}} 個です。\",\"addAction\":\"Action を追加\",\"removeAction\":\"Action を削除\",\"actionAccount\":\"アカウント\",\"chooseAccount\":\"アカウントを選択\",\"permissionSaveFailed\":\"Code の権限を保存できませんでした。再試行してください。\",\"chatText\":\"チャットテキスト\",\"connectorAction\":\"Connector アクション\",\"definition\":\"タスク定義\",\"discardCode\":\"変更を破棄\",\"editorLoading\":\"エディターを読み込み中…\",\"editorUnavailable\":\"コードエディターを読み込めませんでした。\",\"inputPorts\":\"入力ポート\",\"javascriptModule\":\"コード\",\"missing\":\"参照しているタスクが存在しません。\",\"outputPorts\":\"出力ポート\",\"responseMode\":\"応答モード\",\"source\":\"ソースコード\",\"structuredJson\":\"構造化 JSON\",\"retrySave\":\"保存を再試行\",\"additionalInputs\":\"追加入力\",\"httpHostsUpdated\":\"ホスト設定が別の場所で更新されました。最新の設定を読み込みました。確認してから保存してください。\"},\"wait\":{\"approval\":\"承認または拒否\",\"changeNotification\":\"変更\",\"continue\":\"続行\",\"mode\":\"処理方法\",\"inputsLoading\":\"通知パラメーターを読み込んでいます…\",\"pendingDescription\":\"確認待ち出力は待機開始時に一度だけ発火し、確認リンクと関連データを提供します。接続先でメッセージの送信や他のステップを実行できます。\",\"prompt\":\"プロンプト\",\"promptError\":\"プロンプトは1〜1,000文字で入力してください。\",\"autoContinue\":\"自動続行\",\"autoOff\":\"オフ\",\"autoAfter\":\"一定時間後\",\"autoAt\":\"指定日時\",\"autoSeconds\":\"待機時間(秒)\",\"autoDate\":\"日時\",\"autoInvalid\":\"正の待機時間または有効な日時を入力してください。\",\"autoDescription\":\"予定時刻前に手動で続行できます。\"},\"title\":\"インスペクター\",\"sources\":{\"loading\":\"入力元を読み込み中…\",\"loadFailed\":\"入力元を読み込めません。メニューを開き直してください。\",\"checkFailed\":\"このソースを確認できませんでした。\",\"select\":\"入力元を選択\",\"title\":\"入力元\",\"sourceMissing\":\"元の入力元は存在しません。選択し直してください。\",\"outputMissing\":\"「{{source}}」に「{{output}}」が見つかりません。選択し直してください。\",\"wholeObject\":\"オブジェクト全体\",\"fieldMissing\":\"「{{output}}」にフィールド {{field}} が宣言されていません。選択し直してください。\",\"notReady\":\"ここを実行するとき、「{{source}} {{handle}}」にまだ値がない可能性があります。\",\"sourceConflict\":\"同時に値を持つ可能性があります:{{sources}}。ここでは 1 つだけ使用できます。\",\"incompatibleRight\":\"右辺の値の型はこの比較に対応していません。\",\"incompatible\":\"非互換\",\"unverified\":\"未検証\",\"schemaIncompatible\":\"データ形式が一致しません。\",\"schemaPathIncompatible\":\"「{{path}}」のデータ形式が一致しません。\",\"schemaCompareFailed\":\"データ形式を確認できません。JSON Schema を確認してください。\",\"binaryIncompatible\":\"バイナリデータは使用できません。\",\"artifactIncompatible\":\"ファイルデータは使用できません。\",\"nullableIncompatible\":\"値が必要ですが、選択したフィールドは空になる可能性があります。\",\"typeIncompatible\":\"{{target}}が必要ですが、選択したフィールドは{{source}}です。\",\"propertyTypeIncompatible\":\"「{{path}}」は{{target}}である必要がありますが、実際は{{source}}です。\",\"requiredIncompatible\":\"必須プロパティ「{{property}}」がない可能性があります。\",\"enumIncompatible\":\"使用できない値が含まれる可能性があります:{{values}}。\",\"constIncompatible\":\"{{target}}のみ使用できますが、選択したフィールドは常に {{source}} です。\",\"constraintSubject\":\"「{{path}}」は\",\"minLength\":\"{{subject}}少なくとも {{value}} 文字必要です。\",\"maxLength\":\"{{subject}}最大 {{value}} 文字です。\",\"pattern\":\"{{subject}}{{value}} に一致する必要があります。\",\"minimum\":\"{{subject}}{{value}} 未満にできません。\",\"exclusiveMinimum\":\"{{subject}}{{value}} より大きい必要があります。\",\"maximum\":\"{{subject}}{{value}} を超えられません。\",\"exclusiveMaximum\":\"{{subject}}{{value}} より小さい必要があります。\",\"multipleOf\":\"{{subject}}{{value}} の倍数である必要があります。\",\"minItems\":\"{{subject}}少なくとも {{value}} 項必要です。\",\"maxItems\":\"{{subject}}最大 {{value}} 項です。\",\"minProperties\":\"{{subject}}少なくとも {{value}} 個のプロパティが必要です。\",\"maxProperties\":\"{{subject}}最大 {{value}} 個のプロパティです。\",\"integer\":\"整数\",\"unknownType\":\"不明な型\",\"typeSeparator\":\"または\"},\"actions\":{\"flowAccess\":\"利用可能なサービス\",\"flowAccessHint\":\"この Flow のすべての Code ノードで共有する接続を管理\",\"chooseConnection\":\"{{provider}} Connection を選択\",\"connectionDescription\":\"Connection はこの呼び出しに挿入されます。使用可否は引き続き Flow Provider Access によって制御されます。\",\"title\":\"このコードから呼び出せるアクション\",\"search\":\"Action を検索\",\"description\":\"このコードで使用する Action とアカウントを選択します。\",\"empty\":\"一致する Action はありません。\",\"remove\":\"削除\",\"default\":\"既定のアカウント\",\"defaultHint\":\"呼び出し時にアカウントを指定しない場合に使用します。\",\"removeAction\":\"アクションを削除\",\"explicit\":\"コード内で明示的に選択\",\"connect\":\"アカウントを接続\",\"refresh\":\"アカウントを更新\",\"aliases\":\"保存済みの別名を更新\",\"add\":\"アクションを追加\",\"cancel\":\"キャンセル\",\"loading\":\"検索中…\",\"needsAccount\":\"アカウントを接続\",\"accounts\":\"{{count}} アカウント\",\"public\":\"アカウント不要\",\"allowed\":\"使用するアカウント\",\"unavailable\":\"利用不可\",\"details\":\"接続の詳細\",\"example\":\"呼び出し例\",\"syntax\":\"呼び出し形式\",\"nested\":\"プロバイダー形式\",\"fullId\":\"完全な ID\",\"copy\":\"コピー\",\"copied\":\"コピー済み\",\"copyError\":\"コピーできませんでした。コードを選択して手動でコピーしてください。\",\"introDescription\":\"必要に応じてアクションを追加し、{{context}} から外部アプリを呼び出せます。\",\"insertAction\":\"コードを挿入\",\"chooseAccounts\":\"アカウントを管理\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"プレビュー\"},\"ports\":{\"reorder\":\"{{name}} の順序を変更\",\"reorderHint\":\"ドラッグでグループ内の順序を変更。フォーカス時は上下キーでも移動できます。\",\"moved\":\"{{name}} を {{position}} 番目に移動しました。\",\"groupSettings\":\"グループ設定\",\"connected\":\"接続済み\",\"sort\":\"並べ替え\",\"finishSorting\":\"並べ替えを完了\",\"inputsTitle\":\"入力\",\"requiredInputs\":\"必須\",\"optionalInputs\":\"任意\",\"noInputs\":\"このノードには入力データが必要ありません。\",\"noOutputs\":\"このノードは出力データを提供しません。\",\"outputsTitle\":\"出力\",\"valuesTitle\":\"値\",\"columnHandle\":\"Handle\",\"columnName\":\"名前\",\"columnType\":\"型\",\"columnValue\":\"値\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"この実行をトリガーした予定時刻(ISO 8601 形式)です。\"},\"webhook\":{\"headers\":\"この Webhook リクエストで受信したリクエストヘッダーです。\",\"query\":\"この Webhook リクエストで受信した URL クエリパラメーターです。\",\"body\":\"この Webhook リクエストで受信したリクエストボディです。\",\"webhookUrl\":\"このリクエストを受信した Webhook URL(クエリパラメーターを除く)です。\"}},\"startParametersTitle\":\"開始パラメーター\"}}"),
@@ -107000,7 +107059,6 @@ var resources = {
107000
107059
  snapshot: {
107001
107060
  "title": "スナップショット",
107002
107061
  "restore": "配置を復元",
107003
- "missingLayout": "保存された配置がないため、自動で配置しました。",
107004
107062
  "loading": "バージョンを読み込み中…",
107005
107063
  "failed": "このバージョンを読み込めません。内容が利用できなくなった可能性があります。",
107006
107064
  "root": "メインフロー"
@@ -107242,41 +107300,52 @@ var resources = {
107242
107300
  "nodeTitle": "重複をスキップ",
107243
107301
  "warning": "履歴は Run の成功後に保存されます。失敗またはキャンセル時は、次回もこれらの項目を処理できます。",
107244
107302
  "field": "識別フィールド",
107303
+ "fieldDescription": "フィールドの値で重複を判定します。複数のフィールドは組み合わせて判定し、未指定の場合は項目自体を比較します。",
107245
107304
  "values": "保存データ",
107246
- "spaces": "重複除去の記録",
107247
- "clearAll": "すべて消去",
107305
+ "spaces": "重複排除の履歴",
107248
107306
  "delete": "削除",
107249
107307
  "clear": "消去",
107250
- "orphaned": "現在のビューに対応ノードなし",
107308
+ "orphaned": "現在のビューの外",
107251
107309
  "nearLimit": "フローの重複履歴が 80% 以上使用されています。不要な履歴を削除してください。",
107252
- "history": "履歴",
107310
+ "history": "使用量",
107253
107311
  "scope": "スコープ",
107254
- "showValue": "値を表示",
107255
- "hideValue": "値を隠す",
107256
107312
  "refresh": "更新",
107257
- "confirmLive": "本番環境の状態が直ちに消去されます。以降の Live Run で同じ項目が再処理される場合があります。続行しますか?",
107258
107313
  "cancel": "キャンセル",
107259
- "loading": "状態を読み込み中…",
107260
- "draft": "デバッグデータ",
107261
- "live": "本番データ",
107262
- "isolation": "デバッグと本番のデータは独立しています。",
107263
- "rules": "保存ルール",
107264
- "retention": "公開やロールバックでは削除されません。不要なデータは手動で削除してください。認証情報は保存しないでください。",
107265
- "emptyValues": "保存データはありません",
107266
- "emptySpaces": "重複除去の記録はありません",
107267
- "entries": "{{count}} / {{limit}} 件",
107314
+ "loading": "読み込み中…",
107315
+ "draft": "下書き",
107316
+ "live": "公開済み",
107317
+ "isolation": "デバッグと本番のデータは別々に保存されます。公開やロールバックでは消去されません。",
107318
+ "rules": "保存について",
107268
107319
  "records": "{{count}} 件",
107269
- "valueLimit": "JSON 値ごとに最大 {{size}} UTF-8 バイトです。",
107270
- "sharedLimit": "すべての領域で上限を共有します。領域:{{count}} / {{limit}}。確定待ちの記録も容量を予約します。",
107271
107320
  "fieldPlaceholder": "項目全体(文字列または数値)",
107272
107321
  "addField": "フィールドを追加",
107273
107322
  "removeField": "フィールド {{index}} を削除",
107274
107323
  "fieldIndex": "識別フィールド {{index}}",
107275
107324
  "invalidFields": "id や record.id のような空でない異なるパスを指定してください。",
107276
- "pendingRecords": "{{count}} 件が確定待ち",
107277
107325
  "pathPlaceholder": "id または record.id",
107278
107326
  "saveFailed": "識別フィールドを保存できませんでした。",
107279
- "retry": "再試行"
107327
+ "retry": "再試行",
107328
+ "limit": " / {{limit}}",
107329
+ "source": "保存元",
107330
+ "count": "件数",
107331
+ "updated": "最終更新",
107332
+ "shared": "フロー共有",
107333
+ "globalUsage": "フロー全体の重複排除記録数",
107334
+ "valuesNearLimit": "保存データが上限の 80% 以上です。不要なデータを消去してください。",
107335
+ "pendingClear": "{{count}} 件が確定待ちです。関連する実行の完了またはキャンセル後に消去できます。",
107336
+ "clearBlocked": "確定待ちの記録があります。関連する実行の完了またはキャンセル後に更新してください。",
107337
+ "clearSource": "{{name}}を消去",
107338
+ "sourceHistory": "{{name}}の履歴",
107339
+ "confirmTitle": "「{{name}}」を消去しますか?",
107340
+ "confirmValues": "{{scope}}環境の保存データ {{count}} 件を消去します。以降の実行ではこれらの値を読み取れなくなります。",
107341
+ "confirmHistory": "{{scope}}環境の重複排除記録 {{count}} 件を消去します。これらの項目が再処理される場合があります。",
107342
+ "confirmClear": "消去",
107343
+ "retainedHistory": "未確定の記録があるソースの履歴はすべて保持されます(未確定 {{count}} 件)。",
107344
+ "emptyValues": "データはありません",
107345
+ "emptySpaces": "履歴はありません",
107346
+ "loadFailed": "読み込みに失敗しました",
107347
+ "valuesHelp": "{{name}}:フローが明示的に保存し、後続の実行で読み取れる内容です。",
107348
+ "historyHelp": "{{name}}:同じ項目を繰り返し処理しないための識別情報です。"
107280
107349
  }
107281
107350
  },
107282
107351
  "ko": {
@@ -107500,11 +107569,15 @@ var resources = {
107500
107569
  "deleteDescription": "워크플로와 실행 기록을 영구 삭제하고 게시된 트리거를 중지합니다.",
107501
107570
  "importFlow": "워크플로 가져오기",
107502
107571
  "exportFlow": "워크플로 내보내기",
107503
- "exportSvg": "SVG 이미지 내보내기",
107504
- "exportSvgPending": "SVG 내보내는 중…",
107505
- "exportSvgPendingDescription": "워크플로와 이미지를 준비하고 있습니다. 이미지가 크면 시간이 더 걸릴 수 있습니다.",
107506
- "exportSvgComplete": "SVG 이미지를 내보냈습니다.",
107507
- "exportSvgFailed": "SVG 이미지를 내보내지 못했습니다. 다시 시도해 주세요.",
107572
+ "exportPng": "PNG 이미지 내보내기",
107573
+ "exportPngFrame": "프레임 표시",
107574
+ "exportPngLight": "라이트",
107575
+ "exportPngDark": "다크",
107576
+ "exportPngPending": "PNG 내보내는 중…",
107577
+ "exportPngPendingDescription": "워크플로와 이미지를 준비하고 있습니다. 이미지가 크면 시간이 더 걸릴 수 있습니다.",
107578
+ "exportPngComplete": "PNG 이미지를 내보냈습니다.",
107579
+ "exportPngPartial": "PNG 이미지를 내보냈습니다. 일부 이미지는 자리 표시자로 대체되었습니다.",
107580
+ "exportPngFailed": "PNG 이미지를 내보내지 못했습니다. 다시 시도해 주세요.",
107508
107581
  "importInvalid": "잘못되었거나 지원하지 않는 워크플로 파일입니다."
107509
107582
  },
107510
107583
  inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"노드 목록\",\"backToOutline\":\"노드 목록으로 돌아가기\",\"emptyOutline\":\"아직 노드가 없습니다\",\"triggers\":\"트리거\",\"nodes\":\"노드\",\"multipleSelected\":\"노드 {{count}}개 선택됨\",\"account\":{\"contactAdmin\":\"이 작업을 실행할 권한이 없습니다. 관리자에게 문의하세요.\",\"accessTitle\":\"접근 권한\",\"manageFlowAccess\":\"Code에서 사용할 수 있는 연결\",\"configureAccess\":\"계정 선택\",\"manageAccount\":\"계정 관리\",\"required\":\"계정 연결 필요\",\"addAccount\":\"계정 추가\",\"manage\":\"관리\",\"authorizationPending\":\"Connection 페이지에서 인증을 마친 뒤 여기로 돌아와 이 계정을 새로 고치세요.\",\"chooseAccount\":\"계정 선택\",\"deferred\":\"지금은 설정하지 않음\",\"clearDeferred\":\"선택 지우기\",\"noAccounts\":\"사용 가능한 계정이 없습니다\",\"connectBeforeRun\":\"이 블록을 실행하거나 게시하려면 먼저 {{service}}에 연결하세요.\",\"connectService\":\"{{service}} 연결\",\"connection\":\"Connection\",\"loading\":\"Connection 불러오는 중…\",\"oomolBuiltIn\":\"OOMOL 기본 제공 계정\",\"missing\":\"이 노드에서 선택한 계정을 현재 사용할 수 없습니다. 다른 계정을 선택하거나 계정을 관리하세요.\",\"refreshFailed\":\"Connection을 새로 고치지 못했습니다.\",\"retry\":\"다시 시도\",\"status\":{\"disconnected\":\"이 Connection은 연결이 끊어졌습니다. 다시 연결하거나 다른 계정을 선택하세요.\",\"error\":\"이 Connection에 오류가 있습니다. 문제를 해결하거나 다른 계정을 선택하세요.\",\"reauth_required\":\"이 Connection은 다시 인증해야 합니다. 다시 연결하거나 다른 계정을 선택하세요.\"},\"statusUnavailable\":\"{{action}}의 Connection 상태를 확인할 수 없습니다.\",\"teamDefault\":\"팀 기본값\",\"title\":\"계정\",\"unavailable\":\"사용할 수 없음\"},\"close\":\"인스펙터 닫기\",\"configurationRequired\":\"설정 필요\",\"diagnostics\":\"진단\",\"errors\":{\"jsonObject\":\"{{label}} 값은 JSON 객체여야 합니다.\",\"portDefinitions\":\"올바른 포트 정의를 입력하세요.\"},\"node\":{\"nameDuplicate\":\"이 그래프에 같은 이름의 노드가 이미 있습니다.\",\"nameEmpty\":\"노드 이름은 비워 둘 수 없습니다.\",\"timeout\":\"제한 시간(ms)\",\"maxExecutions\":\"노드 실행 한도\",\"maxExecutionsError\":\"노드 실행 한도는 양의 정수여야 합니다.\",\"timeoutError\":\"제한 시간은 밀리초 단위의 양의 정수여야 합니다.\",\"title\":\"노드 설정\",\"description\":\"목적\",\"describe\":\"이 단계의 목적을 설명하세요.\",\"icon\":\"아이콘\",\"name\":\"제목\",\"retry\":\"실패 시 재시도\",\"retryCount\":\"최대 {{count}}회 재시도\",\"retryInterval\":\"재시도 간격\",\"retryError\":\"간격은 1~60초의 정수로 입력하세요.\",\"retryHint\":\"재시도 횟수는 최초 실행 실패 후 추가로 시도하는 횟수입니다. 노드 전체를 다시 실행하므로 외부 작업이 중복될 수 있습니다. 제한 시간에는 모든 시도와 대기 시간이 포함됩니다.\",\"retryNone\":\"재시도 안 함\",\"retrySeconds\":\"초\",\"retryHelp\":\"재시도 안내\",\"retryOnce\":\"최대 1회 재시도\",\"onError\":\"실패 처리\",\"onErrorStop\":\"워크플로 중지\",\"onErrorOutput\":\"error 포트로 출력\",\"onErrorHelp\":\"실패 처리 안내\",\"onErrorHint\":\"재시도 후에도 실패하면 시스템 error에 오류를 기록하고 기존 연결을 따라 계속합니다. 성공 시 null입니다. 취소, 시간 초과, 리소스 제한 및 결과 불명 상태는 실행을 중지합니다.\",\"systemOutputs\":\"시스템 출력\",\"systemError\":\"오류 정보(시스템)\",\"errorFields\":{\"error\":\"노드 실패 시 오류 정보입니다. 성공 시 null입니다.\",\"code\":\"오류 유형을 식별하는 코드입니다.\",\"message\":\"민감한 내용이 가려진 오류 설명입니다.\",\"nodeId\":\"오류가 발생한 노드의 ID입니다.\",\"nodeName\":\"오류 발생 시점의 노드 이름입니다.\",\"runId\":\"이번 워크플로 실행의 ID입니다.\",\"executionId\":\"이번 노드 실행의 ID입니다. 재시도에서도 같은 ID를 사용합니다.\"}},\"selectNode\":\"확인하고 편집할 초안 노드를 하나 선택하세요.\",\"locateNode\":\"캔버스에서 이 노드 위치 보기\",\"task\":{\"sharedPermissions\":\"Flow 공유 권한 그룹 사용\",\"sharedPermissionsHint\":\"Flow 공유 권한 그룹에서 승인한 모든 Action을 사용합니다. 개별적으로 추가할 필요가 없습니다.\",\"httpHosts\":\"HTTP 호스트\",\"httpHostsHint\":\"한 줄에 호스트 하나. *.example.com은 하위 도메인과 일치합니다.\",\"httpHostsInvalid\":\"\\\"{{host}}\\\"은(는) 올바른 호스트가 아닙니다. api.example.com 같은 호스트 이름을 입력하세요.\",\"httpHostsLimit\":\"호스트는 최대 {{count}}개까지 선언할 수 있습니다.\",\"addAction\":\"Action 추가\",\"removeAction\":\"Action 제거\",\"actionAccount\":\"계정\",\"chooseAccount\":\"계정 선택\",\"permissionSaveFailed\":\"Code 권한을 저장하지 못했습니다. 다시 시도하세요.\",\"chatText\":\"대화 텍스트\",\"connectorAction\":\"Connector 액션\",\"definition\":\"태스크 정의\",\"discardCode\":\"변경 사항 버리기\",\"editorLoading\":\"편집기 불러오는 중…\",\"editorUnavailable\":\"코드 편집기를 불러오지 못했습니다.\",\"inputPorts\":\"입력 포트\",\"javascriptModule\":\"코드\",\"missing\":\"참조된 태스크가 존재하지 않습니다.\",\"outputPorts\":\"출력 포트\",\"responseMode\":\"응답 모드\",\"source\":\"소스\",\"structuredJson\":\"구조화된 JSON\",\"retrySave\":\"저장 재시도\",\"additionalInputs\":\"추가 입력\",\"httpHostsUpdated\":\"다른 곳에서 호스트 설정이 변경되었습니다. 최신 설정을 불러왔습니다. 확인 후 저장하세요.\"},\"wait\":{\"approval\":\"승인 또는 거부\",\"changeNotification\":\"변경\",\"continue\":\"계속\",\"mode\":\"처리 방식\",\"inputsLoading\":\"알림 매개변수를 불러오는 중…\",\"pendingDescription\":\"확인 대기 출력은 대기가 시작될 때 한 번 실행되어 확인 링크와 관련 데이터를 제공합니다. 연결하여 메시지를 보내거나 다른 단계를 실행할 수 있습니다.\",\"prompt\":\"프롬프트\",\"promptError\":\"프롬프트는 1~1,000자여야 합니다.\",\"autoContinue\":\"자동 계속\",\"autoOff\":\"끄기\",\"autoAfter\":\"일정 시간 후\",\"autoAt\":\"지정 시간에\",\"autoSeconds\":\"대기 시간(초)\",\"autoDate\":\"날짜 및 시간\",\"autoInvalid\":\"양수 대기 시간 또는 유효한 날짜와 시간을 입력하세요.\",\"autoDescription\":\"예정 시간 전에 수동으로 계속할 수 있습니다.\"},\"title\":\"인스펙터\",\"sources\":{\"loading\":\"입력 소스 불러오는 중…\",\"loadFailed\":\"입력 소스를 불러올 수 없습니다. 메뉴를 다시 열어 주세요.\",\"checkFailed\":\"이 소스를 확인할 수 없습니다.\",\"select\":\"입력 소스 선택\",\"title\":\"입력 소스\",\"sourceMissing\":\"기존 입력 소스가 더 이상 존재하지 않습니다. 다시 선택하세요.\",\"outputMissing\":\"“{{source}}”에서 “{{output}}”을(를) 찾을 수 없습니다. 다시 선택하세요.\",\"wholeObject\":\"전체 객체\",\"fieldMissing\":\"“{{output}}”에 {{field}} 필드가 선언되어 있지 않습니다. 다시 선택하세요.\",\"notReady\":\"여기까지 실행될 때 “{{source}} {{handle}}”에 아직 값이 없을 수 있습니다.\",\"sourceConflict\":\"다음 필드에 값이 동시에 있을 수 있습니다: {{sources}}. 여기서는 하나만 사용할 수 있습니다.\",\"incompatibleRight\":\"오른쪽 값의 형식이 이 비교와 호환되지 않습니다.\",\"incompatible\":\"호환되지 않음\",\"unverified\":\"확인되지 않음\",\"schemaIncompatible\":\"데이터 형식이 일치하지 않습니다.\",\"schemaPathIncompatible\":\"“{{path}}”의 데이터 형식이 일치하지 않습니다.\",\"schemaCompareFailed\":\"데이터 형식을 확인할 수 없습니다. JSON Schema를 확인하세요.\",\"binaryIncompatible\":\"바이너리 데이터는 사용할 수 없습니다.\",\"artifactIncompatible\":\"파일 데이터는 사용할 수 없습니다.\",\"nullableIncompatible\":\"값이 필요하지만 선택한 필드는 비어 있을 수 있습니다.\",\"typeIncompatible\":\"{{target}}이(가) 필요하지만 선택한 필드는 {{source}}입니다.\",\"propertyTypeIncompatible\":\"“{{path}}”은(는) {{target}}이어야 하지만 실제로는 {{source}}입니다.\",\"requiredIncompatible\":\"필수 속성 “{{property}}”이(가) 없을 수 있습니다.\",\"enumIncompatible\":\"허용되지 않는 값이 포함될 수 있습니다: {{values}}.\",\"constIncompatible\":\"{{target}}만 허용되지만 선택한 필드는 항상 {{source}}입니다.\",\"constraintSubject\":\"“{{path}}”은(는) \",\"minLength\":\"{{subject}}최소 {{value}}자여야 합니다.\",\"maxLength\":\"{{subject}}최대 {{value}}자여야 합니다.\",\"pattern\":\"{{subject}}{{value}} 형식과 일치해야 합니다.\",\"minimum\":\"{{subject}}{{value}}보다 작을 수 없습니다.\",\"exclusiveMinimum\":\"{{subject}}{{value}}보다 커야 합니다.\",\"maximum\":\"{{subject}}{{value}}보다 클 수 없습니다.\",\"exclusiveMaximum\":\"{{subject}}{{value}}보다 작아야 합니다.\",\"multipleOf\":\"{{subject}}{{value}}의 배수여야 합니다.\",\"minItems\":\"{{subject}}최소 {{value}}개 항목이 필요합니다.\",\"maxItems\":\"{{subject}}최대 {{value}}개 항목을 허용합니다.\",\"minProperties\":\"{{subject}}최소 {{value}}개 속성이 필요합니다.\",\"maxProperties\":\"{{subject}}최대 {{value}}개 속성을 허용합니다.\",\"integer\":\"정수\",\"unknownType\":\"알 수 없는 유형\",\"typeSeparator\":\" 또는 \"},\"actions\":{\"flowAccess\":\"사용 가능한 서비스\",\"flowAccessHint\":\"이 Flow의 모든 Code 노드가 공유하는 연결 관리\",\"chooseConnection\":\"{{provider}} Connection 선택\",\"connectionDescription\":\"Connection이 이 호출에 삽입됩니다. 사용 가능 여부는 계속 Flow Provider Access에서 제어합니다.\",\"title\":\"이 코드에서 호출할 수 있는 작업\",\"search\":\"Action 검색\",\"description\":\"이 코드에서 사용할 Action과 계정을 선택하세요.\",\"empty\":\"일치하는 Action이 없습니다.\",\"remove\":\"제거\",\"default\":\"기본 계정\",\"defaultHint\":\"호출 시 계정을 지정하지 않으면 이 계정을 사용합니다.\",\"removeAction\":\"액션 제거\",\"explicit\":\"코드에서 명시적으로 선택\",\"connect\":\"계정 연결\",\"refresh\":\"계정 새로 고침\",\"aliases\":\"저장된 별칭 업데이트\",\"add\":\"액션 추가\",\"cancel\":\"취소\",\"loading\":\"검색 중…\",\"needsAccount\":\"계정 연결 필요\",\"accounts\":\"계정 {{count}}개\",\"public\":\"계정 불필요\",\"allowed\":\"사용할 계정\",\"unavailable\":\"사용 불가\",\"details\":\"연결 세부 정보\",\"example\":\"호출 예제\",\"syntax\":\"호출 형식\",\"nested\":\"계층형\",\"fullId\":\"전체 ID\",\"copy\":\"복사\",\"copied\":\"복사됨\",\"copyError\":\"복사하지 못했습니다. 코드를 선택하여 직접 복사하세요.\",\"introDescription\":\"필요한 작업을 추가하고 {{context}}로 외부 앱을 호출하세요.\",\"insertAction\":\"코드 삽입\",\"chooseAccounts\":\"계정 관리\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"미리보기\"},\"ports\":{\"reorder\":\"{{name}} 순서 변경\",\"reorderHint\":\"그룹 안에서 드래그하거나 포커스 후 위 / 아래 키로 순서를 변경하세요.\",\"moved\":\"{{name}}이(가) {{position}}번째로 이동했습니다.\",\"groupSettings\":\"그룹 설정\",\"connected\":\"연결됨\",\"sort\":\"순서 변경\",\"finishSorting\":\"순서 변경 완료\",\"inputsTitle\":\"입력\",\"requiredInputs\":\"필수\",\"optionalInputs\":\"선택\",\"noInputs\":\"이 노드에는 입력 데이터가 필요하지 않습니다.\",\"noOutputs\":\"이 노드는 출력 데이터를 제공하지 않습니다.\",\"outputsTitle\":\"출력\",\"valuesTitle\":\"값\",\"columnHandle\":\"Handle\",\"columnName\":\"이름\",\"columnType\":\"유형\",\"columnValue\":\"값\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"이 실행을 트리거한 예약 시간이며 ISO 8601 형식입니다.\"},\"webhook\":{\"headers\":\"이 Webhook 요청과 함께 수신된 요청 헤더입니다.\",\"query\":\"이 Webhook 요청과 함께 수신된 URL 쿼리 매개변수입니다.\",\"body\":\"이 Webhook 요청과 함께 수신된 요청 본문입니다.\",\"webhookUrl\":\"이 요청을 수신한 Webhook URL이며 쿼리 매개변수는 포함하지 않습니다.\"}},\"startParametersTitle\":\"시작 매개변수\"}}"),
@@ -108355,7 +108428,6 @@ var resources = {
108355
108428
  snapshot: {
108356
108429
  "title": "스냅샷",
108357
108430
  "restore": "배치 복원",
108358
- "missingLayout": "저장된 배치가 없어 자동으로 정렬했습니다.",
108359
108431
  "loading": "버전 불러오는 중…",
108360
108432
  "failed": "이 버전을 불러올 수 없습니다. 내용을 더 이상 사용할 수 없을 수 있습니다.",
108361
108433
  "root": "메인 플로"
@@ -108597,41 +108669,52 @@ var resources = {
108597
108669
  "nodeTitle": "중복 건너뛰기",
108598
108670
  "warning": "기록은 Run이 성공한 후 저장됩니다. 실패하거나 취소되면 다음 실행에서 다시 처리할 수 있습니다.",
108599
108671
  "field": "식별 필드",
108672
+ "fieldDescription": "필드 값으로 중복 항목을 식별하며, 여러 필드는 조합해 판단합니다. 비워 두면 항목 자체를 비교합니다.",
108600
108673
  "values": "저장된 데이터",
108601
108674
  "spaces": "중복 제거 기록",
108602
- "clearAll": "모두 지우기",
108603
108675
  "delete": "삭제",
108604
108676
  "clear": "지우기",
108605
- "orphaned": "현재 보기에서 연결된 노드 없음",
108677
+ "orphaned": "현재 보기 외부",
108606
108678
  "nearLimit": "Flow 중복 기록이 80% 이상 찼습니다. 필요 없는 기록을 지우세요.",
108607
- "history": "기록",
108679
+ "history": "사용량",
108608
108680
  "scope": "범위",
108609
- "showValue": "값 보기",
108610
- "hideValue": "값 숨기기",
108611
108681
  "refresh": "새로 고침",
108612
- "confirmLive": "운영 상태가 즉시 지워집니다. 이후 Live Run에서 해당 항목을 다시 처리할 수 있습니다. 계속할까요?",
108613
108682
  "cancel": "취소",
108614
- "loading": "상태 불러오는 중…",
108615
- "draft": "디버그 데이터",
108616
- "live": "운영 데이터",
108617
- "isolation": "디버그 데이터와 운영 데이터는 독립적입니다.",
108618
- "rules": "저장 규칙",
108619
- "retention": "게시와 롤백으로 데이터가 삭제되지 않습니다. 필요 없으면 직접 삭제하세요. 자격 증명을 저장하지 마세요.",
108620
- "emptyValues": "저장된 데이터 없음",
108621
- "emptySpaces": "중복 제거 기록 없음",
108622
- "entries": "{{count}} / {{limit}}개",
108683
+ "loading": "불러오는 중…",
108684
+ "draft": "초안",
108685
+ "live": "게시됨",
108686
+ "isolation": "디버그와 프로덕션 데이터는 별도로 저장됩니다. 게시하거나 롤백해도 삭제되지 않습니다.",
108687
+ "rules": "저장 안내",
108623
108688
  "records": "기록 {{count}}개",
108624
- "valueLimit": "JSON 값 하나당 최대 {{size}} UTF-8 바이트입니다.",
108625
- "sharedLimit": "모든 공간이 한도를 공유합니다. 공간: {{count}} / {{limit}}. 대기 중인 기록도 용량을 예약합니다.",
108626
108689
  "fieldPlaceholder": "항목 전체 (문자열 또는 숫자)",
108627
108690
  "addField": "필드 추가",
108628
108691
  "removeField": "필드 {{index}} 삭제",
108629
108692
  "fieldIndex": "식별 필드 {{index}}",
108630
108693
  "invalidFields": "id 또는 record.id처럼 비어 있지 않은 서로 다른 경로를 입력하세요.",
108631
- "pendingRecords": "{{count}}개 커밋 대기",
108632
108694
  "pathPlaceholder": "id 또는 record.id",
108633
108695
  "saveFailed": "식별 필드를 저장할 수 없습니다.",
108634
- "retry": "다시 시도"
108696
+ "retry": "다시 시도",
108697
+ "limit": " / {{limit}}",
108698
+ "source": "출처",
108699
+ "count": "기록 수",
108700
+ "updated": "최근 업데이트",
108701
+ "shared": "워크플로 공유",
108702
+ "globalUsage": "워크플로 전체 중복 제거 기록 수",
108703
+ "valuesNearLimit": "저장 데이터가 한도의 80% 이상입니다. 불필요한 데이터를 지워 주세요.",
108704
+ "pendingClear": "{{count}}개 확정 대기 중. 관련 실행이 완료되거나 취소된 후 지울 수 있습니다.",
108705
+ "clearBlocked": "확정 대기 중인 기록이 있습니다. 관련 실행을 완료하거나 취소한 후 새로 고침하세요.",
108706
+ "clearSource": "{{name}} 지우기",
108707
+ "sourceHistory": "{{name}} 기록",
108708
+ "confirmTitle": "{{name}}을(를) 지울까요?",
108709
+ "confirmValues": "{{scope}} 환경에 저장된 데이터 {{count}}개를 지웁니다. 이후 실행에서 이 값을 읽을 수 없습니다.",
108710
+ "confirmHistory": "{{scope}} 환경의 중복 제거 기록 {{count}}개를 지웁니다. 해당 항목이 다시 처리될 수 있습니다.",
108711
+ "confirmClear": "지우기",
108712
+ "retainedHistory": "보류 중인 기록이 있는 출처의 기록은 모두 유지됩니다(보류 {{count}}개).",
108713
+ "emptyValues": "저장된 데이터 없음",
108714
+ "emptySpaces": "기록 없음",
108715
+ "loadFailed": "불러오기 실패",
108716
+ "valuesHelp": "{{name}}: 워크플로가 직접 저장하여 이후 실행에서 읽을 수 있는 내용입니다.",
108717
+ "historyHelp": "{{name}}: 같은 항목을 반복 처리하지 않기 위한 식별 정보입니다."
108635
108718
  }
108636
108719
  },
108637
108720
  "ru": {
@@ -108855,11 +108938,15 @@ var resources = {
108855
108938
  "deleteDescription": "Процесс и история запусков будут удалены навсегда, а активные триггеры остановлены.",
108856
108939
  "importFlow": "Импортировать процесс",
108857
108940
  "exportFlow": "Экспортировать процесс",
108858
- "exportSvg": "Экспорт изображения SVG",
108859
- "exportSvgPending": "Экспорт SVG…",
108860
- "exportSvgPendingDescription": "Подготовка рабочего процесса и изображений. Большие изображения могут потребовать больше времени.",
108861
- "exportSvgComplete": "Изображение SVG экспортировано.",
108862
- "exportSvgFailed": "Не удалось экспортировать изображение SVG. Повторите попытку.",
108941
+ "exportPng": "Экспорт изображения PNG",
108942
+ "exportPngFrame": "Показать рамку",
108943
+ "exportPngLight": "Светлая",
108944
+ "exportPngDark": "Тёмная",
108945
+ "exportPngPending": "Экспорт PNG…",
108946
+ "exportPngPendingDescription": "Подготовка рабочего процесса и изображений. Большие изображения могут потребовать больше времени.",
108947
+ "exportPngComplete": "Изображение PNG экспортировано.",
108948
+ "exportPngPartial": "Изображение PNG экспортировано. Некоторые изображения заменены заглушками.",
108949
+ "exportPngFailed": "Не удалось экспортировать изображение PNG. Повторите попытку.",
108863
108950
  "importInvalid": "Некорректный или неподдерживаемый файл процесса."
108864
108951
  },
108865
108952
  inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"Список узлов\",\"backToOutline\":\"Вернуться к списку узлов\",\"emptyOutline\":\"Узлов пока нет\",\"triggers\":\"Триггеры\",\"nodes\":\"Узлы\",\"multipleSelected\":\"Выбрано узлов: {{count}}\",\"account\":{\"contactAdmin\":\"У вас нет прав для выполнения этой операции. Обратитесь к администратору.\",\"accessTitle\":\"Права доступа\",\"manageFlowAccess\":\"Подключения, доступные Code\",\"configureAccess\":\"Выбрать аккаунт\",\"manageAccount\":\"Управление аккаунтами\",\"required\":\"Требуется подключение аккаунта\",\"addAccount\":\"Добавить аккаунт\",\"manage\":\"Управление\",\"authorizationPending\":\"Завершите авторизацию на странице Connection, затем вернитесь сюда, чтобы обновить этот аккаунт.\",\"chooseAccount\":\"Выберите аккаунт\",\"deferred\":\"Пока не настраивать\",\"clearDeferred\":\"Сбросить выбор\",\"noAccounts\":\"Нет доступных аккаунтов\",\"connectBeforeRun\":\"Подключите {{service}}, чтобы этот узел можно было запускать и публиковать.\",\"connectService\":\"Подключить {{service}}\",\"connection\":\"Connection\",\"loading\":\"Загрузка Connection…\",\"oomolBuiltIn\":\"Встроенный аккаунт OOMOL\",\"missing\":\"Выбранный для этого узла аккаунт недоступен. Выберите другой аккаунт или откройте управление подключениями.\",\"refreshFailed\":\"Не удалось обновить Connection.\",\"retry\":\"Повторить\",\"status\":{\"disconnected\":\"Этот Connection отключён. Подключите его заново или выберите другой аккаунт.\",\"error\":\"В этом Connection ошибка. Исправьте её или выберите другой аккаунт.\",\"reauth_required\":\"Этому Connection нужна повторная авторизация. Подключите его заново или выберите другой аккаунт.\"},\"statusUnavailable\":\"Статус Connection недоступен для {{action}}.\",\"teamDefault\":\"По умолчанию для команды\",\"title\":\"Аккаунт\",\"unavailable\":\"недоступно\"},\"close\":\"Закрыть инспектор\",\"configurationRequired\":\"Требуется настройка\",\"diagnostics\":\"Диагностика\",\"errors\":{\"jsonObject\":\"{{label}} должен быть JSON-объектом.\",\"portDefinitions\":\"Введите корректные определения портов.\"},\"node\":{\"nameDuplicate\":\"Узел с таким именем уже существует в этом графе.\",\"nameEmpty\":\"Имя узла не может быть пустым.\",\"timeout\":\"Время ожидания (мс)\",\"maxExecutions\":\"Лимит выполнений узла\",\"maxExecutionsError\":\"Лимит выполнений узла должен быть положительным целым числом.\",\"timeoutError\":\"Время ожидания должно быть положительным целым числом в миллисекундах.\",\"title\":\"Настройки узла\",\"description\":\"Назначение\",\"describe\":\"Опишите назначение этого шага.\",\"icon\":\"Значок\",\"name\":\"Заголовок\",\"retry\":\"Повторять при ошибке\",\"retryCount\":\"До {{count}} повторов\",\"retryInterval\":\"Интервал повторов\",\"retryError\":\"Укажите целый интервал от 1 до 60 секунд.\",\"retryHint\":\"Число повторов означает дополнительные попытки после неудачной первой попытки. Повтор запускает весь узел заново и может повторить внешние операции. Тайм-аут включает все попытки и интервалы.\",\"retryNone\":\"Без повторов\",\"retrySeconds\":\"сек.\",\"retryHelp\":\"О повторах\",\"retryOnce\":\"Не более 1 повтора\",\"onError\":\"При ошибке\",\"onErrorStop\":\"Остановить процесс\",\"onErrorOutput\":\"Вывод в порт error\",\"onErrorHelp\":\"Обработка ошибок\",\"onErrorHint\":\"После неудачных повторов записать ошибку в системный выход error и продолжить по существующим связям. При успехе error равен null. Отмена, тайм-ауты, ограничения ресурсов и неопределённые результаты останавливают выполнение.\",\"systemOutputs\":\"Системные выходы\",\"systemError\":\"Ошибка (системная)\",\"errorFields\":{\"error\":\"Информация об ошибке узла; при успешном выполнении — null.\",\"code\":\"Код, определяющий тип ошибки.\",\"message\":\"Описание ошибки со скрытыми конфиденциальными данными.\",\"nodeId\":\"Идентификатор узла, в котором произошла ошибка.\",\"nodeName\":\"Имя узла на момент ошибки.\",\"runId\":\"Идентификатор этого запуска рабочего процесса.\",\"executionId\":\"Идентификатор этого выполнения узла, общий для всех повторных попыток.\"}},\"selectNode\":\"Выберите один узел черновика, чтобы просмотреть и изменить его.\",\"locateNode\":\"Найти этот узел на холсте\",\"task\":{\"sharedPermissions\":\"Использовать общую группу разрешений Flow\",\"sharedPermissionsHint\":\"Используйте все Actions, разрешённые общей группой Flow. Добавлять их в узел по отдельности не нужно.\",\"httpHosts\":\"HTTP-хосты\",\"httpHostsHint\":\"Один хост на строку. *.example.com включает поддомены.\",\"httpHostsInvalid\":\"«{{host}}» — недопустимый хост. Укажите имя хоста, например api.example.com.\",\"httpHostsLimit\":\"Можно объявить не более {{count}} хостов.\",\"addAction\":\"Добавить Action\",\"removeAction\":\"Удалить Action\",\"actionAccount\":\"Аккаунт\",\"chooseAccount\":\"Выбрать аккаунт\",\"permissionSaveFailed\":\"Не удалось сохранить разрешения Code. Повторите попытку.\",\"chatText\":\"Текст чата\",\"connectorAction\":\"Действие Connector\",\"definition\":\"Определение задачи\",\"discardCode\":\"Отменить изменения\",\"editorLoading\":\"Загрузка редактора…\",\"editorUnavailable\":\"Не удалось загрузить редактор кода.\",\"inputPorts\":\"Входные порты\",\"javascriptModule\":\"Код\",\"missing\":\"Указанная задача не существует.\",\"outputPorts\":\"Выходные порты\",\"responseMode\":\"Режим ответа\",\"source\":\"Исходный код\",\"structuredJson\":\"Структурированный JSON\",\"retrySave\":\"Повторить сохранение\",\"additionalInputs\":\"Дополнительные входы\",\"httpHostsUpdated\":\"Настройки хостов изменены в другом месте. Загружена новая конфигурация; проверьте её перед сохранением.\"},\"wait\":{\"approval\":\"Одобрить или отклонить\",\"changeNotification\":\"Изменить\",\"continue\":\"Продолжить\",\"mode\":\"Обработка\",\"inputsLoading\":\"Загрузка параметров уведомления…\",\"pendingDescription\":\"Выход ожидания срабатывает один раз при начале ожидания и передаёт ссылки подтверждения и связанные данные. Подключите его для отправки сообщения или выполнения других шагов.\",\"prompt\":\"Запрос\",\"promptError\":\"Запрос должен содержать от 1 до 1 000 символов.\",\"autoContinue\":\"Автоматическое продолжение\",\"autoOff\":\"Выключено\",\"autoAfter\":\"Через интервал\",\"autoAt\":\"В указанное время\",\"autoSeconds\":\"Длительность (секунды)\",\"autoDate\":\"Дата и время\",\"autoInvalid\":\"Введите положительную длительность или корректные дату и время.\",\"autoDescription\":\"До указанного времени можно продолжить вручную.\"},\"title\":\"Инспектор\",\"sources\":{\"loading\":\"Загрузка источников входных данных…\",\"loadFailed\":\"Не удалось загрузить источники входных данных. Откройте меню ещё раз.\",\"checkFailed\":\"Не удалось проверить этот источник.\",\"select\":\"Выбрать источник входных данных\",\"title\":\"Источник входных данных\",\"sourceMissing\":\"Исходный источник входных данных больше не существует. Выберите другой.\",\"outputMissing\":\"«{{output}}» не найден в «{{source}}». Выберите снова.\",\"wholeObject\":\"Весь объект\",\"fieldMissing\":\"Поле {{field}} больше не объявлено в «{{output}}». Выберите снова.\",\"notReady\":\"К моменту выполнения этого шага у «{{source}} {{handle}}» может ещё не быть значения.\",\"sourceConflict\":\"Эти поля могут иметь значения одновременно: {{sources}}. Здесь можно использовать только одно.\",\"incompatibleRight\":\"Тип правого значения несовместим с этим сравнением.\",\"incompatible\":\"Несовместимо\",\"unverified\":\"Не проверено\",\"schemaIncompatible\":\"Формат данных не совпадает.\",\"schemaPathIncompatible\":\"Формат данных «{{path}}» не совпадает.\",\"schemaCompareFailed\":\"Не удалось проверить формат данных. Проверьте схему JSON.\",\"binaryIncompatible\":\"Двоичные данные здесь использовать нельзя.\",\"artifactIncompatible\":\"Файловые данные здесь использовать нельзя.\",\"nullableIncompatible\":\"Требуется значение, но выбранное поле может быть пустым.\",\"typeIncompatible\":\"Ожидается {{target}}, но выбранное поле имеет тип {{source}}.\",\"propertyTypeIncompatible\":\"«{{path}}» должно иметь тип {{target}}, но имеет тип {{source}}.\",\"requiredIncompatible\":\"Обязательное свойство «{{property}}» может отсутствовать.\",\"enumIncompatible\":\"Некоторые возможные значения не принимаются: {{values}}.\",\"constIncompatible\":\"Принимается только {{target}}, но выбранное поле всегда равно {{source}}.\",\"constraintSubject\":\"«{{path}}» \",\"minLength\":\"{{subject}}должно содержать не менее {{value}} символов.\",\"maxLength\":\"{{subject}}должно содержать не более {{value}} символов.\",\"pattern\":\"{{subject}}должно соответствовать {{value}}.\",\"minimum\":\"{{subject}}не может быть меньше {{value}}.\",\"exclusiveMinimum\":\"{{subject}}должно быть больше {{value}}.\",\"maximum\":\"{{subject}}не может быть больше {{value}}.\",\"exclusiveMaximum\":\"{{subject}}должно быть меньше {{value}}.\",\"multipleOf\":\"{{subject}}должно быть кратно {{value}}.\",\"minItems\":\"{{subject}}должно содержать не менее {{value}} элементов.\",\"maxItems\":\"{{subject}}должно содержать не более {{value}} элементов.\",\"minProperties\":\"{{subject}}должно содержать не менее {{value}} свойств.\",\"maxProperties\":\"{{subject}}должно содержать не более {{value}} свойств.\",\"integer\":\"Целое число\",\"unknownType\":\"неизвестный тип\",\"typeSeparator\":\" или \"},\"actions\":{\"flowAccess\":\"Доступные сервисы\",\"flowAccessHint\":\"Управлять подключениями, общими для всех узлов Code в этом Flow\",\"chooseConnection\":\"Выбрать подключение {{provider}}\",\"connectionDescription\":\"Подключение будет вставлено в этот вызов. Возможность его использования по-прежнему контролирует Flow Provider Access.\",\"title\":\"Действия, доступные коду\",\"search\":\"Поиск действий\",\"description\":\"Выберите действия и аккаунты, доступные этому коду.\",\"empty\":\"Подходящих действий нет.\",\"remove\":\"Удалить\",\"default\":\"Аккаунт по умолчанию\",\"defaultHint\":\"Используется, если при вызове не указан аккаунт.\",\"removeAction\":\"Удалить действие\",\"explicit\":\"Выбирать явно в коде\",\"connect\":\"Подключить аккаунт\",\"refresh\":\"Обновить аккаунты\",\"aliases\":\"Обновить сохранённые псевдонимы\",\"add\":\"Добавить действие\",\"cancel\":\"Отмена\",\"loading\":\"Поиск…\",\"needsAccount\":\"Подключите аккаунт\",\"accounts\":\"Аккаунты: {{count}}\",\"public\":\"Без аккаунта\",\"allowed\":\"Разрешённые аккаунты\",\"unavailable\":\"Недоступен\",\"details\":\"Данные подключений\",\"example\":\"Пример вызова\",\"syntax\":\"Синтаксис вызова\",\"nested\":\"Через провайдера\",\"fullId\":\"Полный ID\",\"copy\":\"Копировать\",\"copied\":\"Скопировано\",\"copyError\":\"Не удалось скопировать. Выделите код и скопируйте вручную.\",\"introDescription\":\"При необходимости добавьте действия для вызова внешних приложений через {{context}}.\",\"insertAction\":\"Вставить код\",\"chooseAccounts\":\"Управление аккаунтами\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"Предпросмотр\"},\"ports\":{\"reorder\":\"Изменить порядок {{name}}\",\"reorderHint\":\"Перетащите внутри группы или используйте стрелки вверх / вниз при фокусе.\",\"moved\":\"{{name}} перемещён на позицию {{position}}.\",\"groupSettings\":\"Настройки группы\",\"connected\":\"Подключено\",\"sort\":\"Изменить порядок\",\"finishSorting\":\"Готово\",\"inputsTitle\":\"Входы\",\"requiredInputs\":\"Обязательные\",\"optionalInputs\":\"Необязательные\",\"noInputs\":\"Этому узлу не требуются входные данные.\",\"noOutputs\":\"Этот узел не предоставляет выходных данных.\",\"outputsTitle\":\"Выходы\",\"valuesTitle\":\"Значения\",\"columnHandle\":\"Handle\",\"columnName\":\"Имя\",\"columnType\":\"Тип\",\"columnValue\":\"Значение\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"Запланированное время этого запуска в формате ISO 8601.\"},\"webhook\":{\"headers\":\"Заголовки, полученные с этим Webhook-запросом.\",\"query\":\"Параметры URL-запроса, полученные с этим Webhook-запросом.\",\"body\":\"Тело, полученное с этим Webhook-запросом.\",\"webhookUrl\":\"URL Webhook, получивший этот запрос, без параметров запроса.\"}},\"startParametersTitle\":\"Параметры запуска\"}}"),
@@ -109710,7 +109797,6 @@ var resources = {
109710
109797
  snapshot: {
109711
109798
  "title": "Снимок",
109712
109799
  "restore": "Восстановить расположение",
109713
- "missingLayout": "Расположение не сохранено. Узлы размещены автоматически.",
109714
109800
  "loading": "Загрузка версии…",
109715
109801
  "failed": "Не удалось загрузить версию. Её содержимое может быть недоступно.",
109716
109802
  "root": "Основной процесс"
@@ -109952,41 +110038,52 @@ var resources = {
109952
110038
  "nodeTitle": "Пропуск дубликатов",
109953
110039
  "warning": "История сохраняется после успешного Run. После ошибки или отмены элементы можно обработать повторно.",
109954
110040
  "field": "Поля идентификации",
110041
+ "fieldDescription": "Дубликаты определяются по значениям полей. Несколько полей объединяются. Без полей сравниваются сами элементы.",
109955
110042
  "values": "Сохранённые данные",
109956
- "spaces": "Записи дедупликации",
109957
- "clearAll": "Очистить всё",
110043
+ "spaces": "История дедупликации",
109958
110044
  "delete": "Удалить",
109959
110045
  "clear": "Очистить",
109960
- "orphaned": "Нет узла в текущем представлении",
110046
+ "orphaned": "Вне текущего представления",
109961
110047
  "nearLimit": "История Flow заполнена минимум на 80 %. Удалите ненужные записи.",
109962
- "history": "История",
110048
+ "history": "Использование",
109963
110049
  "scope": "Область",
109964
- "showValue": "Показать значение",
109965
- "hideValue": "Скрыть значение",
109966
110050
  "refresh": "Обновить",
109967
- "confirmLive": "Рабочее состояние будет немедленно очищено. Последующие Live Run могут повторно обработать эти элементы. Продолжить?",
109968
110051
  "cancel": "Отмена",
109969
- "loading": "Загрузка состояния…",
109970
- "draft": "Отладочные данные",
109971
- "live": "Рабочие данные",
109972
- "isolation": "Отладочные и рабочие данные независимы.",
109973
- "rules": "Правила хранения",
109974
- "retention": "Публикация и откат не удаляют данные. Удаляйте их вручную, когда они больше не нужны. Не храните учётные данные.",
109975
- "emptyValues": "Нет сохранённых данных",
109976
- "emptySpaces": "Нет записей дедупликации",
109977
- "entries": "{{count}} / {{limit}} записей",
110052
+ "loading": "Загрузка…",
110053
+ "draft": "Черновик",
110054
+ "live": "Опубликовано",
110055
+ "isolation": "Данные отладки и рабочего режима хранятся отдельно. Публикация и откат их не удаляют.",
110056
+ "rules": "О хранении",
109978
110057
  "records": "{{count}} записей",
109979
- "valueLimit": "Каждое значение JSON — не более {{size}} байт UTF-8.",
109980
- "sharedLimit": "Все пространства используют общий лимит. Пространства: {{count}} / {{limit}}. Ожидающие записи резервируют ёмкость.",
109981
110058
  "fieldPlaceholder": "Весь элемент (строка или число)",
109982
110059
  "addField": "Добавить поле",
109983
110060
  "removeField": "Удалить поле {{index}}",
109984
110061
  "fieldIndex": "Поле идентификации {{index}}",
109985
110062
  "invalidFields": "Укажите разные непустые пути, например id или record.id.",
109986
- "pendingRecords": "{{count}} ожидают фиксации",
109987
110063
  "pathPlaceholder": "id или record.id",
109988
110064
  "saveFailed": "Не удалось сохранить поля идентификации.",
109989
- "retry": "Повторить"
110065
+ "retry": "Повторить",
110066
+ "limit": " / {{limit}}",
110067
+ "source": "Источник",
110068
+ "count": "Записи",
110069
+ "updated": "Обновлено",
110070
+ "shared": "Общие записи процесса",
110071
+ "globalUsage": "Всего записей дедупликации в процессе",
110072
+ "valuesNearLimit": "Лимит сохранённых данных заполнен как минимум на 80%. Удалите ненужные данные.",
110073
+ "pendingClear": "Ожидают фиксации: {{count}}. Завершите или отмените связанные запуски перед очисткой.",
110074
+ "clearBlocked": "Есть записи, ожидающие фиксации. Завершите или отмените связанные запуски и обновите данные.",
110075
+ "clearSource": "Очистить {{name}}",
110076
+ "sourceHistory": "История: {{name}}",
110077
+ "confirmTitle": "Очистить «{{name}}»?",
110078
+ "confirmValues": "Будут удалены сохранённые записи ({{count}}) в среде «{{scope}}». Последующие запуски не смогут прочитать эти значения.",
110079
+ "confirmHistory": "Будут удалены записи дедупликации ({{count}}) в среде «{{scope}}». Эти элементы могут быть обработаны повторно.",
110080
+ "confirmClear": "Очистить",
110081
+ "retainedHistory": "История источников с ожидающими записями будет сохранена полностью (ожидают {{count}}).",
110082
+ "emptyValues": "Нет данных",
110083
+ "emptySpaces": "Нет истории",
110084
+ "loadFailed": "Не удалось загрузить",
110085
+ "valuesHelp": "{{name}}: данные, явно сохранённые процессом для чтения в следующих запусках.",
110086
+ "historyHelp": "{{name}}: идентификаторы элементов, предотвращающие повторную обработку."
109990
110087
  }
109991
110088
  },
109992
110089
  "fr": {
@@ -110210,11 +110307,15 @@ var resources = {
110210
110307
  "deleteDescription": "Le workflow et son historique seront définitivement supprimés, et ses déclencheurs actifs arrêtés.",
110211
110308
  "importFlow": "Importer un workflow",
110212
110309
  "exportFlow": "Exporter le workflow",
110213
- "exportSvg": "Exporter une image SVG",
110214
- "exportSvgPending": "Exportation du SVG…",
110215
- "exportSvgPendingDescription": "Préparation du workflow et des images. Les images volumineuses peuvent prendre un peu plus de temps.",
110216
- "exportSvgComplete": "Image SVG exportée.",
110217
- "exportSvgFailed": "Impossible d’exporter l’image SVG. Veuillez réessayer.",
110310
+ "exportPng": "Exporter une image PNG",
110311
+ "exportPngFrame": "Afficher le cadre",
110312
+ "exportPngLight": "Clair",
110313
+ "exportPngDark": "Sombre",
110314
+ "exportPngPending": "Exportation du PNG…",
110315
+ "exportPngPendingDescription": "Préparation du workflow et des images. Les images volumineuses peuvent prendre un peu plus de temps.",
110316
+ "exportPngComplete": "Image PNG exportée.",
110317
+ "exportPngPartial": "Image PNG exportée. Certaines images ont été remplacées par des espaces réservés.",
110318
+ "exportPngFailed": "Impossible d’exporter l’image PNG. Veuillez réessayer.",
110218
110319
  "importInvalid": "Fichier de workflow invalide ou non pris en charge."
110219
110320
  },
110220
110321
  inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"Liste des nœuds\",\"backToOutline\":\"Retour à la liste des nœuds\",\"emptyOutline\":\"Aucun nœud pour le moment\",\"triggers\":\"Déclencheurs\",\"nodes\":\"Nœuds\",\"multipleSelected\":\"{{count}} nœuds sélectionnés\",\"account\":{\"contactAdmin\":\"Vous n’avez pas l’autorisation d’effectuer cette opération. Contactez un administrateur.\",\"accessTitle\":\"Autorisations d’accès\",\"manageFlowAccess\":\"Connexions disponibles pour Code\",\"configureAccess\":\"Choisir un compte\",\"manageAccount\":\"Gérer les comptes\",\"required\":\"Compte à connecter\",\"addAccount\":\"Ajouter un compte\",\"manage\":\"Gérer\",\"authorizationPending\":\"Terminez l'autorisation sur la page Connection, puis revenez ici pour actualiser ce compte.\",\"chooseAccount\":\"Choisir un compte\",\"deferred\":\"Ne pas configurer maintenant\",\"clearDeferred\":\"Effacer la sélection\",\"noAccounts\":\"Aucun compte disponible\",\"connectBeforeRun\":\"Connectez {{service}} pour que ce bloc puisse être exécuté ou publié.\",\"connectService\":\"Connecter {{service}}\",\"connection\":\"Connection\",\"loading\":\"Chargement des Connections…\",\"oomolBuiltIn\":\"Compte intégré OOMOL\",\"missing\":\"Le compte sélectionné pour ce nœud est indisponible. Choisissez un autre compte ou gérez les connexions.\",\"refreshFailed\":\"Impossible d'actualiser les Connections.\",\"retry\":\"Réessayer\",\"status\":{\"disconnected\":\"Cette Connection est déconnectée. Reconnectez-la ou choisissez un autre compte.\",\"error\":\"Cette Connection présente une erreur. Réparez-la ou choisissez un autre compte.\",\"reauth_required\":\"Cette Connection doit être autorisée à nouveau. Reconnectez-la ou choisissez un autre compte.\"},\"statusUnavailable\":\"Le statut de la Connection est indisponible pour {{action}}.\",\"teamDefault\":\"Par défaut de l'équipe\",\"title\":\"Compte\",\"unavailable\":\"indisponible\"},\"close\":\"Fermer l'inspecteur\",\"configurationRequired\":\"Configuration requise\",\"diagnostics\":\"Diagnostics\",\"errors\":{\"jsonObject\":\"{{label}} doit être un objet JSON.\",\"portDefinitions\":\"Saisissez des définitions de ports valides.\"},\"node\":{\"nameDuplicate\":\"Un nœud portant ce nom existe déjà dans ce graphe.\",\"nameEmpty\":\"Le nom du nœud ne peut pas être vide.\",\"timeout\":\"Délai d'expiration (ms)\",\"maxExecutions\":\"Limite d’exécutions du nœud\",\"maxExecutionsError\":\"La limite d’exécutions du nœud doit être un entier positif.\",\"timeoutError\":\"Le délai d'expiration doit être un entier positif exprimé en millisecondes.\",\"title\":\"Paramètres du nœud\",\"description\":\"Objectif\",\"describe\":\"Décrivez le rôle de cette étape.\",\"icon\":\"Icône\",\"name\":\"Titre\",\"retry\":\"Réessayer en cas d’erreur\",\"retryCount\":\"Nouvelles tentatives : {{count}} max.\",\"retryInterval\":\"Intervalle\",\"retryError\":\"Indiquez un intervalle entier de 1 à 60 secondes.\",\"retryHint\":\"Le nombre de nouvelles tentatives s’ajoute à la première exécution en cas d’échec. Chaque tentative réexécute le nœud entier et peut répéter des opérations externes. Le délai maximal inclut toutes les tentatives et les intervalles.\",\"retryNone\":\"Aucune nouvelle tentative\",\"retrySeconds\":\"secondes\",\"retryHelp\":\"À propos des nouvelles tentatives\",\"retryOnce\":\"Une nouvelle tentative max.\",\"onError\":\"En cas d’échec\",\"onErrorStop\":\"Arrêter le workflow\",\"onErrorOutput\":\"Sortir vers le port error\",\"onErrorHelp\":\"Gestion des échecs\",\"onErrorHint\":\"Après les nouvelles tentatives, placer l’erreur dans la sortie système error et continuer par les connexions existantes. En cas de succès, error vaut null. Annulation, délais, limites de ressources et résultats indéterminés arrêtent toujours l’exécution.\",\"systemOutputs\":\"Sorties système\",\"systemError\":\"Erreur (système)\",\"errorFields\":{\"error\":\"Informations sur l’erreur en cas d’échec du nœud ; null en cas de réussite.\",\"code\":\"Code identifiant le type d’erreur.\",\"message\":\"Description de l’erreur, avec les informations sensibles masquées.\",\"nodeId\":\"Identifiant du nœud ayant échoué.\",\"nodeName\":\"Nom du nœud au moment de l’échec.\",\"runId\":\"Identifiant de cette exécution du workflow.\",\"executionId\":\"Identifiant de cette exécution du nœud, commun à toutes ses tentatives.\"}},\"selectNode\":\"Sélectionnez un nœud du Brouillon pour l'inspecter et le modifier.\",\"locateNode\":\"Localiser ce nœud sur le canevas\",\"task\":{\"sharedPermissions\":\"Utiliser le groupe d’autorisations partagé du Flow\",\"sharedPermissionsHint\":\"Utilisez toutes les Actions autorisées par le groupe du Flow, sans les ajouter à ce nœud.\",\"httpHosts\":\"Hôtes HTTP\",\"httpHostsHint\":\"Un hôte par ligne. *.example.com inclut les sous-domaines.\",\"httpHostsInvalid\":\"« {{host}} » n’est pas un hôte valide. Utilisez un nom d’hôte comme api.example.com.\",\"httpHostsLimit\":\"Déclarez au plus {{count}} hôtes.\",\"addAction\":\"Ajouter une action\",\"removeAction\":\"Supprimer l’action\",\"actionAccount\":\"Compte\",\"chooseAccount\":\"Choisir un compte\",\"permissionSaveFailed\":\"Impossible d’enregistrer les autorisations Code. Réessayez.\",\"chatText\":\"Texte de conversation\",\"connectorAction\":\"Action Connector\",\"definition\":\"Définition de la tâche\",\"discardCode\":\"Abandonner les modifications\",\"editorLoading\":\"Chargement de l'éditeur…\",\"editorUnavailable\":\"Impossible de charger l'éditeur de code.\",\"inputPorts\":\"Ports d'entrée\",\"javascriptModule\":\"Code\",\"missing\":\"La tâche référencée n'existe pas.\",\"outputPorts\":\"Ports de sortie\",\"responseMode\":\"Mode de réponse\",\"source\":\"Source\",\"structuredJson\":\"JSON structuré\",\"retrySave\":\"Réessayer\",\"additionalInputs\":\"Entrées supplémentaires\",\"httpHostsUpdated\":\"Les hôtes ont été modifiés ailleurs. La dernière configuration est chargée ; vérifiez-la avant d’enregistrer.\"},\"wait\":{\"approval\":\"Approuver ou refuser\",\"changeNotification\":\"Changer\",\"continue\":\"Continuer\",\"mode\":\"Traitement\",\"inputsLoading\":\"Chargement des paramètres de notification…\",\"pendingDescription\":\"La sortie en attente se déclenche une fois au début de l’attente et fournit les liens de confirmation et les données associées. Reliez-la pour envoyer un message ou exécuter d’autres étapes.\",\"prompt\":\"Invite\",\"promptError\":\"L’invite doit contenir entre 1 et 1 000 caractères.\",\"autoContinue\":\"Reprise automatique\",\"autoOff\":\"Désactivée\",\"autoAfter\":\"Après une durée\",\"autoAt\":\"À une date précise\",\"autoSeconds\":\"Durée (secondes)\",\"autoDate\":\"Date et heure\",\"autoInvalid\":\"Saisissez une durée positive ou une date et une heure valides.\",\"autoDescription\":\"Vous pouvez reprendre manuellement avant l’heure prévue.\"},\"title\":\"Inspecteur\",\"sources\":{\"loading\":\"Chargement des sources d’entrée…\",\"loadFailed\":\"Impossible de charger les sources d’entrée. Rouvrez le menu pour réessayer.\",\"checkFailed\":\"Impossible de vérifier cette source.\",\"select\":\"Sélectionner la source d’entrée\",\"title\":\"Source d’entrée\",\"sourceMissing\":\"La source d’entrée d’origine n’existe plus. Choisissez-en une autre.\",\"outputMissing\":\"« {{output}} » est introuvable dans « {{source}} ». Choisissez à nouveau.\",\"wholeObject\":\"Objet entier\",\"fieldMissing\":\"Le champ {{field}} n’est plus déclaré dans « {{output}} ». Choisissez à nouveau.\",\"notReady\":\"« {{source}} {{handle}} » peut ne pas avoir de valeur lors de cette étape.\",\"sourceConflict\":\"Ces champs peuvent avoir une valeur en même temps : {{sources}}. Un seul peut être utilisé ici.\",\"incompatibleRight\":\"Le type de la valeur de droite est incompatible avec cette comparaison.\",\"incompatible\":\"Incompatible\",\"unverified\":\"Non vérifié\",\"schemaIncompatible\":\"Le format des données ne correspond pas.\",\"schemaPathIncompatible\":\"Le format de « {{path}} » ne correspond pas.\",\"schemaCompareFailed\":\"Impossible de vérifier le format. Vérifiez le schéma JSON.\",\"binaryIncompatible\":\"Les données binaires ne peuvent pas être utilisées ici.\",\"artifactIncompatible\":\"Les données de fichier ne peuvent pas être utilisées ici.\",\"nullableIncompatible\":\"Une valeur est requise, mais le champ sélectionné peut être vide.\",\"typeIncompatible\":\"Le type attendu est {{target}}, mais le champ sélectionné est de type {{source}}.\",\"propertyTypeIncompatible\":\"« {{path}} » doit être de type {{target}}, mais est de type {{source}}.\",\"requiredIncompatible\":\"La propriété requise « {{property}} » peut être absente.\",\"enumIncompatible\":\"Certaines valeurs possibles ne sont pas acceptées : {{values}}.\",\"constIncompatible\":\"Seul {{target}} est accepté, mais le champ sélectionné vaut toujours {{source}}.\",\"constraintSubject\":\"« {{path}} » \",\"minLength\":\"{{subject}}doit contenir au moins {{value}} caractères.\",\"maxLength\":\"{{subject}}doit contenir au plus {{value}} caractères.\",\"pattern\":\"{{subject}}doit correspondre à {{value}}.\",\"minimum\":\"{{subject}}ne peut pas être inférieur à {{value}}.\",\"exclusiveMinimum\":\"{{subject}}doit être supérieur à {{value}}.\",\"maximum\":\"{{subject}}ne peut pas être supérieur à {{value}}.\",\"exclusiveMaximum\":\"{{subject}}doit être inférieur à {{value}}.\",\"multipleOf\":\"{{subject}}doit être un multiple de {{value}}.\",\"minItems\":\"{{subject}}doit contenir au moins {{value}} éléments.\",\"maxItems\":\"{{subject}}doit contenir au plus {{value}} éléments.\",\"minProperties\":\"{{subject}}doit contenir au moins {{value}} propriétés.\",\"maxProperties\":\"{{subject}}doit contenir au plus {{value}} propriétés.\",\"integer\":\"Entier\",\"unknownType\":\"type inconnu\",\"typeSeparator\":\" ou \"},\"actions\":{\"flowAccess\":\"Services disponibles\",\"flowAccessHint\":\"Gérer les connexions partagées par tous les nœuds Code de ce Flow\",\"chooseConnection\":\"Choisir une connexion {{provider}}\",\"connectionDescription\":\"La connexion est insérée dans cet appel. L’accès Provider du Flow détermine toujours si elle peut être utilisée.\",\"title\":\"Actions accessibles au code\",\"search\":\"Rechercher des actions\",\"description\":\"Choisissez les actions et les comptes autorisés pour ce code.\",\"empty\":\"Aucune action correspondante.\",\"remove\":\"Retirer\",\"default\":\"Compte par défaut\",\"defaultHint\":\"Compte utilisé si aucun compte n’est précisé lors de l’appel.\",\"removeAction\":\"Retirer l’action\",\"explicit\":\"Choisir explicitement dans le code\",\"connect\":\"Connecter un compte\",\"refresh\":\"Actualiser les comptes\",\"aliases\":\"Mettre à jour les alias enregistrés\",\"add\":\"Ajouter une action\",\"cancel\":\"Annuler\",\"loading\":\"Recherche…\",\"needsAccount\":\"Connecter un compte\",\"accounts\":\"{{count}} comptes\",\"public\":\"Sans compte\",\"allowed\":\"Comptes autorisés\",\"unavailable\":\"Indisponible\",\"details\":\"Détails des connexions\",\"example\":\"Exemple d’appel\",\"syntax\":\"Syntaxe d’appel\",\"nested\":\"Par fournisseur\",\"fullId\":\"ID complet\",\"copy\":\"Copier\",\"copied\":\"Copié\",\"copyError\":\"Échec de la copie. Sélectionnez le code pour le copier manuellement.\",\"introDescription\":\"Ajoutez des actions au besoin pour appeler des applications externes via {{context}}.\",\"insertAction\":\"Insérer le code\",\"chooseAccounts\":\"Gérer les comptes\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"Aperçu\"},\"ports\":{\"reorder\":\"Réordonner {{name}}\",\"reorderHint\":\"Glissez dans le groupe ou utilisez les flèches haut / bas au clavier.\",\"moved\":\"{{name}} déplacé en position {{position}}.\",\"groupSettings\":\"Paramètres du groupe\",\"connected\":\"Connecté\",\"sort\":\"Réordonner\",\"finishSorting\":\"Terminer\",\"inputsTitle\":\"Entrées\",\"requiredInputs\":\"Obligatoires\",\"optionalInputs\":\"Facultatifs\",\"noInputs\":\"Ce nœud ne nécessite pas de données d’entrée.\",\"noOutputs\":\"Ce nœud ne fournit pas de données de sortie.\",\"outputsTitle\":\"Sorties\",\"valuesTitle\":\"Valeurs\",\"columnHandle\":\"Handle\",\"columnName\":\"Nom\",\"columnType\":\"Type\",\"columnValue\":\"Valeur\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"Heure planifiée ayant déclenché cette exécution, au format ISO 8601.\"},\"webhook\":{\"headers\":\"Les en-têtes reçus avec cette requête Webhook.\",\"query\":\"Les paramètres de requête URL reçus avec cette requête Webhook.\",\"body\":\"Le corps reçu avec cette requête Webhook.\",\"webhookUrl\":\"L’URL Webhook ayant reçu cette requête, sans les paramètres de requête.\"}},\"startParametersTitle\":\"Paramètres de démarrage\"}}"),
@@ -111065,7 +111166,6 @@ var resources = {
111065
111166
  snapshot: {
111066
111167
  "title": "Instantané",
111067
111168
  "restore": "Rétablir la disposition",
111068
- "missingLayout": "Aucune disposition enregistrée. Les nœuds sont placés automatiquement.",
111069
111169
  "loading": "Chargement de la version…",
111070
111170
  "failed": "Impossible de charger cette version. Son contenu est peut-être indisponible.",
111071
111171
  "root": "Flux principal"
@@ -111307,41 +111407,52 @@ var resources = {
111307
111407
  "nodeTitle": "Ignorer les doublons",
111308
111408
  "warning": "L’historique est enregistré après la réussite du Run. En cas d’échec ou d’annulation, ces éléments pourront être traités à nouveau.",
111309
111409
  "field": "Champs d’identification",
111410
+ "fieldDescription": "Les valeurs des champs identifient les doublons. Plusieurs champs sont combinés. Sans champ, les éléments eux-mêmes sont comparés.",
111310
111411
  "values": "Données enregistrées",
111311
- "spaces": "Enregistrements de déduplication",
111312
- "clearAll": "Tout effacer",
111412
+ "spaces": "Historique de déduplication",
111313
111413
  "delete": "Supprimer",
111314
111414
  "clear": "Effacer",
111315
- "orphaned": "Sans nœud dans cette vue",
111415
+ "orphaned": "Hors de la vue actuelle",
111316
111416
  "nearLimit": "L’historique du Flow est rempli à au moins 80 %. Effacez les entrées inutiles.",
111317
- "history": "Historique",
111417
+ "history": "Utilisation",
111318
111418
  "scope": "Portée",
111319
- "showValue": "Voir la valeur",
111320
- "hideValue": "Masquer la valeur",
111321
111419
  "refresh": "Actualiser",
111322
- "confirmLive": "L’état de production sera immédiatement effacé. Les prochains Runs Live pourront traiter à nouveau ces éléments. Continuer ?",
111323
111420
  "cancel": "Annuler",
111324
- "loading": "Chargement de l’état…",
111325
- "draft": "Données de débogage",
111326
- "live": "Données de production",
111327
- "isolation": "Le débogage et la production ont des données indépendantes.",
111328
- "rules": "Règles de stockage",
111329
- "retention": "La publication et le retour arrière ne suppriment pas les données. Effacez-les lorsque nécessaire. Ne stockez pas de secrets.",
111330
- "emptyValues": "Aucune donnée enregistrée",
111331
- "emptySpaces": "Aucun enregistrement de déduplication",
111332
- "entries": "{{count}} / {{limit}} entrées",
111421
+ "loading": "Chargement…",
111422
+ "draft": "Brouillon",
111423
+ "live": "Publié",
111424
+ "isolation": "Les données de débogage et de production sont séparées. La publication et le retour de version ne les effacent pas.",
111425
+ "rules": "À propos du stockage",
111333
111426
  "records": "{{count}} enregistrements",
111334
- "valueLimit": "Chaque valeur JSON peut contenir au plus {{size}} octets UTF-8.",
111335
- "sharedLimit": "Tous les espaces partagent la limite. Espaces : {{count}} / {{limit}}. Les entrées en attente réservent de la capacité.",
111336
111427
  "fieldPlaceholder": "Élément entier (texte ou nombre)",
111337
111428
  "addField": "Ajouter un champ",
111338
111429
  "removeField": "Supprimer le champ {{index}}",
111339
111430
  "fieldIndex": "Champ d’identification {{index}}",
111340
111431
  "invalidFields": "Utilisez des chemins distincts et non vides, comme id ou record.id.",
111341
- "pendingRecords": "{{count}} en attente",
111342
111432
  "pathPlaceholder": "id ou record.id",
111343
111433
  "saveFailed": "Impossible d’enregistrer les champs d’identification.",
111344
- "retry": "Réessayer"
111434
+ "retry": "Réessayer",
111435
+ "limit": " / {{limit}}",
111436
+ "source": "Source",
111437
+ "count": "Entrées",
111438
+ "updated": "Mise à jour",
111439
+ "shared": "Partagé par le workflow",
111440
+ "globalUsage": "Total des entrées de déduplication du workflow",
111441
+ "valuesNearLimit": "Les données enregistrées occupent au moins 80 % du quota. Supprimez les données inutiles.",
111442
+ "pendingClear": "{{count}} en attente de validation. Terminez ou annulez les exécutions concernées avant de vider.",
111443
+ "clearBlocked": "Des entrées sont en attente de validation. Terminez ou annulez les exécutions concernées, puis actualisez.",
111444
+ "clearSource": "Vider {{name}}",
111445
+ "sourceHistory": "Historique de {{name}}",
111446
+ "confirmTitle": "Vider « {{name}} » ?",
111447
+ "confirmValues": "Cela supprimera {{count}} entrées enregistrées en environnement {{scope}}. Les exécutions suivantes ne pourront plus lire ces valeurs.",
111448
+ "confirmHistory": "Cela supprimera {{count}} entrées de déduplication en environnement {{scope}}. Ces éléments pourront être traités à nouveau.",
111449
+ "confirmClear": "Vider",
111450
+ "retainedHistory": "Tout l’historique des sources contenant des entrées en attente sera conservé ({{count}} en attente).",
111451
+ "emptyValues": "Aucune donnée",
111452
+ "emptySpaces": "Aucun historique",
111453
+ "loadFailed": "Chargement impossible",
111454
+ "valuesHelp": "{{name}} : contenu enregistré explicitement par le workflow, accessible aux exécutions suivantes.",
111455
+ "historyHelp": "{{name}} : identifiants des éléments utilisés pour éviter les traitements en double."
111345
111456
  }
111346
111457
  }
111347
111458
  };
@@ -113315,232 +113426,361 @@ function EventSourceTriggerConfig({ inputs, provider = "feishu_app_bot", fieldLa
113315
113426
  }
113316
113427
  //#endregion
113317
113428
  //#region src/workbench/browser/runtime/editor/flowStatePanel.tsx
113318
- function StateValueRow({ item, client, flowId, scope, busy, onClear }) {
113429
+ function sourceName(space, nodes, t) {
113430
+ return space === "flow" ? t("flowState.shared") : nodes.find((node) => `node:${node.id}` === space)?.title ?? space;
113431
+ }
113432
+ function UpdatedTime({ value, container }) {
113433
+ const language = useLang();
113434
+ const delta = value - Date.now();
113435
+ const units = [
113436
+ ["year", 31536e6],
113437
+ ["month", 2592e6],
113438
+ ["day", 864e5],
113439
+ ["hour", 36e5],
113440
+ ["minute", 6e4],
113441
+ ["second", 1e3]
113442
+ ];
113443
+ const [unit, duration] = units.find(([, size]) => Math.abs(delta) >= size) ?? units[units.length - 1];
113444
+ const date = new Date(value);
113445
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
113446
+ render: /* @__PURE__ */ jsx("time", { dateTime: date.toISOString() }),
113447
+ children: new Intl.RelativeTimeFormat(language, { numeric: "auto" }).format(Math.round(delta / duration), unit)
113448
+ }), /* @__PURE__ */ jsx(TooltipContent, {
113449
+ container,
113450
+ children: date.toLocaleString(language)
113451
+ })] });
113452
+ }
113453
+ function Usage({ count, limit }) {
113454
+ const language = useLang();
113319
113455
  const t = useTranslate();
113320
- const [open, setOpen] = useState(false);
113321
- const [result, setResult] = useState();
113322
- const [error, setError] = useState();
113323
- useEffect(() => {
113324
- if (!open) return;
113325
- const controller = new AbortController();
113326
- setResult(void 0);
113327
- setError(void 0);
113328
- client.getFlowStateValues(flowId, scope, [item.key], controller.signal).then((response) => {
113329
- if (!controller.signal.aborted) setResult(response.values[0]);
113330
- }, (reason) => {
113331
- if (!controller.signal.aborted) setError(String(reason));
113332
- });
113333
- return () => controller.abort();
113334
- }, [
113335
- client,
113336
- flowId,
113337
- scope,
113338
- item.key,
113339
- item.updatedAt,
113340
- open
113341
- ]);
113342
- return /* @__PURE__ */ jsxs("div", {
113343
- className: "flex items-start justify-between gap-3 border-b border-border/60 py-2",
113344
- children: [/* @__PURE__ */ jsxs("div", {
113345
- className: "min-w-0 flex-1",
113346
- children: [/* @__PURE__ */ jsx("p", {
113347
- className: "m-0 break-all font-medium",
113348
- children: item.key
113349
- }), open && (result != null ? /* @__PURE__ */ jsx("pre", {
113350
- className: "max-h-40 overflow-auto whitespace-pre-wrap break-all text-xs",
113351
- children: JSON.stringify(result.value, null, 2)
113352
- }) : error != null ? /* @__PURE__ */ jsx("p", {
113353
- role: "alert",
113354
- className: "text-destructive text-sm",
113355
- children: error
113356
- }) : /* @__PURE__ */ jsx("p", {
113357
- role: "status",
113358
- className: "text-muted-foreground text-sm",
113359
- children: t("flowState.loading")
113360
- }))]
113361
- }), /* @__PURE__ */ jsxs("div", {
113362
- className: "flex shrink-0 gap-2",
113363
- children: [/* @__PURE__ */ jsx(Button$1, {
113364
- variant: "outline",
113365
- size: "sm",
113366
- disabled: busy,
113367
- "aria-expanded": open,
113368
- "aria-label": `${t(open ? "flowState.hideValue" : "flowState.showValue")}: ${item.key}`,
113369
- onClick: () => setOpen((value) => !value),
113370
- children: t(open ? "flowState.hideValue" : "flowState.showValue")
113371
- }), /* @__PURE__ */ jsx(Button$1, {
113372
- variant: "outline",
113373
- size: "sm",
113374
- disabled: busy,
113375
- onClick: (event) => onClear(item.key, event.currentTarget),
113376
- children: t("flowState.delete")
113377
- })]
113456
+ return /* @__PURE__ */ jsxs("span", {
113457
+ className: "inline-flex flex-col items-end whitespace-nowrap tabular-nums sm:inline",
113458
+ children: [/* @__PURE__ */ jsx("span", {
113459
+ className: "font-medium text-foreground",
113460
+ children: count?.toLocaleString(language) ?? "—"
113461
+ }), limit != null && /* @__PURE__ */ jsx("span", {
113462
+ className: "text-xs text-muted-foreground",
113463
+ children: t("flowState.limit", { limit: limit.toLocaleString(language) })
113378
113464
  })]
113379
113465
  });
113380
113466
  }
113381
- function FlowStatePanel({ value, client, flowId, nodeIds, busy, onClearValues, onClearSpace, space }) {
113467
+ function StateClearButton({ name, disabled, reason, onClear, container }) {
113468
+ const t = useTranslate();
113469
+ const label = t("flowState.clearSource", { name });
113470
+ const button = /* @__PURE__ */ jsx(Button$1, {
113471
+ variant: "ghost",
113472
+ size: "sm",
113473
+ "aria-label": label,
113474
+ disabled: disabled || reason != null,
113475
+ onClick: (event) => onClear(event.currentTarget),
113476
+ children: t("flowState.clear")
113477
+ });
113478
+ return reason == null ? button : /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
113479
+ render: /* @__PURE__ */ jsx("span", {
113480
+ role: "group",
113481
+ "aria-label": label,
113482
+ tabIndex: 0,
113483
+ className: "inline-flex"
113484
+ }),
113485
+ children: button
113486
+ }), /* @__PURE__ */ jsx(TooltipContent, {
113487
+ container,
113488
+ children: reason
113489
+ })] });
113490
+ }
113491
+ function StateDataRow({ name, quantity, updatedAt, status, source, icon, disabled, clearReason, onClear, container }) {
113492
+ return /* @__PURE__ */ jsxs("tr", {
113493
+ className: "border-b border-border/60 last:border-b-0",
113494
+ children: [
113495
+ /* @__PURE__ */ jsx("th", {
113496
+ scope: "row",
113497
+ className: "py-3 text-left align-middle font-normal [overflow-wrap:anywhere]",
113498
+ children: /* @__PURE__ */ jsxs("div", {
113499
+ className: "flex gap-2",
113500
+ children: [icon != null && /* @__PURE__ */ jsx("span", {
113501
+ "aria-hidden": "true",
113502
+ className: "flex h-5 w-4 shrink-0 items-center justify-center text-base text-muted-foreground",
113503
+ children: icon
113504
+ }), /* @__PURE__ */ jsxs("div", {
113505
+ className: "min-w-0 flex-1",
113506
+ children: [source == null ? name : /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
113507
+ render: /* @__PURE__ */ jsx("span", {}),
113508
+ children: name
113509
+ }), /* @__PURE__ */ jsx(TooltipContent, {
113510
+ container,
113511
+ children: source
113512
+ })] }), (status != null || updatedAt != null) && /* @__PURE__ */ jsx("div", {
113513
+ className: "mt-1 text-xs font-normal text-muted-foreground",
113514
+ children: status ?? (updatedAt != null && /* @__PURE__ */ jsx(UpdatedTime, {
113515
+ value: updatedAt,
113516
+ container
113517
+ }))
113518
+ })]
113519
+ })]
113520
+ })
113521
+ }),
113522
+ /* @__PURE__ */ jsx("td", {
113523
+ className: "w-px py-3 pl-3 text-right align-middle whitespace-nowrap tabular-nums",
113524
+ children: quantity
113525
+ }),
113526
+ /* @__PURE__ */ jsx("td", {
113527
+ className: "w-px py-3 pl-3 text-right align-middle whitespace-nowrap",
113528
+ children: onClear != null && /* @__PURE__ */ jsx(StateClearButton, {
113529
+ name,
113530
+ disabled,
113531
+ reason: clearReason,
113532
+ onClear,
113533
+ container
113534
+ })
113535
+ })
113536
+ ]
113537
+ });
113538
+ }
113539
+ function FlowStatePanel({ value, nodes, busy, loading = false, onClearValues, onClearHistory, onClearSpace, space, container }) {
113382
113540
  const t = useTranslate();
113383
- const count = value.spaces.reduce((total, item) => total + item.reservedCount, 0);
113384
- const spaces = space == null ? value.spaces : value.spaces.filter((item) => item.space === space);
113541
+ const language = useLang();
113542
+ const allSpaces = value?.spaces ?? [];
113543
+ const count = value == null ? void 0 : allSpaces.reduce((total, item) => total + item.reservedCount, 0);
113544
+ const spaces = allSpaces.filter((item) => space == null || item.space === space).toSorted((a, b) => b.reservedCount - a.reservedCount || (a.space < b.space ? -1 : a.space > b.space ? 1 : 0));
113545
+ const readStatus = loading ? t("flowState.loading") : value == null ? t("flowState.loadFailed") : void 0;
113546
+ const valuesDetail = readStatus ?? (value?.values.count === 0 ? t("flowState.emptyValues") : value?.values.updatedAt != null ? /* @__PURE__ */ jsx(UpdatedTime, {
113547
+ value: value.values.updatedAt,
113548
+ container
113549
+ }) : void 0);
113550
+ const historyDetail = readStatus ?? (spaces.length === 0 ? t("flowState.emptySpaces") : void 0);
113385
113551
  return /* @__PURE__ */ jsxs("div", {
113386
113552
  className: "flex flex-col gap-4",
113387
113553
  children: [space == null && /* @__PURE__ */ jsxs("section", {
113388
- className: "flex flex-col gap-2",
113554
+ "aria-label": t("flowState.values"),
113555
+ className: "flex flex-col gap-3 rounded-lg bg-muted/50 p-3",
113556
+ children: [/* @__PURE__ */ jsxs("div", {
113557
+ className: "flex items-center gap-3",
113558
+ children: [
113559
+ /* @__PURE__ */ jsxs("div", {
113560
+ className: "min-w-0 flex-1",
113561
+ children: [/* @__PURE__ */ jsx("h3", {
113562
+ className: "m-0 text-sm font-medium",
113563
+ children: t("flowState.values")
113564
+ }), valuesDetail != null && /* @__PURE__ */ jsx("p", {
113565
+ className: "mt-1 mb-0 text-xs text-muted-foreground",
113566
+ children: valuesDetail
113567
+ })]
113568
+ }),
113569
+ /* @__PURE__ */ jsx(Usage, {
113570
+ count: value?.values.count,
113571
+ limit: value?.limits.maxValues
113572
+ }),
113573
+ value != null && value.values.count > 0 && /* @__PURE__ */ jsx(StateClearButton, {
113574
+ name: t("flowState.values"),
113575
+ disabled: busy,
113576
+ onClear: onClearValues,
113577
+ container
113578
+ })
113579
+ ]
113580
+ }), value != null && value.values.count >= value.limits.maxValues * .8 && /* @__PURE__ */ jsx("p", {
113581
+ role: "status",
113582
+ className: "m-0 text-xs text-destructive",
113583
+ children: t("flowState.valuesNearLimit")
113584
+ })]
113585
+ }), /* @__PURE__ */ jsxs("section", {
113586
+ "aria-label": t("flowState.spaces"),
113587
+ className: "flex flex-col gap-3 rounded-lg bg-muted/50 p-3",
113389
113588
  children: [
113390
- /* @__PURE__ */ jsxs("div", {
113391
- className: "flex items-center justify-between gap-3",
113589
+ (space == null || spaces.length === 0) && /* @__PURE__ */ jsxs("div", {
113590
+ className: "flex items-center gap-3",
113392
113591
  children: [
113393
- /* @__PURE__ */ jsx("h3", {
113394
- className: "m-0 min-w-0 flex-1 text-sm font-medium",
113395
- children: t("flowState.values")
113592
+ /* @__PURE__ */ jsxs("div", {
113593
+ className: "min-w-0 flex-1",
113594
+ children: [/* @__PURE__ */ jsx("h3", {
113595
+ className: "m-0 text-sm font-medium",
113596
+ children: space == null ? t("flowState.spaces") : sourceName(space, nodes, t)
113597
+ }), historyDetail != null && /* @__PURE__ */ jsx("p", {
113598
+ className: "mt-1 mb-0 text-xs text-muted-foreground",
113599
+ children: historyDetail
113600
+ })]
113396
113601
  }),
113397
- /* @__PURE__ */ jsx("span", {
113398
- className: "text-xs text-muted-foreground",
113399
- children: t("flowState.entries", {
113400
- count: value.values.length.toLocaleString(),
113401
- limit: value.limits.maxValues.toLocaleString()
113402
- })
113602
+ space == null ? /* @__PURE__ */ jsx(Usage, {
113603
+ count,
113604
+ limit: value?.limits.maxIdentities
113605
+ }) : /* @__PURE__ */ jsx("span", {
113606
+ className: "text-sm tabular-nums",
113607
+ children: value == null ? "—" : t("flowState.records", { count: "0" })
113403
113608
  }),
113404
- value.values.length > 0 && /* @__PURE__ */ jsx(Button$1, {
113405
- variant: "outline",
113406
- size: "sm",
113609
+ space == null && allSpaces.length > 0 && /* @__PURE__ */ jsx(StateClearButton, {
113610
+ name: t("flowState.spaces"),
113407
113611
  disabled: busy,
113408
- onClick: (event) => onClearValues(void 0, event.currentTarget),
113409
- children: t("flowState.clearAll")
113612
+ reason: allSpaces.some((item) => item.pendingCount === 0) ? void 0 : t("flowState.clearBlocked"),
113613
+ onClear: onClearHistory,
113614
+ container
113410
113615
  })
113411
113616
  ]
113412
113617
  }),
113413
- !value.values.length && /* @__PURE__ */ jsx("p", {
113414
- className: "m-0 text-sm text-muted-foreground",
113415
- children: t("flowState.emptyValues")
113416
- }),
113417
- value.values.map((item) => /* @__PURE__ */ jsx(StateValueRow, {
113418
- item,
113419
- client,
113420
- flowId,
113421
- scope: value.scope,
113422
- busy,
113423
- onClear: onClearValues
113424
- }, item.key))
113425
- ]
113426
- }), /* @__PURE__ */ jsxs("section", {
113427
- className: "flex flex-col gap-2",
113428
- children: [
113429
- /* @__PURE__ */ jsxs("div", {
113430
- className: "flex items-center justify-between gap-3",
113431
- children: [/* @__PURE__ */ jsx("h3", {
113432
- className: "m-0 text-sm font-medium",
113433
- children: t("flowState.spaces")
113434
- }), /* @__PURE__ */ jsx("span", {
113435
- className: "text-xs text-muted-foreground",
113436
- children: t("flowState.entries", {
113437
- count: count.toLocaleString(),
113438
- limit: value.limits.maxIdentities.toLocaleString()
113439
- })
113440
- })]
113441
- }),
113442
- count >= value.limits.maxIdentities * .8 && /* @__PURE__ */ jsx("p", {
113618
+ value != null && count != null && count >= value.limits.maxIdentities * .8 && /* @__PURE__ */ jsx("p", {
113443
113619
  role: "status",
113444
- className: "m-0 text-destructive text-xs",
113620
+ className: "m-0 text-xs text-destructive",
113445
113621
  children: t("flowState.nearLimit")
113446
113622
  }),
113447
- !spaces.length && /* @__PURE__ */ jsx("p", {
113448
- className: "m-0 text-sm text-muted-foreground",
113449
- children: t("flowState.emptySpaces")
113450
- }),
113451
- spaces.map((item) => /* @__PURE__ */ jsxs("div", {
113452
- className: "flex items-start justify-between gap-3 border-b border-border/60 py-2",
113453
- children: [/* @__PURE__ */ jsxs("div", {
113454
- className: "min-w-0",
113455
- children: [/* @__PURE__ */ jsxs("p", {
113456
- className: "m-0 break-all font-medium",
113623
+ spaces.length > 0 && /* @__PURE__ */ jsxs("table", {
113624
+ "aria-label": t("flowState.source"),
113625
+ className: "w-full border-collapse text-sm",
113626
+ children: [/* @__PURE__ */ jsx("thead", {
113627
+ className: "sr-only",
113628
+ children: /* @__PURE__ */ jsxs("tr", {
113629
+ className: "text-xs text-muted-foreground",
113457
113630
  children: [
113458
- item.space,
113459
- " ",
113460
- item.space.startsWith("node:") && !nodeIds.includes(item.space.slice(5)) && /* @__PURE__ */ jsxs("span", {
113461
- className: "text-muted-foreground",
113462
- children: [
113463
- "(",
113464
- t("flowState.orphaned"),
113465
- ")"
113466
- ]
113631
+ /* @__PURE__ */ jsx("th", {
113632
+ scope: "col",
113633
+ className: "pb-2 text-left font-normal",
113634
+ children: t("flowState.source")
113635
+ }),
113636
+ /* @__PURE__ */ jsx("th", {
113637
+ scope: "col",
113638
+ className: "pb-2 pl-4 text-right font-normal",
113639
+ children: t("flowState.count")
113640
+ }),
113641
+ /* @__PURE__ */ jsx("th", {
113642
+ scope: "col",
113643
+ className: "pl-4",
113644
+ children: /* @__PURE__ */ jsx("span", {
113645
+ className: "sr-only",
113646
+ children: t("flowState.clear")
113647
+ })
113467
113648
  })
113468
113649
  ]
113469
- }), /* @__PURE__ */ jsxs("p", {
113470
- className: "m-0 text-xs",
113471
- children: [t("flowState.records", { count: item.count.toLocaleString() }), item.pendingCount > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [" · ", t("flowState.pendingRecords", { count: item.pendingCount.toLocaleString() })] })]
113472
- })]
113473
- }), /* @__PURE__ */ jsx(Button$1, {
113474
- variant: "outline",
113475
- size: "sm",
113476
- disabled: busy || item.pendingCount > 0,
113477
- onClick: (event) => onClearSpace(item.space, event.currentTarget),
113478
- children: t("flowState.clear")
113650
+ })
113651
+ }), /* @__PURE__ */ jsx("tbody", { children: spaces.map((item) => {
113652
+ const node = nodes.find((entry) => `node:${entry.id}` === item.space);
113653
+ const fallback = /* @__PURE__ */ jsx("i", {
113654
+ "aria-hidden": "true",
113655
+ className: "i-lucide-light:workflow"
113656
+ });
113657
+ return /* @__PURE__ */ jsx(StateDataRow, {
113658
+ name: sourceName(item.space, nodes, t),
113659
+ source: item.space.startsWith("node:") && node == null ? `${item.space} · ${t("flowState.orphaned")}` : item.space,
113660
+ icon: item.space === "flow" ? /* @__PURE__ */ jsx("i", {
113661
+ "aria-hidden": "true",
113662
+ className: "i-lucide-light:database"
113663
+ }) : /* @__PURE__ */ jsx(ContentIcon, {
113664
+ src: node?.icon,
113665
+ className: "size-4",
113666
+ fallback: /* @__PURE__ */ jsx(ContentIcon, {
113667
+ src: node?.fallbackIcon,
113668
+ className: "size-4",
113669
+ fallback
113670
+ })
113671
+ }),
113672
+ quantity: item.reservedCount.toLocaleString(language),
113673
+ updatedAt: item.updatedAt,
113674
+ status: space != null ? readStatus : void 0,
113675
+ disabled: busy,
113676
+ clearReason: item.pendingCount > 0 ? t("flowState.pendingClear", { count: item.pendingCount.toLocaleString(language) }) : void 0,
113677
+ onClear: (trigger) => onClearSpace(item.space, trigger),
113678
+ container
113679
+ }, item.space);
113680
+ }) })]
113681
+ }),
113682
+ space != null && /* @__PURE__ */ jsxs("p", {
113683
+ className: "m-0 flex flex-wrap items-baseline justify-between gap-2 border-t border-border/60 pt-3 text-xs text-muted-foreground",
113684
+ children: [/* @__PURE__ */ jsx("span", { children: t("flowState.globalUsage") }), /* @__PURE__ */ jsx(Usage, {
113685
+ count,
113686
+ limit: value?.limits.maxIdentities
113479
113687
  })]
113480
- }, item.space))
113688
+ })
113481
113689
  ]
113482
113690
  })]
113483
113691
  });
113484
113692
  }
113485
- function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
113693
+ function FlowStateButton({ client, flowId, nodes, history, notify, onClose }) {
113486
113694
  const t = useTranslate();
113695
+ const language = useLang();
113487
113696
  const [container, setContainer] = useState(null);
113488
- const portal = useCallback((element) => {
113489
- setContainer(element?.closest(".open-flow-workbench") ?? element?.closest(".open-flow-theme") ?? null);
113490
- }, []);
113697
+ const portal = useCallback((element) => setContainer(element?.closest(".open-flow-workbench, .open-flow-theme") ?? null), []);
113491
113698
  const [open, setOpen] = useState(onClose != null);
113492
113699
  const [scope, setScope] = useState("draft");
113493
113700
  const space = history == null ? void 0 : `node:${history.nodeId}`;
113494
- const [data, setData] = useState();
113495
- const [error, setError] = useState();
113701
+ const [read, setRead] = useState({
113702
+ scope: "draft",
113703
+ loading: true
113704
+ });
113705
+ const data = read.scope === scope ? read.data : void 0;
113706
+ const loading = read.scope !== scope || read.loading;
113496
113707
  const [busy, setBusy] = useState(false);
113708
+ const pending = useRef(false);
113497
113709
  const [refresh, setRefresh] = useState(0);
113498
113710
  const [confirm, setConfirm] = useState();
113499
113711
  const cancelButton = useRef(null);
113712
+ const dialogRoot = useRef(null);
113500
113713
  const confirmTrigger = useRef();
113501
- useEffect(() => {
113502
- if (confirm != null) cancelButton.current?.focus();
113503
- }, [confirm]);
113504
- const cancelConfirm = () => {
113505
- setConfirm(void 0);
113506
- confirmTrigger.current?.focus();
113507
- };
113508
113714
  useEffect(() => {
113509
113715
  if (!open) return;
113510
- let active = true;
113511
- setData(void 0);
113512
- setError(void 0);
113513
- client.getFlowState(flowId, scope).then((result) => {
113514
- if (active) setData(result);
113716
+ const controller = new AbortController();
113717
+ setRead((previous) => ({
113718
+ scope,
113719
+ data: previous.scope === scope ? previous.data : void 0,
113720
+ loading: true
113721
+ }));
113722
+ client.getFlowStateSummary(flowId, scope, controller.signal).then((result) => {
113723
+ if (!controller.signal.aborted) setRead({
113724
+ scope,
113725
+ data: result,
113726
+ loading: false
113727
+ });
113515
113728
  }, (reason) => {
113516
- if (active) setError(String(reason));
113729
+ if (!controller.signal.aborted) setRead((previous) => ({
113730
+ ...previous,
113731
+ loading: false,
113732
+ error: errorNotice(reason, t).message
113733
+ }));
113517
113734
  });
113518
- return () => {
113519
- active = false;
113520
- };
113735
+ return () => controller.abort();
113521
113736
  }, [
113522
113737
  client,
113523
113738
  flowId,
113524
113739
  scope,
113525
113740
  refresh,
113526
113741
  open,
113527
- space
113742
+ t
113528
113743
  ]);
113529
113744
  const clear = async (target) => {
113745
+ if (pending.current) return;
113746
+ pending.current = true;
113530
113747
  setBusy(true);
113531
- setError(void 0);
113532
113748
  try {
113533
- if (target.space != null) await client.clearFlowDedupe(flowId, scope, target.space);
113534
- else await client.clearFlowState(flowId, scope, target.key);
113749
+ if (target.kind === "values") await client.clearFlowState(flowId, target.scope);
113750
+ else if (target.space != null) await client.clearFlowDedupe(flowId, target.scope, target.space);
113751
+ else await client.clearAllFlowDedupe(flowId, target.scope);
113752
+ confirmTrigger.current = dialogRoot.current ?? void 0;
113535
113753
  setConfirm(void 0);
113536
113754
  setRefresh((value) => value + 1);
113755
+ dialogRoot.current?.focus();
113537
113756
  } catch (reason) {
113538
- setError(String(reason));
113757
+ const conflict = target.kind === "dedupe" && reason instanceof ApiError && reason.code === controlErrorCode.flowConflict;
113758
+ notify(conflict ? {
113759
+ kind: "error",
113760
+ message: t("flowState.clearBlocked")
113761
+ } : errorNotice(reason, t));
113762
+ if (conflict) {
113763
+ confirmTrigger.current = dialogRoot.current ?? void 0;
113764
+ setConfirm(void 0);
113765
+ setRefresh((value) => value + 1);
113766
+ }
113539
113767
  } finally {
113768
+ pending.current = false;
113540
113769
  setBusy(false);
113541
113770
  }
113542
113771
  };
113543
- const request = (target, trigger) => {
113772
+ const request = (kind, targetSpace, trigger) => {
113773
+ if (pending.current || data == null) return;
113774
+ const targets = data.spaces.filter((item) => targetSpace == null || item.space === targetSpace);
113775
+ if (kind === "dedupe" && !targets.some((item) => item.pendingCount === 0)) return;
113776
+ const target = {
113777
+ kind,
113778
+ scope,
113779
+ space: targetSpace,
113780
+ name: kind === "values" ? t("flowState.values") : targetSpace == null ? t("flowState.spaces") : sourceName(targetSpace, nodes, t),
113781
+ count: kind === "values" ? data.values.count : targets.filter((item) => item.pendingCount === 0).reduce((total, item) => total + item.count, 0),
113782
+ pendingCount: kind === "values" ? 0 : targets.reduce((total, item) => total + item.pendingCount, 0)
113783
+ };
113544
113784
  confirmTrigger.current = trigger;
113545
113785
  if (scope === "live") setConfirm(target);
113546
113786
  else clear(target);
@@ -113550,13 +113790,20 @@ function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
113550
113790
  ref: portal,
113551
113791
  children: /* @__PURE__ */ jsxs(Dialog, {
113552
113792
  open,
113553
- onOpenChange: (next) => {
113554
- if (!busy) {
113555
- setOpen(next);
113556
- if (next) setScope("draft");
113557
- if (!next) onClose?.();
113558
- setConfirm(void 0);
113793
+ onOpenChange: (next, details) => {
113794
+ if (pending.current) {
113795
+ details.cancel();
113796
+ return;
113559
113797
  }
113798
+ setOpen(next);
113799
+ setConfirm(void 0);
113800
+ if (next) {
113801
+ setScope("draft");
113802
+ setRead({
113803
+ scope: "draft",
113804
+ loading: true
113805
+ });
113806
+ } else onClose?.();
113560
113807
  },
113561
113808
  children: [onClose == null && /* @__PURE__ */ jsxs(DialogTrigger, {
113562
113809
  render: /* @__PURE__ */ jsx(Button$1, {
@@ -113568,121 +113815,150 @@ function FlowStateButton({ client, flowId, nodeIds, history, onClose }) {
113568
113815
  className: "i-lucide-light:database"
113569
113816
  }), t(space == null ? "flowState.title" : "flowState.history")]
113570
113817
  }), /* @__PURE__ */ jsxs(DialogContent, {
113818
+ ref: dialogRoot,
113571
113819
  container,
113572
- className: "max-h-[80vh] overflow-auto",
113820
+ className: "flex h-[min(32rem,80dvh)] flex-col overflow-hidden sm:max-w-2xl",
113573
113821
  closeLabel: t("common.close"),
113574
113822
  children: [
113575
- /* @__PURE__ */ jsx(DialogTitle, { children: t(space == null ? "flowState.title" : "flowState.history") }),
113576
- /* @__PURE__ */ jsxs("div", {
113577
- className: "flex flex-wrap items-center gap-3",
113578
- children: [
113579
- /* @__PURE__ */ jsxs(NativeSelect, {
113823
+ /* @__PURE__ */ jsx(DialogTitle, {
113824
+ className: "break-words pr-8",
113825
+ children: space == null ? t("flowState.title") : t("flowState.sourceHistory", { name: sourceName(space, nodes, t) })
113826
+ }),
113827
+ /* @__PURE__ */ jsxs(Tabs, {
113828
+ value: scope,
113829
+ onValueChange: (value) => {
113830
+ if (!pending.current) {
113831
+ setScope(value);
113832
+ setConfirm(void 0);
113833
+ }
113834
+ },
113835
+ className: "min-h-0 flex-1 gap-4",
113836
+ children: [/* @__PURE__ */ jsxs("div", {
113837
+ className: "flex shrink-0 items-center justify-between gap-2",
113838
+ children: [/* @__PURE__ */ jsxs(TabsList, {
113580
113839
  "aria-label": t("flowState.scope"),
113581
- value: scope,
113582
- disabled: busy,
113583
- onChange: (event) => {
113584
- setScope(event.target.value);
113585
- setConfirm(void 0);
113586
- },
113587
- children: [/* @__PURE__ */ jsx(NativeSelectOption, {
113840
+ children: [/* @__PURE__ */ jsx(TabsTrigger, {
113588
113841
  value: "draft",
113842
+ disabled: busy,
113589
113843
  children: t("flowState.draft")
113590
- }), /* @__PURE__ */ jsx(NativeSelectOption, {
113844
+ }), /* @__PURE__ */ jsx(TabsTrigger, {
113591
113845
  value: "live",
113846
+ disabled: busy,
113592
113847
  children: t("flowState.live")
113593
113848
  })]
113594
- }),
113595
- /* @__PURE__ */ jsx(Button$1, {
113596
- variant: "outline",
113597
- size: "sm",
113598
- disabled: busy,
113599
- onClick: () => setRefresh((value) => value + 1),
113600
- children: t("flowState.refresh")
113601
- }),
113602
- /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
113603
- render: /* @__PURE__ */ jsx(Button$1, {
113604
- variant: "ghost",
113605
- size: "xs",
113606
- className: "ml-auto text-muted-foreground"
113607
- }),
113608
- children: t("flowState.rules")
113609
- }), /* @__PURE__ */ jsx(TooltipContent, {
113610
- container,
113611
- className: "max-w-xs",
113612
- children: /* @__PURE__ */ jsxs("div", {
113613
- className: "flex flex-col gap-2",
113614
- children: [
113615
- /* @__PURE__ */ jsx("p", {
113616
- className: "m-0",
113617
- children: t("flowState.isolation")
113618
- }),
113619
- /* @__PURE__ */ jsx("p", {
113620
- className: "m-0",
113621
- children: t("flowState.retention")
113622
- }),
113623
- data != null && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("p", {
113624
- className: "m-0",
113625
- children: t("flowState.valueLimit", { size: data.limits.maxValueBytes.toLocaleString() })
113626
- }), /* @__PURE__ */ jsx("p", {
113627
- className: "m-0",
113628
- children: t("flowState.sharedLimit", {
113629
- count: data.spaces.length,
113630
- limit: data.limits.maxSpaces
113849
+ }), /* @__PURE__ */ jsxs("div", {
113850
+ className: "flex shrink-0 items-center gap-2",
113851
+ children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
113852
+ render: /* @__PURE__ */ jsx(Button$1, {
113853
+ "aria-label": t("flowState.refresh"),
113854
+ variant: "ghost",
113855
+ size: "icon-sm",
113856
+ disabled: busy || loading,
113857
+ onClick: () => setRefresh((value) => value + 1)
113858
+ }),
113859
+ children: /* @__PURE__ */ jsx("i", {
113860
+ "aria-hidden": "true",
113861
+ className: "i-lucide-light:refresh-cw"
113862
+ })
113863
+ }), /* @__PURE__ */ jsx(TooltipContent, {
113864
+ container,
113865
+ children: t("flowState.refresh")
113866
+ })] }), /* @__PURE__ */ jsx(HelpButton, {
113867
+ label: t("flowState.rules"),
113868
+ container,
113869
+ size: 28,
113870
+ children: /* @__PURE__ */ jsxs("div", {
113871
+ className: "flex flex-col gap-2",
113872
+ children: [
113873
+ /* @__PURE__ */ jsx("p", {
113874
+ className: "m-0",
113875
+ children: t("flowState.valuesHelp", { name: t("flowState.values") })
113876
+ }),
113877
+ /* @__PURE__ */ jsx("p", {
113878
+ className: "m-0",
113879
+ children: t("flowState.historyHelp", { name: t("flowState.spaces") })
113880
+ }),
113881
+ /* @__PURE__ */ jsx("p", {
113882
+ className: "m-0",
113883
+ children: t("flowState.isolation")
113631
113884
  })
113632
- })] })
113633
- ]
113634
- })
113635
- })] })
113636
- ]
113637
- }),
113638
- error && /* @__PURE__ */ jsx("p", {
113639
- role: "alert",
113640
- className: "text-destructive",
113641
- children: error
113642
- }),
113643
- confirm && /* @__PURE__ */ jsxs("div", {
113644
- role: "alert",
113645
- className: "flex flex-col gap-2 rounded border border-border p-3",
113646
- children: [
113647
- /* @__PURE__ */ jsx("p", { children: t("flowState.confirmLive") }),
113648
- /* @__PURE__ */ jsx("p", {
113649
- className: "break-all",
113650
- children: confirm.space ?? confirm.key ?? t("flowState.values")
113651
- }),
113652
- /* @__PURE__ */ jsxs("div", {
113653
- className: "flex gap-2",
113654
- children: [/* @__PURE__ */ jsx(Button$1, {
113655
- disabled: busy,
113656
- variant: "destructive",
113657
- onClick: () => void clear(confirm),
113658
- children: t("flowState.clear")
113659
- }), /* @__PURE__ */ jsx(Button$1, {
113660
- ref: cancelButton,
113661
- disabled: busy,
113662
- variant: "outline",
113663
- onClick: cancelConfirm,
113664
- children: t("flowState.cancel")
113885
+ ]
113886
+ })
113887
+ })]
113888
+ })]
113889
+ }), /* @__PURE__ */ jsx(NativeScrollArea, {
113890
+ className: "min-h-0 flex-1 overflow-y-auto",
113891
+ children: /* @__PURE__ */ jsxs(TabsContent, {
113892
+ value: scope,
113893
+ "aria-busy": busy || loading,
113894
+ children: [read.scope === scope && read.error != null && /* @__PURE__ */ jsxs("div", {
113895
+ className: "mb-3 flex flex-wrap items-center gap-2",
113896
+ children: [/* @__PURE__ */ jsx("p", {
113897
+ role: "alert",
113898
+ className: "m-0 min-w-0 flex-1 text-sm text-destructive",
113899
+ children: read.error
113900
+ }), /* @__PURE__ */ jsx(Button$1, {
113901
+ variant: "outline",
113902
+ size: "sm",
113903
+ disabled: loading || busy,
113904
+ onClick: () => setRefresh((value) => value + 1),
113905
+ children: t("flowState.retry")
113906
+ })]
113907
+ }), /* @__PURE__ */ jsx(FlowStatePanel, {
113908
+ value: data,
113909
+ loading,
113910
+ space,
113911
+ nodes,
113912
+ container,
113913
+ busy: busy || loading,
113914
+ onClearValues: (trigger) => request("values", void 0, trigger),
113915
+ onClearHistory: (trigger) => request("dedupe", void 0, trigger),
113916
+ onClearSpace: (sourceSpace, trigger) => request("dedupe", sourceSpace, trigger)
113665
113917
  })]
113666
113918
  })
113667
- ]
113919
+ })]
113668
113920
  }),
113669
- data == null ? /* @__PURE__ */ jsx("p", {
113670
- role: "status",
113671
- children: error == null ? t("flowState.loading") : ""
113672
- }) : /* @__PURE__ */ jsx(FlowStatePanel, {
113673
- value: data,
113674
- client,
113675
- flowId,
113676
- space,
113677
- nodeIds,
113678
- busy,
113679
- onClearValues: (key, trigger) => request({ key }, trigger),
113680
- onClearSpace: (targetSpace, trigger) => request({ space: targetSpace }, trigger)
113681
- }, JSON.stringify([
113682
- flowId,
113683
- scope,
113684
- refresh
113685
- ]))
113921
+ /* @__PURE__ */ jsx(Dialog, {
113922
+ open: confirm != null,
113923
+ onOpenChange: (next, details) => {
113924
+ if (pending.current) details.cancel();
113925
+ else if (!next) setConfirm(void 0);
113926
+ },
113927
+ children: /* @__PURE__ */ jsxs(DialogContent, {
113928
+ container,
113929
+ initialFocus: cancelButton,
113930
+ finalFocus: () => confirmTrigger.current?.isConnected ? confirmTrigger.current : dialogRoot.current,
113931
+ showCloseButton: false,
113932
+ children: [
113933
+ /* @__PURE__ */ jsx(DialogTitle, { children: t("flowState.confirmTitle", { name: confirm?.name ?? "" }) }),
113934
+ /* @__PURE__ */ jsx(DialogDescription, { children: confirm && t(confirm.kind === "values" ? "flowState.confirmValues" : "flowState.confirmHistory", {
113935
+ count: confirm.count.toLocaleString(language),
113936
+ scope: t(confirm.scope === "draft" ? "flowState.draft" : "flowState.live")
113937
+ }) }),
113938
+ confirm != null && confirm.pendingCount > 0 && /* @__PURE__ */ jsx("p", {
113939
+ className: "m-0 text-sm text-muted-foreground",
113940
+ children: t("flowState.retainedHistory", { count: confirm.pendingCount.toLocaleString(language) })
113941
+ }),
113942
+ /* @__PURE__ */ jsxs("div", {
113943
+ className: "flex justify-end gap-2",
113944
+ children: [/* @__PURE__ */ jsx(Button$1, {
113945
+ ref: cancelButton,
113946
+ disabled: busy,
113947
+ variant: "outline",
113948
+ onClick: () => setConfirm(void 0),
113949
+ children: t("flowState.cancel")
113950
+ }), /* @__PURE__ */ jsx(Button$1, {
113951
+ disabled: busy,
113952
+ variant: "destructive",
113953
+ onClick: () => {
113954
+ if (confirm != null) clear(confirm);
113955
+ },
113956
+ children: t("flowState.confirmClear")
113957
+ })]
113958
+ })
113959
+ ]
113960
+ })
113961
+ })
113686
113962
  ]
113687
113963
  })]
113688
113964
  })
@@ -115533,6 +115809,11 @@ function ResolutionDefinition({ disabled, selection, store }) {
115533
115809
  }
115534
115810
  //#endregion
115535
115811
  //#region src/workbench/browser/runtime/editor/skipDuplicatesSection.tsx
115812
+ var fieldsSchema = {
115813
+ type: "array",
115814
+ items: { type: "string" }
115815
+ };
115816
+ var ignoreDraft$1 = () => {};
115536
115817
  function SkipDuplicatesSection({ task, disabled, onSave, history }) {
115537
115818
  const t = useTranslate();
115538
115819
  const id = useId();
@@ -115555,21 +115836,14 @@ function SkipDuplicatesSection({ task, disabled, onSave, history }) {
115555
115836
  });
115556
115837
  }));
115557
115838
  const initial = task.executor.kind === "skip-duplicates" ? task.executor.fields : [];
115558
- const [fields, setFields] = useState(initial.length ? initial : [""]);
115559
- const inputs = useRef([]);
115560
- const focusField = useRef();
115561
- useEffect(() => {
115562
- if (focusField.current == null) return;
115563
- inputs.current[focusField.current]?.focus();
115564
- focusField.current = void 0;
115565
- }, [fields]);
115839
+ const [fields, setFields] = useState(initial);
115566
115840
  const [error, setError] = useState();
115567
115841
  useEffect(() => {
115568
115842
  const previous = changes.value;
115569
115843
  changes.sync(task.executor);
115570
115844
  if (previous.kind === "skip-duplicates" && changes.value.kind === "skip-duplicates" && !dequal$1(previous.fields, changes.value.fields)) {
115571
115845
  request.current?.abort();
115572
- setFields(changes.value.fields.length ? changes.value.fields : [""]);
115846
+ setFields(changes.value.fields);
115573
115847
  setError(void 0);
115574
115848
  }
115575
115849
  }, [changes, task.executor]);
@@ -115584,11 +115858,10 @@ function SkipDuplicatesSection({ task, disabled, onSave, history }) {
115584
115858
  request.current?.abort();
115585
115859
  const controller = new AbortController();
115586
115860
  request.current = controller;
115587
- const rows = next.length ? next : [""];
115588
- setFields(rows);
115861
+ setFields(next);
115589
115862
  await Promise.resolve();
115590
115863
  if (controller.signal.aborted || request.current !== controller) return;
115591
- const normalized = rows.map((field) => field.trim());
115864
+ const normalized = next.map((field) => field.trim());
115592
115865
  const parsed = skipDuplicatesConfigSchema.safeParse({ fields: normalized.filter(Boolean) });
115593
115866
  if (!parsed.success) {
115594
115867
  setError("invalid");
@@ -115610,87 +115883,60 @@ function SkipDuplicatesSection({ task, disabled, onSave, history }) {
115610
115883
  if (task.executor.kind !== "skip-duplicates") return null;
115611
115884
  return /* @__PURE__ */ jsx(InspectorSection, {
115612
115885
  title: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
115886
+ id: `${id}-label`,
115613
115887
  className: "min-w-0 flex-1",
115614
- children: t("flowState.nodeTitle")
115888
+ children: t("flowState.field")
115615
115889
  }), history] }),
115616
115890
  children: /* @__PURE__ */ jsxs("div", {
115617
115891
  className: "node-settings flex flex-col gap-3",
115618
- children: [
115619
- /* @__PURE__ */ jsxs(Field, { children: [
115620
- /* @__PURE__ */ jsx(FieldLabel, {
115621
- htmlFor: `${id}-field-0`,
115622
- children: t("flowState.field")
115623
- }),
115624
- fields.map((field, index) => /* @__PURE__ */ jsxs("div", {
115625
- className: "flex items-center gap-2",
115626
- children: [/* @__PURE__ */ jsx(Input, {
115627
- ref: (element) => {
115628
- inputs.current[index] = element;
115629
- },
115630
- id: `${id}-field-${index}`,
115631
- "aria-label": t("flowState.fieldIndex", { index: index + 1 }),
115632
- "aria-invalid": error === "invalid" || void 0,
115633
- "aria-describedby": error === "invalid" ? `${id}-error` : void 0,
115634
- disabled,
115635
- value: field,
115636
- placeholder: t(fields.length === 1 ? "flowState.fieldPlaceholder" : "flowState.pathPlaceholder"),
115637
- onChange: (event) => change(fields.map((value, at) => at === index ? event.target.value : value)),
115638
- onBlur: () => {
115639
- commit();
115640
- },
115641
- onKeyDown: (event) => {
115642
- if (event.key === "Enter") {
115643
- event.preventDefault();
115644
- event.currentTarget.blur();
115645
- }
115646
- }
115647
- }), !disabled && (fields.length > 1 || field !== "") && /* @__PURE__ */ jsx(Button$1, {
115648
- variant: "ghost",
115649
- size: "xs",
115650
- "aria-label": t("flowState.removeField", { index: index + 1 }),
115651
- onMouseDown: (event) => event.preventDefault(),
115652
- onClick: () => {
115653
- focusField.current = Math.max(0, index - 1);
115654
- commit(fields.filter((_, at) => at !== index));
115655
- },
115656
- children: t("flowState.delete")
115657
- })]
115658
- }, index)),
115659
- !disabled && /* @__PURE__ */ jsx("div", {
115660
- className: "flex",
115661
- children: /* @__PURE__ */ jsx(Button$1, {
115662
- variant: "ghost",
115663
- size: "sm",
115664
- onMouseDown: (event) => event.preventDefault(),
115665
- onClick: () => {
115666
- const empty = fields.findIndex((field) => field.trim() === "");
115667
- if (empty >= 0) {
115668
- inputs.current[empty]?.focus();
115669
- return;
115670
- }
115671
- focusField.current = fields.length;
115672
- change([...fields, ""]);
115673
- },
115674
- children: t("flowState.addField")
115675
- })
115676
- })
115677
- ] }),
115678
- error != null && /* @__PURE__ */ jsxs("div", {
115679
- role: "alert",
115680
- id: `${id}-error`,
115681
- children: [/* @__PURE__ */ jsx("p", { children: t(error === "invalid" ? "flowState.invalidFields" : "flowState.saveFailed") }), error === "save" && /* @__PURE__ */ jsx(Button$1, {
115892
+ children: [/* @__PURE__ */ jsxs(Field, {
115893
+ "aria-labelledby": `${id}-label`,
115894
+ "aria-invalid": error === "invalid" || void 0,
115895
+ "aria-describedby": `${id}-description${error === "invalid" ? ` ${id}-error` : ""}`,
115896
+ onBlur: (event) => {
115897
+ if (event.target instanceof HTMLInputElement) commit();
115898
+ },
115899
+ onKeyDown: (event) => {
115900
+ if (event.key === "Enter" && event.target instanceof HTMLInputElement) commit();
115901
+ },
115902
+ children: [/* @__PURE__ */ jsx(FieldDescription, {
115903
+ id: `${id}-description`,
115904
+ className: "text-xs",
115905
+ children: t("flowState.fieldDescription")
115906
+ }), /* @__PURE__ */ jsx(FieldTable, {
115907
+ layout: "values",
115908
+ typeColumn: false,
115909
+ columnHeadings: false,
115910
+ actionSlots: 2,
115911
+ standalone: true,
115912
+ children: /* @__PURE__ */ jsx(ArrayValueFields, {
115913
+ label: t("flowState.field"),
115914
+ showIndices: false,
115915
+ schema: fieldsSchema,
115916
+ value: fields,
115917
+ path: "/fields",
115682
115918
  disabled,
115683
- onClick: () => void commit(),
115684
- variant: "outline",
115685
- size: "sm",
115686
- children: t("flowState.retry")
115687
- })]
115688
- }),
115689
- /* @__PURE__ */ jsx("p", {
115690
- className: "m-0 text-muted-foreground text-xs",
115691
- children: t("flowState.warning")
115692
- })
115693
- ]
115919
+ readOnly: disabled,
115920
+ hideValueTools: true,
115921
+ onDraftIssue: ignoreDraft$1,
115922
+ onChange: (value) => {
115923
+ const next = value;
115924
+ change(next);
115925
+ if (next.length !== fields.length) commit(next);
115926
+ }
115927
+ })
115928
+ })]
115929
+ }), error != null && /* @__PURE__ */ jsxs("div", {
115930
+ role: "alert",
115931
+ id: `${id}-error`,
115932
+ children: [/* @__PURE__ */ jsx("p", { children: t(error === "invalid" ? "flowState.invalidFields" : "flowState.saveFailed") }), error === "save" && /* @__PURE__ */ jsx(Button$1, {
115933
+ disabled,
115934
+ onClick: () => void commit(),
115935
+ variant: "outline",
115936
+ size: "sm",
115937
+ children: t("flowState.retry")
115938
+ })]
115939
+ })]
115694
115940
  })
115695
115941
  });
115696
115942
  }
@@ -117658,7 +117904,13 @@ function NodeInspector({ onAddWorkflowOutputs, onAddResponseNode, webhookDeploym
117658
117904
  history: store != null && store.$.flowId.value != null ? /* @__PURE__ */ jsx(FlowStateButton, {
117659
117905
  client: store.state,
117660
117906
  flowId: store.$.flowId.value,
117661
- nodeIds: Object.keys(revision.graph()?.nodes ?? {}),
117907
+ nodes: selection?.kind === "task" ? [{
117908
+ id: selection.id,
117909
+ title: nodeTitle(selection, t),
117910
+ icon: sourceNodeIcons?.[selection.id] ?? semanticNodeIcon(selection, {}),
117911
+ fallbackIcon: nodeIcon(selection)
117912
+ }] : [],
117913
+ notify: store.notify,
117662
117914
  history: { nodeId: selection.id }
117663
117915
  }, selection.id) : void 0,
117664
117916
  onSave: (before, value) => store?.nodes.saveTaskSettings(selection.id, {
@@ -117725,19 +117977,39 @@ function NodeInspector({ onAddWorkflowOutputs, onAddResponseNode, webhookDeploym
117725
117977
  /** Layout restoration deliberately preserves the current viewport and other graphs. */
117726
117978
  function changeRevisionCanvasSession(session, graphId, change) {
117727
117979
  const previous = session[graphId];
117728
- const next = change.kind === "move" ? {
117729
- ...previous,
117730
- positions: {
117731
- ...previous?.positions,
117732
- ...change.positions
117733
- }
117734
- } : change.kind === "viewport" ? {
117735
- ...previous,
117736
- viewport: change.viewport
117737
- } : {
117738
- ...previous,
117739
- positions: void 0
117740
- };
117980
+ let next;
117981
+ switch (change.kind) {
117982
+ case "move":
117983
+ next = {
117984
+ ...previous,
117985
+ positions: {
117986
+ ...previous?.positions,
117987
+ ...change.positions
117988
+ }
117989
+ };
117990
+ break;
117991
+ case "direction":
117992
+ next = {
117993
+ ...previous,
117994
+ direction: change.direction,
117995
+ positions: {
117996
+ ...previous?.positions,
117997
+ ...change.positions
117998
+ }
117999
+ };
118000
+ break;
118001
+ case "viewport":
118002
+ next = {
118003
+ ...previous,
118004
+ viewport: change.viewport
118005
+ };
118006
+ break;
118007
+ case "restore": next = {
118008
+ ...previous,
118009
+ direction: void 0,
118010
+ positions: void 0
118011
+ };
118012
+ }
117741
118013
  return {
117742
118014
  ...session,
117743
118015
  [graphId]: next
@@ -117821,22 +118093,20 @@ function RevisionCanvas({ draft, presentation, theme, interactiveMode$, label, b
117821
118093
  const session = sessions[graphId];
117822
118094
  const model = useMemo(() => ({
117823
118095
  ...baseline,
118096
+ direction: session?.direction ?? baseline.direction,
117824
118097
  viewport: session?.viewport ?? baseline.viewport,
117825
118098
  nodes: baseline.nodes.map((node) => ({
117826
118099
  ...node,
117827
118100
  position: session?.positions?.[node.id] ?? node.position
117828
118101
  }))
117829
118102
  }), [baseline, session]);
117830
- const moved = baseline.nodes.some((node) => {
118103
+ const layoutChanged = model.direction !== baseline.direction || baseline.nodes.some((node) => {
117831
118104
  const position = session?.positions?.[node.id];
117832
118105
  return position != null && (position.x !== node.position.x || position.y !== node.position.y);
117833
118106
  });
117834
118107
  const selection = selected.length === 1 ? revision.node(selected[0]) : void 0;
117835
118108
  const comment = selected.length === 1 ? model.nodes.find((node) => node.id === selected[0] && node.kind === "comment") : void 0;
117836
- const navigation = presentation == null || moved ? /* @__PURE__ */ jsxs(Fragment$1, { children: [presentation == null && /* @__PURE__ */ jsx("span", {
117837
- className: "revision-viewer-hint",
117838
- children: t("snapshot.missingLayout")
117839
- }), moved && /* @__PURE__ */ jsxs(Button$1, {
118109
+ const restoreLayout = layoutChanged ? /* @__PURE__ */ jsxs(Button$1, {
117840
118110
  className: "ml-auto",
117841
118111
  size: "xs",
117842
118112
  variant: "ghost",
@@ -117845,7 +118115,7 @@ function RevisionCanvas({ draft, presentation, theme, interactiveMode$, label, b
117845
118115
  "aria-hidden": "true",
117846
118116
  className: "i-lucide-light:rotate-ccw"
117847
118117
  }), t("snapshot.restore")]
117848
- })] }) : void 0;
118118
+ }) : void 0;
117849
118119
  return /* @__PURE__ */ jsxs("section", {
117850
118120
  ref: root,
117851
118121
  className: `revision-viewer${inspectorOpen ? " inspector-open" : ""}`,
@@ -117858,7 +118128,7 @@ function RevisionCanvas({ draft, presentation, theme, interactiveMode$, label, b
117858
118128
  "aria-hidden": "true",
117859
118129
  className: "i-lucide-light:lock-keyhole"
117860
118130
  }), label ?? t("snapshot.title")]
117861
- }), navigation]
118131
+ }), restoreLayout]
117862
118132
  }), /* @__PURE__ */ jsxs("div", {
117863
118133
  className: "revision-viewer-body",
117864
118134
  children: [/* @__PURE__ */ jsxs("div", {
@@ -117881,6 +118151,14 @@ function RevisionCanvas({ draft, presentation, theme, interactiveMode$, label, b
117881
118151
  kind: "move",
117882
118152
  positions
117883
118153
  })),
118154
+ onChangeDirection: (direction, positions) => {
118155
+ setSessions((current) => changeRevisionCanvasSession(current, graphId, {
118156
+ kind: "direction",
118157
+ direction,
118158
+ positions
118159
+ }));
118160
+ return true;
118161
+ },
117884
118162
  onMoveViewport: (viewport) => setSessions((current) => changeRevisionCanvasSession(current, graphId, {
117885
118163
  kind: "viewport",
117886
118164
  viewport
@@ -117888,7 +118166,7 @@ function RevisionCanvas({ draft, presentation, theme, interactiveMode$, label, b
117888
118166
  onSelectionChange: setSelected,
117889
118167
  onInspectSelection: () => setInspectorOpen((open) => !open),
117890
118168
  inspectorOpen,
117891
- toolbar: showHeader ? void 0 : navigation,
118169
+ toolbar: showHeader ? void 0 : restoreLayout,
117892
118170
  cornerTools: /* @__PURE__ */ jsx(WorkbenchInspectorToggle, {
117893
118171
  label: t("designer.toggleInspector"),
117894
118172
  open: inspectorOpen,