@nocobase/plugin-flow-engine 2.2.0-beta.3 → 2.2.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/client/index.js +1 -1
  2. package/dist/externalVersion.js +9 -9
  3. package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
  4. package/dist/node_modules/acorn/package.json +1 -1
  5. package/dist/node_modules/acorn-jsx/package.json +1 -1
  6. package/dist/node_modules/acorn-walk/package.json +1 -1
  7. package/dist/node_modules/ses/package.json +1 -1
  8. package/dist/node_modules/zod/package.json +1 -1
  9. package/dist/server/flow-surfaces/authoring-validation.js +80 -7
  10. package/dist/server/flow-surfaces/blueprint/export-document.js +3 -1
  11. package/dist/server/flow-surfaces/builder.js +16 -1
  12. package/dist/server/flow-surfaces/catalog.js +3 -1
  13. package/dist/server/flow-surfaces/configure-options.js +4 -3
  14. package/dist/server/flow-surfaces/contract-guard.js +24 -2
  15. package/dist/server/flow-surfaces/planning/key-registry.d.ts +1 -1
  16. package/dist/server/flow-surfaces/runjs-authoring/rules.js +0 -2
  17. package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.d.ts +0 -1
  18. package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.js +11 -19
  19. package/dist/server/flow-surfaces/runjs-authoring/runtime/types.d.ts +0 -12
  20. package/dist/server/flow-surfaces/runjs-authoring/scan/index.d.ts +0 -14
  21. package/dist/server/flow-surfaces/runjs-authoring/scan/index.js +1 -7
  22. package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.d.ts +0 -14
  23. package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.js +18 -73
  24. package/dist/server/flow-surfaces/runjs-authoring/types.d.ts +1 -1
  25. package/dist/server/flow-surfaces/runjs-authoring/validators/index.js +9 -53
  26. package/dist/server/flow-surfaces/service.d.ts +23 -0
  27. package/dist/server/flow-surfaces/service.js +538 -73
  28. package/dist/server/variables/registry.js +3 -0
  29. package/package.json +2 -2
  30. package/dist/server/flow-surfaces/runjs-authoring/blocked-global-stop/index.d.ts +0 -10
  31. package/dist/server/flow-surfaces/runjs-authoring/blocked-global-stop/index.js +0 -40
@@ -235,6 +235,7 @@ const FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE = "exportBlueprint v1 only
235
235
  const FORM_BLOCK_USES = /* @__PURE__ */ new Set(["FormBlockModel", "CreateFormModel", "EditFormModel", ...import_approval.APPROVAL_FORM_BLOCK_USES]);
236
236
  const AUTO_SUBMIT_FORM_BLOCK_USES = /* @__PURE__ */ new Set(["CreateFormModel", "EditFormModel"]);
237
237
  const FLOW_SURFACE_DEFAULT_ACTION_SETTINGS_KEYS = /* @__PURE__ */ new Set(["filter"]);
238
+ const ACTION_BUTTON_GENERAL_SETTING_KEYS = ["title", "tooltip", "icon", "iconOnly", "type", "danger", "color"];
238
239
  const DETAILS_BLOCK_USES = /* @__PURE__ */ new Set(["DetailsBlockModel", ...import_approval.APPROVAL_DETAILS_BLOCK_USES]);
