@nocobase/plugin-flow-engine 2.2.0-beta.1 → 2.2.0-beta.10

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 (70) hide show
  1. package/dist/client/index.js +1 -1
  2. package/dist/externalVersion.js +9 -9
  3. package/dist/locale/en-US.json +1 -0
  4. package/dist/locale/index.d.ts +2 -0
  5. package/dist/locale/zh-CN.json +1 -0
  6. package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
  7. package/dist/node_modules/acorn/package.json +1 -1
  8. package/dist/node_modules/acorn-jsx/package.json +1 -1
  9. package/dist/node_modules/acorn-walk/package.json +1 -1
  10. package/dist/node_modules/ses/package.json +1 -1
  11. package/dist/node_modules/zod/package.json +1 -1
  12. package/dist/server/flow-surfaces/{runjs-authoring/blocked-global-stop/index.d.ts → approval/authoring-validation.d.ts} +1 -2
  13. package/dist/server/flow-surfaces/approval/authoring-validation.js +1151 -0
  14. package/dist/server/flow-surfaces/approval/blueprint-service.js +2 -0
  15. package/dist/server/flow-surfaces/authoring-validation.d.ts +2 -1
  16. package/dist/server/flow-surfaces/authoring-validation.js +495 -57
  17. package/dist/server/flow-surfaces/blueprint/compile-plan.js +19 -15
  18. package/dist/server/flow-surfaces/blueprint/export-document.d.ts +50 -0
  19. package/dist/server/flow-surfaces/blueprint/export-document.js +2510 -0
  20. package/dist/server/flow-surfaces/blueprint/normalize-document.js +2 -1
  21. package/dist/server/flow-surfaces/blueprint/public-types.d.ts +1 -0
  22. package/dist/server/flow-surfaces/builder.js +40 -5
  23. package/dist/server/flow-surfaces/catalog.js +13 -2
  24. package/dist/server/flow-surfaces/configure-options.js +5 -3
  25. package/dist/server/flow-surfaces/constants.d.ts +9 -2
  26. package/dist/server/flow-surfaces/constants.js +1 -0
  27. package/dist/server/flow-surfaces/contract-guard.js +24 -2
  28. package/dist/server/flow-surfaces/default-action-popup.d.ts +2 -0
  29. package/dist/server/flow-surfaces/default-action-popup.js +27 -13
  30. package/dist/server/flow-surfaces/filter-group.d.ts +19 -2
  31. package/dist/server/flow-surfaces/filter-group.js +232 -3
  32. package/dist/server/flow-surfaces/planning/compiler.d.ts +1 -0
  33. package/dist/server/flow-surfaces/planning/compiler.js +205 -82
  34. package/dist/server/flow-surfaces/planning/key-registry.d.ts +1 -1
  35. package/dist/server/flow-surfaces/planning/runtime.js +1 -0
  36. package/dist/server/flow-surfaces/planning/step-link.d.ts +1 -1
  37. package/dist/server/flow-surfaces/planning/step-link.js +22 -3
  38. package/dist/server/flow-surfaces/public-data-surface-default-filter.js +0 -9
  39. package/dist/server/flow-surfaces/reaction/field-value.d.ts +9 -0
  40. package/dist/server/flow-surfaces/reaction/field-value.js +51 -2
  41. package/dist/server/flow-surfaces/reaction/linkage.d.ts +6 -1
  42. package/dist/server/flow-surfaces/reaction/linkage.js +18 -3
  43. package/dist/server/flow-surfaces/reaction/meta.js +19 -1
  44. package/dist/server/flow-surfaces/reaction/types.d.ts +19 -0
  45. package/dist/server/flow-surfaces/relation-backing-foreign-key.d.ts +10 -0
  46. package/dist/server/flow-surfaces/relation-backing-foreign-key.js +79 -0
  47. package/dist/server/flow-surfaces/runjs-authoring/ast/source.d.ts +1 -0
  48. package/dist/server/flow-surfaces/runjs-authoring/ast/source.js +20 -0
  49. package/dist/server/flow-surfaces/runjs-authoring/rules.js +0 -2
  50. package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.d.ts +0 -1
  51. package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.js +11 -19
  52. package/dist/server/flow-surfaces/runjs-authoring/runtime/types.d.ts +0 -12
  53. package/dist/server/flow-surfaces/runjs-authoring/scan/filter.js +12 -2
  54. package/dist/server/flow-surfaces/runjs-authoring/scan/index.d.ts +0 -14
  55. package/dist/server/flow-surfaces/runjs-authoring/scan/index.js +10 -8
  56. package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.d.ts +0 -14
  57. package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.js +18 -73
  58. package/dist/server/flow-surfaces/runjs-authoring/types.d.ts +1 -1
  59. package/dist/server/flow-surfaces/runjs-authoring/validators/index.js +9 -53
  60. package/dist/server/flow-surfaces/service.d.ts +53 -0
  61. package/dist/server/flow-surfaces/service.js +990 -122
  62. package/dist/server/flow-surfaces/types.d.ts +2 -1
  63. package/dist/server/variables/registry.js +3 -0
  64. package/dist/swagger/flow-surfaces.d.ts +193 -0
  65. package/dist/swagger/flow-surfaces.examples.d.ts +11 -0
  66. package/dist/swagger/flow-surfaces.examples.js +11 -0
  67. package/dist/swagger/flow-surfaces.js +179 -10
  68. package/dist/swagger/index.d.ts +193 -0
  69. package/package.json +2 -2
  70. package/dist/server/flow-surfaces/runjs-authoring/blocked-global-stop/index.js +0 -40
@@ -56,6 +56,7 @@ var import_executor = require("./executor");
56
56
  var import_reference_guards = require("./reference-guards");
57
57
  var import_key_registry = require("./planning/key-registry");
58
58
  var import_blueprint = require("./blueprint");
59
+ var import_export_document = require("./blueprint/export-document");
59
60
  var import_compile_blocks = require("./blueprint/compile-blocks");
60
61
  var import_default_block_actions = require("./default-block-actions");
61
62
  var import_template_reference = require("./template-reference");
@@ -96,6 +97,7 @@ var import_meta = require("./reaction/meta");
96
97
  var import_resolver = require("./reaction/resolver");
97
98
  var import_association_title_field = require("./association-title-field");
98
99
  var import_default_action_popup = require("./default-action-popup");
100
+ var import_relation_backing_foreign_key = require("./relation-backing-foreign-key");
99
101
  var import_defaults = require("./blueprint/defaults");
100
102
  var import_service_utils = require("./service-utils");
101
103
  var import_field_type_resolver = require("./field-type-resolver");
@@ -229,9 +231,11 @@ function isFlowSurfaceChartRepairError(error) {
229
231
  var _a, _b;
230
232
  return error instanceof import_errors.FlowSurfaceBadRequestError && ((_b = (_a = error.options) == null ? void 0 : _a.details) == null ? void 0 : _b.repairHint) === FLOW_SURFACE_CHART_REPAIR_HINT;
231
233
  }
234
+ const FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE = "exportBlueprint v1 only supports root page export";
232
235
  const FORM_BLOCK_USES = /* @__PURE__ */ new Set(["FormBlockModel", "CreateFormModel", "EditFormModel", ...import_approval.APPROVAL_FORM_BLOCK_USES]);
233
236
  const AUTO_SUBMIT_FORM_BLOCK_USES = /* @__PURE__ */ new Set(["CreateFormModel", "EditFormModel"]);
234
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"];
235
239
  const DETAILS_BLOCK_USES = /* @__PURE__ */ new Set(["DetailsBlockModel", ...import_approval.APPROVAL_DETAILS_BLOCK_USES]);
236
240
  const SIMPLE_FORM_BLOCK_USES = /* @__PURE__ */ new Set([
237
241
  "FormBlockModel",
@@ -685,6 +689,8 @@ function assertNoFlowSurfaceIdTitleFieldSettings(value, options = {}) {
685
689
  };
686
690
  visit(value, options.basePath || []);
687
691
  }
692
+ const DEFAULT_ADMIN_UI_LAYOUT_UID = "admin-layout-model";
693
+ const MOBILE_UI_LAYOUT_TYPE = "mobile";
688
694
  class FlowSurfacesService {
689
695
  constructor(plugin) {
690
696
  this.plugin = plugin;
@@ -918,12 +924,12 @@ class FlowSurfacesService {
918
924
  transaction
919
925
  });
920
926
  }
921
- async findMenuGroupRoutesByTitle(title, transaction) {
927
+ async findMenuGroupRoutesByTitle(title, transaction, layoutUid) {
922
928
  const normalizedTitle = String(title || "").trim();
923
929
  if (!normalizedTitle) {
924
930
  return [];
925
931
  }
926
- return import_lodash.default.castArray(
932
+ const routes = import_lodash.default.castArray(
927
933
  await this.db.getRepository("desktopRoutes").find({
928
934
  filter: {
929
935
  type: "group",
@@ -932,6 +938,18 @@ class FlowSurfacesService {
932
938
  transaction
933
939
  })
934
940
  );
941
+ const layoutUidFilter = await this.resolveDesktopRouteLayoutUidFilter(layoutUid, transaction);
942
+ if (!layoutUidFilter.length || !this.hasDesktopRouteUiLayoutsRelation()) {
943
+ return routes;
944
+ }
945
+ const matchedRoutes = [];
946
+ for (const route of routes) {
947
+ const routeLayoutUids = await this.readDesktopRouteUiLayoutUids(this.readRouteField(route, "id"), transaction);
948
+ if (import_lodash.default.intersection(routeLayoutUids, layoutUidFilter).length) {
949
+ matchedRoutes.push(route);
950
+ }
951
+ }
952
+ return matchedRoutes;
935
953
  }
936
954
  routeParentIdMatches(routeParentId, parentId) {
937
955
  if (import_lodash.default.isNil(routeParentId) && import_lodash.default.isNil(parentId)) {
@@ -939,28 +957,42 @@ class FlowSurfacesService {
939
957
  }
940
958
  return String(routeParentId ?? "") === String(parentId ?? "");
941
959
  }
942
- async findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction) {
943
- const routes = await this.findMenuGroupRoutesByTitle(title, transaction);
960
+ async findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction, layoutUid) {
961
+ const routes = await this.findMenuGroupRoutesByTitle(title, transaction, layoutUid);
944
962
  return routes.filter(
945
963
  (route) => this.routeParentIdMatches(this.readRouteField(route, "parentId") ?? null, parentId)
946
964
  );
947
965
  }
948
- async findFlowPageRoutesByParentIdAndTitle(parentId, title, transaction) {
966
+ async findFlowPageRoutesByParentIdAndTitle(parentId, title, transaction, layoutUid) {
949
967
  const normalizedTitle = String(title || "").trim();
950
- const normalizedParentId = String(parentId ?? "").trim();
951
- if (!normalizedTitle || !normalizedParentId) {
968
+ if (!normalizedTitle) {
952
969
  return [];
953
970
  }
954
- return import_lodash.default.castArray(
971
+ const routes = import_lodash.default.castArray(
955
972
  await this.db.getRepository("desktopRoutes").find({
956
- filter: {
973
+ filter: (0, import_service_utils.buildDefinedPayload)({
957
974
  type: "flowPage",
958
975
  title: normalizedTitle,
959
- parentId: normalizedParentId
960
- },
976
+ parentId: import_lodash.default.isNil(parentId) ? void 0 : String(parentId)
977
+ }),
961
978
  transaction
962
979
  })
963
980
  );
981
+ const layoutUidFilter = await this.resolveDesktopRouteLayoutUidFilter(layoutUid, transaction);
982
+ const layoutMatchedRoutes = [];
983
+ if (!layoutUidFilter.length || !this.hasDesktopRouteUiLayoutsRelation()) {
984
+ layoutMatchedRoutes.push(...routes);
985
+ } else {
986
+ for (const route of routes) {
987
+ const routeLayoutUids = await this.readDesktopRouteUiLayoutUids(this.readRouteField(route, "id"), transaction);
988
+ if (import_lodash.default.intersection(routeLayoutUids, layoutUidFilter).length) {
989
+ layoutMatchedRoutes.push(route);
990
+ }
991
+ }
992
+ }
993
+ return layoutMatchedRoutes.filter(
994
+ (route) => this.routeParentIdMatches(this.readRouteField(route, "parentId") ?? null, parentId)
995
+ );
964
996
  }
965
997
  async assertMenuParentIsGroup(parentMenuRouteId, transaction) {
966
998
  if (import_lodash.default.isNil(parentMenuRouteId)) {
@@ -1026,6 +1058,204 @@ class FlowSurfacesService {
1026
1058
  ...extras
1027
1059
  };
1028
1060
  }
1061
+ hasDesktopRouteUiLayoutsRelation() {
1062
+ var _a, _b;
1063
+ try {
1064
+ return !!this.db.getCollection("uiLayouts") && !!((_b = (_a = this.db.getCollection("desktopRoutes")) == null ? void 0 : _a.getField) == null ? void 0 : _b.call(_a, "uiLayouts"));
1065
+ } catch (error) {
1066
+ return false;
1067
+ }
1068
+ }
1069
+ normalizeDesktopRouteRelationId(routeId) {
1070
+ return import_lodash.default.isNil(routeId) ? void 0 : routeId;
1071
+ }
1072
+ async readDesktopRouteUiLayoutUids(routeId, transaction) {
1073
+ const relationRouteId = this.normalizeDesktopRouteRelationId(routeId);
1074
+ if (import_lodash.default.isUndefined(relationRouteId) || !this.hasDesktopRouteUiLayoutsRelation()) {
1075
+ return [];
1076
+ }
1077
+ const uiLayouts = await this.db.getRepository("desktopRoutes.uiLayouts", relationRouteId).find({
1078
+ fields: ["uid"],
1079
+ transaction
1080
+ });
1081
+ return import_lodash.default.uniq(
1082
+ uiLayouts.map((uiLayout) => {
1083
+ var _a;
1084
+ return String(((_a = uiLayout == null ? void 0 : uiLayout.get) == null ? void 0 : _a.call(uiLayout, "uid")) || (uiLayout == null ? void 0 : uiLayout.uid) || "").trim();
1085
+ }).filter(Boolean)
1086
+ );
1087
+ }
1088
+ async resolveDefaultDesktopRouteUiLayoutUids(transaction) {
1089
+ if (!this.hasDesktopRouteUiLayoutsRelation()) {
1090
+ return [];
1091
+ }
1092
+ const defaultLayout = await this.db.getRepository("uiLayouts").findOne({
1093
+ filter: {
1094
+ uid: DEFAULT_ADMIN_UI_LAYOUT_UID,
1095
+ enabled: true
1096
+ },
1097
+ transaction
1098
+ });
1099
+ return defaultLayout ? [DEFAULT_ADMIN_UI_LAYOUT_UID] : [];
1100
+ }
1101
+ async findDesktopRouteUiLayoutByUid(layoutUid, transaction) {
1102
+ const normalizedLayoutUid = this.normalizeExplicitDesktopRouteLayoutUid(layoutUid);
1103
+ if (!normalizedLayoutUid || !this.hasDesktopRouteUiLayoutsRelation()) {
1104
+ return null;
1105
+ }
1106
+ return this.db.getRepository("uiLayouts").findOne({
1107
+ filter: {
1108
+ uid: normalizedLayoutUid
1109
+ },
1110
+ transaction
1111
+ });
1112
+ }
1113
+ async getDesktopRouteUiLayoutTypeByUid(layoutUid, transaction) {
1114
+ var _a;
1115
+ const uiLayout = await this.findDesktopRouteUiLayoutByUid(layoutUid, transaction);
1116
+ return String(((_a = uiLayout == null ? void 0 : uiLayout.get) == null ? void 0 : _a.call(uiLayout, "layoutType")) || (uiLayout == null ? void 0 : uiLayout.layoutType) || "").trim() || void 0;
1117
+ }
1118
+ async isMobileDesktopRouteUiLayoutUid(layoutUid, transaction) {
1119
+ if (!layoutUid) {
1120
+ return false;
1121
+ }
1122
+ return await this.getDesktopRouteUiLayoutTypeByUid(layoutUid, transaction) === MOBILE_UI_LAYOUT_TYPE;
1123
+ }
1124
+ async resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction) {
1125
+ const parentRouteId = this.readRouteField(parentRoute, "id");
1126
+ if (!import_lodash.default.isNil(parentRouteId)) {
1127
+ const parentLayoutUids = await this.readDesktopRouteUiLayoutUids(parentRouteId, transaction);
1128
+ if (parentLayoutUids.length) {
1129
+ return parentLayoutUids;
1130
+ }
1131
+ }
1132
+ return this.resolveDefaultDesktopRouteUiLayoutUids(transaction);
1133
+ }
1134
+ normalizeExplicitDesktopRouteLayoutUid(value) {
1135
+ const normalized = String(value || "").trim();
1136
+ return normalized || void 0;
1137
+ }
1138
+ normalizeDesktopRouteLayoutUidFilter(value) {
1139
+ return import_lodash.default.uniq(
1140
+ import_lodash.default.castArray(value).map((item) => this.normalizeExplicitDesktopRouteLayoutUid(item)).filter(Boolean)
1141
+ );
1142
+ }
1143
+ async resolveDesktopRouteLayoutUidFilter(value, transaction) {
1144
+ const explicitLayoutUids = this.normalizeDesktopRouteLayoutUidFilter(value);
1145
+ if (explicitLayoutUids.length) {
1146
+ return explicitLayoutUids;
1147
+ }
1148
+ return this.resolveDefaultDesktopRouteUiLayoutUids(transaction);
1149
+ }
1150
+ async assertEnabledDesktopRouteUiLayoutUid(layoutUid, actionName, path, transaction) {
1151
+ if (!this.hasDesktopRouteUiLayoutsRelation()) {
1152
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} requires plugin-ui-layout desktop route relation support`, {
1153
+ ruleId: "navigation-layout-unsupported",
1154
+ path,
1155
+ details: {
1156
+ layoutUid
1157
+ }
1158
+ });
1159
+ }
1160
+ const uiLayout = await this.db.getRepository("uiLayouts").findOne({
1161
+ filter: {
1162
+ uid: layoutUid,
1163
+ enabled: true
1164
+ },
1165
+ transaction
1166
+ });
1167
+ if (!uiLayout) {
1168
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} must reference an enabled ui layout`, {
1169
+ ruleId: "navigation-layout-not-found",
1170
+ path,
1171
+ details: {
1172
+ layoutUid
1173
+ }
1174
+ });
1175
+ }
1176
+ }
1177
+ async assertDesktopRouteBelongsToUiLayout(actionName, route, layoutUid, path, transaction) {
1178
+ const normalizedLayoutUid = this.normalizeExplicitDesktopRouteLayoutUid(layoutUid);
1179
+ if (!normalizedLayoutUid || !route) {
1180
+ return;
1181
+ }
1182
+ const routeId = this.readRouteField(route, "id");
1183
+ const routeLayoutUids = await this.readDesktopRouteUiLayoutUids(routeId, transaction);
1184
+ if (routeLayoutUids.includes(normalizedLayoutUid)) {
1185
+ return;
1186
+ }
1187
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} does not belong to ui layout '${normalizedLayoutUid}'`, {
1188
+ ruleId: "navigation-route-layout-mismatch",
1189
+ path,
1190
+ details: {
1191
+ routeId,
1192
+ layoutUid: normalizedLayoutUid,
1193
+ routeLayoutUids
1194
+ }
1195
+ });
1196
+ }
1197
+ async resolveRequestedDesktopRouteUiLayoutUids(values, parentRoute, actionName, transaction) {
1198
+ const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid(values.layoutUid);
1199
+ if (layoutUid) {
1200
+ await this.assertEnabledDesktopRouteUiLayoutUid(layoutUid, actionName, "values.layoutUid", transaction);
1201
+ if (parentRoute) {
1202
+ await this.assertDesktopRouteBelongsToUiLayout(
1203
+ actionName,
1204
+ parentRoute,
1205
+ layoutUid,
1206
+ "values.parentMenuRouteId",
1207
+ transaction
1208
+ );
1209
+ }
1210
+ return [layoutUid];
1211
+ }
1212
+ return this.resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction);
1213
+ }
1214
+ async setDesktopRouteUiLayouts(routeId, uiLayoutUids, transaction) {
1215
+ const relationRouteId = this.normalizeDesktopRouteRelationId(routeId);
1216
+ if (import_lodash.default.isUndefined(relationRouteId) || !uiLayoutUids.length || !this.hasDesktopRouteUiLayoutsRelation()) {
1217
+ return;
1218
+ }
1219
+ await this.db.getRepository("desktopRoutes.uiLayouts", relationRouteId).set({
1220
+ tk: uiLayoutUids,
1221
+ transaction
1222
+ });
1223
+ }
1224
+ async attachDesktopRouteUiLayoutsToRouteAndChildren(routeId, uiLayoutUids, transaction) {
1225
+ if (import_lodash.default.isNil(routeId) || !uiLayoutUids.length || !this.hasDesktopRouteUiLayoutsRelation()) {
1226
+ return;
1227
+ }
1228
+ await this.setDesktopRouteUiLayouts(routeId, uiLayoutUids, transaction);
1229
+ const children = await this.db.getRepository("desktopRoutes").find({
1230
+ fields: ["id"],
1231
+ filter: {
1232
+ parentId: routeId
1233
+ },
1234
+ transaction
1235
+ });
1236
+ for (const child of children) {
1237
+ await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
1238
+ this.readRouteField(child, "id"),
1239
+ uiLayoutUids,
1240
+ transaction
1241
+ );
1242
+ }
1243
+ }
1244
+ async ensureDesktopRouteUiLayouts(route, transaction) {
1245
+ const routeId = this.readRouteField(route, "id");
1246
+ if (import_lodash.default.isNil(routeId) || !this.hasDesktopRouteUiLayoutsRelation()) {
1247
+ return [];
1248
+ }
1249
+ const existingLayoutUids = await this.readDesktopRouteUiLayoutUids(routeId, transaction);
1250
+ if (existingLayoutUids.length) {
1251
+ return existingLayoutUids;
1252
+ }
1253
+ const parentRouteId = this.readRouteField(route, "parentId");
1254
+ const parentRoute = import_lodash.default.isNil(parentRouteId) ? null : await this.findMenuRouteById(parentRouteId, transaction);
1255
+ const inheritedLayoutUids = await this.resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction);
1256
+ await this.setDesktopRouteUiLayouts(routeId, inheritedLayoutUids, transaction);
1257
+ return inheritedLayoutUids;
1258
+ }
1029
1259
  isValidMenuIconName(value) {
1030
1260
  const normalized = String(value || "").trim();
1031
1261
  return !!normalized && ANT_DESIGN_ICON_NAMES.has(normalized);
@@ -1081,8 +1311,19 @@ class FlowSurfacesService {
1081
1311
  async createFlowMenuGroup(values, transaction) {
1082
1312
  const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
1083
1313
  const parentId = this.readRouteField(parentRoute, "id") ?? null;
1314
+ const routeUiLayoutUids = await this.resolveRequestedDesktopRouteUiLayoutUids(
1315
+ values,
1316
+ parentRoute,
1317
+ "createMenu",
1318
+ transaction
1319
+ );
1084
1320
  const title = String(values.title || "").trim();
1085
- const existingGroups = await this.findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction);
1321
+ const existingGroups = await this.findMenuGroupRoutesByParentIdAndTitle(
1322
+ parentId,
1323
+ title,
1324
+ transaction,
1325
+ routeUiLayoutUids
1326
+ );
1086
1327
  if (existingGroups.length === 1) {
1087
1328
  return this.buildMenuResult(existingGroups[0]);
1088
1329
  }
@@ -1107,7 +1348,7 @@ class FlowSurfacesService {
1107
1348
  this.assertVisibleNavigationIcon("createMenu", "values", values);
1108
1349
  const schemaUid = values.schemaUid || (0, import_utils.uid)();
1109
1350
  const desktopRoutes = this.db.getRepository("desktopRoutes");
1110
- await desktopRoutes.create({
1351
+ const route = await desktopRoutes.create({
1111
1352
  values: {
1112
1353
  type: "group",
1113
1354
  sort: this.allocateRouteSortValue(),
@@ -1120,15 +1361,22 @@ class FlowSurfacesService {
1120
1361
  },
1121
1362
  transaction
1122
1363
  });
1123
- const route = await desktopRoutes.findOne({
1124
- filter: { schemaUid },
1364
+ await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
1365
+ this.readRouteField(route, "id"),
1366
+ routeUiLayoutUids,
1125
1367
  transaction
1126
- });
1368
+ );
1127
1369
  return this.buildMenuResult(route);
1128
1370
  }
1129
1371
  async createFlowMenuItem(values, transaction) {
1130
1372
  var _a;
1131
1373
  const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
1374
+ const routeUiLayoutUids = await this.resolveRequestedDesktopRouteUiLayoutUids(
1375
+ values,
1376
+ parentRoute,
1377
+ "createMenu",
1378
+ transaction
1379
+ );
1132
1380
  this.assertVisibleNavigationIcon("createMenu", "values", values);
1133
1381
  const pageSchemaUid = values.pageSchemaUid || (0, import_utils.uid)();
1134
1382
  const menuSchemaUid = (0, import_utils.uid)();
@@ -1138,7 +1386,7 @@ class FlowSurfacesService {
1138
1386
  const title = values.title || pageSchemaUid;
1139
1387
  const tabTitle = values.tabTitle || "Untitled";
1140
1388
  const desktopRoutes = this.db.getRepository("desktopRoutes");
1141
- await desktopRoutes.create({
1389
+ const createdRoute = await desktopRoutes.create({
1142
1390
  values: {
1143
1391
  type: "flowPage",
1144
1392
  sort: this.allocateRouteSortValue(),
@@ -1173,6 +1421,11 @@ class FlowSurfacesService {
1173
1421
  },
1174
1422
  transaction
1175
1423
  });
1424
+ await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
1425
+ this.readRouteField(createdRoute, "id"),
1426
+ routeUiLayoutUids,
1427
+ transaction
1428
+ );
1176
1429
  const route = await desktopRoutes.findOne({
1177
1430
  filter: { schemaUid: pageSchemaUid },
1178
1431
  appends: ["children"],
@@ -1207,7 +1460,7 @@ class FlowSurfacesService {
1207
1460
  });
1208
1461
  }
1209
1462
  sanitizePublicCreateMenuValues(values) {
1210
- return import_lodash.default.pick(values, ["title", "type", "icon", "tooltip", "hideInMenu", "parentMenuRouteId"]);
1463
+ return import_lodash.default.pick(values, ["title", "type", "layoutUid", "icon", "tooltip", "hideInMenu", "parentMenuRouteId"]);
1211
1464
  }
1212
1465
  async loadRouteBackedPageStructure(route, transaction) {
1213
1466
  const routeId = this.readRouteField(route, "id");
@@ -1945,6 +2198,9 @@ class FlowSurfacesService {
1945
2198
  if (!(popupProfile == null ? void 0 : popupProfile.currentCollection)) {
1946
2199
  return popupProfile == null ? void 0 : popupProfile.filterByTk;
1947
2200
  }
2201
+ if (popupProfile.popupKind === "recordPopup" && popupProfile.popupHostUse && POPUP_HOST_DEFAULT_RECORD_CONTEXT_ACTION_USES.has(popupProfile.popupHostUse)) {
2202
+ return "{{ctx.view.inputArgs.filterByTk}}";
2203
+ }
1948
2204
  if (popupProfile.popupKind !== "associationPopup") {
1949
2205
  return popupProfile.filterByTk;
1950
2206
  }
@@ -2300,10 +2556,18 @@ class FlowSurfacesService {
2300
2556
  if (!sameCurrentCollection || !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.filterByTk)) {
2301
2557
  return false;
2302
2558
  }
2559
+ const expectedFilterByTk = this.resolvePopupCurrentRecordResourceFilterByTk(input.popupProfile, {
2560
+ usePopupInputArgsWhenSourceIdInferred: true
2561
+ });
2562
+ const matchesCurrentRecordFilterByTk = this.isPopupCurrentRecordFilterByTkMatch(
2563
+ input.popupProfile,
2564
+ normalized.filterByTk,
2565
+ expectedFilterByTk
2566
+ );
2303
2567
  if (input.popupProfile.hasAssociationContext) {
2304
- return this.isSameConfiguredFlowContextValue(normalized.filterByTk, input.popupProfile.filterByTk) && normalized.associationName === input.popupProfile.associationName && this.isSameConfiguredFlowContextValue(normalized.sourceId, input.popupProfile.sourceId);
2568
+ return matchesCurrentRecordFilterByTk && normalized.associationName === input.popupProfile.associationName && this.isSameConfiguredFlowContextValue(normalized.sourceId, input.popupProfile.sourceId);
2305
2569
  }
2306
- return this.isSameConfiguredFlowContextValue(normalized.filterByTk, input.popupProfile.filterByTk) && !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.associationName) && !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.sourceId);
2570
+ return matchesCurrentRecordFilterByTk && !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.associationName) && !(0, import_service_helpers.hasConfiguredFlowContextValue)(normalized.sourceId);
2307
2571
  }
2308
2572
  if (input.binding === "associatedRecords") {
2309
2573
  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)) {
@@ -2346,6 +2610,12 @@ class FlowSurfacesService {
2346
2610
  }
2347
2611
  return import_lodash.default.isEqual(this.normalizeFlowContextTemplateValue(left), this.normalizeFlowContextTemplateValue(right));
2348
2612
  }
2613
+ isPopupCurrentRecordFilterByTkMatch(popupProfile, filterByTk, expectedFilterByTk) {
2614
+ if (this.isSameConfiguredFlowContextValue(filterByTk, expectedFilterByTk)) {
2615
+ return true;
2616
+ }
2617
+ return popupProfile.popupKind === "associationPopup" && this.isSameConfiguredFlowContextValue(filterByTk, popupProfile.filterByTk);
2618
+ }
2349
2619
  isPopupAssociatedRecordsSourceIdMatch(popupProfile, associationField, sourceId) {
2350
2620
  var _a, _b;
2351
2621
  if (!(0, import_service_helpers.hasConfiguredFlowContextValue)(sourceId)) {
@@ -2621,6 +2891,28 @@ class FlowSurfacesService {
2621
2891
  }
2622
2892
  return capability;
2623
2893
  }
2894
+ async getLiveFieldValueCapability(writeTarget, resolvedTarget, node, options = {}) {
2895
+ const context = await this.context(
2896
+ {
2897
+ target: writeTarget
2898
+ },
2899
+ options
2900
+ );
2901
+ const { capabilities } = (0, import_meta.buildReactionMetaCapabilities)({
2902
+ resolvedTarget: {
2903
+ ...resolvedTarget,
2904
+ node
2905
+ },
2906
+ context
2907
+ });
2908
+ const capability = capabilities.find((item) => item.kind === "fieldValue");
2909
+ if (!capability) {
2910
+ (0, import_errors.throwBadRequest)(
2911
+ `flowSurfaces reaction target '${resolvedTarget.use || resolvedTarget.target.uid}' does not support fieldValue`
2912
+ );
2913
+ }
2914
+ return capability;
2915
+ }
2624
2916
  async getReactionMeta(values, options = {}) {
2625
2917
  (0, import_payload_shape.validateFlowSurfacePayloadShape)("getReactionMeta", values, "values");
2626
2918
  const { writeTarget, node, resolvedTarget } = await this.resolveReactionRequest("getReactionMeta", values == null ? void 0 : values.target, {
@@ -2666,6 +2958,8 @@ class FlowSurfacesService {
2666
2958
  },
2667
2959
  rules: Array.isArray(values == null ? void 0 : values.rules) ? values.rules : []
2668
2960
  });
2961
+ const liveCapability = await this.getLiveFieldValueCapability(writeTarget, resolvedTarget, node, options);
2962
+ (0, import_field_value.validateFieldValueRulesAgainstCapability)(result.normalizedRules, liveCapability);
2669
2963
  await this.persistReactionSlot(storageNode, capability.resolvedSlot, result.canonicalRules, options);
2670
2964
  return result;
2671
2965
  }
@@ -2873,6 +3167,41 @@ class FlowSurfacesService {
2873
3167
  const publicNode = this.stripInternalSurfaceMetaFromNodeTree(import_lodash.default.cloneDeep(rawNode));
2874
3168
  return this.buildSurfaceReadPayload(target, resolved, publicNode, options);
2875
3169
  }
3170
+ async exportBlueprint(input, options = {}) {
3171
+ const request = this.normalizeExportBlueprintRequest(input);
3172
+ const resolved = await this.locator.resolve(request.target, options);
3173
+ if (resolved.kind !== "page" || !resolved.pageRoute) {
3174
+ (0, import_errors.throwBadRequest)(FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE);
3175
+ }
3176
+ const pageSchemaUid = this.resolveExportBlueprintPageSchemaUid(request.target, resolved);
3177
+ await this.assertExportBlueprintRootTarget(request.target, resolved, pageSchemaUid, options.transaction);
3178
+ const rawNode = await this.decorateTemplateReadbackTree(
3179
+ this.normalizePopupTreeShape(
3180
+ await this.loadResolvedNode(resolved, options.transaction, {
3181
+ persistCalendarPopupHosts: false
3182
+ })
3183
+ ),
3184
+ options.transaction
3185
+ );
3186
+ if (!(rawNode == null ? void 0 : rawNode.uid)) {
3187
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint target '${pageSchemaUid}' could not resolve a readable page tree`);
3188
+ }
3189
+ const pageRoute = resolved.pageRoute ? await this.routeSync.hydrateRoute(resolved.pageRoute, options.transaction) : void 0;
3190
+ const result = (0, import_export_document.exportFlowSurfaceBlueprintDocument)({
3191
+ page: rawNode,
3192
+ pageRoute,
3193
+ target: {
3194
+ pageSchemaUid
3195
+ },
3196
+ unsupportedPolicy: request.unsupportedPolicy
3197
+ });
3198
+ return {
3199
+ ...result,
3200
+ document: (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(
3201
+ result.document
3202
+ )
3203
+ };
3204
+ }
2876
3205
  getDeclaredKeyPersistenceDeps() {
2877
3206
  return {
2878
3207
  findModelById: (uid2, findOptions) => this.repository.findModelById(uid2, findOptions),
@@ -3041,7 +3370,13 @@ class FlowSurfacesService {
3041
3370
  if (!groupTitle) {
3042
3371
  return document;
3043
3372
  }
3044
- const matchedRoutes = await this.findMenuGroupRoutesByParentIdAndTitle(null, groupTitle, transaction);
3373
+ const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid(document.navigation.layoutUid);
3374
+ const matchedRoutes = await this.findMenuGroupRoutesByParentIdAndTitle(
3375
+ null,
3376
+ groupTitle,
3377
+ transaction,
3378
+ layoutUid || await this.resolveDefaultDesktopRouteUiLayoutUids(transaction)
3379
+ );
3045
3380
  if (!matchedRoutes.length) {
3046
3381
  return document;
3047
3382
  }
@@ -3066,29 +3401,89 @@ class FlowSurfacesService {
3066
3401
  }
3067
3402
  };
3068
3403
  }
3404
+ async normalizeApplyBlueprintCreateMobileNavigation(document, transaction) {
3405
+ var _a;
3406
+ if (document.mode !== "create") {
3407
+ return document;
3408
+ }
3409
+ const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid((_a = document.navigation) == null ? void 0 : _a.layoutUid);
3410
+ if (!await this.isMobileDesktopRouteUiLayoutUid(layoutUid, transaction)) {
3411
+ return document;
3412
+ }
3413
+ return {
3414
+ ...document,
3415
+ navigation: (0, import_service_utils.buildDefinedPayload)({
3416
+ ...document.navigation,
3417
+ layoutUid,
3418
+ group: void 0
3419
+ })
3420
+ };
3421
+ }
3422
+ async assertApplyBlueprintCreateNavigationLayout(document, transaction) {
3423
+ var _a, _b, _c;
3424
+ if (document.mode !== "create") {
3425
+ return;
3426
+ }
3427
+ const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid((_a = document.navigation) == null ? void 0 : _a.layoutUid);
3428
+ if (!layoutUid) {
3429
+ return;
3430
+ }
3431
+ await this.assertEnabledDesktopRouteUiLayoutUid(
3432
+ layoutUid,
3433
+ "applyBlueprint",
3434
+ "values.navigation.layoutUid",
3435
+ transaction
3436
+ );
3437
+ if (await this.isMobileDesktopRouteUiLayoutUid(layoutUid, transaction)) {
3438
+ return;
3439
+ }
3440
+ const groupRouteId = (_c = (_b = document.navigation) == null ? void 0 : _b.group) == null ? void 0 : _c.routeId;
3441
+ if (import_lodash.default.isNil(groupRouteId) || groupRouteId === "") {
3442
+ return;
3443
+ }
3444
+ const groupRoute = await this.assertMenuParentIsGroup(groupRouteId, transaction);
3445
+ await this.assertDesktopRouteBelongsToUiLayout(
3446
+ "applyBlueprint",
3447
+ groupRoute,
3448
+ layoutUid,
3449
+ "values.navigation.group.routeId",
3450
+ transaction
3451
+ );
3452
+ }
3069
3453
  async resolveApplyBlueprintCreatePageIdentity(document, transaction) {
3070
- var _a, _b, _c, _d, _e;
3454
+ var _a, _b, _c, _d, _e, _f;
3071
3455
  if (document.mode !== "create") {
3072
3456
  return document;
3073
3457
  }
3074
3458
  const groupRouteId = (_b = (_a = document.navigation) == null ? void 0 : _a.group) == null ? void 0 : _b.routeId;
3075
- const pageTitle = String(((_c = document.page) == null ? void 0 : _c.title) || ((_e = (_d = document.navigation) == null ? void 0 : _d.item) == null ? void 0 : _e.title) || "").trim();
3076
- if (import_lodash.default.isNil(groupRouteId) || groupRouteId === "" || !pageTitle) {
3459
+ const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid((_c = document.navigation) == null ? void 0 : _c.layoutUid);
3460
+ const pageTitle = String(((_d = document.page) == null ? void 0 : _d.title) || ((_f = (_e = document.navigation) == null ? void 0 : _e.item) == null ? void 0 : _f.title) || "").trim();
3461
+ const hasGroupRouteId = !import_lodash.default.isNil(groupRouteId) && groupRouteId !== "";
3462
+ if (!pageTitle || !hasGroupRouteId && !layoutUid) {
3077
3463
  return document;
3078
3464
  }
3079
- const matchedPages = await this.findFlowPageRoutesByParentIdAndTitle(groupRouteId, pageTitle, transaction);
3465
+ const groupRoute = hasGroupRouteId ? await this.findMenuRouteById(groupRouteId, transaction) : null;
3466
+ const layoutUidFilter = layoutUid || (groupRoute ? await this.resolveInheritedDesktopRouteUiLayoutUids(groupRoute, transaction) : void 0);
3467
+ const matchedPages = await this.findFlowPageRoutesByParentIdAndTitle(
3468
+ hasGroupRouteId ? groupRouteId : null,
3469
+ pageTitle,
3470
+ transaction,
3471
+ layoutUidFilter
3472
+ );
3080
3473
  if (!matchedPages.length) {
3081
3474
  return document;
3082
3475
  }
3083
3476
  if (matchedPages.length > 1) {
3477
+ const locationLabel = hasGroupRouteId ? `under navigation.group.routeId '${groupRouteId}'` : `at the root of ui layout '${layoutUid}'`;
3084
3478
  (0, import_errors.throwBadRequest)(
3085
- `flowSurfaces applyBlueprint navigation.group.routeId '${groupRouteId}' already has ${matchedPages.length} flow pages titled '${pageTitle}'; pass target.pageSchemaUid explicitly before applyBlueprint`
3479
+ `flowSurfaces applyBlueprint ${locationLabel} already has ${matchedPages.length} flow pages titled '${pageTitle}'; pass target.pageSchemaUid explicitly before applyBlueprint`
3086
3480
  );
3087
3481
  }
3088
3482
  const pageSchemaUid = String(this.readRouteField(matchedPages[0], "schemaUid") || "").trim();
3089
3483
  if (!pageSchemaUid) {
3484
+ const locationLabel = hasGroupRouteId ? `under navigation.group.routeId '${groupRouteId}'` : `at the root of ui layout '${layoutUid}'`;
3090
3485
  (0, import_errors.throwBadRequest)(
3091
- `flowSurfaces applyBlueprint existing flow page '${pageTitle}' under navigation.group.routeId '${groupRouteId}' is missing schemaUid; pass target.pageSchemaUid explicitly before applyBlueprint`
3486
+ `flowSurfaces applyBlueprint existing flow page '${pageTitle}' ${locationLabel} is missing schemaUid; pass target.pageSchemaUid explicitly before applyBlueprint`
3092
3487
  );
3093
3488
  }
3094
3489
  return {
@@ -3103,7 +3498,15 @@ class FlowSurfacesService {
3103
3498
  async prepareApplyBlueprintRequest(values, transaction, createdKanbanSortFields) {
3104
3499
  var _a;
3105
3500
  const initialDocument = (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(values);
3106
- const groupResolvedDocument = await this.resolveApplyBlueprintCreateNavigationGroup(initialDocument, transaction);
3501
+ await this.assertApplyBlueprintCreateNavigationLayout(initialDocument, transaction);
3502
+ const mobileNormalizedDocument = await this.normalizeApplyBlueprintCreateMobileNavigation(
3503
+ initialDocument,
3504
+ transaction
3505
+ );
3506
+ const groupResolvedDocument = await this.resolveApplyBlueprintCreateNavigationGroup(
3507
+ mobileNormalizedDocument,
3508
+ transaction
3509
+ );
3107
3510
  const document = await this.resolveApplyBlueprintCreatePageIdentity(groupResolvedDocument, transaction);
3108
3511
  await this.prepareApplyBlueprintKanbanBlocks(document, transaction, createdKanbanSortFields);
3109
3512
  const replaceTarget = document.mode === "replace" && document.target ? await this.resolveApplyBlueprintReplaceTargetInfo(document.target.pageSchemaUid, transaction) : void 0;
@@ -3760,7 +4163,8 @@ class FlowSurfacesService {
3760
4163
  await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("applyBlueprint", values, {
3761
4164
  transaction: options.transaction,
3762
4165
  enabledPackages,
3763
- findMenuGroupRoutesByTitle: (title, transaction) => this.findMenuGroupRoutesByTitle(title, transaction),
4166
+ findMenuGroupRoutesByTitle: (title, transaction, layoutUid) => this.findMenuGroupRoutesByTitle(title, transaction, layoutUid),
4167
+ getUiLayoutTypeByUid: (layoutUid, transaction) => this.getDesktopRouteUiLayoutTypeByUid(layoutUid, transaction),
3764
4168
  getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || "")
3765
4169
  });
3766
4170
  }
@@ -4474,10 +4878,16 @@ class FlowSurfacesService {
4474
4878
  return this.buildPopupTemplateOpenView(template, "reference", templateTargetUid, options);
4475
4879
  }
4476
4880
  shouldHydrateDetachedPopupTemplateBlockResourceContext(blockNode, context) {
4477
- if (!this.isCollectionBlockUse(blockNode == null ? void 0 : blockNode.use) || !context.associationName || !context.sourceId) {
4881
+ if (!this.isCollectionBlockUse(blockNode == null ? void 0 : blockNode.use)) {
4478
4882
  return false;
4479
4883
  }
4480
4884
  const init = import_lodash.default.get(blockNode, ["stepParams", "resourceSettings", "init"]) || {};
4885
+ if (this.resolveDetachedPopupTemplateBlockCurrentRecordFilterByTk(init, context)) {
4886
+ return true;
4887
+ }
4888
+ if (!context.associationName || !context.sourceId) {
4889
+ return false;
4890
+ }
4481
4891
  const popupDataSourceKey = context.dataSourceKey || "main";
4482
4892
  const blockDataSourceKey = init.dataSourceKey || "main";
4483
4893
  if (!context.collectionName || blockDataSourceKey !== popupDataSourceKey || init.collectionName !== context.collectionName) {
@@ -4492,6 +4902,28 @@ class FlowSurfacesService {
4492
4902
  }
4493
4903
  return blockAssociationName !== context.associationName || !this.isSameConfiguredFlowContextValue(init.sourceId, context.sourceId);
4494
4904
  }
4905
+ resolveDetachedPopupTemplateBlockCurrentRecordFilterByTk(init, context) {
4906
+ if (!(0, import_service_helpers.hasConfiguredFlowContextValue)(init.filterByTk)) {
4907
+ return void 0;
4908
+ }
4909
+ if (this.isSameConfiguredFlowContextValue(init.filterByTk, "{{ctx.view.inputArgs.filterByTk}}")) {
4910
+ return void 0;
4911
+ }
4912
+ const popupDataSourceKey = context.dataSourceKey || "main";
4913
+ const blockDataSourceKey = init.dataSourceKey || "main";
4914
+ if (!context.collectionName || blockDataSourceKey !== popupDataSourceKey || init.collectionName !== context.collectionName) {
4915
+ return void 0;
4916
+ }
4917
+ if (context.filterByTk && this.isSameConfiguredFlowContextValue(init.filterByTk, context.filterByTk)) {
4918
+ return "{{ctx.view.inputArgs.filterByTk}}";
4919
+ }
4920
+ const collection = this.getCollection(popupDataSourceKey, context.collectionName);
4921
+ const filterTargetKey = this.getCollectionFilterTargetKey(collection);
4922
+ if (this.isSameConfiguredFlowContextValue(init.filterByTk, `{{ctx.record.${filterTargetKey}}}`)) {
4923
+ return "{{ctx.view.inputArgs.filterByTk}}";
4924
+ }
4925
+ return void 0;
4926
+ }
4495
4927
  collectDetachedPopupTemplateBlockResourceContextPatches(node, context, patches = []) {
4496
4928
  if (!node || typeof node !== "object") {
4497
4929
  return patches;
@@ -4499,6 +4931,7 @@ class FlowSurfacesService {
4499
4931
  if (node.uid && this.shouldHydrateDetachedPopupTemplateBlockResourceContext(node, context)) {
4500
4932
  const nextStepParams = import_lodash.default.cloneDeep(node.stepParams || {});
4501
4933
  const currentInit = import_lodash.default.get(nextStepParams, ["resourceSettings", "init"]) || {};
4934
+ const filterByTk = this.resolveDetachedPopupTemplateBlockCurrentRecordFilterByTk(currentInit, context);
4502
4935
  import_lodash.default.set(
4503
4936
  nextStepParams,
4504
4937
  ["resourceSettings", "init"],
@@ -4506,8 +4939,11 @@ class FlowSurfacesService {
4506
4939
  ...currentInit,
4507
4940
  dataSourceKey: context.dataSourceKey || currentInit.dataSourceKey || "main",
4508
4941
  collectionName: context.collectionName || currentInit.collectionName,
4509
- associationName: context.associationName,
4510
- sourceId: context.sourceId
4942
+ ...context.associationName && context.sourceId ? {
4943
+ associationName: context.associationName,
4944
+ sourceId: context.sourceId
4945
+ } : {},
4946
+ ...filterByTk ? { filterByTk } : {}
4511
4947
  })
4512
4948
  );
4513
4949
  patches.push({
@@ -5767,7 +6203,7 @@ class FlowSurfacesService {
5767
6203
  (0, import_errors.throwBadRequest)("flowSurfaces updateMenu requires menuRouteId");
5768
6204
  }
5769
6205
  const route = await this.assertMenuRouteUpdatable(menuRouteId, options.transaction);
5770
- await this.assertMenuParentIsGroup(values.parentMenuRouteId, options.transaction);
6206
+ const nextParentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, options.transaction);
5771
6207
  await this.assertMenuParentNotSelfOrDescendant(route, values.parentMenuRouteId, options.transaction);
5772
6208
  const nextOptions = { ...this.readRouteOptions(route) };
5773
6209
  const updateValues = {};
@@ -5798,6 +6234,13 @@ class FlowSurfacesService {
5798
6234
  });
5799
6235
  }
5800
6236
  const updated = await this.findMenuRouteById(menuRouteId, options.transaction);
6237
+ if (updated && Object.prototype.hasOwnProperty.call(values, "parentMenuRouteId")) {
6238
+ await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
6239
+ this.readRouteField(updated, "id"),
6240
+ await this.resolveInheritedDesktopRouteUiLayoutUids(nextParentRoute, options.transaction),
6241
+ options.transaction
6242
+ );
6243
+ }
5801
6244
  return this.buildMenuResult(updated);
5802
6245
  }
5803
6246
  async initializeFlowPageForRoute(route, values, transaction) {
@@ -5805,6 +6248,12 @@ class FlowSurfacesService {
5805
6248
  const pageSchemaUid = this.readRouteField(route, "schemaUid");
5806
6249
  const structure = await this.loadRouteBackedPageStructure(route, transaction);
5807
6250
  let tabRoute = structure.tabRoutes[0];
6251
+ const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid(values.layoutUid);
6252
+ if (layoutUid) {
6253
+ await this.assertEnabledDesktopRouteUiLayoutUid(layoutUid, "createPage", "values.layoutUid", transaction);
6254
+ await this.assertDesktopRouteBelongsToUiLayout("createPage", route, layoutUid, "values.menuRouteId", transaction);
6255
+ }
6256
+ const routeUiLayoutUids = await this.ensureDesktopRouteUiLayouts(route, transaction);
5808
6257
  const routeOptions = this.readRouteOptions(route);
5809
6258
  if (!routeOptions[FLOW_SURFACE_MENU_BINDABLE_OPTION_KEY]) {
5810
6259
  (0, import_errors.throwBadRequest)(`flowSurfaces createPage only accepts a bindable menu route created by createMenu(type="item")`);
@@ -5826,7 +6275,7 @@ class FlowSurfacesService {
5826
6275
  const tabSchemaUid2 = values.tabSchemaUid || (0, import_utils.uid)();
5827
6276
  const tabSchemaName2 = values.tabSchemaName || (0, import_utils.uid)();
5828
6277
  const tabTitle = values.tabTitle || "Untitled";
5829
- await this.db.getRepository("desktopRoutes").create({
6278
+ tabRoute = await this.db.getRepository("desktopRoutes").create({
5830
6279
  values: {
5831
6280
  type: "tabs",
5832
6281
  sort: this.allocateRouteSortValue(1),
@@ -5843,10 +6292,7 @@ class FlowSurfacesService {
5843
6292
  },
5844
6293
  transaction
5845
6294
  });
5846
- tabRoute = await this.db.getRepository("desktopRoutes").findOne({
5847
- filter: { schemaUid: tabSchemaUid2 },
5848
- transaction
5849
- });
6295
+ await this.setDesktopRouteUiLayouts(this.readRouteField(tabRoute, "id"), routeUiLayoutUids, transaction);
5850
6296
  } else {
5851
6297
  await this.db.getRepository("desktopRoutes").update({
5852
6298
  filterByTk: String(this.readRouteField(tabRoute, "id")),
@@ -5870,6 +6316,9 @@ class FlowSurfacesService {
5870
6316
  transaction
5871
6317
  });
5872
6318
  }
6319
+ if (tabRoute) {
6320
+ await this.setDesktopRouteUiLayouts(this.readRouteField(tabRoute, "id"), routeUiLayoutUids, transaction);
6321
+ }
5873
6322
  await this.ensureFlowRoutePageSchemaShell(pageSchemaUid, transaction);
5874
6323
  await this.db.getRepository("desktopRoutes").update({
5875
6324
  filterByTk: String(routeId),
@@ -6009,6 +6458,11 @@ class FlowSurfacesService {
6009
6458
  },
6010
6459
  transaction: options.transaction
6011
6460
  });
6461
+ await this.setDesktopRouteUiLayouts(
6462
+ route.get("id"),
6463
+ await this.ensureDesktopRouteUiLayouts(pageRoute, options.transaction),
6464
+ options.transaction
6465
+ );
6012
6466
  const gridUid = await this.ensureGridChild(tabSchemaUid, "BlockGridModel", options.transaction);
6013
6467
  const result = {
6014
6468
  pageUid: pageTarget.uid,
@@ -6679,11 +7133,6 @@ class FlowSurfacesService {
6679
7133
  requiredFieldCount: options.requiredFieldCount
6680
7134
  }
6681
7135
  );
6682
- if (!(0, import_service_utils.hasOwnDefined)(normalizedSettings, "filterableFieldNames")) {
6683
- normalizedSettings.filterableFieldNames = (0, import_public_data_surface_default_filter.resolveFlowSurfaceDefaultFilterFieldNames)(
6684
- normalizedSettings.defaultFilter
6685
- );
6686
- }
6687
7136
  }
6688
7137
  return normalizedSettings;
6689
7138
  }
@@ -11417,6 +11866,7 @@ class FlowSurfacesService {
11417
11866
  }
11418
11867
  if (this.isAIEmployeeActionUse(current == null ? void 0 : current.use) && this.hasAIEmployeePublicSettings(normalizedValues)) {
11419
11868
  const enabledPackages = await this.resolveEnabledPluginPackages(options);
11869
+ const hasRawAIEmployeeStepTasks = import_lodash.default.has(normalizedValues, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
11420
11870
  const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
11421
11871
  "updateSettings",
11422
11872
  import_lodash.default.pick(normalizedValues, AI_EMPLOYEE_PUBLIC_SETTING_KEYS),
@@ -11429,7 +11879,8 @@ class FlowSurfacesService {
11429
11879
  promptContext: {
11430
11880
  kind: "target",
11431
11881
  targetUid: (current == null ? void 0 : current.uid) || writeTarget.uid
11432
- }
11882
+ },
11883
+ skipExistingTaskWorkContextRebase: hasRawAIEmployeeStepTasks
11433
11884
  }
11434
11885
  );
11435
11886
  AI_EMPLOYEE_PUBLIC_SETTING_KEYS.forEach((key) => {
@@ -11511,6 +11962,7 @@ class FlowSurfacesService {
11511
11962
  normalizedValues,
11512
11963
  nextPayload
11513
11964
  );
11965
+ this.syncActionButtonSettingsForUpdateSettings(current, normalizedValues, nextPayload);
11514
11966
  this.syncActionTriggerWorkflowsForUpdateSettings(current, normalizedValues, nextPayload);
11515
11967
  const popupActionContext = options.popupActionContext || await this.resolveRecordContextPopupActionContextForHost(current, options.transaction);
11516
11968
  await this.normalizeOpenViewForUpdateSettings(
@@ -11562,6 +12014,12 @@ class FlowSurfacesService {
11562
12014
  if (Object.keys(nextPayload).length === 1) {
11563
12015
  return { uid: current.uid };
11564
12016
  }
12017
+ await this.assertNoDuplicateAIEmployeeActionForUpdateSettings(
12018
+ options.openViewActionName || "updateSettings",
12019
+ current,
12020
+ effectiveNode,
12021
+ options.transaction
12022
+ );
11565
12023
  if (target.kind === "tab" && target.tabRoute) {
11566
12024
  await this.routeSync.persistTabSettings(target, current, nextPayload, options.transaction);
11567
12025
  return {
@@ -11972,17 +12430,6 @@ class FlowSurfacesService {
11972
12430
  const filterValue = this.normalizeEffectivePublicDataSurfaceDefaultFilter(normalizedFilterValue, {
11973
12431
  requiredFieldCount: options.requiredFieldCount
11974
12432
  });
11975
- if (!hasPropsFilterableFieldNames && !hasStepFilterableFieldNames) {
11976
- const filterableFieldNames = (0, import_public_data_surface_default_filter.resolveFlowSurfaceDefaultFilterFieldNames)(filterValue);
11977
- if (filterableFieldNames.length) {
11978
- nextProps.filterableFieldNames = filterableFieldNames;
11979
- import_lodash.default.set(
11980
- nextStepParams,
11981
- ["filterSettings", "filterableFieldNames", "filterableFieldNames"],
11982
- import_lodash.default.cloneDeep(filterableFieldNames)
11983
- );
11984
- }
11985
- }
11986
12433
  nextProps.defaultFilterValue = import_lodash.default.cloneDeep(filterValue);
11987
12434
  nextProps.filterValue = import_lodash.default.cloneDeep(filterValue);
11988
12435
  import_lodash.default.set(nextStepParams, ["filterSettings", "defaultFilter", "defaultFilter"], import_lodash.default.cloneDeep(filterValue));
@@ -12029,6 +12476,65 @@ class FlowSurfacesService {
12029
12476
  nextPayload.stepParams = nextStepParams;
12030
12477
  }
12031
12478
  }
12479
+ syncActionButtonSettingsForUpdateSettings(current, normalizedValues, nextPayload) {
12480
+ if (!this.supportsActionButtonSettingsSync(current)) {
12481
+ return;
12482
+ }
12483
+ const requestedProps = this.pickRequestedActionButtonSettings(normalizedValues.props);
12484
+ const requestedButtonGeneral = this.pickRequestedActionButtonSettings(
12485
+ import_lodash.default.get(normalizedValues, ["stepParams", "buttonSettings", "general"])
12486
+ );
12487
+ const hasRequestedProps = Object.keys(requestedProps).length > 0;
12488
+ const hasRequestedButtonGeneral = Object.keys(requestedButtonGeneral).length > 0;
12489
+ if (!hasRequestedProps && !hasRequestedButtonGeneral) {
12490
+ return;
12491
+ }
12492
+ const hasRequestedTitle = Object.prototype.hasOwnProperty.call(requestedProps, "title") || Object.prototype.hasOwnProperty.call(requestedButtonGeneral, "title");
12493
+ const shouldStripImplicitTitle = (requestedProps.iconOnly === true || requestedButtonGeneral.iconOnly === true) && !hasRequestedTitle;
12494
+ const nextProps = import_lodash.default.cloneDeep(
12495
+ import_lodash.default.isPlainObject(nextPayload.props) ? nextPayload.props : import_lodash.default.isPlainObject(current == null ? void 0 : current.props) ? current.props : {}
12496
+ );
12497
+ const nextStepParams = import_lodash.default.cloneDeep(
12498
+ import_lodash.default.isPlainObject(nextPayload.stepParams) ? nextPayload.stepParams : import_lodash.default.isPlainObject(current == null ? void 0 : current.stepParams) ? current.stepParams : {}
12499
+ );
12500
+ Object.entries(requestedProps).forEach(([key, value]) => {
12501
+ if (Object.prototype.hasOwnProperty.call(requestedButtonGeneral, key)) {
12502
+ return;
12503
+ }
12504
+ import_lodash.default.set(nextStepParams, ["buttonSettings", "general", key], import_lodash.default.cloneDeep(value));
12505
+ });
12506
+ Object.entries(requestedButtonGeneral).forEach(([key, value]) => {
12507
+ if (Object.prototype.hasOwnProperty.call(requestedProps, key)) {
12508
+ return;
12509
+ }
12510
+ nextProps[key] = import_lodash.default.cloneDeep(value);
12511
+ });
12512
+ if (shouldStripImplicitTitle) {
12513
+ delete nextProps.title;
12514
+ if (import_lodash.default.isPlainObject(import_lodash.default.get(nextStepParams, ["buttonSettings", "general"]))) {
12515
+ delete nextStepParams.buttonSettings.general.title;
12516
+ }
12517
+ }
12518
+ nextPayload.props = nextProps;
12519
+ nextPayload.stepParams = nextStepParams;
12520
+ }
12521
+ supportsActionButtonSettingsSync(current) {
12522
+ var _a, _b, _c, _d, _e, _f;
12523
+ const contract = (0, import_catalog.getNodeContract)(current == null ? void 0 : current.use);
12524
+ 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"));
12525
+ }
12526
+ pickRequestedActionButtonSettings(input) {
12527
+ const picked = {};
12528
+ if (!import_lodash.default.isPlainObject(input)) {
12529
+ return picked;
12530
+ }
12531
+ ACTION_BUTTON_GENERAL_SETTING_KEYS.forEach((key) => {
12532
+ if (Object.prototype.hasOwnProperty.call(input, key) && !import_lodash.default.isUndefined(input[key])) {
12533
+ picked[key] = import_lodash.default.cloneDeep(input[key]);
12534
+ }
12535
+ });
12536
+ return picked;
12537
+ }
12032
12538
  syncCreatedFieldWrapperTitleFieldStepParams(node) {
12033
12539
  const mirror = (UPDATE_SETTINGS_STEP_PARAM_MIRRORS_BY_USE[(node == null ? void 0 : node.use) || ""] || []).find(
12034
12540
  (item) => item.domain === "props" && item.key === "titleField"
@@ -13694,6 +14200,111 @@ class FlowSurfacesService {
13694
14200
  }
13695
14201
  return target;
13696
14202
  }
14203
+ normalizeExportBlueprintRequest(input) {
14204
+ if (!import_lodash.default.isPlainObject(input)) {
14205
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint payload must be an object`);
14206
+ }
14207
+ const unsupportedKeys = Object.keys(input).filter((key) => key !== "target" && key !== "options");
14208
+ if (unsupportedKeys.length) {
14209
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint only accepts target and options`);
14210
+ }
14211
+ if (!import_lodash.default.isPlainObject(input.target)) {
14212
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint requires target`);
14213
+ }
14214
+ const targetInput = input.target;
14215
+ const target = (0, import_service_utils.buildDefinedPayload)({
14216
+ uid: this.normalizeExportBlueprintLocatorValue(targetInput.uid, "uid"),
14217
+ pageSchemaUid: this.normalizeExportBlueprintLocatorValue(targetInput.pageSchemaUid, "pageSchemaUid"),
14218
+ tabSchemaUid: this.normalizeExportBlueprintLocatorValue(targetInput.tabSchemaUid, "tabSchemaUid"),
14219
+ routeId: this.normalizeExportBlueprintLocatorValue(targetInput.routeId, "routeId")
14220
+ });
14221
+ const unsupportedTargetKeys = Object.keys(targetInput).filter(
14222
+ (key) => !["uid", "pageSchemaUid", "tabSchemaUid", "routeId"].includes(key)
14223
+ );
14224
+ if (unsupportedTargetKeys.length) {
14225
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint target only accepts uid, pageSchemaUid, tabSchemaUid or routeId`);
14226
+ }
14227
+ if (!Object.keys(target).length) {
14228
+ (0, import_errors.throwBadRequest)(
14229
+ `flowSurfaces exportBlueprint target requires one of uid, pageSchemaUid, tabSchemaUid or routeId`
14230
+ );
14231
+ }
14232
+ if (Object.keys(target).length > 1) {
14233
+ (0, import_errors.throwBadRequest)(
14234
+ `flowSurfaces exportBlueprint target only accepts exactly one locator: uid, pageSchemaUid, tabSchemaUid or routeId`
14235
+ );
14236
+ }
14237
+ if (target.tabSchemaUid) {
14238
+ (0, import_errors.throwBadRequest)(FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE);
14239
+ }
14240
+ return {
14241
+ target,
14242
+ unsupportedPolicy: this.normalizeExportBlueprintUnsupportedPolicy(input.options)
14243
+ };
14244
+ }
14245
+ normalizeExportBlueprintUnsupportedPolicy(input) {
14246
+ if (import_lodash.default.isUndefined(input)) {
14247
+ return "error";
14248
+ }
14249
+ if (!import_lodash.default.isPlainObject(input)) {
14250
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint options must be an object`);
14251
+ }
14252
+ const options = input;
14253
+ const unsupportedKeys = Object.keys(options).filter((key) => key !== "unsupported");
14254
+ if (unsupportedKeys.length) {
14255
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint options only accepts unsupported`);
14256
+ }
14257
+ const policy = options.unsupported;
14258
+ if (import_lodash.default.isUndefined(policy)) {
14259
+ return "error";
14260
+ }
14261
+ if (policy === "error" || policy === "warn") {
14262
+ return policy;
14263
+ }
14264
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint options.unsupported must be 'error' or 'warn'`);
14265
+ }
14266
+ normalizeExportBlueprintLocatorValue(value, key) {
14267
+ if (import_lodash.default.isNil(value)) {
14268
+ return void 0;
14269
+ }
14270
+ if (typeof value !== "string" && typeof value !== "number") {
14271
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint target.${key} must be a string`);
14272
+ }
14273
+ const normalized = String(value).trim();
14274
+ return normalized || void 0;
14275
+ }
14276
+ readRouteString(route, key) {
14277
+ var _a;
14278
+ const routeRecord = route;
14279
+ const value = ((_a = routeRecord == null ? void 0 : routeRecord.get) == null ? void 0 : _a.call(routeRecord, key)) ?? (routeRecord == null ? void 0 : routeRecord[key]);
14280
+ const normalized = typeof value === "string" ? value.trim() : "";
14281
+ return normalized || void 0;
14282
+ }
14283
+ resolveExportBlueprintPageSchemaUid(target, resolved) {
14284
+ const pageSchemaUid = this.readRouteString(resolved.pageRoute, "schemaUid") || (target.pageSchemaUid ? String(target.pageSchemaUid).trim() : "");
14285
+ if (!pageSchemaUid) {
14286
+ (0, import_errors.throwBadRequest)(FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE);
14287
+ }
14288
+ return pageSchemaUid;
14289
+ }
14290
+ async assertExportBlueprintRootTarget(target, resolved, pageSchemaUid, transaction) {
14291
+ const targetUid = target.uid ? String(target.uid).trim() : "";
14292
+ if (!targetUid) {
14293
+ return;
14294
+ }
14295
+ if (targetUid === pageSchemaUid) {
14296
+ return;
14297
+ }
14298
+ const rootPageModel = await this.repository.findModelByParentId(pageSchemaUid, {
14299
+ transaction,
14300
+ subKey: "page",
14301
+ includeAsyncNode: false
14302
+ });
14303
+ if ((rootPageModel == null ? void 0 : rootPageModel.uid) && targetUid === String(rootPageModel.uid).trim()) {
14304
+ return;
14305
+ }
14306
+ (0, import_errors.throwBadRequest)(FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE);
14307
+ }
13697
14308
  normalizeContextPath(path) {
13698
14309
  if (import_lodash.default.isUndefined(path) || import_lodash.default.isNull(path)) {
13699
14310
  return void 0;
@@ -16860,13 +17471,20 @@ class FlowSurfacesService {
16860
17471
  description: changes.description,
16861
17472
  className: changes.className
16862
17473
  }),
16863
- stepParams: (0, import_service_utils.hasDefinedValue)(changes, ["code", "version"]) ? {
16864
- jsSettings: {
16865
- runJs: (0, import_service_utils.buildDefinedPayload)({
16866
- code: changes.code,
16867
- version: changes.version
16868
- })
16869
- }
17474
+ stepParams: (0, import_service_utils.hasDefinedValue)(changes, ["code", "version", "showBlockCard"]) ? {
17475
+ jsSettings: (0, import_service_utils.buildDefinedPayload)({
17476
+ ...(0, import_service_utils.hasDefinedValue)(changes, ["code", "version"]) ? {
17477
+ runJs: (0, import_service_utils.buildDefinedPayload)({
17478
+ code: changes.code,
17479
+ version: changes.version
17480
+ })
17481
+ } : {},
17482
+ ...(0, import_service_utils.hasOwnDefined)(changes, "showBlockCard") ? {
17483
+ showBlockCard: {
17484
+ showBlockCard: changes.showBlockCard
17485
+ }
17486
+ } : {}
17487
+ })
16870
17488
  } : void 0
16871
17489
  },
16872
17490
  options
@@ -17448,19 +18066,21 @@ class FlowSurfacesService {
17448
18066
  }
17449
18067
  return JSON.stringify(value);
17450
18068
  }
17451
- buildAIEmployeeActionDedupIdentity(values) {
18069
+ buildAIEmployeeActionDedupIdentity(values, defaultActionWorkContext) {
17452
18070
  var _a, _b, _c, _d, _e, _f;
17453
18071
  const username = String(((_b = (_a = values == null ? void 0 : values.props) == null ? void 0 : _a.aiEmployee) == null ? void 0 : _b.username) || "").trim();
17454
18072
  if (!username) {
17455
18073
  return "";
17456
18074
  }
18075
+ const workContext = this.normalizeAIEmployeeActionWorkContextForDedupIdentity(
18076
+ (_d = (_c = values == null ? void 0 : values.props) == null ? void 0 : _c.context) == null ? void 0 : _d.workContext,
18077
+ defaultActionWorkContext
18078
+ );
17457
18079
  return this.stableSerializeAIEmployeeValue({
17458
18080
  username,
17459
- auto: typeof ((_c = values == null ? void 0 : values.props) == null ? void 0 : _c.auto) === "boolean" ? values.props.auto : false,
17460
- workContext: this.normalizeAIEmployeeWorkContextForDedupIdentity((_e = (_d = values == null ? void 0 : values.props) == null ? void 0 : _d.context) == null ? void 0 : _e.workContext),
17461
- tasks: this.normalizeAIEmployeeTasksForDedupIdentity(
17462
- import_lodash.default.get(values, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])
17463
- ),
18081
+ auto: typeof ((_e = values == null ? void 0 : values.props) == null ? void 0 : _e.auto) === "boolean" ? values.props.auto : false,
18082
+ workContext,
18083
+ tasks: this.normalizeAIEmployeeTasksForDedupIdentity(this.readAIEmployeePersistedTasks(values), workContext),
17464
18084
  style: {
17465
18085
  ...AI_EMPLOYEE_DEFAULT_STYLE,
17466
18086
  ...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) : {}
@@ -17468,11 +18088,35 @@ class FlowSurfacesService {
17468
18088
  });
17469
18089
  }
17470
18090
  normalizeAIEmployeeWorkContextForDedupIdentity(value) {
17471
- return import_lodash.default.castArray(value || []).map(
17472
- (item) => import_lodash.default.isPlainObject(item) ? import_lodash.default.pick(item, AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS) : item
17473
- );
18091
+ return import_lodash.default.castArray(value || []).map((item) => {
18092
+ if (!import_lodash.default.isPlainObject(item)) {
18093
+ return item;
18094
+ }
18095
+ const output = import_lodash.default.pick(item, AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS);
18096
+ if (!Object.prototype.hasOwnProperty.call(output, "type") || import_lodash.default.isUndefined(output.type) || output.type === null) {
18097
+ output.type = "flow-model";
18098
+ }
18099
+ return output;
18100
+ });
18101
+ }
18102
+ normalizeAIEmployeeActionWorkContextForDedupIdentity(value, defaultWorkContext) {
18103
+ if (!Array.isArray(value)) {
18104
+ return import_lodash.default.cloneDeep(defaultWorkContext || []);
18105
+ }
18106
+ return this.normalizeAIEmployeeWorkContextForDedupIdentity(value);
18107
+ }
18108
+ normalizeAIEmployeeDefaultActionWorkContextForSelfUid(selfUid) {
18109
+ const uid2 = String(selfUid || "").trim();
18110
+ return uid2 ? [{ type: "flow-model", uid: uid2 }] : [];
18111
+ }
18112
+ normalizeAIEmployeeTaskWorkContextForDedupIdentity(value, defaultWorkContext) {
18113
+ const normalized = this.normalizeAIEmployeeWorkContextForDedupIdentity(value);
18114
+ if (Array.isArray(defaultWorkContext) && !normalized.length) {
18115
+ return import_lodash.default.cloneDeep(defaultWorkContext);
18116
+ }
18117
+ return normalized;
17474
18118
  }
17475
- normalizeAIEmployeeTasksForDedupIdentity(value) {
18119
+ normalizeAIEmployeeTasksForDedupIdentity(value, defaultWorkContext) {
17476
18120
  return import_lodash.default.castArray(value || []).map((task) => {
17477
18121
  if (!import_lodash.default.isPlainObject(task)) {
17478
18122
  return task;
@@ -17481,9 +18125,19 @@ class FlowSurfacesService {
17481
18125
  if (import_lodash.default.isPlainObject(output.message)) {
17482
18126
  output.message = import_lodash.default.pick(output.message, AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS);
17483
18127
  if (Object.prototype.hasOwnProperty.call(output.message, "workContext")) {
17484
- output.message.workContext = this.normalizeAIEmployeeWorkContextForDedupIdentity(output.message.workContext);
18128
+ output.message.workContext = this.normalizeAIEmployeeTaskWorkContextForDedupIdentity(
18129
+ output.message.workContext,
18130
+ defaultWorkContext
18131
+ );
17485
18132
  }
17486
18133
  }
18134
+ if (!import_lodash.default.isPlainObject(output.message) && Array.isArray(defaultWorkContext)) {
18135
+ output.message = {
18136
+ workContext: import_lodash.default.cloneDeep(defaultWorkContext)
18137
+ };
18138
+ } else if (import_lodash.default.isPlainObject(output.message) && !Object.prototype.hasOwnProperty.call(output.message, "workContext")) {
18139
+ output.message.workContext = import_lodash.default.cloneDeep(defaultWorkContext || []);
18140
+ }
17487
18141
  if (import_lodash.default.isPlainObject(output.model)) {
17488
18142
  output.model = import_lodash.default.pick(output.model, AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS);
17489
18143
  }
@@ -17493,25 +18147,38 @@ class FlowSurfacesService {
17493
18147
  return output;
17494
18148
  });
17495
18149
  }
17496
- async assertNoDuplicateAIEmployeeAction(actionName, parentUid, values, transaction) {
18150
+ async assertNoDuplicateAIEmployeeAction(actionName, parentUid, values, transaction, excludeUid) {
17497
18151
  var _a;
17498
- const identity = this.buildAIEmployeeActionDedupIdentity(values);
17499
- if (!identity) {
17500
- return;
17501
- }
17502
18152
  const parentNode = await this.repository.findModelById(parentUid, {
17503
18153
  transaction,
17504
18154
  includeAsyncNode: true
17505
18155
  });
17506
- const duplicate = import_lodash.default.castArray(((_a = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _a.actions) || []).find((action) => {
18156
+ const defaultActionWorkContext = this.normalizeAIEmployeeDefaultActionWorkContextForSelfUid(
18157
+ await this.resolveAIEmployeeActionSelfUidFromParentNode(parentNode, transaction)
18158
+ );
18159
+ const identity = this.buildAIEmployeeActionDedupIdentity(values, defaultActionWorkContext);
18160
+ if (!identity) {
18161
+ return;
18162
+ }
18163
+ let duplicate;
18164
+ for (const action of import_lodash.default.castArray(((_a = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _a.actions) || [])) {
17507
18165
  if (!this.isAIEmployeeActionUse(action == null ? void 0 : action.use)) {
17508
- return false;
18166
+ continue;
17509
18167
  }
17510
- return this.buildAIEmployeeActionDedupIdentity({
17511
- props: action.props,
17512
- stepParams: action.stepParams
17513
- }) === identity;
17514
- });
18168
+ if (excludeUid && String((action == null ? void 0 : action.uid) || "") === excludeUid) {
18169
+ continue;
18170
+ }
18171
+ if (this.buildAIEmployeeActionDedupIdentity(
18172
+ {
18173
+ props: action.props,
18174
+ stepParams: action.stepParams
18175
+ },
18176
+ defaultActionWorkContext
18177
+ ) === identity) {
18178
+ duplicate = action;
18179
+ break;
18180
+ }
18181
+ }
17515
18182
  if (!(duplicate == null ? void 0 : duplicate.uid)) {
17516
18183
  return;
17517
18184
  }
@@ -17526,6 +18193,25 @@ class FlowSurfacesService {
17526
18193
  }
17527
18194
  );
17528
18195
  }
18196
+ async assertNoDuplicateAIEmployeeActionForUpdateSettings(actionName, current, effectiveNode, transaction) {
18197
+ if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
18198
+ return;
18199
+ }
18200
+ const parentUid = String((current == null ? void 0 : current.parentId) || "").trim() || ((current == null ? void 0 : current.uid) ? await this.locator.findParentUid(current.uid, transaction).catch(() => "") : "");
18201
+ if (!parentUid) {
18202
+ return;
18203
+ }
18204
+ await this.assertNoDuplicateAIEmployeeAction(
18205
+ actionName,
18206
+ parentUid,
18207
+ {
18208
+ props: effectiveNode == null ? void 0 : effectiveNode.props,
18209
+ stepParams: effectiveNode == null ? void 0 : effectiveNode.stepParams
18210
+ },
18211
+ transaction,
18212
+ String((current == null ? void 0 : current.uid) || "")
18213
+ );
18214
+ }
17529
18215
  hasAIEmployeePublicSettings(settings) {
17530
18216
  return import_lodash.default.isPlainObject(settings) && AI_EMPLOYEE_PUBLIC_SETTING_KEYS.some((key) => Object.prototype.hasOwnProperty.call(settings, key));
17531
18217
  }
@@ -17580,11 +18266,24 @@ class FlowSurfacesService {
17580
18266
  var _a;
17581
18267
  const stepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
17582
18268
  if (Array.isArray(stepTasks)) {
17583
- return stepTasks;
18269
+ return this.normalizeAIEmployeeLegacyInheritedTaskWorkContext(stepTasks);
17584
18270
  }
17585
- const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
18271
+ const legacyPropsTasks = this.normalizeAIEmployeeLegacyInheritedTaskWorkContext((_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks);
17586
18272
  return Array.isArray(legacyPropsTasks) ? legacyPropsTasks : [];
17587
18273
  }
18274
+ normalizeAIEmployeeLegacyInheritedTaskWorkContext(tasks) {
18275
+ if (!Array.isArray(tasks)) {
18276
+ return tasks;
18277
+ }
18278
+ return tasks.map((task) => {
18279
+ if (!import_lodash.default.isPlainObject(task) || !import_lodash.default.isPlainObject(task.message) || task.message.workContext !== null) {
18280
+ return task;
18281
+ }
18282
+ const nextTask = import_lodash.default.cloneDeep(task);
18283
+ delete nextTask.message.workContext;
18284
+ return nextTask;
18285
+ });
18286
+ }
17588
18287
  buildAIEmployeeTaskStepParams(tasks) {
17589
18288
  const stepParams = {};
17590
18289
  import_lodash.default.set(stepParams, AI_EMPLOYEE_TASK_STEP_PARAMS_PATH, import_lodash.default.cloneDeep(tasks));
@@ -17613,7 +18312,7 @@ class FlowSurfacesService {
17613
18312
  if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
17614
18313
  return;
17615
18314
  }
17616
- const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
18315
+ const legacyPropsTasks = this.normalizeAIEmployeeLegacyInheritedTaskWorkContext((_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks);
17617
18316
  const hasLegacyPropsTasks = Array.isArray(legacyPropsTasks);
17618
18317
  const hasNextStepTasks = import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
17619
18318
  const currentStepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
@@ -17785,6 +18484,20 @@ class FlowSurfacesService {
17785
18484
  };
17786
18485
  });
17787
18486
  }
18487
+ normalizeAIEmployeeEffectiveActionWorkContext(actionName, settings, currentProps, options) {
18488
+ var _a;
18489
+ const hasSettingsWorkContext = Object.prototype.hasOwnProperty.call(settings, "workContext");
18490
+ const currentWorkContext = (_a = currentProps == null ? void 0 : currentProps.context) == null ? void 0 : _a.workContext;
18491
+ if (!hasSettingsWorkContext && !Array.isArray(currentWorkContext) && !options.requireUsername && !options.selfUid) {
18492
+ return void 0;
18493
+ }
18494
+ const rawWorkContext = hasSettingsWorkContext ? settings.workContext : Array.isArray(currentWorkContext) ? currentWorkContext : [{ type: "flow-model", target: "self" }];
18495
+ return this.normalizeAIEmployeeWorkContext(actionName, rawWorkContext, {
18496
+ selfUid: options.selfUid,
18497
+ keyMap: options.keyMap,
18498
+ path: "settings.workContext"
18499
+ });
18500
+ }
17788
18501
  normalizeAIEmployeeTaskModel(actionName, path, value) {
17789
18502
  if (import_lodash.default.isUndefined(value) || value === null) {
17790
18503
  return value;
@@ -18100,6 +18813,7 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18100
18813
  );
18101
18814
  }
18102
18815
  async normalizeAIEmployeeStepParamTasksForUpdateSettings(current, nextPayload, writeTarget, options) {
18816
+ var _a, _b, _c, _d;
18103
18817
  if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use) || !import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])) {
18104
18818
  return;
18105
18819
  }
@@ -18108,15 +18822,63 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18108
18822
  return;
18109
18823
  }
18110
18824
  const actionName = options.openViewActionName || "updateSettings";
18111
- const normalizedTasks = this.normalizeAIEmployeeTasks(
18825
+ const selfUid = await this.resolveAIEmployeeActionSelfUid(current || { uid: writeTarget.uid }, options.transaction);
18826
+ const currentPropsForDefault = import_lodash.default.mergeWith(
18827
+ {},
18828
+ import_lodash.default.isPlainObject(current == null ? void 0 : current.props) ? current.props : {},
18829
+ import_lodash.default.isPlainObject(nextPayload.props) ? nextPayload.props : {},
18830
+ (_currentValue, nextValue) => {
18831
+ if (Array.isArray(nextValue)) {
18832
+ return import_lodash.default.cloneDeep(nextValue);
18833
+ }
18834
+ return void 0;
18835
+ }
18836
+ );
18837
+ const defaultWorkContext = this.normalizeAIEmployeeEffectiveActionWorkContext(
18112
18838
  actionName,
18113
- tasks,
18114
- this.readAIEmployeePersistedTasks(current),
18839
+ {},
18840
+ currentPropsForDefault,
18115
18841
  {
18116
- selfUid: await this.resolveAIEmployeeActionSelfUid(current || { uid: writeTarget.uid }, options.transaction),
18117
- path: "stepParams.shortcutSettings.editTasks.tasks"
18842
+ selfUid,
18843
+ requireUsername: true
18118
18844
  }
18119
18845
  );
18846
+ const currentTasks = this.readAIEmployeePersistedTasks(current);
18847
+ const previousActionWorkContext = this.normalizeAIEmployeeActionWorkContextForDedupIdentity(
18848
+ (_b = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.context) == null ? void 0 : _b.workContext,
18849
+ this.normalizeAIEmployeeDefaultActionWorkContextForSelfUid(selfUid)
18850
+ );
18851
+ const nextActionWorkContext = this.normalizeAIEmployeeActionWorkContextForDedupIdentity(
18852
+ (_c = currentPropsForDefault == null ? void 0 : currentPropsForDefault.context) == null ? void 0 : _c.workContext,
18853
+ defaultWorkContext
18854
+ );
18855
+ if (Array.isArray(defaultWorkContext) && !import_lodash.default.isEqual((_d = currentPropsForDefault == null ? void 0 : currentPropsForDefault.context) == null ? void 0 : _d.workContext, defaultWorkContext)) {
18856
+ nextPayload.props = import_lodash.default.mergeWith(
18857
+ {},
18858
+ currentPropsForDefault,
18859
+ {
18860
+ context: {
18861
+ workContext: import_lodash.default.cloneDeep(defaultWorkContext)
18862
+ }
18863
+ },
18864
+ (_currentValue, nextValue) => {
18865
+ if (Array.isArray(nextValue)) {
18866
+ return import_lodash.default.cloneDeep(nextValue);
18867
+ }
18868
+ return void 0;
18869
+ }
18870
+ );
18871
+ }
18872
+ const currentTasksForNormalization = this.rebaseAIEmployeeInheritedTaskWorkContext(
18873
+ currentTasks,
18874
+ previousActionWorkContext,
18875
+ nextActionWorkContext
18876
+ );
18877
+ const normalizedTasks = this.normalizeAIEmployeeTasks(actionName, tasks, currentTasksForNormalization, {
18878
+ selfUid,
18879
+ defaultWorkContext,
18880
+ path: "stepParams.shortcutSettings.editTasks.tasks"
18881
+ });
18120
18882
  import_lodash.default.set(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH], normalizedTasks);
18121
18883
  }
18122
18884
  normalizeAIEmployeeTaskMessage(actionName, path, value, existing, options) {
@@ -18145,13 +18907,18 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18145
18907
  if (Object.prototype.hasOwnProperty.call(nextMessage, "user") && typeof nextMessage.user !== "string") {
18146
18908
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.user must be a string`);
18147
18909
  }
18148
- if (Object.prototype.hasOwnProperty.call(value, "workContext")) {
18910
+ if (value.workContext === null) {
18911
+ delete nextMessage.workContext;
18912
+ } else if (Object.prototype.hasOwnProperty.call(value, "workContext")) {
18149
18913
  nextMessage.workContext = this.normalizeAIEmployeeWorkContext(actionName, value.workContext, {
18150
18914
  selfUid: options.selfUid,
18151
18915
  keyMap: options.keyMap,
18152
18916
  path: `${path}.workContext`
18153
18917
  });
18154
18918
  }
18919
+ if (!Object.prototype.hasOwnProperty.call(nextMessage, "workContext") && this.shouldMaterializeAIEmployeeTaskDefaultWorkContext(options.defaultWorkContext)) {
18920
+ nextMessage.workContext = import_lodash.default.cloneDeep(options.defaultWorkContext);
18921
+ }
18155
18922
  return nextMessage;
18156
18923
  }
18157
18924
  normalizeAIEmployeeTaskPatch(actionName, patch, existing, options) {
@@ -18175,7 +18942,8 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18175
18942
  if (key === "message") {
18176
18943
  next.message = this.normalizeAIEmployeeTaskMessage(actionName, `${options.path}.message`, value, next.message, {
18177
18944
  selfUid: options.selfUid,
18178
- keyMap: options.keyMap
18945
+ keyMap: options.keyMap,
18946
+ defaultWorkContext: options.defaultWorkContext
18179
18947
  });
18180
18948
  return;
18181
18949
  }
@@ -18225,6 +18993,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18225
18993
  if (!import_lodash.default.isPlainObject(next.message)) {
18226
18994
  next.message = {};
18227
18995
  }
18996
+ if (!Object.prototype.hasOwnProperty.call(next.message, "workContext") && this.shouldMaterializeAIEmployeeTaskDefaultWorkContext(options.defaultWorkContext)) {
18997
+ next.message.workContext = import_lodash.default.cloneDeep(options.defaultWorkContext);
18998
+ }
18228
18999
  if (import_lodash.default.isPlainObject(next.skillSettings)) {
18229
19000
  if (Array.isArray(next.skillSettings.skills) && !Object.prototype.hasOwnProperty.call(next.skillSettings, "skillsVersion")) {
18230
19001
  next.skillSettings.skillsVersion = 2;
@@ -18251,10 +19022,52 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18251
19022
  nextTasks[index] = this.normalizeAIEmployeeTaskPatch(actionName, task, existingTasks[index], {
18252
19023
  selfUid: options.selfUid,
18253
19024
  keyMap: options.keyMap,
18254
- path: `${options.path}[${index}]`
19025
+ path: `${options.path}[${index}]`,
19026
+ defaultWorkContext: options.defaultWorkContext
18255
19027
  });
18256
19028
  });
18257
- return nextTasks;
19029
+ return this.withAIEmployeeTaskDefaultWorkContext(nextTasks, options.defaultWorkContext);
19030
+ }
19031
+ withAIEmployeeTaskDefaultWorkContext(tasks, defaultWorkContext) {
19032
+ const nextTasks = Array.isArray(tasks) ? import_lodash.default.cloneDeep(tasks) : [];
19033
+ if (!this.shouldMaterializeAIEmployeeTaskDefaultWorkContext(defaultWorkContext)) {
19034
+ return nextTasks;
19035
+ }
19036
+ return nextTasks.map((task) => {
19037
+ if (!import_lodash.default.isPlainObject(task)) {
19038
+ return task;
19039
+ }
19040
+ const nextTask = import_lodash.default.cloneDeep(task);
19041
+ if (!import_lodash.default.isPlainObject(nextTask.message)) {
19042
+ nextTask.message = {
19043
+ workContext: import_lodash.default.cloneDeep(defaultWorkContext)
19044
+ };
19045
+ } else if (!Object.prototype.hasOwnProperty.call(nextTask.message, "workContext")) {
19046
+ nextTask.message.workContext = import_lodash.default.cloneDeep(defaultWorkContext);
19047
+ }
19048
+ return nextTask;
19049
+ });
19050
+ }
19051
+ shouldMaterializeAIEmployeeTaskDefaultWorkContext(defaultWorkContext) {
19052
+ return Array.isArray(defaultWorkContext) && defaultWorkContext.length > 0;
19053
+ }
19054
+ rebaseAIEmployeeInheritedTaskWorkContext(currentTasks, previousActionWorkContext, nextActionWorkContext) {
19055
+ const tasks = this.normalizeAIEmployeeLegacyInheritedTaskWorkContext(currentTasks) || [];
19056
+ if (!previousActionWorkContext.length || import_lodash.default.isEqual(previousActionWorkContext, nextActionWorkContext)) {
19057
+ return tasks;
19058
+ }
19059
+ return tasks.map((task) => {
19060
+ const nextTask = import_lodash.default.cloneDeep(task);
19061
+ if (import_lodash.default.isPlainObject(nextTask == null ? void 0 : nextTask.message)) {
19062
+ const currentTaskWorkContext = this.normalizeAIEmployeeWorkContextForDedupIdentity(
19063
+ nextTask.message.workContext
19064
+ );
19065
+ if (import_lodash.default.isEqual(currentTaskWorkContext, previousActionWorkContext)) {
19066
+ delete nextTask.message.workContext;
19067
+ }
19068
+ }
19069
+ return nextTask;
19070
+ });
18258
19071
  }
18259
19072
  normalizeAIEmployeeActionSettingsReferences(actionName, settings, options) {
18260
19073
  if (!this.hasAIEmployeePublicSettings(settings)) {
@@ -18268,15 +19081,22 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18268
19081
  });
18269
19082
  }
18270
19083
  if (Object.prototype.hasOwnProperty.call(nextSettings, "tasks")) {
19084
+ const defaultWorkContext = this.normalizeAIEmployeeEffectiveActionWorkContext(
19085
+ actionName,
19086
+ nextSettings,
19087
+ {},
19088
+ options
19089
+ );
18271
19090
  nextSettings.tasks = this.normalizeAIEmployeeTasks(actionName, nextSettings.tasks, [], {
18272
19091
  ...options,
18273
- path: "settings.tasks"
19092
+ path: "settings.tasks",
19093
+ defaultWorkContext
18274
19094
  });
18275
19095
  }
18276
19096
  return nextSettings;
18277
19097
  }
18278
19098
  async normalizeAIEmployeeActionPublicSettings(actionName, settings, options) {
18279
- var _a, _b;
19099
+ var _a, _b, _c, _d;
18280
19100
  this.assertAIEmployeePluginEnabled(actionName, options.enabledPackages);
18281
19101
  if (!import_lodash.default.isPlainObject(settings)) {
18282
19102
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings must be an object`);
@@ -18296,6 +19116,17 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18296
19116
  }
18297
19117
  const props = {};
18298
19118
  const stepParams = {};
19119
+ const effectiveActionWorkContext = this.normalizeAIEmployeeEffectiveActionWorkContext(
19120
+ actionName,
19121
+ settings,
19122
+ currentProps,
19123
+ options
19124
+ );
19125
+ const previousActionWorkContext = this.normalizeAIEmployeeActionWorkContextForDedupIdentity(
19126
+ (_c = currentProps == null ? void 0 : currentProps.context) == null ? void 0 : _c.workContext,
19127
+ this.normalizeAIEmployeeDefaultActionWorkContextForSelfUid(options.selfUid)
19128
+ );
19129
+ const nextActionWorkContext = this.normalizeAIEmployeeWorkContextForDedupIdentity(effectiveActionWorkContext);
18299
19130
  if (effectiveUsername && (hasUsername || options.requireUsername)) {
18300
19131
  props.aiEmployee = {
18301
19132
  ...import_lodash.default.isPlainObject(currentProps.aiEmployee) ? import_lodash.default.cloneDeep(currentProps.aiEmployee) : {},
@@ -18309,28 +19140,25 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18309
19140
  }
18310
19141
  props.auto = auto;
18311
19142
  }
18312
- if (Object.prototype.hasOwnProperty.call(settings, "workContext") || options.requireUsername) {
18313
- const rawWorkContext = Object.prototype.hasOwnProperty.call(settings, "workContext") ? settings.workContext : [{ type: "flow-model", target: "self" }];
19143
+ 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))) {
18314
19144
  props.context = {
18315
19145
  ...import_lodash.default.isPlainObject(currentProps.context) ? import_lodash.default.cloneDeep(currentProps.context) : {},
18316
- workContext: this.normalizeAIEmployeeWorkContext(actionName, rawWorkContext, {
18317
- selfUid: options.selfUid,
18318
- keyMap: options.keyMap,
18319
- path: "settings.workContext"
18320
- })
19146
+ workContext: import_lodash.default.cloneDeep(effectiveActionWorkContext)
18321
19147
  };
18322
19148
  }
18323
19149
  if (Object.prototype.hasOwnProperty.call(settings, "tasks")) {
18324
- const normalizedTasks = this.normalizeAIEmployeeTasks(
18325
- actionName,
18326
- settings.tasks,
18327
- this.readAIEmployeePersistedTasks(options.current),
18328
- {
18329
- selfUid: options.selfUid,
18330
- keyMap: options.keyMap,
18331
- path: "settings.tasks"
18332
- }
19150
+ const currentTasks = this.readAIEmployeePersistedTasks(options.current);
19151
+ const currentTasksForNormalization = this.rebaseAIEmployeeInheritedTaskWorkContext(
19152
+ currentTasks,
19153
+ previousActionWorkContext,
19154
+ nextActionWorkContext
18333
19155
  );
19156
+ const normalizedTasks = this.normalizeAIEmployeeTasks(actionName, settings.tasks, currentTasksForNormalization, {
19157
+ selfUid: options.selfUid,
19158
+ keyMap: options.keyMap,
19159
+ path: "settings.tasks",
19160
+ defaultWorkContext: effectiveActionWorkContext
19161
+ });
18334
19162
  const validation = options.promptContext && normalizedTasks.length ? await this.buildAIEmployeePromptValidationContext(
18335
19163
  actionName,
18336
19164
  [
@@ -18351,6 +19179,17 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18351
19179
  const tasks = this.appendAIEmployeeCurrentRecordPromptVariableToTasks(normalizedTasks, validation);
18352
19180
  this.assertAIEmployeeTaskPromptVariablesAllowed(actionName, tasks, validation);
18353
19181
  import_lodash.default.merge(stepParams, this.buildAIEmployeeTaskStepParams(tasks));
19182
+ } else if (!options.skipExistingTaskWorkContextRebase && Object.prototype.hasOwnProperty.call(settings, "workContext") && !import_lodash.default.isEqual(previousActionWorkContext, nextActionWorkContext)) {
19183
+ const currentTasks = this.readAIEmployeePersistedTasks(options.current);
19184
+ const rebasedTasks = this.rebaseAIEmployeeInheritedTaskWorkContext(
19185
+ currentTasks,
19186
+ previousActionWorkContext,
19187
+ nextActionWorkContext
19188
+ );
19189
+ const tasks = this.withAIEmployeeTaskDefaultWorkContext(rebasedTasks, effectiveActionWorkContext);
19190
+ if (tasks.length) {
19191
+ import_lodash.default.merge(stepParams, this.buildAIEmployeeTaskStepParams(tasks));
19192
+ }
18354
19193
  }
18355
19194
  if (Object.prototype.hasOwnProperty.call(settings, "style") || options.requireUsername) {
18356
19195
  const style = Object.prototype.hasOwnProperty.call(settings, "style") ? settings.style : {};
@@ -18392,7 +19231,16 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18392
19231
  transaction,
18393
19232
  includeAsyncNode: true
18394
19233
  });
18395
- if (["TableActionsColumnModel", "ListItemModel", "GridCardItemModel"].includes(String((parentNode == null ? void 0 : parentNode.use) || ""))) {
19234
+ return await this.resolveAIEmployeeActionSelfUidFromParentNode(parentNode, transaction) || parentUid;
19235
+ }
19236
+ async resolveAIEmployeeActionSelfUidFromParentNode(parentNode, transaction) {
19237
+ const parentUid = String((parentNode == null ? void 0 : parentNode.uid) || "").trim();
19238
+ if (!parentUid) {
19239
+ return "";
19240
+ }
19241
+ if (["TableActionsColumnModel", "ListItemModel", "GridCardItemModel", "CommentItemModel"].includes(
19242
+ String((parentNode == null ? void 0 : parentNode.use) || "")
19243
+ )) {
18396
19244
  const ownerUid = String((parentNode == null ? void 0 : parentNode.parentId) || "").trim() || ((parentNode == null ? void 0 : parentNode.uid) ? await this.locator.findParentUid(parentNode.uid, transaction).catch(() => "") : "");
18397
19245
  return ownerUid || parentUid;
18398
19246
  }
@@ -18441,13 +19289,14 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18441
19289
  }
18442
19290
  const normalizedDefaultFilter = (0, import_service_utils.hasOwnDefined)(changes, "defaultFilter") ? this.normalizeFilterActionDefaultFilterValue(changes.defaultFilter) : void 0;
18443
19291
  const stepParams = {};
18444
- if ((0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "type", "danger", "color", "linkageRules"])) {
19292
+ if ((0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "iconOnly", "type", "danger", "color", "linkageRules"])) {
18445
19293
  stepParams.buttonSettings = {
18446
- ...(0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "type", "danger", "color"]) ? {
19294
+ ...(0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "iconOnly", "type", "danger", "color"]) ? {
18447
19295
  general: (0, import_service_utils.buildDefinedPayload)({
18448
19296
  title: changes.title,
18449
19297
  tooltip: changes.tooltip,
18450
19298
  icon: changes.icon,
19299
+ iconOnly: changes.iconOnly,
18451
19300
  type: changes.type,
18452
19301
  danger: changes.danger,
18453
19302
  color: changes.color
@@ -18657,6 +19506,7 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18657
19506
  title: changes.title,
18658
19507
  tooltip: changes.tooltip,
18659
19508
  icon: changes.icon,
19509
+ iconOnly: changes.iconOnly,
18660
19510
  type: changes.type,
18661
19511
  htmlType: changes.htmlType,
18662
19512
  position: changes.position,
@@ -18786,6 +19636,11 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18786
19636
  useStrictOnly: input.useStrictOnly
18787
19637
  });
18788
19638
  }
19639
+ isCollectionTitleField(collection, fieldName) {
19640
+ const normalizedFieldName = String(fieldName || "").trim();
19641
+ const titleFieldName = String((0, import_service_helpers.getCollectionTitleFieldName)(collection) || "").trim();
19642
+ return !!normalizedFieldName && normalizedFieldName === titleFieldName;
19643
+ }
18789
19644
  resolveAssociationLeafDisplaySemantics(field, dataSourceKey, enabledPackages) {
18790
19645
  const registeredBinding = this.resolveRegisteredFieldBinding({
18791
19646
  containerUse: "DetailsItemModel",
@@ -18821,6 +19676,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18821
19676
  }
18822
19677
  buildFieldMenuDirectCandidates(input) {
18823
19678
  const collection = this.getCollection(input.resourceInit.dataSourceKey, input.resourceInit.collectionName);
19679
+ const explicitDefaultFieldPaths = (0, import_default_action_popup.collectFlowSurfaceDefaultActionPopupFieldGroupFieldPaths)(
19680
+ input.defaultFieldGroups
19681
+ );
18824
19682
  return (0, import_service_helpers.getCollectionFields)(collection).flatMap((field) => {
18825
19683
  var _a;
18826
19684
  const fieldName = (0, import_service_helpers.getFieldName)(field);
@@ -18831,6 +19689,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18831
19689
  if (input.generatedPopupOnly && !(0, import_default_action_popup.isFlowSurfaceDefaultActionPopupBusinessField)(field)) {
18832
19690
  return [];
18833
19691
  }
19692
+ if ((0, import_relation_backing_foreign_key.isRelationBackingForeignKeyField)(collection, field) && !explicitDefaultFieldPaths.has(fieldName)) {
19693
+ return [];
19694
+ }
18834
19695
  if (input.mode === "table" && ((_a = field == null ? void 0 : field.options) == null ? void 0 : _a.treeChildren)) {
18835
19696
  return [];
18836
19697
  }
@@ -18918,6 +19779,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18918
19779
  if (!targetFieldName) {
18919
19780
  continue;
18920
19781
  }
19782
+ if ((0, import_relation_backing_foreign_key.isRelationBackingForeignKeyField)(targetCollection, targetField) && !this.isCollectionTitleField(targetCollection, targetFieldName)) {
19783
+ continue;
19784
+ }
18921
19785
  nextCandidates.push({
18922
19786
  field: targetField,
18923
19787
  fieldPath: `${associationPathName}.${targetFieldName}`,
@@ -19092,7 +19956,7 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
19092
19956
  const getFields = (targetCollection) => (0, import_service_helpers.getCollectionFields)(targetCollection);
19093
19957
  const isFilterFieldVisible = (field) => (0, import_service_helpers.getFieldFilterable)(field) !== false && !!(0, import_service_helpers.getFieldInterface)(field);
19094
19958
  const directFields = getFields(collection).filter(
19095
- (field) => ["FilterFormBlockModel", "FilterFormGridModel", "FilterFormItemModel"].includes(input.ownerUse) ? isFilterFieldVisible(field) : !!(0, import_service_helpers.getFieldInterface)(field)
19959
+ (field) => !(0, import_relation_backing_foreign_key.isRelationBackingForeignKeyField)(collection, field) && (["FilterFormBlockModel", "FilterFormGridModel", "FilterFormItemModel"].includes(input.ownerUse) ? isFilterFieldVisible(field) : !!(0, import_service_helpers.getFieldInterface)(field))
19096
19960
  );
19097
19961
  if (!directFields.length && !collection) {
19098
19962
  return [];
@@ -19106,9 +19970,13 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
19106
19970
  if (!(0, import_service_helpers.isAssociationField)(field) || !targetCollection) {
19107
19971
  return [];
19108
19972
  }
19109
- return getFields(targetCollection).filter(
19110
- (targetField) => ["FilterFormBlockModel", "FilterFormGridModel", "FilterFormItemModel"].includes(input.ownerUse) ? isFilterFieldVisible(targetField) : !!(0, import_service_helpers.getFieldInterface)(targetField)
19111
- ).map((targetField) => ({
19973
+ return getFields(targetCollection).filter((targetField) => {
19974
+ const targetFieldName = (0, import_service_helpers.getFieldName)(targetField);
19975
+ if ((0, import_relation_backing_foreign_key.isRelationBackingForeignKeyField)(targetCollection, targetField) && !this.isCollectionTitleField(targetCollection, targetFieldName)) {
19976
+ return false;
19977
+ }
19978
+ return ["FilterFormBlockModel", "FilterFormGridModel", "FilterFormItemModel"].includes(input.ownerUse) ? isFilterFieldVisible(targetField) : !!(0, import_service_helpers.getFieldInterface)(targetField);
19979
+ }).map((targetField) => ({
19112
19980
  field: targetField,
19113
19981
  fieldPath: `${(0, import_service_helpers.getFieldName)(field)}.${(0, import_service_helpers.getFieldName)(targetField)}`,
19114
19982
  associationPathName: (0, import_service_helpers.getFieldName)(field),