239
240
  const SIMPLE_FORM_BLOCK_USES = /* @__PURE__ */ new Set([
240
241
  "FormBlockModel",
@@ -688,6 +689,7 @@ function assertNoFlowSurfaceIdTitleFieldSettings(value, options = {}) {
688
689
  };
689
690
  visit(value, options.basePath || []);
690
691
  }
692
+ const DEFAULT_ADMIN_UI_LAYOUT_UID = "admin-layout-model";
691
693
  class FlowSurfacesService {
692
694
  constructor(plugin) {
693
695
  this.plugin = plugin;
@@ -1029,6 +1031,101 @@ class FlowSurfacesService {
1029
1031
  ...extras
1030
1032
  };
1031
1033
  }
1034
+ hasDesktopRouteUiLayoutsRelation() {
1035
+ var _a, _b;
1036
+ try {
1037
+ return !!this.db.getCollection("uiLayouts") && !!((_b = (_a = this.db.getCollection("desktopRoutes")) == null ? void 0 : _a.getField) == null ? void 0 : _b.call(_a, "uiLayouts"));
1038
+ } catch (error) {
1039
+ return false;
1040
+ }
1041
+ }
1042
+ normalizeDesktopRouteRelationId(routeId) {
1043
+ return import_lodash.default.isNil(routeId) ? void 0 : routeId;
1044
+ }
1045
+ async readDesktopRouteUiLayoutUids(routeId, transaction) {
1046
+ const relationRouteId = this.normalizeDesktopRouteRelationId(routeId);
1047
+ if (import_lodash.default.isUndefined(relationRouteId) || !this.hasDesktopRouteUiLayoutsRelation()) {
1048
+ return [];
1049
+ }
1050
+ const uiLayouts = await this.db.getRepository("desktopRoutes.uiLayouts", relationRouteId).find({
1051
+ fields: ["uid"],
1052
+ transaction
1053
+ });
1054
+ return import_lodash.default.uniq(
1055
+ uiLayouts.map((uiLayout) => {
1056
+ var _a;
1057
+ return String(((_a = uiLayout == null ? void 0 : uiLayout.get) == null ? void 0 : _a.call(uiLayout, "uid")) || (uiLayout == null ? void 0 : uiLayout.uid) || "").trim();
1058
+ }).filter(Boolean)
1059
+ );
1060
+ }
1061
+ async resolveDefaultDesktopRouteUiLayoutUids(transaction) {
1062
+ if (!this.hasDesktopRouteUiLayoutsRelation()) {
1063
+ return [];
1064
+ }
1065
+ const defaultLayout = await this.db.getRepository("uiLayouts").findOne({
1066
+ filter: {
1067
+ uid: DEFAULT_ADMIN_UI_LAYOUT_UID,
1068
+ enabled: true
1069
+ },
1070
+ transaction
1071
+ });
1072
+ return defaultLayout ? [DEFAULT_ADMIN_UI_LAYOUT_UID] : [];
1073
+ }
1074
+ async resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction) {
1075
+ const parentRouteId = this.readRouteField(parentRoute, "id");
1076
+ if (!import_lodash.default.isNil(parentRouteId)) {
1077
+ const parentLayoutUids = await this.readDesktopRouteUiLayoutUids(parentRouteId, transaction);
1078
+ if (parentLayoutUids.length) {
1079
+ return parentLayoutUids;
1080
+ }
1081
+ }
1082
+ return this.resolveDefaultDesktopRouteUiLayoutUids(transaction);
1083
+ }
1084
+ async setDesktopRouteUiLayouts(routeId, uiLayoutUids, transaction) {
1085
+ const relationRouteId = this.normalizeDesktopRouteRelationId(routeId);
1086
+ if (import_lodash.default.isUndefined(relationRouteId) || !uiLayoutUids.length || !this.hasDesktopRouteUiLayoutsRelation()) {
1087
+ return;
1088
+ }
1089
+ await this.db.getRepository("desktopRoutes.uiLayouts", relationRouteId).set({
1090
+ tk: uiLayoutUids,
1091
+ transaction
1092
+ });
1093
+ }
1094
+ async attachDesktopRouteUiLayoutsToRouteAndChildren(routeId, uiLayoutUids, transaction) {
1095
+ if (import_lodash.default.isNil(routeId) || !uiLayoutUids.length || !this.hasDesktopRouteUiLayoutsRelation()) {
1096
+ return;
1097
+ }
1098
+ await this.setDesktopRouteUiLayouts(routeId, uiLayoutUids, transaction);
1099
+ const children = await this.db.getRepository("desktopRoutes").find({
1100
+ fields: ["id"],
1101
+ filter: {
1102
+ parentId: routeId
1103
+ },
1104
+ transaction
1105
+ });
1106
+ for (const child of children) {
1107
+ await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
1108
+ this.readRouteField(child, "id"),
1109
+ uiLayoutUids,
1110
+ transaction
1111
+ );
1112
+ }
1113
+ }
1114
+ async ensureDesktopRouteUiLayouts(route, transaction) {
1115
+ const routeId = this.readRouteField(route, "id");
1116
+ if (import_lodash.default.isNil(routeId) || !this.hasDesktopRouteUiLayoutsRelation()) {
1117
+ return [];
1118
+ }
1119
+ const existingLayoutUids = await this.readDesktopRouteUiLayoutUids(routeId, transaction);
1120
+ if (existingLayoutUids.length) {
1121
+ return existingLayoutUids;
1122
+ }
1123
+ const parentRouteId = this.readRouteField(route, "parentId");
1124
+ const parentRoute = import_lodash.default.isNil(parentRouteId) ? null : await this.findMenuRouteById(parentRouteId, transaction);
1125
+ const inheritedLayoutUids = await this.resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction);
1126
+ await this.setDesktopRouteUiLayouts(routeId, inheritedLayoutUids, transaction);
1127
+ return inheritedLayoutUids;
1128
+ }
1032
1129
  isValidMenuIconName(value) {
1033
1130
  const normalized = String(value || "").trim();
1034
1131
  return !!normalized && ANT_DESIGN_ICON_NAMES.has(normalized);
@@ -1110,7 +1207,7 @@ class FlowSurfacesService {
1110
1207
  this.assertVisibleNavigationIcon("createMenu", "values", values);
1111
1208
  const schemaUid = values.schemaUid || (0, import_utils.uid)();
1112
1209
  const desktopRoutes = this.db.getRepository("desktopRoutes");
1113
- await desktopRoutes.create({
1210
+ const route = await desktopRoutes.create({
1114
1211
  values: {
1115
1212
  type: "group",
1116
1213
  sort: this.allocateRouteSortValue(),
@@ -1123,10 +1220,11 @@ class FlowSurfacesService {
1123
1220
  },
1124
1221
  transaction
1125
1222
  });
1126
- const route = await desktopRoutes.findOne({
1127
- filter: { schemaUid },
1223
+ await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
1224
+ this.readRouteField(route, "id"),
1225
+ await this.resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction),
1128
1226
  transaction
1129
- });
1227
+ );
1130
1228
  return this.buildMenuResult(route);
1131
1229
  }
1132
1230
  async createFlowMenuItem(values, transaction) {
@@ -1141,7 +1239,7 @@ class FlowSurfacesService {
1141
1239
  const title = values.title || pageSchemaUid;
1142
1240
  const tabTitle = values.tabTitle || "Untitled";
1143
1241
  const desktopRoutes = this.db.getRepository("desktopRoutes");
1144
- await desktopRoutes.create({
1242
+ const createdRoute = await desktopRoutes.create({
1145
1243
  values: {
1146
1244
  type: "flowPage",
1147
1245
  sort: this.allocateRouteSortValue(),
@@ -1176,6 +1274,11 @@ class FlowSurfacesService {
1176
1274
  },
1177
1275
  transaction
1178
1276
  });
1277
+ await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
1278
+ this.readRouteField(createdRoute, "id"),
1279
+ await this.resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction),
1280
+ transaction
1281
+ );
1179
1282
  const route = await desktopRoutes.findOne({
1180
1283
  filter: { schemaUid: pageSchemaUid },
1181
1284
  appends: ["children"],
@@ -1948,6 +2051,9 @@ class FlowSurfacesService {
1948
2051
  if (!(popupProfile == null ? void 0 : popupProfile.currentCollection)) {
1949
2052
  return popupProfile == null ? void 0 : popupProfile.filterByTk;
1950
2053
  }
2054
+ if (popupProfile.popupKind === "recordPopup" && popupProfile.popupHostUse && POPUP_HOST_DEFAULT_RECORD_CONTEXT_ACTION_USES.has(popupProfile.popupHostUse)) {
2055
+ return "{{ctx.view.inputArgs.filterByTk}}";
2056
+ }
1951
2057
  if (popupProfile.popupKind !== "associationPopup") {
1952
2058
  return popupProfile.filterByTk;
1953
2059
  }
@@ -2303,10 +2409,18 @@ class FlowSurfacesService {
2303
2409
  if (!sameCurrentCollection || !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.filterByTk)) {
2304
2410
  return false;
2305
2411
  }
2412
+ const expectedFilterByTk = this.resolvePopupCurrentRecordResourceFilterByTk(input.popupProfile, {
2413
+ usePopupInputArgsWhenSourceIdInferred: true
2414
+ });
2415
+ const matchesCurrentRecordFilterByTk = this.isPopupCurrentRecordFilterByTkMatch(
2416
+ input.popupProfile,
2417
+ normalized.filterByTk,
2418
+ expectedFilterByTk
2419
+ );
2306
2420
  if (input.popupProfile.hasAssociationContext) {
2307
- return this.isSameConfiguredFlowContextValue(normalized.filterByTk, input.popupProfile.filterByTk) && normalized.associationName === input.popupProfile.associationName && this.isSameConfiguredFlowContextValue(normalized.sourceId, input.popupProfile.sourceId);
2421
+ return matchesCurrentRecordFilterByTk && normalized.associationName === input.popupProfile.associationName && this.isSameConfiguredFlowContextValue(normalized.sourceId, input.popupProfile.sourceId);
2308
2422
  }
2309
- return this.isSameConfiguredFlowContextValue(normalized.filterByTk, input.popupProfile.filterByTk) && !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.associationName) && !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.sourceId);
2423
+ return matchesCurrentRecordFilterByTk && !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.associationName) && !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.sourceId);
2310
2424
  }
2311
2425
  if (input.binding === "associatedRecords") {
2312
2426
  if (!(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.collectionName) || !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.associationName) || !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.sourceId) || (0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.filterByTk)) {
@@ -2349,6 +2463,12 @@ class FlowSurfacesService {
2349
2463
  }
2350
2464
  return import_lodash.default.isEqual(this.normalizeFlowContextTemplateValue(left), this.normalizeFlowContextTemplateValue(right));
2351
2465
  }
2466
+ isPopupCurrentRecordFilterByTkMatch(popupProfile, filterByTk, expectedFilterByTk) {
2467
+ if (this.isSameConfiguredFlowContextValue(filterByTk, expectedFilterByTk)) {
2468
+ return true;
2469
+ }
2470
+ return popupProfile.popupKind === "associationPopup" && this.isSameConfiguredFlowContextValue(filterByTk, popupProfile.filterByTk);
2471
+ }
2352
2472
  isPopupAssociatedRecordsSourceIdMatch(popupProfile, associationField, sourceId) {
2353
2473
  var _a, _b;
2354
2474
  if (!(0, import_service_helpers.hasConfiguredFlowContextValue)(sourceId)) {
@@ -4536,10 +4656,16 @@ class FlowSurfacesService {
4536
4656
  return this.buildPopupTemplateOpenView(template, "reference", templateTargetUid, options);
4537
4657
  }
4538
4658
  shouldHydrateDetachedPopupTemplateBlockResourceContext(blockNode, context) {
4539
- if (!this.isCollectionBlockUse(blockNode == null ? void 0 : blockNode.use) || !context.associationName || !context.sourceId) {
4659
+ if (!this.isCollectionBlockUse(blockNode == null ? void 0 : blockNode.use)) {
4540
4660
  return false;
4541
4661
  }
4542
4662
  const init = import_lodash.default.get(blockNode, ["stepParams", "resourceSettings", "init"]) || {};
4663
+ if (this.resolveDetachedPopupTemplateBlockCurrentRecordFilterByTk(init, context)) {
4664
+ return true;
4665
+ }
4666
+ if (!context.associationName || !context.sourceId) {
4667
+ return false;
4668
+ }
4543
4669
  const popupDataSourceKey = context.dataSourceKey || "main";
4544
4670
  const blockDataSourceKey = init.dataSourceKey || "main";
4545
4671
  if (!context.collectionName || blockDataSourceKey !== popupDataSourceKey || init.collectionName !== context.collectionName) {
@@ -4554,6 +4680,28 @@ class FlowSurfacesService {
4554
4680
  }
4555
4681
  return blockAssociationName !== context.associationName || !this.isSameConfiguredFlowContextValue(init.sourceId, context.sourceId);
4556
4682
  }
4683
+ resolveDetachedPopupTemplateBlockCurrentRecordFilterByTk(init, context) {
4684
+ if (!(0, import_service_helpers.hasConfiguredFlowContextValue)(init.filterByTk)) {
4685
+ return void 0;
4686
+ }
4687
+ if (this.isSameConfiguredFlowContextValue(init.filterByTk, "{{ctx.view.inputArgs.filterByTk}}")) {
4688
+ return void 0;
4689
+ }
4690
+ const popupDataSourceKey = context.dataSourceKey || "main";
4691
+ const blockDataSourceKey = init.dataSourceKey || "main";
4692
+ if (!context.collectionName || blockDataSourceKey !== popupDataSourceKey || init.collectionName !== context.collectionName) {
4693
+ return void 0;
4694
+ }
4695
+ if (context.filterByTk && this.isSameConfiguredFlowContextValue(init.filterByTk, context.filterByTk)) {
4696
+ return "{{ctx.view.inputArgs.filterByTk}}";
4697
+ }
4698
+ const collection = this.getCollection(popupDataSourceKey, context.collectionName);
4699
+ const filterTargetKey = this.getCollectionFilterTargetKey(collection);
4700
+ if (this.isSameConfiguredFlowContextValue(init.filterByTk, `{{ctx.record.${filterTargetKey}}}`)) {
4701
+ return "{{ctx.view.inputArgs.filterByTk}}";
4702
+ }
4703
+ return void 0;
4704
+ }
4557
4705
  collectDetachedPopupTemplateBlockResourceContextPatches(node, context, patches = []) {
4558
4706
  if (!node || typeof node !== "object") {
4559
4707
  return patches;
@@ -4561,6 +4709,7 @@ class FlowSurfacesService {
4561
4709
  if (node.uid && this.shouldHydrateDetachedPopupTemplateBlockResourceContext(node, context)) {
4562
4710
  const nextStepParams = import_lodash.default.cloneDeep(node.stepParams || {});
4563
4711
  const currentInit = import_lodash.default.get(nextStepParams, ["resourceSettings", "init"]) || {};
4712
+ const filterByTk = this.resolveDetachedPopupTemplateBlockCurrentRecordFilterByTk(currentInit, context);
4564
4713
  import_lodash.default.set(
4565
4714
  nextStepParams,
4566
4715
  ["resourceSettings", "init"],
@@ -4568,8 +4717,11 @@ class FlowSurfacesService {
4568
4717
  ...currentInit,
4569
4718
  dataSourceKey: context.dataSourceKey || currentInit.dataSourceKey || "main",
4570
4719
  collectionName: context.collectionName || currentInit.collectionName,
4571
- associationName: context.associationName,
4572
- sourceId: context.sourceId
4720
+ ...context.associationName && context.sourceId ? {
4721
+ associationName: context.associationName,
4722
+ sourceId: context.sourceId
4723
+ } : {},
4724
+ ...filterByTk ? { filterByTk } : {}
4573
4725
  })
4574
4726
  );
4575
4727
  patches.push({
@@ -5829,7 +5981,7 @@ class FlowSurfacesService {
5829
5981
  (0, import_errors.throwBadRequest)("flowSurfaces updateMenu requires menuRouteId");
5830
5982
  }
5831
5983
  const route = await this.assertMenuRouteUpdatable(menuRouteId, options.transaction);
5832
- await this.assertMenuParentIsGroup(values.parentMenuRouteId, options.transaction);
5984
+ const nextParentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, options.transaction);
5833
5985
  await this.assertMenuParentNotSelfOrDescendant(route, values.parentMenuRouteId, options.transaction);
5834
5986
  const nextOptions = { ...this.readRouteOptions(route) };
5835
5987
  const updateValues = {};
@@ -5860,6 +6012,13 @@ class FlowSurfacesService {
5860
6012
  });
5861
6013
  }
5862
6014
  const updated = await this.findMenuRouteById(menuRouteId, options.transaction);
6015
+ if (updated && Object.prototype.hasOwnProperty.call(values, "parentMenuRouteId")) {
6016
+ await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
6017
+ this.readRouteField(updated, "id"),
6018
+ await this.resolveInheritedDesktopRouteUiLayoutUids(nextParentRoute, options.transaction),
6019
+ options.transaction
6020
+ );
6021
+ }
5863
6022
  return this.buildMenuResult(updated);
5864
6023
  }
5865
6024
  async initializeFlowPageForRoute(route, values, transaction) {
@@ -5867,6 +6026,7 @@ class FlowSurfacesService {
5867
6026
  const pageSchemaUid = this.readRouteField(route, "schemaUid");
5868
6027
  const structure = await this.loadRouteBackedPageStructure(route, transaction);
5869
6028
  let tabRoute = structure.tabRoutes[0];
6029
+ const routeUiLayoutUids = await this.ensureDesktopRouteUiLayouts(route, transaction);
5870
6030
  const routeOptions = this.readRouteOptions(route);
5871
6031
  if (!routeOptions[FLOW_SURFACE_MENU_BINDABLE_OPTION_KEY]) {
5872
6032
  (0, import_errors.throwBadRequest)(`flowSurfaces createPage only accepts a bindable menu route created by createMenu(type="item")`);
@@ -5888,7 +6048,7 @@ class FlowSurfacesService {
5888
6048
  const tabSchemaUid2 = values.tabSchemaUid || (0, import_utils.uid)();
5889
6049
  const tabSchemaName2 = values.tabSchemaName || (0, import_utils.uid)();
5890
6050
  const tabTitle = values.tabTitle || "Untitled";
5891
- await this.db.getRepository("desktopRoutes").create({
6051
+ tabRoute = await this.db.getRepository("desktopRoutes").create({
5892
6052
  values: {
5893
6053
  type: "tabs",
5894
6054
  sort: this.allocateRouteSortValue(1),
@@ -5905,10 +6065,7 @@ class FlowSurfacesService {
5905
6065
  },
5906
6066
  transaction
5907
6067
  });
5908
- tabRoute = await this.db.getRepository("desktopRoutes").findOne({
5909
- filter: { schemaUid: tabSchemaUid2 },
5910
- transaction
5911
- });
6068
+ await this.setDesktopRouteUiLayouts(this.readRouteField(tabRoute, "id"), routeUiLayoutUids, transaction);
5912
6069
  } else {
5913
6070
  await this.db.getRepository("desktopRoutes").update({
5914
6071
  filterByTk: String(this.readRouteField(tabRoute, "id")),
@@ -5932,6 +6089,9 @@ class FlowSurfacesService {
5932
6089
  transaction
5933
6090
  });
5934
6091
  }
6092
+ if (tabRoute) {
6093
+ await this.setDesktopRouteUiLayouts(this.readRouteField(tabRoute, "id"), routeUiLayoutUids, transaction);
6094
+ }
5935
6095
  await this.ensureFlowRoutePageSchemaShell(pageSchemaUid, transaction);
5936
6096
  await this.db.getRepository("desktopRoutes").update({
5937
6097
  filterByTk: String(routeId),
@@ -6071,6 +6231,11 @@ class FlowSurfacesService {
6071
6231
  },
6072
6232
  transaction: options.transaction
6073
6233
  });
6234
+ await this.setDesktopRouteUiLayouts(
6235
+ route.get("id"),
6236
+ await this.ensureDesktopRouteUiLayouts(pageRoute, options.transaction),
6237
+ options.transaction
6238
+ );
6074
6239
  const gridUid = await this.ensureGridChild(tabSchemaUid, "BlockGridModel", options.transaction);
6075
6240
  const result = {
6076
6241
  pageUid: pageTarget.uid,
@@ -11474,6 +11639,7 @@ class FlowSurfacesService {
11474
11639
  }
11475
11640
  if (this.isAIEmployeeActionUse(current == null ? void 0 : current.use) && this.hasAIEmployeePublicSettings(normalizedValues)) {
11476
11641
  const enabledPackages = await this.resolveEnabledPluginPackages(options);
11642
+ const hasRawAIEmployeeStepTasks = import_lodash.default.has(normalizedValues, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
11477
11643
  const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
11478
11644
  "updateSettings",
11479
11645
  import_lodash.default.pick(normalizedValues, AI_EMPLOYEE_PUBLIC_SETTING_KEYS),
@@ -11486,7 +11652,8 @@ class FlowSurfacesService {
11486
11652
  promptContext: {
11487
11653
  kind: "target",
11488
11654
  targetUid: (current == null ? void 0 : current.uid) || writeTarget.uid
11489
- }
11655
+ },
11656
+ skipExistingTaskWorkContextRebase: hasRawAIEmployeeStepTasks
11490
11657
  }
11491
11658
  );
11492
11659
  AI_EMPLOYEE_PUBLIC_SETTING_KEYS.forEach((key) => {
@@ -11568,6 +11735,7 @@ class FlowSurfacesService {
11568
11735
  normalizedValues,
11569
11736
  nextPayload
11570
11737
  );
11738
+ this.syncActionButtonSettingsForUpdateSettings(current, normalizedValues, nextPayload);
11571
11739
  this.syncActionTriggerWorkflowsForUpdateSettings(current, normalizedValues, nextPayload);
11572
11740
  const popupActionContext = options.popupActionContext || await this.resolveRecordContextPopupActionContextForHost(current, options.transaction);
11573
11741
  await this.normalizeOpenViewForUpdateSettings(
@@ -11619,6 +11787,12 @@ class FlowSurfacesService {
11619
11787
  if (Object.keys(nextPayload).length === 1) {
11620
11788
  return { uid: current.uid };
11621
11789
  }
11790
+ await this.assertNoDuplicateAIEmployeeActionForUpdateSettings(
11791
+ options.openViewActionName || "updateSettings",
11792
+ current,
11793
+ effectiveNode,
11794
+ options.transaction
11795
+ );
11622
11796
  if (target.kind === "tab" && target.tabRoute) {
11623
11797
  await this.routeSync.persistTabSettings(target, current, nextPayload, options.transaction);
11624
11798
  return {
@@ -12075,6 +12249,65 @@ class FlowSurfacesService {
12075
12249
  nextPayload.stepParams = nextStepParams;
12076
12250
  }
12077
12251
  }
12252
+ syncActionButtonSettingsForUpdateSettings(current, normalizedValues, nextPayload) {
12253
+ if (!this.supportsActionButtonSettingsSync(current)) {
12254
+ return;
12255
+ }
12256
+ const requestedProps = this.pickRequestedActionButtonSettings(normalizedValues.props);
12257
+ const requestedButtonGeneral = this.pickRequestedActionButtonSettings(
12258
+ import_lodash.default.get(normalizedValues, ["stepParams", "buttonSettings", "general"])
12259
+ );
12260
+ const hasRequestedProps = Object.keys(requestedProps).length > 0;
12261
+ const hasRequestedButtonGeneral = Object.keys(requestedButtonGeneral).length > 0;
12262
+ if (!hasRequestedProps && !hasRequestedButtonGeneral) {
12263
+ return;
12264
+ }
12265
+ const hasRequestedTitle = Object.prototype.hasOwnProperty.call(requestedProps, "title") || Object.prototype.hasOwnProperty.call(requestedButtonGeneral, "title");
12266
+ const shouldStripImplicitTitle = (requestedProps.iconOnly === true || requestedButtonGeneral.iconOnly === true) && !hasRequestedTitle;
12267
+ const nextProps = import_lodash.default.cloneDeep(
12268
+ import_lodash.default.isPlainObject(nextPayload.props) ? nextPayload.props : import_lodash.default.isPlainObject(current == null ? void 0 : current.props) ? current.props : {}
12269
+ );
12270
+ const nextStepParams = import_lodash.default.cloneDeep(
12271
+ import_lodash.default.isPlainObject(nextPayload.stepParams) ? nextPayload.stepParams : import_lodash.default.isPlainObject(current == null ? void 0 : current.stepParams) ? current.stepParams : {}
12272
+ );
12273
+ Object.entries(requestedProps).forEach(([key, value]) => {
12274
+ if (Object.prototype.hasOwnProperty.call(requestedButtonGeneral, key)) {
12275
+ return;
12276
+ }
12277
+ import_lodash.default.set(nextStepParams, ["buttonSettings", "general", key], import_lodash.default.cloneDeep(value));
12278
+ });
12279
+ Object.entries(requestedButtonGeneral).forEach(([key, value]) => {
12280
+ if (Object.prototype.hasOwnProperty.call(requestedProps, key)) {
12281
+ return;
12282
+ }
12283
+ nextProps[key] = import_lodash.default.cloneDeep(value);
12284
+ });
12285
+ if (shouldStripImplicitTitle) {
12286
+ delete nextProps.title;
12287
+ if (import_lodash.default.isPlainObject(import_lodash.default.get(nextStepParams, ["buttonSettings", "general"]))) {
12288
+ delete nextStepParams.buttonSettings.general.title;
12289
+ }
12290
+ }
12291
+ nextPayload.props = nextProps;
12292
+ nextPayload.stepParams = nextStepParams;
12293
+ }
12294
+ supportsActionButtonSettingsSync(current) {
12295
+ var _a, _b, _c, _d, _e, _f;
12296
+ const contract = (0, import_catalog.getNodeContract)(current == null ? void 0 : current.use);
12297
+ return ((_b = (_a = contract.domains.props) == null ? void 0 : _a.allowedKeys) == null ? void 0 : _b.includes("iconOnly")) && ((_f = (_e = (_d = (_c = contract.domains.stepParams) == null ? void 0 : _c.groups) == null ? void 0 : _d.buttonSettings) == null ? void 0 : _e.allowedPaths) == null ? void 0 : _f.includes("general.iconOnly"));
12298
+ }
12299
+ pickRequestedActionButtonSettings(input) {
12300
+ const picked = {};
12301
+ if (!import_lodash.default.isPlainObject(input)) {
12302
+ return picked;
12303
+ }
12304
+ ACTION_BUTTON_GENERAL_SETTING_KEYS.forEach((key) => {
12305
+ if (Object.prototype.hasOwnProperty.call(input, key) && !import_lodash.default.isUndefined(input[key])) {
12306
+ picked[key] = import_lodash.default.cloneDeep(input[key]);
12307
+ }
12308
+ });
12309
+ return picked;
12310
+ }
12078
12311
  syncCreatedFieldWrapperTitleFieldStepParams(node) {
12079
12312
  const mirror = (UPDATE_SETTINGS_STEP_PARAM_MIRRORS_BY_USE[(node == null ? void 0 : node.use) || ""] || []).find(
12080
12313
  (item) => item.domain === "props" && item.key === "titleField"
@@ -17599,19 +17832,21 @@ class FlowSurfacesService {
17599
17832
  }
17600
17833
  return JSON.stringify(value);
17601
17834
  }
17602
- buildAIEmployeeActionDedupIdentity(values) {
17835
+ buildAIEmployeeActionDedupIdentity(values, defaultActionWorkContext) {
17603
17836
  var _a, _b, _c, _d, _e, _f;
17604
17837
  const username = String(((_b = (_a = values == null ? void 0 : values.props) == null ? void 0 : _a.aiEmployee) == null ? void 0 : _b.username) || "").trim();
17605
17838
  if (!username) {
17606
17839
  return "";
17607
17840
  }
17841
+ const workContext = this.normalizeAIEmployeeActionWorkContextForDedupIdentity(
17842
+ (_d = (_c = values == null ? void 0 : values.props) == null ? void 0 : _c.context) == null ? void 0 : _d.workContext,
17843
+ defaultActionWorkContext
17844
+ );
17608
17845
  return this.stableSerializeAIEmployeeValue({
17609
17846
  username,
17610
- auto: typeof ((_c = values == null ? void 0 : values.props) == null ? void 0 : _c.auto) === "boolean" ? values.props.auto : false,
17611
- workContext: this.normalizeAIEmployeeWorkContextForDedupIdentity((_e = (_d = values == null ? void 0 : values.props) == null ? void 0 : _d.context) == null ? void 0 : _e.workContext),
17612
- tasks: this.normalizeAIEmployeeTasksForDedupIdentity(
17613
- import_lodash.default.get(values, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])
17614
- ),
17847
+ auto: typeof ((_e = values == null ? void 0 : values.props) == null ? void 0 : _e.auto) === "boolean" ? values.props.auto : false,
17848
+ workContext,
17849
+ tasks: this.normalizeAIEmployeeTasksForDedupIdentity(this.readAIEmployeePersistedTasks(values), workContext),
17615
17850
  style: {
17616
17851
  ...AI_EMPLOYEE_DEFAULT_STYLE,
17617
17852
  ...import_lodash.default.isPlainObject((_f = values == null ? void 0 : values.props) == null ? void 0 : _f.style) ? import_lodash.default.pick(values.props.style, AI_EMPLOYEE_STYLE_PUBLIC_KEYS) : {}
@@ -17619,11 +17854,35 @@ class FlowSurfacesService {
17619
17854
  });
17620
17855
  }
17621
17856
  normalizeAIEmployeeWorkContextForDedupIdentity(value) {
17622
- return import_lodash.default.castArray(value || []).map(
17623
- (item) => import_lodash.default.isPlainObject(item) ? import_lodash.default.pick(item, AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS) : item
17624
- );
17857
+ return import_lodash.default.castArray(value || []).map((item) => {
17858
+ if (!import_lodash.default.isPlainObject(item)) {
17859
+ return item;
17860
+ }
17861
+ const output = import_lodash.default.pick(item, AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS);
17862
+ if (!Object.prototype.hasOwnProperty.call(output, "type") || import_lodash.default.isUndefined(output.type) || output.type === null) {
17863
+ output.type = "flow-model";
17864
+ }
17865
+ return output;
17866
+ });
17625
17867
  }
17626
- normalizeAIEmployeeTasksForDedupIdentity(value) {
17868
+ normalizeAIEmployeeActionWorkContextForDedupIdentity(value, defaultWorkContext) {
17869
+ if (!Array.isArray(value)) {
17870
+ return import_lodash.default.cloneDeep(defaultWorkContext || []);
17871
+ }
17872
+ return this.normalizeAIEmployeeWorkContextForDedupIdentity(value);
17873
+ }
17874
+ normalizeAIEmployeeDefaultActionWorkContextForSelfUid(selfUid) {
17875
+ const uid2 = String(selfUid || "").trim();
17876
+ return uid2 ? [{ type: "flow-model", uid: uid2 }] : [];
17877
+ }
17878
+ normalizeAIEmployeeTaskWorkContextForDedupIdentity(value, defaultWorkContext) {
17879
+ const normalized = this.normalizeAIEmployeeWorkContextForDedupIdentity(value);
17880
+ if (Array.isArray(defaultWorkContext) && !normalized.length) {
17881
+ return import_lodash.default.cloneDeep(defaultWorkContext);
17882
+ }
17883
+ return normalized;
17884
+ }
17885
+ normalizeAIEmployeeTasksForDedupIdentity(value, defaultWorkContext) {
17627
17886
  return import_lodash.default.castArray(value || []).map((task) => {
17628
17887
  if (!import_lodash.default.isPlainObject(task)) {
17629
17888
  return task;
@@ -17632,9 +17891,19 @@ class FlowSurfacesService {
17632
17891
  if (import_lodash.default.isPlainObject(output.message)) {
17633
17892
  output.message = import_lodash.default.pick(output.message, AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS);
17634
17893
  if (Object.prototype.hasOwnProperty.call(output.message, "workContext")) {
17635
- output.message.workContext = this.normalizeAIEmployeeWorkContextForDedupIdentity(output.message.workContext);
17894
+ output.message.workContext = this.normalizeAIEmployeeTaskWorkContextForDedupIdentity(
17895
+ output.message.workContext,
17896
+ defaultWorkContext
17897
+ );
17636
17898
  }
17637
17899
  }
17900
+ if (!import_lodash.default.isPlainObject(output.message) && Array.isArray(defaultWorkContext)) {
17901
+ output.message = {
17902
+ workContext: import_lodash.default.cloneDeep(defaultWorkContext)
17903
+ };
17904
+ } else if (import_lodash.default.isPlainObject(output.message) && !Object.prototype.hasOwnProperty.call(output.message, "workContext")) {
17905
+ output.message.workContext = import_lodash.default.cloneDeep(defaultWorkContext || []);
17906
+ }
17638
17907
  if (import_lodash.default.isPlainObject(output.model)) {
17639
17908
  output.model = import_lodash.default.pick(output.model, AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS);
17640
17909
  }
@@ -17644,25 +17913,38 @@ class FlowSurfacesService {
17644
17913
  return output;
17645
17914
  });
17646
17915
  }
17647
- async assertNoDuplicateAIEmployeeAction(actionName, parentUid, values, transaction) {
17916
+ async assertNoDuplicateAIEmployeeAction(actionName, parentUid, values, transaction, excludeUid) {
17648
17917
  var _a;
17649
- const identity = this.buildAIEmployeeActionDedupIdentity(values);
17650
- if (!identity) {
17651
- return;
17652
- }
17653
17918
  const parentNode = await this.repository.findModelById(parentUid, {
17654
17919
  transaction,
17655
17920
  includeAsyncNode: true
17656
17921
  });
17657
- const duplicate = import_lodash.default.castArray(((_a = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _a.actions) || []).find((action) => {
17922
+ const defaultActionWorkContext = this.normalizeAIEmployeeDefaultActionWorkContextForSelfUid(
17923
+ await this.resolveAIEmployeeActionSelfUidFromParentNode(parentNode, transaction)
17924
+ );
17925
+ const identity = this.buildAIEmployeeActionDedupIdentity(values, defaultActionWorkContext);
17926
+ if (!identity) {
17927
+ return;
17928
+ }
17929
+ let duplicate;
17930
+ for (const action of import_lodash.default.castArray(((_a = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _a.actions) || [])) {
17658
17931
  if (!this.isAIEmployeeActionUse(action == null ? void 0 : action.use)) {
17659
- return false;
17932
+ continue;
17660
17933
  }
17661
- return this.buildAIEmployeeActionDedupIdentity({
17662
- props: action.props,
17663
- stepParams: action.stepParams
17664
- }) === identity;
17665
- });
17934
+ if (excludeUid && String((action == null ? void 0 : action.uid) || "") === excludeUid) {
17935
+ continue;
17936
+ }
17937
+ if (this.buildAIEmployeeActionDedupIdentity(
17938
+ {
17939
+ props: action.props,
17940
+ stepParams: action.stepParams
17941
+ },
17942
+ defaultActionWorkContext
17943
+ ) === identity) {
17944
+ duplicate = action;
17945
+ break;
17946
+ }
17947
+ }
17666
17948
  if (!(duplicate == null ? void 0 : duplicate.uid)) {
17667
17949
  return;
17668
17950
  }
@@ -17677,6 +17959,25 @@ class FlowSurfacesService {
17677
17959
  }
17678
17960
  );
17679
17961
  }
17962
+ async assertNoDuplicateAIEmployeeActionForUpdateSettings(actionName, current, effectiveNode, transaction) {
17963
+ if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
17964
+ return;
17965
+ }
17966
+ const parentUid = String((current == null ? void 0 : current.parentId) || "").trim() || ((current == null ? void 0 : current.uid) ? await this.locator.findParentUid(current.uid, transaction).catch(() => "") : "");
17967
+ if (!parentUid) {
17968
+ return;
17969
+ }
17970
+ await this.assertNoDuplicateAIEmployeeAction(
17971
+ actionName,
17972
+ parentUid,
17973
+ {
17974
+ props: effectiveNode == null ? void 0 : effectiveNode.props,
17975
+ stepParams: effectiveNode == null ? void 0 : effectiveNode.stepParams
17976
+ },
17977
+ transaction,
17978
+ String((current == null ? void 0 : current.uid) || "")
17979
+ );
17980
+ }
17680
17981
  hasAIEmployeePublicSettings(settings) {
17681
17982
  return import_lodash.default.isPlainObject(settings) && AI_EMPLOYEE_PUBLIC_SETTING_KEYS.some((key) => Object.prototype.hasOwnProperty.call(settings, key));
17682
17983
  }
@@ -17731,11 +18032,24 @@ class FlowSurfacesService {
17731
18032
  var _a;
17732
18033
  const stepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
17733
18034
  if (Array.isArray(stepTasks)) {
17734
- return stepTasks;
18035
+ return this.normalizeAIEmployeeLegacyInheritedTaskWorkContext(stepTasks);
17735
18036
  }
17736
- const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
18037
+ const legacyPropsTasks = this.normalizeAIEmployeeLegacyInheritedTaskWorkContext((_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks);
17737
18038
  return Array.isArray(legacyPropsTasks) ? legacyPropsTasks : [];
17738
18039
  }
18040
+ normalizeAIEmployeeLegacyInheritedTaskWorkContext(tasks) {
18041
+ if (!Array.isArray(tasks)) {
18042
+ return tasks;
18043
+ }
18044
+ return tasks.map((task) => {
18045
+ if (!import_lodash.default.isPlainObject(task) || !import_lodash.default.isPlainObject(task.message) || task.message.workContext !== null) {
18046
+ return task;
18047
+ }
18048
+ const nextTask = import_lodash.default.cloneDeep(task);
18049
+ delete nextTask.message.workContext;
18050
+ return nextTask;
18051
+ });
18052
+ }
17739
18053
  buildAIEmployeeTaskStepParams(tasks) {
17740
18054
  const stepParams = {};
17741
18055
  import_lodash.default.set(stepParams, AI_EMPLOYEE_TASK_STEP_PARAMS_PATH, import_lodash.default.cloneDeep(tasks));
@@ -17764,7 +18078,7 @@ class FlowSurfacesService {
17764
18078
  if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
17765
18079
  return;
17766
18080
  }
17767
- const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
18081
+ const legacyPropsTasks = this.normalizeAIEmployeeLegacyInheritedTaskWorkContext((_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks);
17768
18082
  const hasLegacyPropsTasks = Array.isArray(legacyPropsTasks);
17769
18083
  const hasNextStepTasks = import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
17770
18084
  const currentStepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
@@ -17936,6 +18250,20 @@ class FlowSurfacesService {
17936
18250
  };
17937
18251
  });
17938
18252
  }
18253
+ normalizeAIEmployeeEffectiveActionWorkContext(actionName, settings, currentProps, options) {
18254
+ var _a;
18255
+ const hasSettingsWorkContext = Object.prototype.hasOwnProperty.call(settings, "workContext");
18256
+ const currentWorkContext = (_a = currentProps == null ? void 0 : currentProps.context) == null ? void 0 : _a.workContext;
18257
+ if (!hasSettingsWorkContext && !Array.isArray(currentWorkContext) && !options.requireUsername && !options.selfUid) {
18258
+ return void 0;
18259
+ }
18260
+ const rawWorkContext = hasSettingsWorkContext ? settings.workContext : Array.isArray(currentWorkContext) ? currentWorkContext : [{ type: "flow-model", target: "self" }];
18261
+ return this.normalizeAIEmployeeWorkContext(actionName, rawWorkContext, {
18262
+ selfUid: options.selfUid,
18263
+ keyMap: options.keyMap,
18264
+ path: "settings.workContext"
18265
+ });
18266
+ }
17939
18267
  normalizeAIEmployeeTaskModel(actionName, path, value) {
17940
18268
  if (import_lodash.default.isUndefined(value) || value === null) {
17941
18269
  return value;
@@ -18251,6 +18579,7 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18251
18579
  );
18252
18580
  }
18253
18581
  async normalizeAIEmployeeStepParamTasksForUpdateSettings(current, nextPayload, writeTarget, options) {
18582
+ var _a, _b, _c, _d;
18254
18583
  if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use) || !import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])) {
18255
18584
  return;
18256
18585
  }
@@ -18259,15 +18588,63 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18259
18588
  return;
18260
18589
  }
18261
18590
  const actionName = options.openViewActionName || "updateSettings";
18262
- const normalizedTasks = this.normalizeAIEmployeeTasks(
18591
+ const selfUid = await this.resolveAIEmployeeActionSelfUid(current || { uid: writeTarget.uid }, options.transaction);
18592
+ const currentPropsForDefault = import_lodash.default.mergeWith(
18593
+ {},
18594
+ import_lodash.default.isPlainObject(current == null ? void 0 : current.props) ? current.props : {},
18595
+ import_lodash.default.isPlainObject(nextPayload.props) ? nextPayload.props : {},
18596
+ (_currentValue, nextValue) => {
18597
+ if (Array.isArray(nextValue)) {
18598
+ return import_lodash.default.cloneDeep(nextValue);
18599
+ }
18600
+ return void 0;
18601
+ }
18602
+ );
18603
+ const defaultWorkContext = this.normalizeAIEmployeeEffectiveActionWorkContext(
18263
18604
  actionName,
18264
- tasks,
18265
- this.readAIEmployeePersistedTasks(current),
18605
+ {},
18606
+ currentPropsForDefault,
18266
18607
  {
18267
- selfUid: await this.resolveAIEmployeeActionSelfUid(current || { uid: writeTarget.uid }, options.transaction),
18268
- path: "stepParams.shortcutSettings.editTasks.tasks"
18608
+ selfUid,
18609
+ requireUsername: true
18269
18610
  }
18270
18611
  );
18612
+ const currentTasks = this.readAIEmployeePersistedTasks(current);
18613
+ const previousActionWorkContext = this.normalizeAIEmployeeActionWorkContextForDedupIdentity(
18614
+ (_b = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.context) == null ? void 0 : _b.workContext,
18615
+ this.normalizeAIEmployeeDefaultActionWorkContextForSelfUid(selfUid)
18616
+ );
18617
+ const nextActionWorkContext = this.normalizeAIEmployeeActionWorkContextForDedupIdentity(
18618
+ (_c = currentPropsForDefault == null ? void 0 : currentPropsForDefault.context) == null ? void 0 : _c.workContext,
18619
+ defaultWorkContext
18620
+ );
18621
+ if (Array.isArray(defaultWorkContext) && !import_lodash.default.isEqual((_d = currentPropsForDefault == null ? void 0 : currentPropsForDefault.context) == null ? void 0 : _d.workContext, defaultWorkContext)) {
18622
+ nextPayload.props = import_lodash.default.mergeWith(
18623
+ {},
18624
+ currentPropsForDefault,
18625
+ {
18626
+ context: {
18627
+ workContext: import_lodash.default.cloneDeep(defaultWorkContext)
18628
+ }
18629
+ },
18630
+ (_currentValue, nextValue) => {
18631
+ if (Array.isArray(nextValue)) {
18632
+ return import_lodash.default.cloneDeep(nextValue);
18633
+ }
18634
+ return void 0;
18635
+ }
18636
+ );
18637
+ }
18638
+ const currentTasksForNormalization = this.rebaseAIEmployeeInheritedTaskWorkContext(
18639
+ currentTasks,
18640
+ previousActionWorkContext,
18641
+ nextActionWorkContext
18642
+ );
18643
+ const normalizedTasks = this.normalizeAIEmployeeTasks(actionName, tasks, currentTasksForNormalization, {
18644
+ selfUid,
18645
+ defaultWorkContext,
18646
+ path: "stepParams.shortcutSettings.editTasks.tasks"
18647
+ });
18271
18648
  import_lodash.default.set(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH], normalizedTasks);
18272
18649
  }
18273
18650
  normalizeAIEmployeeTaskMessage(actionName, path, value, existing, options) {
@@ -18296,13 +18673,18 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18296
18673
  if (Object.prototype.hasOwnProperty.call(nextMessage, "user") && typeof nextMessage.user !== "string") {
18297
18674
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.user must be a string`);
18298
18675
  }
18299
- if (Object.prototype.hasOwnProperty.call(value, "workContext")) {
18676
+ if (value.workContext === null) {
18677
+ delete nextMessage.workContext;
18678
+ } else if (Object.prototype.hasOwnProperty.call(value, "workContext")) {
18300
18679
  nextMessage.workContext = this.normalizeAIEmployeeWorkContext(actionName, value.workContext, {
18301
18680
  selfUid: options.selfUid,
18302
18681
  keyMap: options.keyMap,
18303
18682
  path: `${path}.workContext`
18304
18683
  });
18305
18684
  }
18685
+ if (!Object.prototype.hasOwnProperty.call(nextMessage, "workContext") && this.shouldMaterializeAIEmployeeTaskDefaultWorkContext(options.defaultWorkContext)) {
18686
+ nextMessage.workContext = import_lodash.default.cloneDeep(options.defaultWorkContext);
18687
+ }
18306
18688
  return nextMessage;
18307
18689
  }
18308
18690
  normalizeAIEmployeeTaskPatch(actionName, patch, existing, options) {
@@ -18326,7 +18708,8 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18326
18708
  if (key === "message") {
18327
18709
  next.message = this.normalizeAIEmployeeTaskMessage(actionName, `${options.path}.message`, value, next.message, {
18328
18710
  selfUid: options.selfUid,
18329
- keyMap: options.keyMap
18711
+ keyMap: options.keyMap,
18712
+ defaultWorkContext: options.defaultWorkContext
18330
18713
  });
18331
18714
  return;
18332
18715
  }
@@ -18376,6 +18759,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18376
18759
  if (!import_lodash.default.isPlainObject(next.message)) {
18377
18760
  next.message = {};
18378
18761
  }
18762
+ if (!Object.prototype.hasOwnProperty.call(next.message, "workContext") && this.shouldMaterializeAIEmployeeTaskDefaultWorkContext(options.defaultWorkContext)) {
18763
+ next.message.workContext = import_lodash.default.cloneDeep(options.defaultWorkContext);
18764
+ }
18379
18765
  if (import_lodash.default.isPlainObject(next.skillSettings)) {
18380
18766
  if (Array.isArray(next.skillSettings.skills) && !Object.prototype.hasOwnProperty.call(next.skillSettings, "skillsVersion")) {
18381
18767
  next.skillSettings.skillsVersion = 2;
@@ -18402,10 +18788,52 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18402
18788
  nextTasks[index] = this.normalizeAIEmployeeTaskPatch(actionName, task, existingTasks[index], {
18403
18789
  selfUid: options.selfUid,
18404
18790
  keyMap: options.keyMap,
18405
- path: `${options.path}[${index}]`
18791
+ path: `${options.path}[${index}]`,
18792
+ defaultWorkContext: options.defaultWorkContext
18406
18793
  });
18407
18794
  });
18408
- return nextTasks;
18795
+ return this.withAIEmployeeTaskDefaultWorkContext(nextTasks, options.defaultWorkContext);
18796
+ }
18797
+ withAIEmployeeTaskDefaultWorkContext(tasks, defaultWorkContext) {
18798
+ const nextTasks = Array.isArray(tasks) ? import_lodash.default.cloneDeep(tasks) : [];
18799
+ if (!this.shouldMaterializeAIEmployeeTaskDefaultWorkContext(defaultWorkContext)) {
18800
+ return nextTasks;
18801
+ }
18802
+ return nextTasks.map((task) => {
18803
+ if (!import_lodash.default.isPlainObject(task)) {
18804
+ return task;
18805
+ }
18806
+ const nextTask = import_lodash.default.cloneDeep(task);
18807
+ if (!import_lodash.default.isPlainObject(nextTask.message)) {
18808
+ nextTask.message = {
18809
+ workContext: import_lodash.default.cloneDeep(defaultWorkContext)
18810
+ };
18811
+ } else if (!Object.prototype.hasOwnProperty.call(nextTask.message, "workContext")) {
18812
+ nextTask.message.workContext = import_lodash.default.cloneDeep(defaultWorkContext);
18813
+ }
18814
+ return nextTask;
18815
+ });
18816
+ }
18817
+ shouldMaterializeAIEmployeeTaskDefaultWorkContext(defaultWorkContext) {
18818
+ return Array.isArray(defaultWorkContext) && defaultWorkContext.length > 0;
18819
+ }
18820
+ rebaseAIEmployeeInheritedTaskWorkContext(currentTasks, previousActionWorkContext, nextActionWorkContext) {
18821
+ const tasks = this.normalizeAIEmployeeLegacyInheritedTaskWorkContext(currentTasks) || [];
18822
+ if (!previousActionWorkContext.length || import_lodash.default.isEqual(previousActionWorkContext, nextActionWorkContext)) {
18823
+ return tasks;
18824
+ }
18825
+ return tasks.map((task) => {
18826
+ const nextTask = import_lodash.default.cloneDeep(task);
18827
+ if (import_lodash.default.isPlainObject(nextTask == null ? void 0 : nextTask.message)) {
18828
+ const currentTaskWorkContext = this.normalizeAIEmployeeWorkContextForDedupIdentity(
18829
+ nextTask.message.workContext
18830
+ );
18831
+ if (import_lodash.default.isEqual(currentTaskWorkContext, previousActionWorkContext)) {
18832
+ delete nextTask.message.workContext;
18833
+ }
18834
+ }
18835
+ return nextTask;
18836
+ });
18409
18837
  }
18410
18838
  normalizeAIEmployeeActionSettingsReferences(actionName, settings, options) {
18411
18839
  if (!this.hasAIEmployeePublicSettings(settings)) {
@@ -18419,15 +18847,22 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18419
18847
  });
18420
18848
  }
18421
18849
  if (Object.prototype.hasOwnProperty.call(nextSettings, "tasks")) {
18850
+ const defaultWorkContext = this.normalizeAIEmployeeEffectiveActionWorkContext(
18851
+ actionName,
18852
+ nextSettings,
18853
+ {},
18854
+ options
18855
+ );
18422
18856
  nextSettings.tasks = this.normalizeAIEmployeeTasks(actionName, nextSettings.tasks, [], {
18423
18857
  ...options,
18424
- path: "settings.tasks"
18858
+ path: "settings.tasks",
18859
+ defaultWorkContext
18425
18860
  });
18426
18861
  }
18427
18862
  return nextSettings;
18428
18863
  }
18429
18864
  async normalizeAIEmployeeActionPublicSettings(actionName, settings, options) {
18430
- var _a, _b;
18865
+ var _a, _b, _c, _d;
18431
18866
  this.assertAIEmployeePluginEnabled(actionName, options.enabledPackages);
18432
18867
  if (!import_lodash.default.isPlainObject(settings)) {
18433
18868
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings must be an object`);
@@ -18447,6 +18882,17 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18447
18882
  }
18448
18883
  const props = {};
18449
18884
  const stepParams = {};
18885
+ const effectiveActionWorkContext = this.normalizeAIEmployeeEffectiveActionWorkContext(
18886
+ actionName,
18887
+ settings,
18888
+ currentProps,
18889
+ options
18890
+ );
18891
+ const previousActionWorkContext = this.normalizeAIEmployeeActionWorkContextForDedupIdentity(
18892
+ (_c = currentProps == null ? void 0 : currentProps.context) == null ? void 0 : _c.workContext,
18893
+ this.normalizeAIEmployeeDefaultActionWorkContextForSelfUid(options.selfUid)
18894
+ );
18895
+ const nextActionWorkContext = this.normalizeAIEmployeeWorkContextForDedupIdentity(effectiveActionWorkContext);
18450
18896
  if (effectiveUsername && (hasUsername || options.requireUsername)) {
18451
18897
  props.aiEmployee = {
18452
18898
  ...import_lodash.default.isPlainObject(currentProps.aiEmployee) ? import_lodash.default.cloneDeep(currentProps.aiEmployee) : {},
@@ -18460,28 +18906,25 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18460
18906
  }
18461
18907
  props.auto = auto;
18462
18908
  }
18463
- if (Object.prototype.hasOwnProperty.call(settings, "workContext") || options.requireUsername) {
18464
- const rawWorkContext = Object.prototype.hasOwnProperty.call(settings, "workContext") ? settings.workContext : [{ type: "flow-model", target: "self" }];
18909
+ if (Array.isArray(effectiveActionWorkContext) && (Object.prototype.hasOwnProperty.call(settings, "workContext") || options.requireUsername || !import_lodash.default.isEqual((_d = currentProps == null ? void 0 : currentProps.context) == null ? void 0 : _d.workContext, effectiveActionWorkContext))) {
18465
18910
  props.context = {
18466
18911
  ...import_lodash.default.isPlainObject(currentProps.context) ? import_lodash.default.cloneDeep(currentProps.context) : {},
18467
- workContext: this.normalizeAIEmployeeWorkContext(actionName, rawWorkContext, {
18468
- selfUid: options.selfUid,
18469
- keyMap: options.keyMap,
18470
- path: "settings.workContext"
18471
- })
18912
+ workContext: import_lodash.default.cloneDeep(effectiveActionWorkContext)
18472
18913
  };
18473
18914
  }
18474
18915
  if (Object.prototype.hasOwnProperty.call(settings, "tasks")) {
18475
- const normalizedTasks = this.normalizeAIEmployeeTasks(
18476
- actionName,
18477
- settings.tasks,
18478
- this.readAIEmployeePersistedTasks(options.current),
18479
- {
18480
- selfUid: options.selfUid,
18481
- keyMap: options.keyMap,
18482
- path: "settings.tasks"
18483
- }
18916
+ const currentTasks = this.readAIEmployeePersistedTasks(options.current);
18917
+ const currentTasksForNormalization = this.rebaseAIEmployeeInheritedTaskWorkContext(
18918
+ currentTasks,
18919
+ previousActionWorkContext,
18920
+ nextActionWorkContext
18484
18921
  );
18922
+ const normalizedTasks = this.normalizeAIEmployeeTasks(actionName, settings.tasks, currentTasksForNormalization, {
18923
+ selfUid: options.selfUid,
18924
+ keyMap: options.keyMap,
18925
+ path: "settings.tasks",
18926
+ defaultWorkContext: effectiveActionWorkContext
18927
+ });
18485
18928
  const validation = options.promptContext && normalizedTasks.length ? await this.buildAIEmployeePromptValidationContext(
18486
18929
  actionName,
18487
18930
  [
@@ -18502,6 +18945,17 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18502
18945
  const tasks = this.appendAIEmployeeCurrentRecordPromptVariableToTasks(normalizedTasks, validation);
18503
18946
  this.assertAIEmployeeTaskPromptVariablesAllowed(actionName, tasks, validation);
18504
18947
  import_lodash.default.merge(stepParams, this.buildAIEmployeeTaskStepParams(tasks));
18948
+ } else if (!options.skipExistingTaskWorkContextRebase && Object.prototype.hasOwnProperty.call(settings, "workContext") && !import_lodash.default.isEqual(previousActionWorkContext, nextActionWorkContext)) {
18949
+ const currentTasks = this.readAIEmployeePersistedTasks(options.current);
18950
+ const rebasedTasks = this.rebaseAIEmployeeInheritedTaskWorkContext(
18951
+ currentTasks,
18952
+ previousActionWorkContext,
18953
+ nextActionWorkContext
18954
+ );
18955
+ const tasks = this.withAIEmployeeTaskDefaultWorkContext(rebasedTasks, effectiveActionWorkContext);
18956
+ if (tasks.length) {
18957
+ import_lodash.default.merge(stepParams, this.buildAIEmployeeTaskStepParams(tasks));
18958
+ }
18505
18959
  }
18506
18960
  if (Object.prototype.hasOwnProperty.call(settings, "style") || options.requireUsername) {
18507
18961
  const style = Object.prototype.hasOwnProperty.call(settings, "style") ? settings.style : {};
@@ -18543,7 +18997,16 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18543
18997
  transaction,
18544
18998
  includeAsyncNode: true
18545
18999
  });
18546
- if (["TableActionsColumnModel", "ListItemModel", "GridCardItemModel"].includes(String((parentNode == null ? void 0 : parentNode.use) || ""))) {
19000
+ return await this.resolveAIEmployeeActionSelfUidFromParentNode(parentNode, transaction) || parentUid;
19001
+ }
19002
+ async resolveAIEmployeeActionSelfUidFromParentNode(parentNode, transaction) {
19003
+ const parentUid = String((parentNode == null ? void 0 : parentNode.uid) || "").trim();
19004
+ if (!parentUid) {
19005
+ return "";
19006
+ }
19007
+ if (["TableActionsColumnModel", "ListItemModel", "GridCardItemModel", "CommentItemModel"].includes(
19008
+ String((parentNode == null ? void 0 : parentNode.use) || "")
19009
+ )) {
18547
19010
  const ownerUid = String((parentNode == null ? void 0 : parentNode.parentId) || "").trim() || ((parentNode == null ? void 0 : parentNode.uid) ? await this.locator.findParentUid(parentNode.uid, transaction).catch(() => "") : "");
18548
19011
  return ownerUid || parentUid;
18549
19012
  }
@@ -18592,13 +19055,14 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18592
19055
  }
18593
19056
  const normalizedDefaultFilter = (0, import_service_utils.hasOwnDefined)(changes, "defaultFilter") ? this.normalizeFilterActionDefaultFilterValue(changes.defaultFilter) : void 0;
18594
19057
  const stepParams = {};
18595
- if ((0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "type", "danger", "color", "linkageRules"])) {
19058
+ if ((0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "iconOnly", "type", "danger", "color", "linkageRules"])) {
18596
19059
  stepParams.buttonSettings = {
18597
- ...(0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "type", "danger", "color"]) ? {
19060
+ ...(0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "iconOnly", "type", "danger", "color"]) ? {
18598
19061
  general: (0, import_service_utils.buildDefinedPayload)({
18599
19062
  title: changes.title,
18600
19063
  tooltip: changes.tooltip,
18601
19064
  icon: changes.icon,
19065
+ iconOnly: changes.iconOnly,
18602
19066
  type: changes.type,
18603
19067
  danger: changes.danger,
18604
19068
  color: changes.color
@@ -18808,6 +19272,7 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18808
19272
  title: changes.title,
18809
19273
  tooltip: changes.tooltip,
18810
19274
  icon: changes.icon,
19275
+ iconOnly: changes.iconOnly,
18811
19276
  type: changes.type,
18812
19277
  htmlType: changes.htmlType,
18813
19278
  position: changes.position,